FastFiles and Zone files (MW2)
Main FastFile Structure
//Note, on PS3 all values are << 1
enum language_t
{
LANGUAGE_ENGLISH = 0x1,
LANGUAGE_FRENCH = 0x2,
LANGUAGE_GERMAN = 0x3,
LANGUAGE_ITALIAN = 0x4,
LANGUAGE_SPANISH = 0x5,
LANGUAGE_BRITISH = 0x6,
LANGUAGE_RUSSIAN = 0x7,
LANGUAGE_POLISH = 0x8,
LANGUAGE_KOREAN = 0x9,
LANGUAGE_TAIWANESE = 0xA,
LANGUAGE_JAPANESE = 0xB,
LANGUAGE_CHINESE = 0xC,
LANGUAGE_THAI = 0xD,
LANGUAGE_LEET = 0xE,
LANGUAGE_CZECH = 0xF,
MAX_LANGUAGES
};
//Entry point for the FF.
struct DB_AuthHeader
{
char magic[8];
int version;
bool allowOnlineUpdate;
unsigned __int64 fileCreationTime;
language_t region;
int entryCount;
Entry entries[];
int fileSize;
int maxFileSize;
};
Magic
The magic is a string that is 8 characters long. It is either "IWff0100" or "IWffu100". It indicates what is read after maxFileSize. If it is "IWff0100" then this FF is signed. If it is "IWffu100", then this FF is unsigned.
Version
Helps to dictate the version of the FF, so Modern Warfare 3 FastFiles cannot be loaded on Modern Warfare 2. The Modern Warfare 2 version is 0x10D for console systems and 0x114 for PC.
if (version > 0x10D)
Com_Error("Fastfile for zone '%s' is newer than client executable (version %d, expecting %d)", version, 0x10D);
else if (version < 0x10D)
Com_Error("Fastfile for zone '%s' is out of date (version %d, expecting %d)", version, 0x10D);
AllowOnlineUpdate
Whether or not assets in this FF may be replaced by an FF loaded at a later time.
Entries
These are still not entirely understood. Most FF systems simply parse past them.
Xbox 360
for (int32 i = 0; i < 0x0f; i++)
{
if (((1 << i) & language) == 0)
continue;
else
ReadBytes(((entryCount << 1) + entryCount) << 2);
}
PS3
readBytes(entryCount * 0x14);
File Sizes
The fileSize is the size of the FF, everything included. The maxFileSize is the highest number that fileSize can be, and in most FFs they are equal.
Subheader
The rest of the FF is read depending on what the main FF magic was. If the magic was "IWff0100" then the FF is signed. If it was "IWffu100", the FF is unsigned.
Unsigned Files
PS3 only supports unsigned fastfiles. For Xbox 360, only single player FastFiles are unsigned. Unsigned FastFiles are very simple. The only data remaining is compressed zlib data. Decompressing the data yields the zone file.
Signed Files
struct DB_AuthHash
{
char bytes[32];
};
struct DB_AuthSignatureHash
{
char bytes[256];
};
struct DB_AuthSubheader
{
char fastfileName[32];
int reserved;
DB_AuthHash masterBlockHashes[244];
};
struct DB_AuthXBlock
{
#ifdef XBOX
DB_AuthHash blockSignature[0x100];
char blockData[0x200000];
#elif defined PS3
char blockData[0x10000];
#endif
};
//Sub DB_AuthHeader, continuation on the earlier.
struct DB_AuthHeader
{
char magic[8];
int reserved;
DB_AuthHash subheaderHash;
DB_AuthSignatureHash signedSubheaderHash;
DB_AuthSubHeader subheader;
DB_AuthXBlock xBlocks[];
};
The signatures on the XBlocks are checked as the FastFile loads. Then the sub-header master block hashes are checked, followed by the signedSubheaderHash, and lastly the subheaderHash. If any fail, then the loading of the FF is aborted. Only Activision and the game developers can generate the RSA signatures.
Magic
The subheader magic is always "IWffs100".
XBlocks
XBlocks are used until they are no longer needed. If the compressed data can fit into 1, then only 1 will exist.
Compression
PS3
After the zone file is created, it is split into blocks each 0x10000 bytes. Each block is compressed using default zlib compression. The size of the compressed block is stored as an unsigned 16 bit integer over the zlib header (0x78DA). Compressed blocks are concatenated and appended to the fastfile.
Xbox 360
Once the zone file is created, the entire zone is compressed using default zlib compression. If the FastFile is unsigned (single player) then the data is simply concatenated to the header. Signed files split the data up into 0x200000 byte XBlocks, each with a 0x2000 byte hash block.
Zone File
The zone file is the decompressed data from an FF. The fastfile compiler creates a rawfile as the last asset which contains any compiler errors (as seen in french code_post_gfx_mp.ff).
struct XAsset
{
XAssetType type; //See enum below
XAssetHeader * header;
};
struct XAssetList
{
int scriptStringCount;
const char * * scriptStrings;
int assetCount;
XAsset *assets;
};
#ifdef PS3
#define MAX_BLOCKS 7
struct XFile
{
int size;
int unknown;
int blockSize[MAX_BLOCKS];
};
General Asset Information
Asset Types
The types of assets loaded are determined by this enum.
| Asset Type | Xbox ID | PS3 ID | PC ID | Is Used | Max Count | Asset Size (PC) |
|---|---|---|---|---|---|---|
| physpreset | 0x00 | 0x00 | 0x00 | True | 0x40 | 0x2C |
| phys_collmap | 0x01 | 0x01 | 0x01 | True | 0x400 | 0x48 |
| xanim | 0x02 | 0x02 | 0x02 | True | 0x1000 | 0x58 |
| xmodelsurfs | 0x03 | 0x03 | 0x03 | True | 0x1000 | 0x24 |
| xmodel | 0x04 | 0x04 | 0x04 | True | 0x600 | 0x130 |
| material | 0x05 | 0x05 | 0x05 | True | 0x1000 | 0x60 |
| pixelshader | 0x06 | 0x06 | 0x06 | True | 0x1FA0 | 0x10 |
| vertexshader | N/A | 0x07 | 0x07 | True | 0x400 | 0x10 |
| vertexdecl | N/A | N/A | 0x08 | True | 0x30 | 0x64 |
| techset | 0x07 | 0x08 | 0x09 | True | 0x300 | 0xCC |
| image | 0x08 | 0x09 | 0x0A | True | 0xE00 | 0x20 |
| sound | 0x09 | 0x0A | 0x0B | True | 0x3E80 | 0x0C |
| sndcurve | 0x0A | 0x0B | 0x0C | True | 0x40 | 0x88 |
| loaded_sound | 0x0B | 0x0C | 0x0D | True | 0x546 | 0x2C |
| col_map_sp | 0x0C | 0x0D | 0x0E | True | 1 | 0x100 |
| col_map_mp | 0x0D | 0x0E | 0x0F | True | 1 | 0x100 |
| com_map | 0x0E | 0x0F | 0x10 | True | 1 | 0x10 |
| game_map_sp | 0x0F | 0x10 | 0x11 | True | 1 | 0x38 |
| game_map_mp | 0x10 | 0x11 | 0x12 | True | 1 | 0x08 |
| map_ents | 0x11 | 0x12 | 0x13 | True | 2 | 0x2C |
| fx_map | 0x12 | 0x13 | 0x14 | True | 1 | 0x74 |
| gfx_map | 0x13 | 0x14 | 0x15 | True | 1 | 0x274 |
| lightdef | 0x14 | 0x15 | 0x16 | True | 0x20 | 0x10 |
| ui_map | 0x15 | 0x16 | 0x17 | False | 0 | N/A |
| font | 0x16 | 0x17 | 0x18 | True | 0x10 | 0x18 |
| menufile | 0x17 | 0x18 | 0x19 | True | 0x80 | 0x0C |
| menu | 0x18 | 0x19 | 0x1A | True | 0x264 | 0x190 |
| localize | 0x19 | 0x1A | 0x1B | True | 0x1B58 | 0x08 |
| weapon | 0x1A | 0x1B | 0x1C | True | 0x578 | 0x684 |
| snddriverglobals | 0x1B | 0x1C | 0x1D | True | 1 | N/A |
| fx | 0x1C | 0x1D | 0x1E | True | 0x258 | 0x20 |
| impactfx | 0x1D | 0x1E | 0x1F | True | 4 | 0x08 |
| aitype | 0x1E | 0x1F | 0x20 | False | 0 | N/A |
| mptype | 0x1F | 0x20 | 0x21 | False | 0 | N/A |
| character | 0x20 | 0x21 | 0x22 | False | 0 | N/A |
| xmodelalias | 0x21 | 0x22 | 0x23 | False | 0 | N/A |
| rawfile | 0x22 | 0x23 | 0x24 | True | 0x400 | 0x10 |
| stringtable | 0x23 | 0x24 | 0x25 | True | 0x190 | 0x10 |
| leaderboarddef | 0x24 | 0x25 | 0x26 | True | 0x64 | 0x18 |
| structureddatadef | 0x25 | 0x26 | 0x27 | True | 0x18 | 0x0C |
| tracer | 0x26 | 0x27 | 0x28 | True | 0x20 | 0x70 |
| vehicle | 0x27 | 0x28 | 0x29 | True | 0x80 | 0x2D0 |
| addon_map_ents | 0x28 | 0x29 | 0x2A | True | 1 | 0x24 |