MPQ
MPQ File Header and MPQ File Shunt
Great majority of file format begins with a header and MPQ format is no exception. Size of MPQ header is at least 32 bytes (0x20). When processing MPQ, the application looks at every offsets 0, 0x200, 0x400, 0x600, and so on, until the header has been found or until the end of the file has been reached. This feature allows to store the MPQ archives into other file types, e.g. into EXE files. Install.exe on StarCraft or BroodWar installation CD are actually MPQ archives. At this offset, there may either be MPQ header or a MPQ shunt. This is determined by the 32-bit ID:
- 'MPQ\x1A' means there's MPQ header at that offset
- 'MPQ\x1B' means there's MPQ shunt structure at that offset
MPQ Shunt
Offset | Type | Name | Description | |
---|---|---|---|---|
0x00 | uint32 | Magic | The ID_MPQ_SHUNT ('MPQ\x1B') signature | |
0x04 | uint32 | UserDataSize | Maximum size of the user data | |
0x08 | uint32 | HeaderPosition | Position of the MPQ header, relative to the begin of the shunt |
MPQ Header
Offset | Type | Name | Description | |
---|---|---|---|---|
0x00 | uint32 | Magic | The ID_MPQ_SHUNT ('MPQ\x1A') signature | |
0x04 | uint32 | HeaderSize | ||
0x08 | uint32 | ArchiveSize | ||
0x0C | uint16 | FormatVersion | 0 = Original format, 1 = Extended format (The Burning Crusade and newer) | |
0x10 | uint16 | BlockSize | ||
0x12 | uint32 | HastTablePosition | Relative to the beginning of the archive | |
0x14 | uint32 | BlockTablePosition | Relative to the beginning of the archive | |
0x18 | uint32 | HashTableSize | ||
0x1C | uint32 | BlockTableSize |
Extended MPQ Header
Extended MPQ file header. Valid only if FormatVersion is 1 or higher
Offset | Type | Name | Description | |
---|---|---|---|---|
0x00 | uint64 | ExtBlockTablePos | Offset to the beginning of the extended block table, relative to the beginning of the archive. | |
0x08 | uint16 | HashTablePosHigh | High 16 bits of the hash table offset for large archives. | |
0x0A | uint16 | BlockTablePosHigh | High 16 bits of the block table offset for large archives. |
Hash Table
When searching large array of strings, it is necessary to do large number of string comparisons, which slows the application. To prevent this, MPQ archives contain so called hash table. Hash is a data type (integer), which represents larger data, e.g. string. Searched string is recalculated into hash value (32-bit integer), which is the compared. This means that there are no file names stored in the MPQ archives. And because the hashing algorithm is one way (it's impossible to get back the original string value), it is also no way to search the file names in the archive. Hash table in the MPQ contains also two control hash values as test for the file name, one control value and a offset info block table. Size of one entry of hash table is 16 bytes. The structure of hash table is the following:
Offset | Type | Name | Description | |
---|---|---|---|---|
0x00 | uint32 | Name1 | ||
0x04 | uint32 | Name2 | ||
0x08 | uint16 | Locale | The language of the file. This is a Windows LANGID data type, and uses the same values | |
0x0A | uint16 | Platform | The platform the file is used for. 0 indicates the default platform. | |
0x0C | uint32 | BlockIndex | If the hash table entry is valid, this is the index into the block table of the file. |
Block Table
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. The entry in the block table has the following structure:
Offset | Type | Name | Description | |
---|---|---|---|---|
0x00 | uint32 | FilePosition | ||
0x08 | uint32 | compressedSize | ||
0x0C | uint32 | uncompressedSize | ||
0x10 | uint32 | Flags | The platform the file is used for. 0 indicates the default platform. |
Retrieved from "http://www.zezula.net/en/mpq/mpqformat.html"