diff --git a/BurnOutSharp/FileType/MPQ.cs b/BurnOutSharp/FileType/MPQ.cs
index af4c68a3..3a708ea0 100644
--- a/BurnOutSharp/FileType/MPQ.cs
+++ b/BurnOutSharp/FileType/MPQ.cs
@@ -763,7 +763,7 @@ namespace BurnOutSharp.FileType
}
///
- /// lock table contains informations about file sizes and way of their storage within
+ /// Block table contains informations about file sizes and way of their storage within
/// the archive. It also contains the position of file content in the archive. Size
/// of block table entry is (like hash table entry). The block table is also encrypted.
///
@@ -855,6 +855,270 @@ namespace BurnOutSharp.FileType
MPQ_FILE_EXISTS = 0x80000000,
}
+ ///
+ /// This structure contains size of the patch, flags and also MD5 of the patch.
+ ///
+ internal class MoPaQPatchInfo
+ {
+ #region Properties
+
+ ///
+ /// Length of patch info header, in bytes
+ ///
+ public int Length { get; private set; }
+
+ ///
+ /// Flags. 0x80000000 = MD5 (?)
+ ///
+ public uint Flags { get; private set; }
+
+ ///
+ /// Uncompressed size of the patch file
+ ///
+ public int DataSize { get; private set; }
+
+ ///
+ /// MD5 of the entire patch file after decompression
+ ///
+ public byte[] MD5 { get; private set; } = new byte[0x10];
+
+ ///
+ /// The sector offset table (variable length)
+ ///
+ public int[] SectorOffsetTable { get; private set; }
+
+ #endregion
+ }
+
+ ///
+ /// Each incremental patch file in a patch MPQ starts with a header. It is supposed
+ /// to be a structure with variable length.
+ ///
+ 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
+
+ #region Properties
+
+ #region PATCH Header
+
+ ///
+ /// 'PTCH'
+ ///
+ public uint PatchSignature { get; private set; }
+
+ ///
+ /// Size of the entire patch (decompressed)
+ ///
+ public int SizeOfPatchData { get; private set; }
+
+ ///
+ /// Size of the file before patch
+ ///
+ public int SizeBeforePatch { get; private set; }
+
+ ///
+ /// Size of file after patch
+ ///
+ public int SizeAfterPatch { get; private set; }
+
+ #endregion
+
+ #region MD5 Block
+
+ ///
+ /// 'MD5_'
+ ///
+ public uint Md5Signature { get; private set; }
+
+ ///
+ /// Size of the MD5 block, including the signature and size itself
+ ///
+ public int Md5BlockSize { get; private set; }
+
+ ///
+ /// MD5 of the original (unpached) file
+ ///
+ public byte[] Md5BeforePatch { get; private set; } = new byte[0x10];
+
+ ///
+ /// MD5 of the patched file
+ ///
+ public byte[] Md5AfterPatch { get; private set; } = new byte[0x10];
+
+ #endregion
+
+ #region XFRM Block
+
+ ///
+ /// 'XFRM'
+ ///
+ public uint XfrmSignature { get; private set; }
+
+ ///
+ /// Size of the XFRM block, includes XFRM header and patch data
+ ///
+ public int XfrmBlockSize { get; private set; }
+
+ ///
+ /// Type of patch ('BSD0' or 'COPY')
+ ///
+ public MoPaQPatchType PatchType { get; private set; }
+
+ #endregion
+
+ #region Patch Data - BSD0
+
+ ///
+ /// 'BSDIFF40' signature
+ ///
+ public ulong BsdiffSignature { get; private set; }
+
+ ///
+ /// Size of CTRL block (in bytes)
+ ///
+ public long CtrlBlockSize { get; private set; }
+
+ ///
+ /// Size of DATA block (in bytes)
+ ///
+ public long DataBlockSize { get; private set; }
+
+ ///
+ /// Size of file after applying the patch (in bytes)
+ ///
+ public long NewFileSize { get; private set; }
+
+ // TODO: Fill rest of data from http://zezula.net/en/mpq/patchfiles.html
+ // CTRL block
+ // DATA block
+ // EXTRA block
+
+ #endregion
+
+ #region Patch Data - COPY
+
+ ///
+ /// File data are simply replaced by the data in the patch.
+ ///
+ public byte[] PatchDataCopy { get; private set; }
+
+ #endregion
+
+ #endregion
+ }
+
+ internal enum MoPaQPatchType : uint
+ {
+ ///
+ /// Blizzard-modified version of BSDIFF40 incremental patch
+ ///
+ BSD0 = 0x30445342,
+
+ ///
+ /// Unknown
+ ///
+ BSDP = 0x50445342,
+
+ ///
+ /// Plain replace
+ ///
+ COPY = 0x59504F43,
+
+ ///
+ /// Unknown
+ ///
+ COUP = 0x50554F43,
+
+ ///
+ /// Unknown
+ ///
+ CPOG = 0x474F5043,
+ }
+
#endregion
}
}