General refactor and restyling.

This commit is contained in:
2021-11-09 19:44:38 +00:00
parent f351cbcf14
commit 38ba41368d
11 changed files with 371 additions and 495 deletions

View File

@@ -29,7 +29,7 @@
<ExternalConsole>true</ExternalConsole>
</PropertyGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Program.cs"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Claunia.RsrcFork\Claunia.RsrcFork.csproj">

View File

@@ -31,7 +31,7 @@ using System.Text;
namespace Claunia.RsrcFork.CLI;
class MainClass
internal class MainClass
{
public static void Main(string[] args)
{
@@ -39,103 +39,101 @@ class MainClass
Console.WriteLine("© 2016 Natalia Portillo");
Console.WriteLine();
if(args.Length != 2 && args.Length != 4)
if(args.Length != 2 &&
args.Length != 4)
{
Usage();
return;
}
if(args.Length == 2)
{
if(args[0] != "-l")
{
Usage();
return;
}
if(!File.Exists(args[1]))
{
Console.WriteLine("Specified file does not exist.");
return;
}
FileStream rsrcStream = new FileStream(args[1], FileMode.Open, FileAccess.Read);
ResourceFork rsrc = new ResourceFork(rsrcStream);
foreach(uint type in rsrc.GetTypes())
{
byte[] typeBytes = BitConverter.GetBytes(type);
typeBytes = typeBytes.Reverse().ToArray();
string typeName = Types.GetName(type);
if(typeName != null)
Console.WriteLine("\"{0}\" (0x{1:X8}) - {2}", Encoding.ASCII.GetString(typeBytes), type,
typeName);
else Console.WriteLine("\"{0}\" (0x{1:X8})", Encoding.ASCII.GetString(typeBytes), type);
Resource rez = rsrc.GetResource(type);
Console.WriteLine("{0,6}{1,8}\t{2}", "ID", "Length", "Name");
Console.WriteLine("{0,6}{1,8}--{2}", "------", "--------", "----------------");
foreach(short id in rez.GetIds())
if(rez.GetName(id) != null)
Console.WriteLine("{0,6}{1,8}\t\"{2}\"", id, rez.GetLength(id), rez.GetName(id));
else Console.WriteLine("{0,6}{1,8}", id, rez.GetLength(id));
Console.WriteLine();
}
return;
}
if(args.Length == 4)
switch(args.Length)
{
if(args[0] != "-x")
{
case 2 when args[0] != "-l":
Usage();
return;
}
if(args[1] != "-o")
{
Usage();
return;
}
if(Directory.Exists(args[2]))
{
Console.WriteLine("Output directory exists, not proceeding");
return;
}
if(!File.Exists(args[3]))
{
case 2 when !File.Exists(args[1]):
Console.WriteLine("Specified file does not exist.");
return;
}
FileStream rsrcStream = new FileStream(args[3], FileMode.Open, FileAccess.Read);
FileStream outStream;
ResourceFork rsrc = new ResourceFork(rsrcStream);
foreach(uint type in rsrc.GetTypes())
case 2:
{
byte[] typeBytes = BitConverter.GetBytes(type);
typeBytes = typeBytes.Reverse().ToArray();
var rsrcStream = new FileStream(args[1], FileMode.Open, FileAccess.Read);
Directory.CreateDirectory(Path.Combine(args[2], Encoding.ASCII.GetString(typeBytes)));
var rsrc = new ResourceFork(rsrcStream);
Resource rez = rsrc.GetResource(type);
foreach(short id in rez.GetIds())
foreach(uint type in rsrc.GetTypes())
{
outStream =
new
FileStream(Path.Combine(args[2], Encoding.ASCII.GetString(typeBytes), string.Format("{0}", id)),
FileMode.Create, FileAccess.ReadWrite);
byte[] rez_b = rez.GetResource(id);
outStream.Write(rez_b, 0, rez_b.Length);
outStream.Close();
byte[] typeBytes = BitConverter.GetBytes(type);
typeBytes = typeBytes.Reverse().ToArray();
string typeName = Types.GetName(type);
if(typeName != null)
Console.WriteLine("\"{0}\" (0x{1:X8}) - {2}", Encoding.ASCII.GetString(typeBytes), type,
typeName);
else
Console.WriteLine("\"{0}\" (0x{1:X8})", Encoding.ASCII.GetString(typeBytes), type);
Resource rez = rsrc.GetResource(type);
Console.WriteLine("{0,6}{1,8}\t{2}", "ID", "Length", "Name");
Console.WriteLine("{0,6}{1,8}--{2}", "------", "--------", "----------------");
foreach(short id in rez.GetIds())
if(rez.GetName(id) != null)
Console.WriteLine("{0,6}{1,8}\t\"{2}\"", id, rez.GetLength(id), rez.GetName(id));
else
Console.WriteLine("{0,6}{1,8}", id, rez.GetLength(id));
Console.WriteLine();
}
return;
}
case 4 when args[0] != "-x":
Usage();
return;
case 4 when args[1] != "-o":
Usage();
return;
case 4 when Directory.Exists(args[2]):
Console.WriteLine("Output directory exists, not proceeding");
return;
case 4 when !File.Exists(args[3]):
Console.WriteLine("Specified file does not exist.");
return;
case 4:
{
var rsrcStream = new FileStream(args[3], FileMode.Open, FileAccess.Read);
FileStream outStream;
var rsrc = new ResourceFork(rsrcStream);
foreach(uint type in rsrc.GetTypes())
{
byte[] typeBytes = BitConverter.GetBytes(type);
typeBytes = typeBytes.Reverse().ToArray();
Directory.CreateDirectory(Path.Combine(args[2], Encoding.ASCII.GetString(typeBytes)));
Resource rez = rsrc.GetResource(type);
foreach(short id in rez.GetIds())
{
outStream = new FileStream(Path.Combine(args[2], Encoding.ASCII.GetString(typeBytes), $"{id}"),
FileMode.Create, FileAccess.ReadWrite);
byte[] rez_b = rez.GetResource(id);
outStream.Write(rez_b, 0, rez_b.Length);
outStream.Close();
}
}
break;
}
}
}

View File

@@ -29,7 +29,7 @@
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<ItemGroup>
<Compile Include="Test.cs" />
<Compile Include="Test.cs"/>
</ItemGroup>
<ItemGroup>
<None Include="Samples\SelfMountingImage.rsrc">
@@ -46,7 +46,7 @@
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="Samples\" />
<Folder Include="Samples\"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Claunia.RsrcFork\Claunia.RsrcFork.csproj">
@@ -60,15 +60,15 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="NUnit" Version="3.13.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0"/>
<PackageReference Include="NUnit" Version="3.13.2"/>
</ItemGroup>
<ProjectExtensions>
<MonoDevelop>
<Properties>
<Policies>
<TextStylePolicy FileWidth="120" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
<CSharpFormattingPolicy SpacingAfterMethodDeclarationName="False" SpaceAfterMethodCallName="False" SpaceAfterControlFlowStatementKeyword="False" SpaceBeforeOpenSquareBracket="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
<TextStylePolicy FileWidth="120" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp"/>
<CSharpFormattingPolicy SpacingAfterMethodDeclarationName="False" SpaceAfterMethodCallName="False" SpaceAfterControlFlowStatementKeyword="False" SpaceBeforeOpenSquareBracket="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp"/>
</Policies>
</Properties>
</MonoDevelop>

View File

@@ -35,17 +35,20 @@ public class Test
{
readonly byte[] DC42_Vers =
{
0x06, 0x40, 0x80, 0x00, 0x00, 0x00, 0x09, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x43, 0x6F, 0x70, 0x79, 0x1C,
0x34, 0x2E, 0x32, 0x2C, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x63, 0x68, 0x65, 0x63, 0x6B, 0x73, 0x75,
0x6D, 0x3D, 0x24, 0x41, 0x35, 0x31, 0x34, 0x37, 0x46, 0x37, 0x45
0x06, 0x40, 0x80, 0x00, 0x00, 0x00, 0x09, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x43, 0x6F, 0x70, 0x79, 0x1C, 0x34,
0x2E, 0x32, 0x2C, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x63, 0x68, 0x65, 0x63, 0x6B, 0x73, 0x75, 0x6D, 0x3D,
0x24, 0x41, 0x35, 0x31, 0x34, 0x37, 0x46, 0x37, 0x45
};
readonly byte[] DC42_Str =
{
0x09, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x43, 0x6F, 0x70, 0x79
};
readonly byte[] DC42_Str = {0x09, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x43, 0x6F, 0x70, 0x79};
[Test]
public void TestDC42()
{
FileStream dc42Stream = new FileStream("Samples/DiskCopy42.rsrc", FileMode.Open, FileAccess.Read);
ResourceFork rsrc = new ResourceFork(dc42Stream);
var dc42Stream = new FileStream("Samples/DiskCopy42.rsrc", FileMode.Open, FileAccess.Read);
var rsrc = new ResourceFork(dc42Stream);
uint[] types = rsrc.GetTypes();
Assert.AreEqual(0x53545220, types[0]);
@@ -56,7 +59,7 @@ public class Test
short[] str_Ids = str_.GetIds();
Assert.AreEqual(-16396, str_Ids[0]);
Assert.AreEqual(10, str_.GetLength(-16396));
Assert.AreEqual(10, str_.GetLength(-16396));
byte[] str1 = str_.GetResource(-16396);
Assert.AreEqual(DC42_Str, str1);
@@ -67,7 +70,7 @@ public class Test
Resource vers = rsrc.GetResource(0x76657273);
Assert.IsNotNull(vers);
short[] versIds = vers.GetIds();
Assert.AreEqual(1, versIds[0]);
Assert.AreEqual(1, versIds[0]);
Assert.AreEqual(45, vers.GetLength(1));
byte[] vers1 = vers.GetResource(1);
@@ -76,21 +79,21 @@ public class Test
string versStr = vers.GetName(1);
Assert.IsNull(versStr);
Version versDec = new Version(vers1);
Assert.AreEqual(6, versDec.MajorVersion);
Assert.AreEqual(40, versDec.MinorVersion);
var versDec = new Version(vers1);
Assert.AreEqual(6, versDec.MajorVersion);
Assert.AreEqual(40, versDec.MinorVersion);
Assert.AreEqual(Version.DevelopmentStage.Final, versDec.DevStage);
Assert.AreEqual(0, versDec.PreReleaseVersion);
Assert.AreEqual(0, versDec.RegionCode);
Assert.AreEqual("Disk Copy", versDec.VersionString);
Assert.AreEqual(0, versDec.PreReleaseVersion);
Assert.AreEqual(0, versDec.RegionCode);
Assert.AreEqual("Disk Copy", versDec.VersionString);
Assert.AreEqual("4.2, data checksum=$A5147F7E", versDec.VersionMessage);
}
[Test]
public void TestDC6()
{
FileStream dc6Stream = new FileStream("Samples/DiskCopy6.rsrc", FileMode.Open, FileAccess.Read);
ResourceFork rsrc = new ResourceFork(dc6Stream);
var dc6Stream = new FileStream("Samples/DiskCopy6.rsrc", FileMode.Open, FileAccess.Read);
var rsrc = new ResourceFork(dc6Stream);
uint[] types = rsrc.GetTypes();
Assert.AreEqual(0x53545220, types[0]);
@@ -103,7 +106,7 @@ public class Test
short[] str_Ids = str_.GetIds();
Assert.AreEqual(-16396, str_Ids[0]);
Assert.AreEqual(10, str_.GetLength(-16396));
Assert.AreEqual(10, str_.GetLength(-16396));
byte[] str1 = str_.GetResource(-16396);
Assert.AreEqual(DC42_Str, str1);
@@ -114,7 +117,7 @@ public class Test
Resource vers = rsrc.GetResource(0x76657273);
Assert.IsNotNull(vers);
short[] versIds = vers.GetIds();
Assert.AreEqual(1, versIds[0]);
Assert.AreEqual(1, versIds[0]);
Assert.AreEqual(66, vers.GetLength(1));
string versStr = vers.GetName(1);
@@ -136,25 +139,25 @@ public class Test
string bceSStr = bceS.GetName(128);
Assert.IsNull(bceSStr);
byte[] vers1 = vers.GetResource(1);
Version versDec = new Version(vers1);
Assert.AreEqual(6, versDec.MajorVersion);
Assert.AreEqual(40, versDec.MinorVersion);
Assert.AreEqual(Version.DevelopmentStage.Final, versDec.DevStage);
Assert.AreEqual(0, versDec.PreReleaseVersion);
Assert.AreEqual(0, versDec.RegionCode);
Assert.AreEqual("6.4 Disk Copy", versDec.VersionString);
byte[] vers1 = vers.GetResource(1);
var versDec = new Version(vers1);
Assert.AreEqual(6, versDec.MajorVersion);
Assert.AreEqual(40, versDec.MinorVersion);
Assert.AreEqual(Version.DevelopmentStage.Final, versDec.DevStage);
Assert.AreEqual(0, versDec.PreReleaseVersion);
Assert.AreEqual(0, versDec.RegionCode);
Assert.AreEqual("6.4 Disk Copy", versDec.VersionString);
Assert.AreEqual("Mac? OS HFS 1680K disk image\rCRC28: $07213FB7", versDec.VersionMessage);
}
[Test]
public void TestSMI()
{
FileStream smiStream = new FileStream("Samples/SelfMountingImage.rsrc", FileMode.Open, FileAccess.Read);
ResourceFork rsrc = new ResourceFork(smiStream);
var smiStream = new FileStream("Samples/SelfMountingImage.rsrc", FileMode.Open, FileAccess.Read);
var rsrc = new ResourceFork(smiStream);
uint[] types = rsrc.GetTypes();
Assert.AreEqual(29, types.Length);
Assert.AreEqual(29, types.Length);
Assert.AreEqual(0x424E444C, types[0]);
Assert.AreEqual(0x434F4445, types[1]);
Assert.AreEqual(0x44415441, types[2]);
@@ -170,8 +173,8 @@ public class Test
Resource code = rsrc.GetResource(0x434F4445);
Assert.IsNotNull(code);
short[] codeIds = code.GetIds();
Assert.AreEqual(0, codeIds[0]);
Assert.AreEqual(1, codeIds[1]);
Assert.AreEqual(0, codeIds[0]);
Assert.AreEqual(1, codeIds[1]);
Assert.AreEqual(35130, code.GetLength(1));
string codeStr = code.GetName(1);
Assert.AreEqual("First Segment", codeStr); //"First Segment"
@@ -180,38 +183,38 @@ public class Test
Assert.IsNotNull(bndl);
short[] bndlIds = bndl.GetIds();
Assert.AreEqual(128, bndlIds[0]);
Assert.AreEqual(28, bndl.GetLength(128));
Assert.AreEqual(28, bndl.GetLength(128));
string bndlStr = bndl.GetName(128);
Assert.IsNull(bndlStr);
Resource vers = rsrc.GetResource(0x76657273);
Assert.IsNotNull(vers);
byte[] vers1 = vers.GetResource(1);
Version versDec = new Version(vers1);
Assert.AreEqual(1, versDec.MajorVersion);
Assert.AreEqual(10, versDec.MinorVersion);
Assert.AreEqual(Version.DevelopmentStage.Beta, versDec.DevStage);
Assert.AreEqual(6, versDec.PreReleaseVersion);
Assert.AreEqual(0, versDec.RegionCode);
Assert.AreEqual("1.1b6", versDec.VersionString);
byte[] vers1 = vers.GetResource(1);
var versDec = new Version(vers1);
Assert.AreEqual(1, versDec.MajorVersion);
Assert.AreEqual(10, versDec.MinorVersion);
Assert.AreEqual(Version.DevelopmentStage.Beta, versDec.DevStage);
Assert.AreEqual(6, versDec.PreReleaseVersion);
Assert.AreEqual(0, versDec.RegionCode);
Assert.AreEqual("1.1b6", versDec.VersionString);
Assert.AreEqual("1.1b6, Copyright 1997-2001 Apple Computer, Inc.", versDec.VersionMessage);
}
[Test]
public void TestUDIF()
{
FileStream udifStream = new FileStream("Samples/UDIF.rsrc", FileMode.Open, FileAccess.Read);
ResourceFork rsrc = new ResourceFork(udifStream);
var udifStream = new FileStream("Samples/UDIF.rsrc", FileMode.Open, FileAccess.Read);
var rsrc = new ResourceFork(udifStream);
uint[] types = rsrc.GetTypes();
Assert.AreEqual(2, types.Length);
Assert.AreEqual(2, types.Length);
Assert.AreEqual(0x626C6B78, types[0]);
Assert.AreEqual(0x706C7374, types[1]);
Resource blkx = rsrc.GetResource(0x626C6B78);
Assert.IsNotNull(blkx);
short[] blkxIds = blkx.GetIds();
Assert.AreEqual(0, blkxIds[0]);
Assert.AreEqual(0, blkxIds[0]);
Assert.AreEqual(524, blkx.GetLength(0));
string blkxStr = blkx.GetName(0);
Assert.AreEqual("Whole Device (Apple_XXX : 0)", blkxStr); //"First Segment"
@@ -219,7 +222,7 @@ public class Test
Resource plst = rsrc.GetResource(0x706C7374);
Assert.IsNotNull(plst);
short[] plstIds = plst.GetIds();
Assert.AreEqual(0, plstIds[0]);
Assert.AreEqual(0, plstIds[0]);
Assert.AreEqual(1544, plst.GetLength(0));
string plstStr = plst.GetName(0);
Assert.IsNull(plstStr);

View File

@@ -60,6 +60,6 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Folder Include="Resources\" />
<Folder Include="Resources\"/>
</ItemGroup>
</Project>

View File

@@ -29,37 +29,27 @@ using System.Text;
namespace Claunia.RsrcFork;
/// <summary>
/// Contains convertes between .NET and Pascal strings. Only ASCII supported right now.
/// </summary>
/// <summary>Contains convertes between .NET and Pascal strings. Only ASCII supported right now.</summary>
public static class PascalString
{
/// <summary>
/// Converts an ASCII Pascal string to a .NET string.
/// </summary>
/// <summary>Converts an ASCII Pascal string to a .NET string.</summary>
/// <returns>The .NET string.</returns>
/// <param name="PStr">The ASCII Pascal string.</param>
public static string GetString(byte[] PStr)
{
if(PStr == null || PStr[0] >= PStr.Length) return null;
public static string GetString(byte[] PStr) =>
PStr == null || PStr[0] >= PStr.Length ? null : Encoding.ASCII.GetString(PStr, 1, PStr[0]);
return Encoding.ASCII.GetString(PStr, 1, PStr[0]);
}
/// <summary>
/// Converts a .NET string to an ASCII Pascal string.
/// </summary>
/// <summary>Converts a .NET string to an ASCII Pascal string.</summary>
/// <returns>The ASCII Pascal string.</returns>
/// <param name="str">The .NET string.</param>
public static byte[] GetBytes(string str)
{
if(str == null) return new byte[1];
if(str == null)
return new byte[1];
byte[] str_b = Encoding.ASCII.GetBytes(str);
byte[] PStr;
if(str_b.Length >= 256) PStr = new byte[256];
else PStr = new byte[str_b.Length + 1];
PStr = str_b.Length >= 256 ? new byte[256] : new byte[str_b.Length + 1];
Array.Copy(str_b, 0, PStr, 1, PStr.Length - 1);
PStr[0] = (byte)(PStr.Length - 1);

View File

@@ -32,149 +32,127 @@ using System.Text;
namespace Claunia.RsrcFork;
/// <summary>
/// This class represents a resource type.
/// </summary>
/// <summary>This class represents a resource type.</summary>
public class Resource
{
readonly List<short> ids;
readonly Dictionary<short, byte[]> resourceCache;
readonly Dictionary<short, string> resourceNames;
readonly Dictionary<short, ResourceData> resources;
readonly Stream rsrcStream;
readonly List<short> _ids;
readonly Dictionary<short, byte[]> _resourceCache;
readonly Dictionary<short, string> _resourceNames;
readonly Dictionary<short, ResourceData> _resources;
readonly Stream _rsrcStream;
/// <summary>
/// Initializates the specified resource type.
/// </summary>
/// <summary>Initializates the specified resource type.</summary>
/// <param name="stream">Stream where the resources of this reside.</param>
/// <param name="resources">How many resource of this type are.</param>
/// <param name="referenceListOff">Offset from start of stream to reference list for this type.</param>
/// <param name="resourceNameOffset">Offset from start of stream to resource name list.</param>
/// <param name="resourceDataOffset">Offset from start of stream to resource data.</param>
/// <param name="OSType">Resource type.</param>
internal Resource(Stream stream, ushort resources, long referenceListOff, long resourceNameOffset,
long resourceDataOffset, uint OSType)
internal Resource(Stream stream, ushort resources, long referenceListOff, long resourceNameOffset,
long resourceDataOffset, uint OSType)
{
rsrcStream = stream;
Dictionary<short, ResourceTypeReferenceListItem> referenceLists =
new Dictionary<short, ResourceTypeReferenceListItem>();
resourceNames = new Dictionary<short, string>();
this.resources = new Dictionary<short, ResourceData>();
ids = new List<short>();
_rsrcStream = stream;
Dictionary<short, ResourceTypeReferenceListItem> referenceLists = new();
_resourceNames = new Dictionary<short, string>();
_resources = new Dictionary<short, ResourceData>();
_ids = new List<short>();
byte[] tmp;
rsrcStream.Seek(referenceListOff + 2, SeekOrigin.Begin);
_rsrcStream.Seek(referenceListOff + 2, SeekOrigin.Begin);
for(int i = 0; i < resources; i++)
{
ResourceTypeReferenceListItem item = new ResourceTypeReferenceListItem();
ResourceTypeReferenceListItem item = new();
tmp = new byte[2];
rsrcStream.Read(tmp, 0, 2);
item.id = BitConverter.ToInt16(tmp.Reverse().ToArray(), 0);
rsrcStream.Read(tmp, 0, 2);
item.nameOff = BitConverter.ToInt16(tmp.Reverse().ToArray(), 0);
_rsrcStream.Read(tmp, 0, 2);
item.Id = BitConverter.ToInt16(tmp.Reverse().ToArray(), 0);
_rsrcStream.Read(tmp, 0, 2);
item.NameOff = BitConverter.ToInt16(tmp.Reverse().ToArray(), 0);
tmp = new byte[4];
rsrcStream.Read(tmp, 0, 4);
item.attributes = tmp[0];
_rsrcStream.Read(tmp, 0, 4);
item.Attributes = tmp[0];
tmp[0] = 0;
item.dataOff = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0);
rsrcStream.Read(tmp, 0, 4);
item.handle = BitConverter.ToUInt32(tmp.Reverse().ToArray(), 0);
item.DataOff = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0);
_rsrcStream.Read(tmp, 0, 4);
item.Handle = BitConverter.ToUInt32(tmp.Reverse().ToArray(), 0);
referenceLists.Add(item.id, item);
ids.Add(item.id);
referenceLists.Add(item.Id, item);
_ids.Add(item.Id);
}
foreach(ResourceTypeReferenceListItem item in referenceLists.Values)
{
string name;
ResourceData data = new ResourceData();
ResourceData data = new();
if(item.nameOff == -1) name = null;
if(item.NameOff == -1)
name = null;
else
{
rsrcStream.Seek(resourceNameOffset + item.nameOff, SeekOrigin.Begin);
byte nameLen = (byte)rsrcStream.ReadByte();
_rsrcStream.Seek(resourceNameOffset + item.NameOff, SeekOrigin.Begin);
byte nameLen = (byte)_rsrcStream.ReadByte();
byte[] nameBytes = new byte[nameLen];
rsrcStream.Read(nameBytes, 0, nameLen);
_rsrcStream.Read(nameBytes, 0, nameLen);
// TODO: Use MacRoman
name = Encoding.ASCII.GetString(nameBytes);
}
rsrcStream.Seek(resourceDataOffset + item.dataOff, SeekOrigin.Begin);
_rsrcStream.Seek(resourceDataOffset + item.DataOff, SeekOrigin.Begin);
tmp = new byte[4];
rsrcStream.Read(tmp, 0, 4);
data.offset = rsrcStream.Position;
data.length = BitConverter.ToUInt32(tmp.Reverse().ToArray(), 0);
_rsrcStream.Read(tmp, 0, 4);
data.Offset = _rsrcStream.Position;
data.Length = BitConverter.ToUInt32(tmp.Reverse().ToArray(), 0);
resourceNames.Add(item.id, name);
this.resources.Add(item.id, data);
_resourceNames.Add(item.Id, name);
_resources.Add(item.Id, data);
}
resourceCache = new Dictionary<short, byte[]>();
_resourceCache = new Dictionary<short, byte[]>();
}
/// <summary>
/// Gets the name of the specified resource id, or null if there is no name.
/// </summary>
/// <summary>Gets the name of the specified resource id, or null if there is no name.</summary>
/// <returns>The name.</returns>
/// <param name="id">Identifier.</param>
public string GetName(short id)
{
string name;
return resourceNames.TryGetValue(id, out name) ? name : null;
}
public string GetName(short id) => _resourceNames.TryGetValue(id, out string name) ? name : null;
/// <summary>
/// Gets the resource contents.
/// </summary>
/// <summary>Gets the resource contents.</summary>
/// <returns>The resource.</returns>
/// <param name="id">Identifier.</param>
public byte[] GetResource(short id)
{
byte[] resource;
if(_resourceCache.TryGetValue(id, out byte[] resource))
return resource;
if(resourceCache.TryGetValue(id, out resource)) return resource;
if(!_resources.TryGetValue(id, out ResourceData data))
return null;
ResourceData data;
resource = new byte[data.Length];
_rsrcStream.Seek(data.Offset, SeekOrigin.Begin);
_rsrcStream.Read(resource, 0, resource.Length);
if(!resources.TryGetValue(id, out data)) return null;
resource = new byte[data.length];
rsrcStream.Seek(data.offset, SeekOrigin.Begin);
rsrcStream.Read(resource, 0, resource.Length);
resourceCache.Add(id, resource);
_resourceCache.Add(id, resource);
return resource;
}
/// <summary>
/// Gets the length of the resource specified by ID.
/// </summary>
/// <summary>Gets the length of the resource specified by ID.</summary>
/// <returns>The length.</returns>
/// <param name="id">Resource identifier.</param>
public long GetLength(short id)
{
ResourceData data;
return !resources.TryGetValue(id, out data) ? 0 : data.length;
}
public long GetLength(short id) => !_resources.TryGetValue(id, out ResourceData data) ? 0 : data.Length;
/// <summary>
/// Gets the IDs of all the resources contained by this instance.
/// </summary>
/// <summary>Gets the IDs of all the resources contained by this instance.</summary>
/// <returns>The identifiers.</returns>
public short[] GetIds() => ids.ToArray();
public short[] GetIds() => _ids.ToArray();
/// <summary>
/// Checks if the resource specified by ID is contained by this instance.
/// </summary>
/// <summary>Checks if the resource specified by ID is contained by this instance.</summary>
/// <returns><c>true</c>, if the resource is contained in this instance, <c>false</c> otherwise.</returns>
/// <param name="id">Resource identifier.</param>
public bool ContainsId(short id) => ids.Contains(id);
public bool ContainsId(short id) => _ids.Contains(id);
struct ResourceData
{
public long offset;
public long length;
public long Offset;
public long Length;
}
}

View File

@@ -30,161 +30,146 @@ using System.Linq;
namespace Claunia.RsrcFork;
/// <summary>
/// This class represents a resource fork.
/// </summary>
/// <summary>This class represents a resource fork.</summary>
public class ResourceFork
{
ResourceHeader header;
ResourceMap map;
List<uint> osTypes;
Dictionary<uint, Resource> resourceCache;
Dictionary<uint, ResourceTypeListItem> resourceTypeList;
readonly Stream rsrcStream;
readonly Stream _rsrcStream;
ResourceHeader _header;
ResourceMap _map;
List<uint> _osTypes;
Dictionary<uint, Resource> _resourceCache;
Dictionary<uint, ResourceTypeListItem> _resourceTypeList;
/// <summary>
/// Initializates a resource fork using a byte array as backend.
/// </summary>
/// <summary>Initializates a resource fork using a byte array as backend.</summary>
/// <param name="buffer">Buffer.</param>
public ResourceFork(byte[] buffer)
{
rsrcStream = new MemoryStream(buffer, false);
_rsrcStream = new MemoryStream(buffer, false);
Init();
}
/// <summary>
/// Initializates a resource fork using a stream as backed.
/// </summary>
/// <summary>Initializates a resource fork using a stream as backed.</summary>
/// <param name="stream">Stream.</param>
public ResourceFork(Stream stream)
{
rsrcStream = stream;
_rsrcStream = stream;
Init();
}
/// <summary>
/// Cleans up this instances and closes the underlying stream.
/// </summary>
~ResourceFork()
{
if(rsrcStream != null) rsrcStream.Dispose();
}
/// <summary>Cleans up this instances and closes the underlying stream.</summary>
~ResourceFork() => _rsrcStream?.Dispose();
/// <summary>
/// Initializes this instance.
/// </summary>
/// <summary>Initializes this instance.</summary>
void Init()
{
header = new ResourceHeader();
_header = new ResourceHeader();
byte[] tmp = new byte[4];
rsrcStream.Seek(0, SeekOrigin.Begin);
rsrcStream.Read(tmp, 0, 4);
header.resourceDataOff = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0);
rsrcStream.Read(tmp, 0, 4);
header.resourceMapOff = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0);
rsrcStream.Read(tmp, 0, 4);
header.resourceDataLen = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0);
rsrcStream.Read(tmp, 0, 4);
header.resourceMapLen = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0);
_rsrcStream.Seek(0, SeekOrigin.Begin);
_rsrcStream.Read(tmp, 0, 4);
_header.ResourceDataOff = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0);
_rsrcStream.Read(tmp, 0, 4);
_header.ResourceMapOff = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0);
_rsrcStream.Read(tmp, 0, 4);
_header.ResourceDataLen = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0);
_rsrcStream.Read(tmp, 0, 4);
_header.ResourceMapLen = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0);
if(header.resourceDataOff <= 0 || header.resourceMapOff <= 0 || header.resourceDataLen <= 0 ||
header.resourceMapLen <= 0) throw new InvalidCastException("Not a resource fork");
if(header.resourceDataOff + header.resourceDataLen > rsrcStream.Length ||
header.resourceMapOff + header.resourceMapLen > rsrcStream.Length)
if(_header.ResourceDataOff <= 0 ||
_header.ResourceMapOff <= 0 ||
_header.ResourceDataLen <= 0 ||
_header.ResourceMapLen <= 0)
throw new InvalidCastException("Not a resource fork");
map = new ResourceMap();
map.header = new ResourceHeader();
rsrcStream.Seek(header.resourceMapOff, SeekOrigin.Begin);
rsrcStream.Read(tmp, 0, 4);
map.header.resourceDataOff = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0);
rsrcStream.Read(tmp, 0, 4);
map.header.resourceMapOff = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0);
rsrcStream.Read(tmp, 0, 4);
map.header.resourceDataLen = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0);
rsrcStream.Read(tmp, 0, 4);
map.header.resourceMapLen = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0);
if(_header.ResourceDataOff + _header.ResourceDataLen > _rsrcStream.Length ||
_header.ResourceMapOff + _header.ResourceMapLen > _rsrcStream.Length)
throw new InvalidCastException("Not a resource fork");
if(map.header.resourceDataOff != header.resourceDataOff ||
map.header.resourceDataLen != header.resourceDataLen ||
map.header.resourceMapOff != header.resourceMapOff ||
map.header.resourceMapLen != header.resourceMapLen)
_map = new ResourceMap
{
Header = new ResourceHeader()
};
_rsrcStream.Seek(_header.ResourceMapOff, SeekOrigin.Begin);
_rsrcStream.Read(tmp, 0, 4);
_map.Header.ResourceDataOff = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0);
_rsrcStream.Read(tmp, 0, 4);
_map.Header.ResourceMapOff = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0);
_rsrcStream.Read(tmp, 0, 4);
_map.Header.ResourceDataLen = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0);
_rsrcStream.Read(tmp, 0, 4);
_map.Header.ResourceMapLen = BitConverter.ToInt32(tmp.Reverse().ToArray(), 0);
if(_map.Header.ResourceDataOff != _header.ResourceDataOff ||
_map.Header.ResourceDataLen != _header.ResourceDataLen ||
_map.Header.ResourceMapOff != _header.ResourceMapOff ||
_map.Header.ResourceMapLen != _header.ResourceMapLen)
throw new InvalidCastException("Header copy is not same as header.");
rsrcStream.Read(tmp, 0, 4);
map.handleToNextMap = BitConverter.ToUInt32(tmp.Reverse().ToArray(), 0);
tmp = new byte[2];
rsrcStream.Read(tmp, 0, 2);
map.fileRefNo = BitConverter.ToUInt16(tmp.Reverse().ToArray(), 0);
rsrcStream.Read(tmp, 0, 2);
map.attributes = BitConverter.ToUInt16(tmp.Reverse().ToArray(), 0);
rsrcStream.Read(tmp, 0, 2);
map.typeListOff = BitConverter.ToInt16(tmp.Reverse().ToArray(), 0);
rsrcStream.Read(tmp, 0, 2);
map.nameListOff = BitConverter.ToInt16(tmp.Reverse().ToArray(), 0);
_rsrcStream.Read(tmp, 0, 4);
_map.HandleToNextMap = BitConverter.ToUInt32(tmp.Reverse().ToArray(), 0);
tmp = new byte[2];
_rsrcStream.Read(tmp, 0, 2);
_map.FileRefNo = BitConverter.ToUInt16(tmp.Reverse().ToArray(), 0);
_rsrcStream.Read(tmp, 0, 2);
_map.Attributes = BitConverter.ToUInt16(tmp.Reverse().ToArray(), 0);
_rsrcStream.Read(tmp, 0, 2);
_map.TypeListOff = BitConverter.ToInt16(tmp.Reverse().ToArray(), 0);
_rsrcStream.Read(tmp, 0, 2);
_map.NameListOff = BitConverter.ToInt16(tmp.Reverse().ToArray(), 0);
// Number of types is part of the resource type list not of the map
rsrcStream.Seek(header.resourceMapOff + map.typeListOff, SeekOrigin.Begin);
rsrcStream.Read(tmp, 0, 2);
map.numberOfTypes = BitConverter.ToUInt16(tmp.Reverse().ToArray(), 0);
_rsrcStream.Seek(_header.ResourceMapOff + _map.TypeListOff, SeekOrigin.Begin);
_rsrcStream.Read(tmp, 0, 2);
_map.NumberOfTypes = BitConverter.ToUInt16(tmp.Reverse().ToArray(), 0);
resourceTypeList = new Dictionary<uint, ResourceTypeListItem>();
osTypes = new List<uint>();
_resourceTypeList = new Dictionary<uint, ResourceTypeListItem>();
_osTypes = new List<uint>();
for(int i = 0; i <= map.numberOfTypes; i++)
for(int i = 0; i <= _map.NumberOfTypes; i++)
{
ResourceTypeListItem typeList = new ResourceTypeListItem();
ResourceTypeListItem typeList = new();
tmp = new byte[4];
rsrcStream.Read(tmp, 0, 4);
typeList.type = BitConverter.ToUInt32(tmp.Reverse().ToArray(), 0);
_rsrcStream.Read(tmp, 0, 4);
typeList.Type = BitConverter.ToUInt32(tmp.Reverse().ToArray(), 0);
tmp = new byte[2];
rsrcStream.Read(tmp, 0, 2);
typeList.resources = BitConverter.ToUInt16(tmp.Reverse().ToArray(), 0);
rsrcStream.Read(tmp, 0, 2);
typeList.referenceOff = BitConverter.ToInt16(tmp.Reverse().ToArray(), 0);
_rsrcStream.Read(tmp, 0, 2);
typeList.Resources = BitConverter.ToUInt16(tmp.Reverse().ToArray(), 0);
_rsrcStream.Read(tmp, 0, 2);
typeList.ReferenceOff = BitConverter.ToInt16(tmp.Reverse().ToArray(), 0);
resourceTypeList.Add(typeList.type, typeList);
osTypes.Add(typeList.type);
_resourceTypeList.Add(typeList.Type, typeList);
_osTypes.Add(typeList.Type);
}
resourceCache = new Dictionary<uint, Resource>();
_resourceCache = new Dictionary<uint, Resource>();
}
/// <summary>
/// Gets the resources with indicated type
/// </summary>
/// <summary>Gets the resources with indicated type</summary>
/// <returns>The resource.</returns>
/// <param name="OSType">OSType.</param>
public Resource GetResource(uint OSType)
{
Resource rsrc;
if(_resourceCache.TryGetValue(OSType, out Resource rsrc))
return rsrc;
if(resourceCache.TryGetValue(OSType, out rsrc)) return rsrc;
if(!_resourceTypeList.TryGetValue(OSType, out ResourceTypeListItem typeList))
return null;
ResourceTypeListItem typeList;
if(!resourceTypeList.TryGetValue(OSType, out typeList)) return null;
rsrc = new Resource(_rsrcStream, (ushort)(typeList.Resources + 1),
_header.ResourceMapOff + _map.TypeListOff + typeList.ReferenceOff - 2,
_header.ResourceMapOff + _map.NameListOff, _header.ResourceDataOff, OSType);
rsrc = new Resource(rsrcStream, (ushort)(typeList.resources + 1),
header.resourceMapOff + map.typeListOff + typeList.referenceOff - 2,
header.resourceMapOff + map.nameListOff,
header.resourceDataOff, OSType);
resourceCache.Add(OSType, rsrc);
_resourceCache.Add(OSType, rsrc);
return rsrc;
}
/// <summary>
/// Gets all OSTypes stored in this resource fork
/// </summary>
/// <summary>Gets all OSTypes stored in this resource fork</summary>
/// <returns>The types.</returns>
public uint[] GetTypes() => osTypes.ToArray();
public uint[] GetTypes() => _osTypes.ToArray();
/// <summary>
/// Returns true if the specified OSType is present in this resource fork.
/// </summary>
/// <summary>Returns true if the specified OSType is present in this resource fork.</summary>
/// <param name="OSType">OSType.</param>
public bool ContainsKey(uint OSType) => resourceTypeList.ContainsKey(OSType);
public bool ContainsKey(uint OSType) => _resourceTypeList.ContainsKey(OSType);
}

