diff --git a/BurnOutSharp.Builder/MoPaQ.cs b/BurnOutSharp.Builder/MoPaQ.cs
new file mode 100644
index 00000000..32abcb43
--- /dev/null
+++ b/BurnOutSharp.Builder/MoPaQ.cs
@@ -0,0 +1,812 @@
+using System;
+using System.IO;
+using BurnOutSharp.Models.MoPaQ;
+
+namespace BurnOutSharp.Builder
+{
+ // TODO: Make Stream Data rely on Byte Data
+ public class MoPaQ
+ {
+ #region Constants
+
+ #region User Data
+
+ public const int UserDataSize = 0x10;
+
+ ///
+ /// Human-readable signature
+ ///
+ public static readonly string UserDataSignatureString = $"MPQ{(char)0x1B}";
+
+ ///
+ /// Signature as an unsigned Int32 value
+ ///
+ public const uint UserDataSignatureValue = 0x1B51504D;
+
+ ///
+ /// Signature as a byte array
+ ///
+ public static readonly byte[] UserDataSignatureBytes = new byte[] { 0x4D, 0x50, 0x51, 0x1B };
+
+ #endregion
+
+ #region Archive Header
+
+ #region Signatures
+
+ ///
+ /// Human-readable signature
+ ///
+ public static readonly string ArchiveHeaderSignatureString = $"MPQ{(char)0x1A}";
+
+ ///
+ /// Signature as an unsigned Int32 value
+ ///
+ public const uint ArchiveHeaderSignatureValue = 0x1A51504D;
+
+ ///
+ /// Signature as a byte array
+ ///
+ public static readonly byte[] ArchiveHeaderSignatureBytes = new byte[] { 0x4D, 0x50, 0x51, 0x1A };
+
+ #endregion
+
+ #region Header Sizes
+
+ public const int ArchiveHeaderHeaderVersion1Size = 0x20;
+
+ public const int ArchiveHeaderHeaderVersion2Size = 0x2C;
+
+ public const int ArchiveHeaderHeaderVersion3Size = 0x44;
+
+ public const int ArchiveHeaderHeaderVersion4Size = 0xD0;
+
+ #endregion
+
+ #endregion
+
+ #region HET Table
+
+ public const int HetTableSize = 0x44;
+
+ ///
+ /// Human-readable signature
+ ///
+ public static readonly string HetTableSignatureString = $"HET{(char)0x1A}";
+
+ ///
+ /// Signature as an unsigned Int32 value
+ ///
+ public const uint HetTableSignatureValue = 0x1A544548;
+
+ ///
+ /// Signature as a byte array
+ ///
+ public static readonly byte[] HetTableSignatureBytes = new byte[] { 0x48, 0x45, 0x54, 0x1A };
+
+ #endregion
+
+ #region BET Table
+
+ public const int BetTableSize = 0x88;
+
+ ///
+ /// Human-readable signature
+ ///
+ public static readonly string BetTableSignatureString = $"BET{(char)0x1A}";
+
+ ///
+ /// Signature as an unsigned Int32 value
+ ///
+ public const uint BetTableSignatureValue = 0x1A544542;
+
+ ///
+ /// Signature as a byte array
+ ///
+ public static readonly byte[] BetTableSignatureBytes = new byte[] { 0x42, 0x45, 0x54, 0x1A };
+
+ #endregion
+
+ #region Hash Entry
+
+ public const int HashEntrySize = 0x10;
+
+ #endregion
+
+ #region Block Entry
+
+ public const int BlockEntrySize = 0x10;
+
+ #endregion
+
+ #region Patch Header
+
+ #region Signatures
+
+ #region Patch Header
+
+ ///
+ /// Human-readable signature
+ ///
+ public static readonly string PatchSignatureString = $"PTCH";
+
+ ///
+ /// Signature as an unsigned Int32 value
+ ///
+ public const uint PatchSignatureValue = 0x48435450;
+
+ ///
+ /// Signature as a byte array
+ ///
+ public static readonly byte[] PatchSignatureBytes = new byte[] { 0x50, 0x54, 0x43, 0x48 };
+
+ #endregion
+
+ #region MD5 Block
+
+ ///
+ /// Human-readable signature
+ ///
+ public static readonly string Md5SignatureString = $"MD5_";
+
+ ///
+ /// Signature as an unsigned Int32 value
+ ///
+ public const uint Md5SignatureValue = 0x5F35444D;
+
+ ///
+ /// Signature as a byte array
+ ///
+ public static readonly byte[] Md5SignatureBytes = new byte[] { 0x4D, 0x44, 0x35, 0x5F };
+
+ #endregion
+
+ #region XFRM Block
+
+ ///
+ /// Human-readable signature
+ ///
+ public static readonly string XFRMSignatureString = $"XFRM";
+
+ ///
+ /// Signature as an unsigned Int32 value
+ ///
+ public const uint XFRMSignatureValue = 0x4D524658;
+
+ ///
+ /// Signature as a byte array
+ ///
+ public static readonly byte[] XFRMSignatureBytes = new byte[] { 0x58, 0x46, 0x52, 0x4D };
+
+ #endregion
+
+ #region BSDIFF Patch Type
+
+ ///
+ /// Human-readable signature
+ ///
+ public static readonly string BSDIFF40SignatureString = $"BSDIFF40";
+
+ ///
+ /// Signature as an unsigned Int64 value
+ ///
+ public const ulong BSDIFF40SignatureValue = 0x3034464649445342;
+
+ ///
+ /// Signature as a byte array
+ ///
+ public static readonly byte[] BSDIFF40SignatureBytes = new byte[] { 0x42, 0x53, 0x44, 0x49, 0x46, 0x46, 0x34, 0x30 };
+
+ #endregion
+
+ #endregion
+
+ #endregion
+
+ #endregion
+
+ #region Byte Data
+
+ ///
+ /// Parse a byte array into a MoPaQ archive
+ ///
+ /// Byte array to parse
+ /// Offset into the byte array
+ /// Filled archive on success, null on error
+ public static Archive ParseArchive(byte[] data, int offset)
+ {
+ // If the data is invalid
+ if (data == null)
+ return null;
+
+ // If the offset is out of bounds
+ if (offset < 0 || offset >= data.Length)
+ return null;
+
+ // Cache the current offset
+ int initialOffset = offset;
+
+ // Create a new archive to fill
+ var archive = new Archive();
+
+ #region User Data
+
+ // Check for User Data
+ uint possibleSignature = BitConverter.ToUInt32(data, offset);
+ if (possibleSignature == UserDataSignatureValue)
+ {
+ // Save the current position for offset correction
+ int basePtr = offset;
+
+ // Deserialize the user data, returning null if invalid
+ var userData = ParseUserData(data, ref offset);
+ if (userData == null)
+ return null;
+
+ // Set the user data
+ archive.UserData = userData;
+
+ // Set the starting position according to the header offset
+ offset = basePtr + (int)archive.UserData.HeaderOffset;
+ }
+
+ #endregion
+
+ #region Archive Header
+
+ // Check for the Header
+ possibleSignature = BitConverter.ToUInt32(data, offset);
+ if (possibleSignature == ArchiveHeaderSignatureValue)
+ {
+ // Try to parse the archive header
+ var archiveHeader = ParseArchiveHeader(data, ref offset);
+ if (archiveHeader == null)
+ return null;
+
+ // Set the archive header
+ archive.ArchiveHeader = archiveHeader;
+ }
+
+ #endregion
+
+ // TODO: Read in Hash Table
+ // TODO: Read in Block Table
+ // TODO: Read in Hi-Block Table
+ // TODO: Read in BET Table
+ // TODO: Read in HET Table
+
+ return archive;
+ }
+
+ ///
+ /// Parse a byte array into a archive header
+ ///
+ /// Byte array to parse
+ /// Offset into the byte array
+ /// Filled archive header on success, null on error
+ private static ArchiveHeader ParseArchiveHeader(byte[] data, ref int offset)
+ {
+ // TODO: Use marshalling here instead of building
+ ArchiveHeader archiveHeader = new ArchiveHeader();
+
+ // V1 - Common
+ archiveHeader.Signature = data.ReadUInt32(ref offset);
+ if (archiveHeader.Signature != ArchiveHeaderSignatureValue)
+ return null;
+
+ archiveHeader.HeaderSize = data.ReadUInt32(ref offset);
+ archiveHeader.ArchiveSize = data.ReadUInt32(ref offset);
+ archiveHeader.FormatVersion = data.ReadUInt16(ref offset);
+ archiveHeader.BlockSize = data.ReadUInt16(ref offset);
+ archiveHeader.HashTablePosition = data.ReadUInt32(ref offset);
+ archiveHeader.BlockTablePosition = data.ReadUInt32(ref offset);
+ archiveHeader.HashTableSize = data.ReadUInt32(ref offset);
+ archiveHeader.BlockTableSize = data.ReadUInt32(ref offset);
+
+ // V2
+ if (archiveHeader.FormatVersion >= 2 && archiveHeader.HeaderSize >= ArchiveHeaderHeaderVersion2Size)
+ {
+ archiveHeader.HiBlockTablePosition = data.ReadUInt64(ref offset);
+ archiveHeader.HashTablePositionHi = data.ReadUInt16(ref offset);
+ archiveHeader.BlockTablePositionHi = data.ReadUInt16(ref offset);
+ }
+
+ // V3
+ if (archiveHeader.FormatVersion >= 3 && archiveHeader.HeaderSize >= ArchiveHeaderHeaderVersion3Size)
+ {
+ archiveHeader.ArchiveSizeLong = data.ReadUInt64(ref offset);
+ archiveHeader.BetTablePosition = data.ReadUInt64(ref offset);
+ archiveHeader.HetTablePosition = data.ReadUInt64(ref offset);
+ }
+
+ // V4
+ if (archiveHeader.FormatVersion >= 4 && archiveHeader.HeaderSize >= ArchiveHeaderHeaderVersion4Size)
+ {
+ archiveHeader.HashTableSizeLong = data.ReadUInt64(ref offset);
+ archiveHeader.BlockTableSizeLong = data.ReadUInt64(ref offset);
+ archiveHeader.HiBlockTableSize = data.ReadUInt64(ref offset);
+ archiveHeader.HetTableSize = data.ReadUInt64(ref offset);
+ archiveHeader.BetTablesize = data.ReadUInt64(ref offset);
+ archiveHeader.RawChunkSize = data.ReadUInt32(ref offset);
+
+ archiveHeader.BlockTableMD5 = data.ReadBytes(ref offset, 0x10);
+ archiveHeader.HashTableMD5 = data.ReadBytes(ref offset, 0x10);
+ archiveHeader.HiBlockTableMD5 = data.ReadBytes(ref offset, 0x10);
+ archiveHeader.BetTableMD5 = data.ReadBytes(ref offset, 0x10);
+ archiveHeader.HetTableMD5 = data.ReadBytes(ref offset, 0x10);
+ archiveHeader.HetTableMD5 = data.ReadBytes(ref offset, 0x10);
+ }
+
+ return archiveHeader;
+ }
+
+ ///
+ /// Parse a byte array into a user data object
+ ///
+ /// Byte array to parse
+ /// Offset into the byte array
+ /// Filled user data on success, null on error
+ private static UserData ParseUserData(byte[] data, ref int offset)
+ {
+ // TODO: Use marshalling here instead of building
+ UserData userData = new UserData();
+
+ userData.Signature = data.ReadUInt32(ref offset);
+ if (userData.Signature != UserDataSignatureValue)
+ return null;
+
+ userData.UserDataSize = data.ReadUInt32(ref offset);
+ userData.HeaderOffset = data.ReadUInt32(ref offset);
+ userData.UserDataHeaderSize = data.ReadUInt32(ref offset);
+
+ return userData;
+ }
+
+ ///
+ /// Parse a byte array into a HET table
+ ///
+ /// Byte array to parse
+ /// Offset into the byte array
+ /// Filled HET table on success, null on error
+ private static HetTable ParseHetTable(byte[] data, ref int offset)
+ {
+ // TODO: Use marshalling here instead of building
+ HetTable hetTable = new HetTable();
+
+ // Common Headers
+ hetTable.Signature = data.ReadUInt32(ref offset);
+ if (hetTable.Signature != HetTableSignatureValue)
+ return null;
+
+ hetTable.Version = data.ReadUInt32(ref offset);
+ hetTable.DataSize = data.ReadUInt32(ref offset);
+
+ // HET-Specific
+ hetTable.TableSize = data.ReadUInt32(ref offset);
+ hetTable.MaxFileCount = data.ReadUInt32(ref offset);
+ hetTable.HashTableSize = data.ReadUInt32(ref offset);
+ hetTable.TotalIndexSize = data.ReadUInt32(ref offset);
+ hetTable.IndexSizeExtra = data.ReadUInt32(ref offset);
+ hetTable.IndexSize = data.ReadUInt32(ref offset);
+ hetTable.BlockTableSize = data.ReadUInt32(ref offset);
+ hetTable.HashTable = data.ReadBytes(ref offset, (int)hetTable.HashTableSize);
+
+ // TODO: Populate the file indexes array
+ hetTable.FileIndexes = new byte[(int)hetTable.HashTableSize][];
+
+ return hetTable;
+ }
+
+ ///
+ /// Parse a byte array into a BET table
+ ///
+ /// Byte array to parse
+ /// Offset into the byte array
+ /// Filled BET table on success, null on error
+ private static BetTable ParseBetTable(byte[] data, ref int offset)
+ {
+ // TODO: Use marshalling here instead of building
+ BetTable betTable = new BetTable();
+
+ // Common Headers
+ betTable.Signature = data.ReadUInt32(ref offset);
+ if (betTable.Signature != BetTableSignatureValue)
+ return null;
+
+ betTable.Version = data.ReadUInt32(ref offset);
+ betTable.DataSize = data.ReadUInt32(ref offset);
+
+ // BET-Specific
+ betTable.TableSize = data.ReadUInt32(ref offset);
+ betTable.FileCount = data.ReadUInt32(ref offset);
+ betTable.Unknown = data.ReadUInt32(ref offset);
+ betTable.TableEntrySize = data.ReadUInt32(ref offset);
+
+ betTable.FilePositionBitIndex = data.ReadUInt32(ref offset);
+ betTable.FileSizeBitIndex = data.ReadUInt32(ref offset);
+ betTable.CompressedSizeBitIndex = data.ReadUInt32(ref offset);
+ betTable.FlagIndexBitIndex = data.ReadUInt32(ref offset);
+ betTable.UnknownBitIndex = data.ReadUInt32(ref offset);
+
+ betTable.FilePositionBitCount = data.ReadUInt32(ref offset);
+ betTable.FileSizeBitCount = data.ReadUInt32(ref offset);
+ betTable.CompressedSizeBitCount = data.ReadUInt32(ref offset);
+ betTable.FlagIndexBitCount = data.ReadUInt32(ref offset);
+ betTable.UnknownBitCount = data.ReadUInt32(ref offset);
+
+ betTable.TotalBetHashSize = data.ReadUInt32(ref offset);
+ betTable.BetHashSizeExtra = data.ReadUInt32(ref offset);
+ betTable.BetHashSize = data.ReadUInt32(ref offset);
+ betTable.BetHashArraySize = data.ReadUInt32(ref offset);
+ betTable.FlagCount = data.ReadUInt32(ref offset);
+
+ betTable.FlagsArray = new uint[betTable.FlagCount];
+ Buffer.BlockCopy(data, offset, betTable.FlagsArray, 0, (int)betTable.FlagCount * 4);
+ offset += (int)betTable.FlagCount * 4;
+
+ // TODO: Populate the file table
+ // TODO: Populate the hash table
+
+ return betTable;
+ }
+
+ ///
+ /// Parse a byte array into a hash entry
+ ///
+ /// Byte array to parse
+ /// Offset into the byte array
+ /// Filled hash entry on success, null on error
+ private static HashEntry ParseHashEntry(byte[] data, ref int offset)
+ {
+ // TODO: Use marshalling here instead of building
+ HashEntry hashEntry = new HashEntry();
+
+ hashEntry.NameHashPartA = data.ReadUInt32(ref offset);
+ hashEntry.NameHashPartB = data.ReadUInt32(ref offset);
+ hashEntry.Locale = (Locale)data.ReadUInt16(ref offset);
+ hashEntry.Platform = data.ReadUInt16(ref offset);
+ hashEntry.BlockIndex = data.ReadUInt32(ref offset);
+
+ return hashEntry;
+ }
+
+ ///
+ /// Parse a byte array into a block entry
+ ///
+ /// Byte array to parse
+ /// Offset into the byte array
+ /// Filled block entry on success, null on error
+ private static BlockEntry ParseBlockEntry(byte[] data, ref int offset)
+ {
+ // TODO: Use marshalling here instead of building
+ BlockEntry blockEntry = new BlockEntry();
+
+ blockEntry.FilePosition = data.ReadUInt32(ref offset);
+ blockEntry.CompressedSize = data.ReadUInt32(ref offset);
+ blockEntry.UncompressedSize = data.ReadUInt32(ref offset);
+ blockEntry.Flags = (FileFlags)data.ReadUInt32(ref offset);
+
+ return blockEntry;
+ }
+
+ ///
+ /// Parse a byte array into a patch info
+ ///
+ /// Byte array to parse
+ /// Offset into the byte array
+ /// Filled patch info on success, null on error
+ private static PatchInfo ParsePatchInfo(byte[] data, ref int offset)
+ {
+ // TODO: Use marshalling here instead of building
+ PatchInfo patchInfo = new PatchInfo();
+
+ patchInfo.Length = data.ReadUInt32(ref offset);
+ patchInfo.Flags = data.ReadUInt32(ref offset);
+ patchInfo.DataSize = data.ReadUInt32(ref offset);
+ patchInfo.MD5 = data.ReadBytes(ref offset, 0x10);
+
+ // TODO: Fill the sector offset table
+
+ return patchInfo;
+ }
+
+ #endregion
+
+ #region Stream Data
+
+ ///
+ /// Parse a Stream into a MoPaQ archive
+ ///
+ /// Stream to parse
+ /// Filled archive on success, null on error
+ public static Archive ParseCabinet(Stream data)
+ {
+ // If the data is invalid
+ if (data == null)
+ return null;
+
+ // If the offset is out of bounds
+ if (data.Position < 0 || data.Position >= data.Length)
+ return null;
+
+ // Cache the current offset
+ int initialOffset = (int)data.Position;
+
+ // Create a new archive to fill
+ var archive = new Archive();
+
+ #region User Data
+
+ // Check for User Data
+ uint possibleSignature = data.ReadUInt32();
+ data.Seek(-4, SeekOrigin.Current);
+ if (possibleSignature == UserDataSignatureValue)
+ {
+ // Save the current position for offset correction
+ long basePtr = data.Position;
+
+ // Deserialize the user data, returning null if invalid
+ var userData = ParseUserData(data);
+ if (userData == null)
+ return null;
+
+ // Set the user data
+ archive.UserData = userData;
+
+ // Set the starting position according to the header offset
+ data.Seek(basePtr + (int)archive.UserData.HeaderOffset, SeekOrigin.Begin);
+ }
+
+ #endregion
+
+ #region Archive Header
+
+ // Check for the Header
+ possibleSignature = data.ReadUInt32();
+ data.Seek(-4, SeekOrigin.Current);
+ if (possibleSignature == ArchiveHeaderSignatureValue)
+ {
+ // Try to parse the archive header
+ var archiveHeader = ParseArchiveHeader(data);
+ if (archiveHeader == null)
+ return null;
+
+ // Set the archive header
+ archive.ArchiveHeader = archiveHeader;
+ }
+
+ #endregion
+
+ // TODO: Read in Hash Table
+ // TODO: Read in Block Table
+ // TODO: Read in Hi-Block Table
+ // TODO: Read in BET Table
+ // TODO: Read in HET Table
+
+ return archive;
+ }
+
+ ///
+ /// Parse a Stream into a archive header
+ ///
+ /// Stream to parse
+ /// Filled archive header on success, null on error
+ private static ArchiveHeader ParseArchiveHeader(Stream data)
+ {
+ ArchiveHeader archiveHeader = new ArchiveHeader();
+
+ // V1 - Common
+ archiveHeader.Signature = data.ReadUInt32();
+ if (archiveHeader.Signature != ArchiveHeaderSignatureValue)
+ return null;
+
+ archiveHeader.HeaderSize = data.ReadUInt32();
+ archiveHeader.ArchiveSize = data.ReadUInt32();
+ archiveHeader.FormatVersion = data.ReadUInt16();
+ archiveHeader.BlockSize = data.ReadUInt16();
+ archiveHeader.HashTablePosition = data.ReadUInt32();
+ archiveHeader.BlockTablePosition = data.ReadUInt32();
+ archiveHeader.HashTableSize = data.ReadUInt32();
+ archiveHeader.BlockTableSize = data.ReadUInt32();
+
+ // V2
+ if (archiveHeader.FormatVersion >= 2 && archiveHeader.HeaderSize >= ArchiveHeaderHeaderVersion2Size)
+ {
+ archiveHeader.HiBlockTablePosition = data.ReadUInt64();
+ archiveHeader.HashTablePositionHi = data.ReadUInt16();
+ archiveHeader.BlockTablePositionHi = data.ReadUInt16();
+ }
+
+ // V3
+ if (archiveHeader.FormatVersion >= 3 && archiveHeader.HeaderSize >= ArchiveHeaderHeaderVersion3Size)
+ {
+ archiveHeader.ArchiveSizeLong = data.ReadUInt64();
+ archiveHeader.BetTablePosition = data.ReadUInt64();
+ archiveHeader.HetTablePosition = data.ReadUInt64();
+ }
+
+ // V4
+ if (archiveHeader.FormatVersion >= 4 && archiveHeader.HeaderSize >= ArchiveHeaderHeaderVersion4Size)
+ {
+ archiveHeader.HashTableSizeLong = data.ReadUInt64();
+ archiveHeader.BlockTableSizeLong = data.ReadUInt64();
+ archiveHeader.HiBlockTableSize = data.ReadUInt64();
+ archiveHeader.HetTableSize = data.ReadUInt64();
+ archiveHeader.BetTablesize = data.ReadUInt64();
+ archiveHeader.RawChunkSize = data.ReadUInt32();
+
+ archiveHeader.BlockTableMD5 = data.ReadBytes(0x10);
+ archiveHeader.HashTableMD5 = data.ReadBytes(0x10);
+ archiveHeader.HiBlockTableMD5 = data.ReadBytes(0x10);
+ archiveHeader.BetTableMD5 = data.ReadBytes(0x10);
+ archiveHeader.HetTableMD5 = data.ReadBytes(0x10);
+ archiveHeader.HetTableMD5 = data.ReadBytes(0x10);
+ }
+
+ return archiveHeader;
+ }
+
+ ///
+ /// Parse a Stream into a user data object
+ ///
+ /// Stream to parse
+ /// Filled user data on success, null on error
+ private static UserData ParseUserData(Stream data)
+ {
+ UserData userData = new UserData();
+
+ userData.Signature = data.ReadUInt32();
+ if (userData.Signature != UserDataSignatureValue)
+ return null;
+
+ userData.UserDataSize = data.ReadUInt32();
+ userData.HeaderOffset = data.ReadUInt32();
+ userData.UserDataHeaderSize = data.ReadUInt32();
+
+ return userData;
+ }
+
+ ///
+ /// Parse a Stream into a HET table
+ ///
+ /// Stream to parse
+ /// Filled HET table on success, null on error
+ private static HetTable ParseHetTable(Stream data)
+ {
+ HetTable hetTable = new HetTable();
+
+ // Common Headers
+ hetTable.Signature = data.ReadUInt32();
+ if (hetTable.Signature != HetTableSignatureValue)
+ return null;
+
+ hetTable.Version = data.ReadUInt32();
+ hetTable.DataSize = data.ReadUInt32();
+
+ // HET-Specific
+ hetTable.TableSize = data.ReadUInt32();
+ hetTable.MaxFileCount = data.ReadUInt32();
+ hetTable.HashTableSize = data.ReadUInt32();
+ hetTable.TotalIndexSize = data.ReadUInt32();
+ hetTable.IndexSizeExtra = data.ReadUInt32();
+ hetTable.IndexSize = data.ReadUInt32();
+ hetTable.BlockTableSize = data.ReadUInt32();
+ hetTable.HashTable = data.ReadBytes((int)hetTable.HashTableSize);
+
+ // TODO: Populate the file indexes array
+ hetTable.FileIndexes = new byte[(int)hetTable.HashTableSize][];
+
+ return hetTable;
+ }
+
+ ///
+ /// Parse a Stream into a BET table
+ ///
+ /// Stream to parse
+ /// Filled BET table on success, null on error
+ private static BetTable ParseBetTable(Stream data)
+ {
+ BetTable betTable = new BetTable();
+
+ // Common Headers
+ betTable.Signature = data.ReadUInt32();
+ if (betTable.Signature != BetTableSignatureValue)
+ return null;
+
+ betTable.Version = data.ReadUInt32();
+ betTable.DataSize = data.ReadUInt32();
+
+ // BET-Specific
+ betTable.TableSize = data.ReadUInt32();
+ betTable.FileCount = data.ReadUInt32();
+ betTable.Unknown = data.ReadUInt32();
+ betTable.TableEntrySize = data.ReadUInt32();
+
+ betTable.FilePositionBitIndex = data.ReadUInt32();
+ betTable.FileSizeBitIndex = data.ReadUInt32();
+ betTable.CompressedSizeBitIndex = data.ReadUInt32();
+ betTable.FlagIndexBitIndex = data.ReadUInt32();
+ betTable.UnknownBitIndex = data.ReadUInt32();
+
+ betTable.FilePositionBitCount = data.ReadUInt32();
+ betTable.FileSizeBitCount = data.ReadUInt32();
+ betTable.CompressedSizeBitCount = data.ReadUInt32();
+ betTable.FlagIndexBitCount = data.ReadUInt32();
+ betTable.UnknownBitCount = data.ReadUInt32();
+
+ betTable.TotalBetHashSize = data.ReadUInt32();
+ betTable.BetHashSizeExtra = data.ReadUInt32();
+ betTable.BetHashSize = data.ReadUInt32();
+ betTable.BetHashArraySize = data.ReadUInt32();
+ betTable.FlagCount = data.ReadUInt32();
+
+ betTable.FlagsArray = new uint[betTable.FlagCount];
+ byte[] flagsArray = data.ReadBytes((int)betTable.FlagCount * 4);
+ Buffer.BlockCopy(flagsArray, 0, betTable.FlagsArray, 0, (int)betTable.FlagCount * 4);
+
+ // TODO: Populate the file table
+ // TODO: Populate the hash table
+
+ return betTable;
+ }
+
+ ///
+ /// Parse a Stream into a hash entry
+ ///
+ /// Stream to parse
+ /// Filled hash entry on success, null on error
+ private static HashEntry ParseHashEntry(Stream data)
+ {
+ // TODO: Use marshalling here instead of building
+ HashEntry hashEntry = new HashEntry();
+
+ hashEntry.NameHashPartA = data.ReadUInt32();
+ hashEntry.NameHashPartB = data.ReadUInt32();
+ hashEntry.Locale = (Locale)data.ReadUInt16();
+ hashEntry.Platform = data.ReadUInt16();
+ hashEntry.BlockIndex = data.ReadUInt32();
+
+ return hashEntry;
+ }
+
+ ///
+ /// Parse a Stream into a block entry
+ ///
+ /// Stream to parse
+ /// Filled block entry on success, null on error
+ private static BlockEntry ParseBlockEntry(Stream data)
+ {
+ BlockEntry blockEntry = new BlockEntry();
+
+ blockEntry.FilePosition = data.ReadUInt32();
+ blockEntry.CompressedSize = data.ReadUInt32();
+ blockEntry.UncompressedSize = data.ReadUInt32();
+ blockEntry.Flags = (FileFlags)data.ReadUInt32();
+
+ return blockEntry;
+ }
+
+ ///
+ /// Parse a Stream into a patch info
+ ///
+ /// Stream to parse
+ /// Offset into the byte array
+ /// Filled patch info on success, null on error
+ private static PatchInfo ParsePatchInfo(Stream data)
+ {
+ // TODO: Use marshalling here instead of building
+ PatchInfo patchInfo = new PatchInfo();
+
+ patchInfo.Length = data.ReadUInt32();
+ patchInfo.Flags = data.ReadUInt32();
+ patchInfo.DataSize = data.ReadUInt32();
+ patchInfo.MD5 = data.ReadBytes(0x10);
+
+ // TODO: Fill the sector offset table
+
+ return patchInfo;
+ }
+
+ #endregion
+ }
+}
diff --git a/BurnOutSharp.Models/MoPaQ/BlockEntry.cs b/BurnOutSharp.Models/MoPaQ/BlockEntry.cs
index ff769260..38eb06d1 100644
--- a/BurnOutSharp.Models/MoPaQ/BlockEntry.cs
+++ b/BurnOutSharp.Models/MoPaQ/BlockEntry.cs
@@ -29,6 +29,6 @@ namespace BurnOutSharp.Models.MoPaQ
///
/// Flags for the file.
///
- public MoPaQFileFlags Flags;
+ public FileFlags Flags;
}
}
diff --git a/BurnOutSharp.Models/MoPaQ/Enums.cs b/BurnOutSharp.Models/MoPaQ/Enums.cs
index 3ccf683e..b157119e 100644
--- a/BurnOutSharp.Models/MoPaQ/Enums.cs
+++ b/BurnOutSharp.Models/MoPaQ/Enums.cs
@@ -3,7 +3,7 @@
namespace BurnOutSharp.Models.MoPaQ
{
[Flags]
- public enum MoPaQFileFlags : uint
+ public enum FileFlags : uint
{
///
/// File is compressed using PKWARE Data compression library
@@ -76,7 +76,7 @@ namespace BurnOutSharp.Models.MoPaQ
EnglishUK = 0x809,
}
- public enum MoPaQPatchType : uint
+ public enum PatchType : uint
{
///
/// Blizzard-modified version of BSDIFF40 incremental patch
diff --git a/BurnOutSharp.Models/MoPaQ/PatchHeader.cs b/BurnOutSharp.Models/MoPaQ/PatchHeader.cs
index 09b5fff8..91d7b1a2 100644
--- a/BurnOutSharp.Models/MoPaQ/PatchHeader.cs
+++ b/BurnOutSharp.Models/MoPaQ/PatchHeader.cs
@@ -73,7 +73,7 @@ namespace BurnOutSharp.Models.MoPaQ
///
/// Type of patch ('BSD0' or 'COPY')
///
- public MoPaQPatchType PatchType { get; private set; }
+ public PatchType PatchType { get; private set; }
#endregion
diff --git a/BurnOutSharp/FileType/MPQ.cs b/BurnOutSharp/FileType/MPQ.cs
index 43141f2d..61033068 100644
--- a/BurnOutSharp/FileType/MPQ.cs
+++ b/BurnOutSharp/FileType/MPQ.cs
@@ -95,541 +95,5 @@ namespace BurnOutSharp.FileType
return null;
}
-
- // http://zezula.net/en/mpq/mpqformat.html
- #region TEMPORARY AREA FOR MPQ FORMAT
-
- internal class MoPaQArchive
- {
- //#region Serialization
-
- /////
- ///// Deserialize at into a new MoPaQArchive object
- /////
- //public static MoPaQArchive Deserialize(byte[] data, ref int dataPtr)
- //{
- // if (data == null || dataPtr < 0)
- // return null;
-
- // MoPaQArchive archive = new MoPaQArchive();
-
- // // Check for User Data
- // uint possibleSignature = BitConverter.ToUInt32(data, dataPtr);
- // if (possibleSignature == MoPaQUserData.SignatureValue)
- // {
- // // Save the current position for offset correction
- // int basePtr = dataPtr;
-
- // // Deserialize the user data, returning null if invalid
- // archive.UserData = MoPaQUserData.Deserialize(data, ref dataPtr);
- // if (archive.UserData == null)
- // return null;
-
- // // Set the starting position according to the header offset
- // dataPtr = basePtr + (int)archive.UserData.HeaderOffset;
- // }
-
- // // Check for the Header
- // possibleSignature = BitConverter.ToUInt32(data, dataPtr);
- // if (possibleSignature == MoPaQArchiveHeader.SignatureValue)
- // {
- // // Deserialize the header, returning null if invalid
- // archive.ArchiveHeader = MoPaQArchiveHeader.Deserialize(data, ref dataPtr);
- // if (archive.ArchiveHeader == null)
- // return null;
- // }
-
- // // If we don't have a header, return null
- // if (archive.ArchiveHeader == null)
- // return null;
-
- // // TODO: Read in Hash Table
- // // TODO: Read in Block Table
- // // TODO: Read in Hi-Block Table
- // // TODO: Read in BET Table
- // // TODO: Read in HET Table
-
- // return archive;
- //}
-
- //#endregion
- }
-
- internal class MoPaQUserData
- {
- //#region Constants
-
- //public const int Size = 0x10;
-
- /////
- ///// Human-readable signature
- /////
- //public static readonly string SignatureString = $"MPQ{(char)0x1B}";
-
- /////
- ///// Signature as an unsigned Int32 value
- /////
- //public const uint SignatureValue = 0x1B51504D;
-
- /////
- ///// Signature as a byte array
- /////
- //public static readonly byte[] SignatureBytes = new byte[] { 0x4D, 0x50, 0x51, 0x1B };
-
- //#endregion
-
- //#region Serialization
-
- /////
- ///// Deserialize at into a new MoPaQUserData object
- /////
- //public static MoPaQUserData Deserialize(byte[] data, ref int dataPtr)
- //{
- // if (data == null || dataPtr < 0)
- // return null;
-
- // MoPaQUserData userData = new MoPaQUserData();
-
- // userData.Signature = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // if (userData.Signature != SignatureValue)
- // return null;
-
- // userData.UserDataSize = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // userData.HeaderOffset = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // userData.UserDataHeaderSize = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
-
- // return userData;
- //}
-
- //#endregion
- }
-
- internal class MoPaQArchiveHeader
- {
- //#region Constants
-
- //#region Signatures
-
- /////
- ///// Human-readable signature
- /////
- //public static readonly string SignatureString = $"MPQ{(char)0x1A}";
-
- /////
- ///// Signature as an unsigned Int32 value
- /////
- //public const uint SignatureValue = 0x1A51504D;
-
- /////
- ///// Signature as a byte array
- /////
- //public static readonly byte[] SignatureBytes = new byte[] { 0x4D, 0x50, 0x51, 0x1A };
-
- //#endregion
-
- //#region Header Sizes
-
- //public const int HeaderVersion1Size = 0x20;
-
- //public const int HeaderVersion2Size = 0x2C;
-
- //public const int HeaderVersion3Size = 0x44;
-
- //public const int HeaderVersion4Size = 0xD0;
-
- //#endregion
-
- //#endregion
-
- //#region Serialization
-
- /////
- ///// Deserialize at into a new MoPaQArchiveHeader object
- /////
- //public static MoPaQArchiveHeader Deserialize(byte[] data, ref int dataPtr)
- //{
- // if (data == null || dataPtr < 0)
- // return null;
-
- // MoPaQArchiveHeader archiveHeader = new MoPaQArchiveHeader();
-
- // // V1 - Common
- // archiveHeader.Signature = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // if (archiveHeader.Signature != SignatureValue)
- // return null;
-
- // archiveHeader.HeaderSize = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // archiveHeader.ArchiveSize = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // archiveHeader.FormatVersion = BitConverter.ToUInt16(data, dataPtr); dataPtr += 2;
- // archiveHeader.BlockSize = BitConverter.ToUInt16(data, dataPtr); dataPtr += 2;
- // archiveHeader.HashTablePosition = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // archiveHeader.BlockTablePosition = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // archiveHeader.HashTableSize = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // archiveHeader.BlockTableSize = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
-
- // // V2
- // if (archiveHeader.FormatVersion >= 2 && archiveHeader.HeaderSize >= HeaderVersion2Size)
- // {
- // archiveHeader.HiBlockTablePosition = BitConverter.ToUInt64(data, dataPtr); dataPtr += 8;
- // archiveHeader.HashTablePositionHi = BitConverter.ToUInt16(data, dataPtr); dataPtr += 2;
- // archiveHeader.BlockTablePositionHi = BitConverter.ToUInt16(data, dataPtr); dataPtr += 2;
- // }
-
- // // V3
- // if (archiveHeader.FormatVersion >= 3 && archiveHeader.HeaderSize >= HeaderVersion3Size)
- // {
- // archiveHeader.ArchiveSizeLong = BitConverter.ToUInt64(data, dataPtr); dataPtr += 8;
- // archiveHeader.BetTablePosition = BitConverter.ToUInt64(data, dataPtr); dataPtr += 8;
- // archiveHeader.HetTablePosition = BitConverter.ToUInt64(data, dataPtr); dataPtr += 8;
- // }
-
- // // V4
- // if (archiveHeader.FormatVersion >= 4 && archiveHeader.HeaderSize >= HeaderVersion4Size)
- // {
- // archiveHeader.HashTableSizeLong = BitConverter.ToUInt64(data, dataPtr); dataPtr += 8;
- // archiveHeader.BlockTableSizeLong = BitConverter.ToUInt64(data, dataPtr); dataPtr += 8;
- // archiveHeader.HiBlockTableSize = BitConverter.ToUInt64(data, dataPtr); dataPtr += 8;
- // archiveHeader.HetTableSize = BitConverter.ToUInt64(data, dataPtr); dataPtr += 8;
- // archiveHeader.BetTablesize = BitConverter.ToUInt64(data, dataPtr); dataPtr += 8;
- // archiveHeader.RawChunkSize = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
-
- // Array.Copy(data, dataPtr, archiveHeader.BlockTableMD5, 0, 0x10); dataPtr += 0x10;
- // Array.Copy(data, dataPtr, archiveHeader.HashTableMD5, 0, 0x10); dataPtr += 0x10;
- // Array.Copy(data, dataPtr, archiveHeader.HiBlockTableMD5, 0, 0x10); dataPtr += 0x10;
- // Array.Copy(data, dataPtr, archiveHeader.BetTableMD5, 0, 0x10); dataPtr += 0x10;
- // Array.Copy(data, dataPtr, archiveHeader.HetTableMD5, 0, 0x10); dataPtr += 0x10;
- // Array.Copy(data, dataPtr, archiveHeader.MpqHeaderMD5, 0, 0x10); dataPtr += 0x10;
- // }
-
- // return archiveHeader;
- //}
-
- //#endregion
- }
-
- internal class MoPaQHetTable
- {
- //#region Constants
-
- //public const int Size = 0x44;
-
- /////
- ///// Human-readable signature
- /////
- //public static readonly string SignatureString = $"HET{(char)0x1A}";
-
- /////
- ///// Signature as an unsigned Int32 value
- /////
- //public const uint SignatureValue = 0x1A544548;
-
- /////
- ///// Signature as a byte array
- /////
- //public static readonly byte[] SignatureBytes = new byte[] { 0x48, 0x45, 0x54, 0x1A };
-
- //#endregion
-
- //#region Serialization
-
- /////
- ///// Deserialize at into a new MoPaQHetTable object
- /////
- //public static MoPaQHetTable Deserialize(byte[] data, ref int dataPtr)
- //{
- // if (data == null || dataPtr < 0)
- // return null;
-
- // MoPaQHetTable hetTable = new MoPaQHetTable();
-
- // // Common Headers
- // hetTable.Signature = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // if (hetTable.Signature != SignatureValue)
- // return null;
-
- // hetTable.Version = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // hetTable.DataSize = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
-
- // // HET-Specific
- // hetTable.TableSize = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // hetTable.MaxFileCount = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // hetTable.HashTableSize = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // hetTable.TotalIndexSize = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // hetTable.IndexSizeExtra = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // hetTable.IndexSize = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // hetTable.BlockTableSize = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
-
- // hetTable.HashTable = new byte[hetTable.HashTableSize];
- // Array.Copy(data, dataPtr, hetTable.HashTable, 0, hetTable.HashTableSize);
- // dataPtr += (int)hetTable.HashTableSize;
-
- // // TODO: Populate the file indexes array
- // hetTable.FileIndexes = new byte[(int)hetTable.HashTableSize][];
-
- // return hetTable;
- //}
-
- //#endregion
- }
-
- internal class MoPaQBetTable
- {
- //#region Constants
-
- //public const int Size = 0x88;
-
- /////
- ///// Human-readable signature
- /////
- //public static readonly string SignatureString = $"BET{(char)0x1A}";
-
- /////
- ///// Signature as an unsigned Int32 value
- /////
- //public const uint SignatureValue = 0x1A544542;
-
- /////
- ///// Signature as a byte array
- /////
- //public static readonly byte[] SignatureBytes = new byte[] { 0x42, 0x45, 0x54, 0x1A };
-
- //#endregion
-
- //#region Serialization
-
- /////
- ///// Deserialize at into a new MoPaQBetTable object
- /////
- //public static MoPaQBetTable Deserialize(byte[] data, ref int dataPtr)
- //{
- // if (data == null || dataPtr < 0)
- // return null;
-
- // MoPaQBetTable betTable = new MoPaQBetTable();
-
- // // Common Headers
- // betTable.Signature = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // if (betTable.Signature != SignatureValue)
- // return null;
-
- // betTable.Version = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // betTable.DataSize = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
-
- // // BET-Specific
- // betTable.TableSize = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // betTable.FileCount = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // betTable.Unknown = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // betTable.TableEntrySize = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
-
- // betTable.FilePositionBitIndex = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // betTable.FileSizeBitIndex = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // betTable.CompressedSizeBitIndex = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // betTable.FlagIndexBitIndex = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // betTable.UnknownBitIndex = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
-
- // betTable.FilePositionBitCount = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // betTable.FileSizeBitCount = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // betTable.CompressedSizeBitCount = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // betTable.FlagIndexBitCount = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // betTable.UnknownBitCount = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
-
- // betTable.TotalBetHashSize = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // betTable.BetHashSizeExtra = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // betTable.BetHashSize = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // betTable.BetHashArraySize = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // betTable.FlagCount = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
-
- // betTable.FlagsArray = new uint[betTable.FlagCount];
- // Buffer.BlockCopy(data, dataPtr, betTable.FlagsArray, 0, (int)betTable.FlagCount * 4);
- // dataPtr += (int)betTable.FlagCount * 4;
-
- // // TODO: Populate the file table
- // // TODO: Populate the hash table
-
- // return betTable;
- //}
-
- //#endregion
- }
-
- internal class MoPaQHashEntry
- {
- //#region Constants
-
- //public const int Size = 0x10;
-
- //#endregion
-
- //#region Serialization
-
- /////
- ///// Deserialize at into a new MoPaQHashEntry object
- /////
- //public static MoPaQHashEntry Deserialize(byte[] data, ref int dataPtr)
- //{
- // if (data == null || dataPtr < 0)
- // return null;
-
- // MoPaQHashEntry hashEntry = new MoPaQHashEntry();
-
- // hashEntry.NameHashPartA = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // hashEntry.NameHashPartB = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // hashEntry.Locale = (MoPaQLocale)BitConverter.ToUInt16(data, dataPtr); dataPtr += 2;
- // hashEntry.Platform = BitConverter.ToUInt16(data, dataPtr); dataPtr += 2;
- // hashEntry.BlockIndex = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
-
- // return hashEntry;
- //}
-
- //#endregion
- }
-
- internal class MoPaQBlockEntry
- {
- //#region Constants
-
- //public const int Size = 0x10;
-
- //#endregion
-
- //#region Serialization
-
- /////
- ///// Deserialize at into a new MoPaQBlockEntry object
- /////
- //public static MoPaQBlockEntry Deserialize(byte[] data, ref int dataPtr)
- //{
- // if (data == null || dataPtr < 0)
- // return null;
-
- // MoPaQBlockEntry blockEntry = new MoPaQBlockEntry();
-
- // blockEntry.FilePosition = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // blockEntry.CompressedSize = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // blockEntry.UncompressedSize = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // blockEntry.Flags = (MoPaQFileFlags)BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
-
- // return blockEntry;
- //}
-
- //#endregion
- }
-
- internal class MoPaQPatchInfo
- {
- //#region Serialization
-
- /////
- ///// Deserialize at into a new MoPaQPatchInfo object
- /////
- //public static MoPaQPatchInfo Deserialize(byte[] data, ref int dataPtr)
- //{
- // if (data == null || dataPtr < 0)
- // return null;
-
- // MoPaQPatchInfo patchInfo = new MoPaQPatchInfo();
-
- // patchInfo.Length = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // patchInfo.Flags = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // patchInfo.DataSize = BitConverter.ToUInt32(data, dataPtr); dataPtr += 4;
- // Array.Copy(data, dataPtr, patchInfo.MD5, 0, 0x10); dataPtr += 0x10;
-
- // // TODO: Fill the sector offset table
-
- // return patchInfo;
- //}
-
- //#endregion
- }
-
- internal class MoPaQPatchHeader
- {
- //#region Constants
-
- //#region Signatures
-
- //#region Patch Header
-
- /////
- ///// Human-readable signature
- /////
- //public static readonly string PatchSignatureString = $"PTCH";
-
- /////
- ///// Signature as an unsigned Int32 value
- /////
- //public const uint PatchSignatureValue = 0x48435450;
-
- /////
- ///// Signature as a byte array
- /////
- //public static readonly byte[] PatchSignatureBytes = new byte[] { 0x50, 0x54, 0x43, 0x48 };
-
- //#endregion
-
- //#region MD5 Block
-
- /////
- ///// Human-readable signature
- /////
- //public static readonly string Md5SignatureString = $"MD5_";
-
- /////
- ///// Signature as an unsigned Int32 value
- /////
- //public const uint Md5SignatureValue = 0x5F35444D;
-
- /////
- ///// Signature as a byte array
- /////
- //public static readonly byte[] Md5SignatureBytes = new byte[] { 0x4D, 0x44, 0x35, 0x5F };
-
- //#endregion
-
- //#region XFRM Block
-
- /////
- ///// Human-readable signature
- /////
- //public static readonly string XFRMSignatureString = $"XFRM";
-
- /////
- ///// Signature as an unsigned Int32 value
- /////
- //public const uint XFRMSignatureValue = 0x4D524658;
-
- /////
- ///// Signature as a byte array
- /////
- //public static readonly byte[] XFRMSignatureBytes = new byte[] { 0x58, 0x46, 0x52, 0x4D };
-
- //#endregion
-
- //#region BSDIFF Patch Type
-
- /////
- ///// Human-readable signature
- /////
- //public static readonly string BSDIFF40SignatureString = $"BSDIFF40";
-
- /////
- ///// Signature as an unsigned Int64 value
- /////
- //public const ulong BSDIFF40SignatureValue = 0x3034464649445342;
-
- /////
- ///// Signature as a byte array
- /////
- //public static readonly byte[] BSDIFF40SignatureBytes = new byte[] { 0x42, 0x53, 0x44, 0x49, 0x46, 0x46, 0x34, 0x30 };
-
-
- //#endregion
-
- //#endregion
-
- //#endregion
- }
-
- #endregion
}
}