mirror of
https://github.com/claunia/Claunia.RsrcFork.git
synced 2025-12-16 19:24:46 +00:00
General refactor and restyling.
This commit is contained in:
@@ -31,7 +31,7 @@ using System.Text;
|
||||
|
||||
namespace Claunia.RsrcFork.CLI;
|
||||
|
||||
class MainClass
|
||||
internal class MainClass
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
@@ -39,84 +39,79 @@ 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")
|
||||
switch(args.Length)
|
||||
{
|
||||
case 2 when args[0] != "-l":
|
||||
Usage();
|
||||
return;
|
||||
}
|
||||
|
||||
if(!File.Exists(args[1]))
|
||||
{
|
||||
return;
|
||||
case 2 when !File.Exists(args[1]):
|
||||
Console.WriteLine("Specified file does not exist.");
|
||||
|
||||
return;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
var rsrcStream = new FileStream(args[1], FileMode.Open, FileAccess.Read);
|
||||
|
||||
FileStream rsrcStream = new FileStream(args[1], FileMode.Open, FileAccess.Read);
|
||||
|
||||
ResourceFork rsrc = new ResourceFork(rsrcStream);
|
||||
var 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);
|
||||
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));
|
||||
else
|
||||
Console.WriteLine("{0,6}{1,8}", id, rez.GetLength(id));
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(args.Length == 4)
|
||||
{
|
||||
if(args[0] != "-x")
|
||||
{
|
||||
case 4 when args[0] != "-x":
|
||||
Usage();
|
||||
return;
|
||||
}
|
||||
|
||||
if(args[1] != "-o")
|
||||
{
|
||||
return;
|
||||
case 4 when args[1] != "-o":
|
||||
Usage();
|
||||
return;
|
||||
}
|
||||
|
||||
if(Directory.Exists(args[2]))
|
||||
{
|
||||
return;
|
||||
case 4 when Directory.Exists(args[2]):
|
||||
Console.WriteLine("Output directory exists, not proceeding");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!File.Exists(args[3]))
|
||||
{
|
||||
return;
|
||||
case 4 when !File.Exists(args[3]):
|
||||
Console.WriteLine("Specified file does not exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
FileStream rsrcStream = new FileStream(args[3], FileMode.Open, FileAccess.Read);
|
||||
return;
|
||||
case 4:
|
||||
{
|
||||
var rsrcStream = new FileStream(args[3], FileMode.Open, FileAccess.Read);
|
||||
FileStream outStream;
|
||||
|
||||
ResourceFork rsrc = new ResourceFork(rsrcStream);
|
||||
var rsrc = new ResourceFork(rsrcStream);
|
||||
|
||||
foreach(uint type in rsrc.GetTypes())
|
||||
{
|
||||
@@ -126,17 +121,20 @@ class MainClass
|
||||
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), string.Format("{0}", id)),
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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]);
|
||||
@@ -76,7 +79,7 @@ public class Test
|
||||
string versStr = vers.GetName(1);
|
||||
Assert.IsNull(versStr);
|
||||
|
||||
Version versDec = new Version(vers1);
|
||||
var versDec = new Version(vers1);
|
||||
Assert.AreEqual(6, versDec.MajorVersion);
|
||||
Assert.AreEqual(40, versDec.MinorVersion);
|
||||
Assert.AreEqual(Version.DevelopmentStage.Final, versDec.DevStage);
|
||||
@@ -89,8 +92,8 @@ public class Test
|
||||
[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]);
|
||||
@@ -137,7 +140,7 @@ public class Test
|
||||
Assert.IsNull(bceSStr);
|
||||
|
||||
byte[] vers1 = vers.GetResource(1);
|
||||
Version versDec = new Version(vers1);
|
||||
var versDec = new Version(vers1);
|
||||
Assert.AreEqual(6, versDec.MajorVersion);
|
||||
Assert.AreEqual(40, versDec.MinorVersion);
|
||||
Assert.AreEqual(Version.DevelopmentStage.Final, versDec.DevStage);
|
||||
@@ -150,8 +153,8 @@ public class Test
|
||||
[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);
|
||||
@@ -187,7 +190,7 @@ public class Test
|
||||
Resource vers = rsrc.GetResource(0x76657273);
|
||||
Assert.IsNotNull(vers);
|
||||
byte[] vers1 = vers.GetResource(1);
|
||||
Version versDec = new Version(vers1);
|
||||
var versDec = new Version(vers1);
|
||||
Assert.AreEqual(1, versDec.MajorVersion);
|
||||
Assert.AreEqual(10, versDec.MinorVersion);
|
||||
Assert.AreEqual(Version.DevelopmentStage.Beta, versDec.DevStage);
|
||||
@@ -200,8 +203,8 @@ public class Test
|
||||
[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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -32,20 +32,16 @@ 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>
|
||||
@@ -55,126 +51,108 @@ public class Resource
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
_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, 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);
|
||||
}
|
||||
@@ -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,31 +58,25 @@ 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[] 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);
|
||||
@@ -112,43 +90,30 @@ public class Version
|
||||
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
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user