View File

@@ -30,43 +30,27 @@ using Claunia.RsrcFork;
namespace Resources;
/// <summary>
/// This class handles the "VERS" resource fork
/// </summary>
/// <summary>This class handles the "VERS" resource fork</summary>
public class Version
{
/// <summary>
/// Known development stages
/// </summary>
/// <summary>Known development stages</summary>
public enum DevelopmentStage : byte
{
/// <summary>
/// Pre-alpha.
/// </summary>
/// <summary>Pre-alpha.</summary>
PreAlpha = 0x20,
/// <summary>
/// Alpha.
/// </summary>
/// <summary>Alpha.</summary>
Alpha = 0x40,
/// <summary>
/// Beta.
/// </summary>
/// <summary>Beta.</summary>
Beta = 0x60,
/// <summary>
/// Final release.
/// </summary>
/// <summary>Final release.</summary>
Final = 0x80
}
/// <summary>
/// Initializes a new instance of the <see cref="T:Resources.Version" /> class.
/// </summary>
/// <summary>Initializes a new instance of the <see cref="T:Resources.Version" /> class.</summary>
/// <param name="resource">Byte array containing the "VERS" resource.</param>
public Version(byte[] resource)
{
byte[] tmpShort, tmpStr, tmpMsg;
tmpShort = new byte[2];
byte[] tmpShort = new byte[2];
MajorVersion = BCDToNumber(resource[0]);
MinorVersion = BCDToNumber(resource[1]);
@@ -74,81 +58,62 @@ public class Version
PreReleaseVersion = BCDToNumber(resource[3]);
Array.Copy(resource, 4, tmpShort, 0, 2);
RegionCode = BitConverter.ToUInt16(tmpShort.Reverse().ToArray(), 0);
tmpStr = new byte[resource[6] + 1];
byte[] tmpStr = new byte[resource[6] + 1];
Array.Copy(resource, 6, tmpStr, 0, tmpStr.Length);
VersionString = PascalString.GetString(tmpStr);
tmpMsg = new byte[resource[6 + tmpStr.Length] + 1];
byte[] tmpMsg = new byte[resource[6 + tmpStr.Length] + 1];
Array.Copy(resource, 6 + tmpStr.Length, tmpMsg, 0, tmpMsg.Length);
VersionMessage = PascalString.GetString(tmpMsg);
}
/// <summary>
/// Gets the OSTYPE of this resource.
/// </summary>
/// <summary>Gets the OSTYPE of this resource.</summary>
/// <value>The OSTYPE.</value>
public static uint OSType { get; } = 0x76657273;
/// <summary>
/// Gets a byte array with the "VERS" resource contained by this instance.
/// </summary>
/// <summary>Gets a byte array with the "VERS" resource contained by this instance.</summary>
/// <returns>The "VERS" resource.</returns>
public byte[] GetBytes()
{
byte[] tmpShort, tmpStr, tmpMsg;
tmpShort = BitConverter.GetBytes(RegionCode).Reverse().ToArray();
tmpStr = PascalString.GetBytes(VersionString);
tmpMsg = PascalString.GetBytes(VersionMessage);
byte[] vers = new byte[6 + tmpStr.Length + tmpMsg.Length];
byte[] tmpShort = BitConverter.GetBytes(RegionCode).Reverse().ToArray();
byte[] tmpStr = PascalString.GetBytes(VersionString);
byte[] tmpMsg = PascalString.GetBytes(VersionMessage);
byte[] vers = new byte[6 + tmpStr.Length + tmpMsg.Length];
vers[0] = NumberToBCD(MajorVersion);
vers[1] = NumberToBCD(MinorVersion);
vers[2] = (byte)DevStage;
vers[3] = NumberToBCD(PreReleaseVersion);
Array.Copy(tmpShort, 0, vers, 4, 2);
Array.Copy(tmpStr, 0, vers, 6, tmpStr.Length);
Array.Copy(tmpMsg, 0, vers, 6 + tmpStr.Length, tmpMsg.Length);
Array.Copy(tmpShort, 0, vers, 4, 2);
Array.Copy(tmpStr, 0, vers, 6, tmpStr.Length);
Array.Copy(tmpMsg, 0, vers, 6 + tmpStr.Length, tmpMsg.Length);
return vers;
}
byte BCDToNumber(byte bcd) => Convert.ToByte(string.Format("{0:X2}", bcd), 10);
byte BCDToNumber(byte bcd) => Convert.ToByte($"{bcd:X2}", 10);
byte NumberToBCD(byte number)
{
if(number >= 100) number = 99;
if(number >= 100)
number = 99;
return Convert.ToByte(string.Format("{0:D2}", number), 16);
return Convert.ToByte($"{number:D2}", 16);
}
#region On-disk structure
/// <summary>
/// Major version.
/// </summary>
/// <summary>Major version.</summary>
public byte MajorVersion;
/// <summary>
/// Minor version.
/// </summary>
/// <summary>Minor version.</summary>
public byte MinorVersion;
/// <summary>
/// Development stage.
/// </summary>
/// <summary>Development stage.</summary>
public DevelopmentStage DevStage;
/// <summary>
/// Pre-release version.
/// </summary>
/// <summary>Pre-release version.</summary>
public byte PreReleaseVersion;
/// <summary>
/// Region code.
/// </summary>
/// <summary>Region code.</summary>
public ushort RegionCode;
/// <summary>
/// Version string.
/// </summary>
/// <summary>Version string.</summary>
public string VersionString;
/// <summary>
/// Version message.
/// </summary>
/// <summary>Version message.</summary>
public string VersionMessage;
#endregion
}

