diff --git a/CHD/CompressedMapEntryV5.cs b/CHD/CompressedMapEntryV5.cs new file mode 100644 index 0000000..d5437b8 --- /dev/null +++ b/CHD/CompressedMapEntryV5.cs @@ -0,0 +1,28 @@ +namespace SabreTools.Models.CHD +{ + /// + public class CompressedMapEntryV5 + { + /// + /// Compression type + /// + public byte Compression { get; set; } + + /// + /// Compressed length + /// + /// Actually UInt24 + public uint CompLength { get; set; } + + /// + /// Offset + /// + /// Actually UInt48 + public ulong Offset { get; set; } + + /// + /// CRC-16 of the data + /// + public ushort CRC { get; set; } + } +} diff --git a/CHD/CompressedMapHeaderV5.cs b/CHD/CompressedMapHeaderV5.cs new file mode 100644 index 0000000..19f4447 --- /dev/null +++ b/CHD/CompressedMapHeaderV5.cs @@ -0,0 +1,42 @@ +namespace SabreTools.Models.CHD +{ + /// + public class CompressedMapHeaderV5 + { + /// + /// Length of compressed map + /// + public uint Length { get; set; } + + /// + /// Offset of first block + /// + /// Actually UInt48 + public ulong DataStart { get; set; } + + /// + /// CRC-16 of the map + /// + public ushort CRC { get; set; } + + /// + /// Bits used to encode complength + /// + public byte LengthBits { get; set; } + + /// + /// Bits used to encode self-refs + /// + public byte HunkBits { get; set; } + + /// + /// Bits used to encode parent unit refs + /// + public byte ParentUnitBits { get; set; } + + /// + /// Future use + /// + public byte Reserved { get; set; } + } +} diff --git a/CHD/Enums.cs b/CHD/Enums.cs new file mode 100644 index 0000000..74dffe3 --- /dev/null +++ b/CHD/Enums.cs @@ -0,0 +1,42 @@ +using System; + +namespace SabreTools.Models.CHD +{ + /// + public enum CompressionType : uint + { + #region V1 + + CHDCOMPRESSION_NONE = 0, + CHDCOMPRESSION_ZLIB = 1, + + #endregion + + #region V3 + + CHDCOMPRESSION_ZLIB_PLUS = 2, + + #endregion + + #region V4 + + CHDCOMPRESSION_AV = 3, + + #endregion + } + + /// + [Flags] + public enum Flags : uint + { + /// + /// Set if this drive has a parent + /// + DriveHasParent = 0x00000001, + + /// + /// Set if this drive allows writes + /// + DriveAllowsWrites = 0x00000002, + } +} \ No newline at end of file diff --git a/CHD/Header.cs b/CHD/Header.cs new file mode 100644 index 0000000..13b9e0d --- /dev/null +++ b/CHD/Header.cs @@ -0,0 +1,25 @@ +namespace SabreTools.Models.CHD +{ + /// + public abstract class Header + { + /// + /// 'MComprHD' + /// +#if NET48 + public string Tag { get; set; } +#else + public string? Tag { get; set; } +#endif + + /// + /// Length of header (including tag and length fields) + /// + public uint Length { get; set; } + + /// + /// Drive format version + /// + public uint Version { get; set; } + } +} \ No newline at end of file diff --git a/CHD/HeaderV1.cs b/CHD/HeaderV1.cs new file mode 100644 index 0000000..95a7f83 --- /dev/null +++ b/CHD/HeaderV1.cs @@ -0,0 +1,59 @@ +namespace SabreTools.Models.CHD +{ + /// + public class HeaderV1 : Header + { + /// + /// Flags + /// + public Flags Flags { get; set; } + + /// + /// Compression type + /// + public CompressionType Compression { get; set; } + + /// + /// 512-byte sectors per hunk + /// + public uint HunkSize { get; set; } + + /// + /// Total # of hunks represented + /// + public uint TotalHunks { get; set; } + + /// + /// Number of cylinders on hard disk + /// + public uint Cylinders { get; set; } + + /// + /// Number of heads on hard disk + /// + public uint Heads { get; set; } + + /// + /// Number of sectors on hard disk + /// + public uint Sectors { get; set; } + + /// + /// MD5 checksum of raw data + /// +#if NET48 + public byte[] MD5 { get; set; } = new byte[16]; +#else + public byte[]? MD5 { get; set; } = new byte[16]; +#endif + + /// + /// MD5 checksum of parent file + /// +#if NET48 + public byte[] ParentMD5 { get; set; } = new byte[16]; +#else + public byte[]? ParentMD5 { get; set; } = new byte[16]; +#endif + } +} diff --git a/CHD/HeaderV2.cs b/CHD/HeaderV2.cs new file mode 100644 index 0000000..a77e246 --- /dev/null +++ b/CHD/HeaderV2.cs @@ -0,0 +1,64 @@ +namespace SabreTools.Models.CHD +{ + /// + public class HeaderV2 : Header + { + /// + /// Flags + /// + public Flags Flags { get; set; } + + /// + /// Compression type + /// + public CompressionType Compression { get; set; } + + /// + /// Seclen-byte sectors per hunk + /// + public uint HunkSize { get; set; } + + /// + /// Total # of hunks represented + /// + public uint TotalHunks { get; set; } + + /// + /// Number of cylinders on hard disk + /// + public uint Cylinders { get; set; } + + /// + /// Number of heads on hard disk + /// + public uint Heads { get; set; } + + /// + /// Number of sectors on hard disk + /// + public uint Sectors { get; set; } + + /// + /// MD5 checksum of raw data + /// +#if NET48 + public byte[] MD5 { get; set; } = new byte[16]; +#else + public byte[]? MD5 { get; set; } = new byte[16]; +#endif + + /// + /// MD5 checksum of parent file + /// +#if NET48 + public byte[] ParentMD5 { get; set; } = new byte[16]; +#else + public byte[]? ParentMD5 { get; set; } = new byte[16]; +#endif + + /// + /// Number of bytes per sector + /// + public uint BytesPerSector { get; set; } + } +} diff --git a/CHD/HeaderV3.cs b/CHD/HeaderV3.cs new file mode 100644 index 0000000..7292894 --- /dev/null +++ b/CHD/HeaderV3.cs @@ -0,0 +1,72 @@ +namespace SabreTools.Models.CHD +{ + /// + public class HeaderV3 : Header + { + /// + /// Flags + /// + public Flags Flags { get; set; } + + /// + /// Compression type + /// + public CompressionType Compression { get; set; } + + /// + /// Total # of hunks represented + /// + public uint TotalHunks { get; set; } + + /// + /// Logical size of the data (in bytes) + /// + public ulong LogicalBytes { get; set; } + + /// + /// Offset to the first blob of metadata + /// + public ulong MetaOffset { get; set; } + + /// + /// MD5 checksum of raw data + /// +#if NET48 + public byte[] MD5 { get; set; } = new byte[16]; +#else + public byte[]? MD5 { get; set; } = new byte[16]; +#endif + + /// + /// MD5 checksum of parent file + /// +#if NET48 + public byte[] ParentMD5 { get; set; } = new byte[16]; +#else + public byte[]? ParentMD5 { get; set; } = new byte[16]; +#endif + + /// + /// Number of bytes per hunk + /// + public uint HunkBytes { get; set; } + + /// + /// SHA1 checksum of raw data + /// +#if NET48 + public byte[] SHA1 { get; set; } = new byte[20]; +#else + public byte[]? SHA1 { get; set; } = new byte[20]; +#endif + + /// + /// SHA1 checksum of parent file + /// +#if NET48 + public byte[] ParentSHA1 { get; set; } = new byte[20]; +#else + public byte[]? ParentSHA1 { get; set; } = new byte[20]; +#endif + } +} diff --git a/CHD/HeaderV4.cs b/CHD/HeaderV4.cs new file mode 100644 index 0000000..cf8abf9 --- /dev/null +++ b/CHD/HeaderV4.cs @@ -0,0 +1,63 @@ +namespace SabreTools.Models.CHD +{ + /// + public class HeaderV4 : Header + { + /// + /// Flags + /// + public Flags Flags { get; set; } + + /// + /// Compression type + /// + public CompressionType Compression { get; set; } + + /// + /// Total # of hunks represented + /// + public uint TotalHunks { get; set; } + + /// + /// Logical size of the data (in bytes) + /// + public ulong LogicalBytes { get; set; } + + /// + /// Offset to the first blob of metadata + /// + public ulong MetaOffset { get; set; } + + /// + /// Number of bytes per hunk + /// + public uint HunkBytes { get; set; } + + /// + /// Combined raw+meta SHA1 + /// +#if NET48 + public byte[] SHA1 { get; set; } = new byte[20]; +#else + public byte[]? SHA1 { get; set; } = new byte[20]; +#endif + + /// + /// Combined raw+meta SHA1 of parent + /// +#if NET48 + public byte[] ParentSHA1 { get; set; } = new byte[20]; +#else + public byte[]? ParentSHA1 { get; set; } = new byte[20]; +#endif + + /// + /// Raw data SHA1 + /// +#if NET48 + public byte[] RawSHA1 { get; set; } = new byte[20]; +#else + public byte[]? RawSHA1 { get; set; } = new byte[20]; +#endif + } +} diff --git a/CHD/HeaderV5.cs b/CHD/HeaderV5.cs new file mode 100644 index 0000000..970fa17 --- /dev/null +++ b/CHD/HeaderV5.cs @@ -0,0 +1,63 @@ +namespace SabreTools.Models.CHD +{ + /// + public class HeaderV5 : Header + { + /// + /// Which custom compressors are used? + /// + public uint[] Compressors { get; set; } = new uint[4]; + + /// + /// Logical size of the data (in bytes) + /// + public ulong LogicalBytes { get; set; } + + /// + /// Offset to the map + /// + public ulong MapOffset { get; set; } + + /// + /// Offset to the first blob of metadata + /// + public ulong MetaOffset { get; set; } + + /// + /// Number of bytes per hunk (512k maximum) + /// + public uint HunkBytes { get; set; } + + /// + /// Number of bytes per unit within each hunk + /// + public uint UnitBytes { get; set; } + + /// + /// Raw data SHA1 + /// +#if NET48 + public byte[] RawSHA1 { get; set; } +#else + public byte[]? RawSHA1 { get; set; } +#endif + + /// + /// Combined raw+meta SHA1 + /// +#if NET48 + public byte[] SHA1 { get; set; } +#else + public byte[]? SHA1 { get; set; } +#endif + + /// + /// Combined raw+meta SHA1 of parent + /// +#if NET48 + public byte[] ParentSHA1 { get; set; } +#else + public byte[]? ParentSHA1 { get; set; } +#endif + } +} diff --git a/CHD/MapV1.cs b/CHD/MapV1.cs new file mode 100644 index 0000000..bdb8451 --- /dev/null +++ b/CHD/MapV1.cs @@ -0,0 +1,16 @@ +namespace SabreTools.Models.CHD +{ + /// + public class MapV1 + { + /// + /// Starting offset within the file + /// + public ulong StartingOffset { get; set; } + + /// + /// Length of data; If == hunksize, data is uncompressed + /// + public ulong Length { get; set; } + } +} diff --git a/CHD/MapV3.cs b/CHD/MapV3.cs new file mode 100644 index 0000000..9953ac6 --- /dev/null +++ b/CHD/MapV3.cs @@ -0,0 +1,31 @@ +namespace SabreTools.Models.CHD +{ + /// + public class MapV3 + { + /// + /// Starting offset within the file + /// + public ulong StartingOffset { get; set; } + + /// + /// 32-bit CRC of the uncompressed data + /// + public uint CRC32 { get; set; } + + /// + /// Lower 16 bits of length + /// + public ushort LengthLo { get; set; } + + /// + /// Upper 8 bits of length + /// + public byte LengthHi { get; set; } + + /// + /// Flags, indicating compression info + /// + public byte Flags { get; set; } + } +} diff --git a/CHD/UncompressedMapV5.cs b/CHD/UncompressedMapV5.cs new file mode 100644 index 0000000..4fcb346 --- /dev/null +++ b/CHD/UncompressedMapV5.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Models.CHD +{ + /// + public class UncompressedMapV5 + { + /// + /// Starting offset / hunk size + /// + public uint StartingOffset { get; set; } + } +}