View File

@@ -26,94 +26,56 @@
namespace Claunia.RsrcFork;
struct ResourceHeader
internal struct ResourceHeader
{
/// <summary>
/// Offset from start of resource fork to resource data
/// </summary>
public int resourceDataOff;
/// <summary>
/// Offset from start of resource fork to resource map
/// </summary>
public int resourceMapOff;
/// <summary>
/// Length of resource data
/// </summary>
public int resourceDataLen;
/// <summary>
/// Length of resource map
/// </summary>
public int resourceMapLen;
/// <summary>Offset from start of resource fork to resource data</summary>
public int ResourceDataOff;
/// <summary>Offset from start of resource fork to resource map</summary>
public int ResourceMapOff;
/// <summary>Length of resource data</summary>
public int ResourceDataLen;
/// <summary>Length of resource map</summary>
public int ResourceMapLen;
}
struct ResourceMap
internal struct ResourceMap
{
/// <summary>
/// Copy of the resource fork header
/// </summary>
public ResourceHeader header;
/// <summary>
/// Reserved for handle to next resource map
/// </summary>
public uint handleToNextMap;
/// <summary>
/// Reserved for file reference number
/// </summary>
public ushort fileRefNo;
/// <summary>
/// Resource fork attributes
/// </summary>
public ushort attributes;
/// <summary>
/// Offset from start of resource map to resource type list
/// </summary>
public short typeListOff;
/// <summary>
/// Offset from start of resource map to resource name list
/// </summary>
public short nameListOff;
/// <summary>
/// Number of types in the map minus 1
/// </summary>
public ushort numberOfTypes;
/// <summary>Copy of the resource fork header</summary>
public ResourceHeader Header;
/// <summary>Reserved for handle to next resource map</summary>
public uint HandleToNextMap;
/// <summary>Reserved for file reference number</summary>
public ushort FileRefNo;
/// <summary>Resource fork attributes</summary>
public ushort Attributes;
/// <summary>Offset from start of resource map to resource type list</summary>
public short TypeListOff;
/// <summary>Offset from start of resource map to resource name list</summary>
public short NameListOff;
/// <summary>Number of types in the map minus 1</summary>
public ushort NumberOfTypes;
}
struct ResourceTypeListItem
internal struct ResourceTypeListItem
{
/// <summary>
/// Resource type
/// </summary>
public uint type;
/// <summary>
/// Number of resources of this type minus 1
/// </summary>
public ushort resources;
/// <summary>
/// Offset from beginning of resource type list to reference list
/// </summary>
public short referenceOff;
/// <summary>Resource type</summary>
public uint Type;
/// <summary>Number of resources of this type minus 1</summary>
public ushort Resources;
/// <summary>Offset from beginning of resource type list to reference list</summary>
public short ReferenceOff;
}
struct ResourceTypeReferenceListItem
internal struct ResourceTypeReferenceListItem
{
/// <summary>
/// Resource ID
/// </summary>
public short id;
/// <summary>
/// Offset from beginning of resource name list to resource name. -1 if it does not have a name
/// </summary>
public short nameOff;
/// <summary>
/// Resource attributes
/// </summary>
public byte attributes;
/// <summary>
/// Offset from beginning of resource data to resource. First byte is <see cref="attributes" />.
/// </summary>
public int dataOff;
/// <summary>
/// Reserved for handle to resource
/// </summary>
public uint handle;
/// <summary>Resource ID</summary>
public short Id;
/// <summary>Offset from beginning of resource name list to resource name. -1 if it does not have a name</summary>
public short NameOff;
/// <summary>Resource attributes</summary>
public byte Attributes;
/// <summary>Offset from beginning of resource data to resource. First byte is <see cref="Attributes" />.</summary>
public int DataOff;
/// <summary>Reserved for handle to resource</summary>
public uint Handle;
}

View File

@@ -30,14 +30,10 @@ using System.Text;
namespace Claunia.RsrcFork;
/// <summary>
/// This class contains static methods for OSTYPE handling.
/// </summary>
/// <summary>This class contains static methods for OSTYPE handling.</summary>
public static class Types
{
/// <summary>
/// Gets a descriptive name of a resource from its OSTYPE.
/// </summary>
/// <summary>Gets a descriptive name of a resource from its OSTYPE.</summary>
/// <returns>The name corresponding to the specified OSTYPE.</returns>
/// <param name="OSType">The OSTYPE.</param>
public static string GetName(uint OSType)
@@ -688,14 +684,13 @@ public static class Types
}
}
/// <summary>
/// Gets a descriptive name of a resource from its OSTYPE.
/// </summary>
/// <summary>Gets a descriptive name of a resource from its OSTYPE.</summary>
/// <returns>The name corresponding to the specified OSTYPE.</returns>
/// <param name="OSType">The OSTYPE.</param>
public static string GetName(string OSType)
{
if(OSType.Length != 4) return null;
if(OSType.Length != 4)
return null;
byte[] typB = Encoding.ASCII.GetBytes(OSType);
uint type = BitConverter.ToUInt32(typB.Reverse().ToArray(), 0);