FastFiles and Zone files (MW2): Difference between revisions

From COD Engine Research
No edit summary
Jakes625 (talk | contribs)
 
(23 intermediate revisions by 5 users not shown)
Line 3: Line 3:


== Main FastFile Structure ==
== Main FastFile Structure ==
<syntaxhighlight lang="cpp">
#define MAX_DB_HEADER_ENTRIES 0x3800
  //Note, on PS3 all values are << 1
  //Note, on PS3 all values are << 1
  enum language_t
  enum language_t
Line 25: Line 28:
   
   
  //Entry point for the FF.
  //Entry point for the FF.
  struct DB_AuthHeader
  struct DB_Header
  {
  {
   char magic[8];
   char magic[8];
Line 31: Line 34:
   bool allowOnlineUpdate;
   bool allowOnlineUpdate;
   unsigned __int64 fileCreationTime;
   unsigned __int64 fileCreationTime;
   language_t region;
   language_t languageMask;
   int entryCount;
   int entryCount;
   Entry entries[];
   DbHeaderImageStreamEntry entries[]; //entryCount
   int fileSize;
   int fileSize;
   int maxFileSize;
   int maxFileSize;
  };
  };
</syntaxhighlight>
=== Magic ===
=== 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.
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 ===
=== 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.
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 ===
=== AllowOnlineUpdate ===
Whether or not assets in this FF may be replaced by an FF loaded at a later time.
Whether or not assets in this FF may be replaced by an FF loaded at a later time.
=== Entries ===
=== Entries ===
These are still not entirely understood. Most FF systems simply parse past them.
On PS3 Entries are the serialized source ranges and logical decode positions for streamed GfxImage payloads.
 
The serialized header row order is not the same as the runtime record order. The engine reads:  DbHeaderImageStreamEntry, Then stores runtime records as: GfxImageStreamRecord.
 
<syntaxhighlight lang="cpp">
public struct DbHeaderImageStreamEntry
{
    uint FileIndex;      // 0 = current fastfile, 1..4 = imagefile%d
    uint SourceStart;    // compressed/source offset in selected file
    uint SourceEnd;      // compressed/source end offset, not size
    uint BlockOffset;    // low 16-bit/intra-block logical stream offset
    uint StreamOffset;  // full logical uncompressed stream offset
}
 
public struct GfxImageStreamRecord
{
    uint SourceStart;
    uint BlockOffset;
    uint StreamOffset;
    uint SourceEnd;
    void* File;
}
</syntaxhighlight>
 
==== Xbox 360 ====
==== Xbox 360 ====
  for (int32 i = 0; i < 0x0f; i++)
  for (int32 i = 0; i < 0x0f; i++)
Line 54: Line 85:
  }
  }
==== PS3 ====
==== PS3 ====
readBytes(entryCount * 0x14);
The language selector comes from DB global/state storage:
<code>dbManager->selectedLanguageMask; // offset +0x46024 in the manager block</code>
 
Behavior from the eboot:
* If selectedLanguageMask == 0, the first header’s languageMask initializes it.
* If it is already set, the header language mask must intersect it.
* The entry table for the selected language bit is read.
* Entry tables for other language bits are skipped with entryCount * 0x14.
 
<syntaxhighlight lang="cpp">
    for (uint32_t i = 0; i < (language_t->MAX_LANGUAGES - 1); i++)
    {
        uint32_t bit = 1u << i;
 
        if ((DB_Header->languageMask & bit) == 0)
            continue;
 
        if (DB_Header->entryCount > MAX_DB_HEADER_ENTRIES)
            Com_Error("Too many DB header entries");
 
        uint32_t entryBytes = DB_Header->entryCount * 0x14;
 
        if (bit != db->selectedLanguageMask) //See notes above
        {
            SkipBytes(r, entryBytes);
            continue;
        }
 
        for (uint32_t entryIndex = 0;
            entryIndex < DB_Header->entryCount;
            entryIndex++)
        {
            DbHeaderImageStreamEntry *entry = &DB_Header->entries[entryIndex];
 
            entry->fileIndex    = ReadU32BE(r);
            entry->sourceStart  = ReadU32BE(r);
            entry->sourceEnd    = ReadU32BE(r);
            entry->blockOffset  = ReadU32BE(r);
            entry->streamOffset = ReadU32BE(r);
        }
    }
</syntaxhighlight>
 
=== File Sizes ===
=== 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.
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 ==
== 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.
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 ===
=== Unsigned Files ===
Unsigned files are used for SP data and are very simple. The only data remaining is compressed zlib data. Decompressing the data yields the [[Modern Warfare 2 Zone File|zone file]].
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|zone file]].
=== Signed Files ===
=== Signed Files ===
<syntaxhighlight lang="cpp">
  struct DB_AuthHash
  struct DB_AuthHash
  {
  {
Line 81: Line 156:
  struct DB_AuthXBlock
  struct DB_AuthXBlock
  {
  {
#ifdef XBOX
   DB_AuthHash blockSignature[0x100];
   DB_AuthHash blockSignature[0x100];
   char blockData[0x200000];
   char blockData[0x200000];
#elif defined PS3
  char blockData[0x10000];
#endif
  };
  };
   
   
Line 95: Line 174:
   DB_AuthXBlock xBlocks[];
   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. Once all the signatures are checked, then the data is combined and decompressed to give the [[Modern Warfare 2 Zone File|zone file]].
</syntaxhighlight>
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 ====
==== Magic ====
The subheader magic is always "IWffs100".
The subheader magic is always "IWffs100".
==== XBlocks ====
==== XBlocks ====
XBlocks are used until they are no longer needed. If the compressed data can fit into 1, then only 1 will exist.
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, the last block being padded with zeroes if not 0x10000 bytes long. 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.
=== Header ===
The XFile header is loaded first. It contains XBlock sizes to be allocated for g_streamBlocks.
<syntaxhighlight lang="cpp">
enum
{
XFILE_BLOCK_TEMP = 0,
XFILE_BLOCK_PHYSICAL = 1,
XFILE_BLOCK_RUNTIME = 2,
XFILE_BLOCK_VIRTUAL = 3,
XFILE_BLOCK_LARGE = 4,
XFILE_BLOCK_CALLBACK = 5,
#if defined(PC) || defined(PS3)
XFILE_BLOCK_VERTEX = 6,
#ifdef PC
XFILE_BLOCK_INDEX = 7,
#endif
#endif
MAX_XFILE_COUNT
};
struct XFile
{
  int size;
  int externalSize;
  int blockSize[MAX_XFILE_COUNT];
};
</syntaxhighlight>
=== g_streamBlocks ===
Remember that g_streamBlocks are loaded as the zone is read. Here are some examples. The raw dumps are collapsed by default to keep the page readable:
==== Temp ====
<div class="mw-collapsible mw-collapsed" style="border:1px solid #a2a9b1; padding:0.5em; margin:0.5em 0;">
'''Temp block dump'''
<div class="mw-collapsible-content">
<syntaxhighlight lang="text">
0000000B 40000001 000001AF 400000F5 40153A79 00000000 00000000 40153A82 401537C1 42820000 00000000 00000000 00000001 00000000 00000168 00000000 00000000 00000000 00000000 4000844B 00000000 00000000 00000085 00000085 0000016E 000001F4 00000001 00000000 00000000 00000000 00000000 00000000 00000000 40153A59 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 40000E89 4012CA4D 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
</syntaxhighlight>
</div>
</div>
==== Large ====
<div class="mw-collapsible mw-collapsed" style="border:1px solid #a2a9b1; padding:0.5em; margin:0.5em 0;">
'''Large block dump'''
<div class="mw-collapsible-content">
<syntaxhighlight lang="text">
00000000 4000002D 4000003E 40000052 40000066 4000007A 4000008F 4000009F 400000B0 400000C0 400000DA 6D656C65 655F6B6E 6966655F 73746162 00776561 705F6D31 3838375F 6C696674 5F706C72 00776561 705F6D31 3838375F 6F70656E 5F706C72 00776561 705F6D31 3838375F 6C6F6F70 5F706C72 00776561 705F6D31 3838375F 636C6F73 655F706C 72007669 65776D6F 64656C5F 736D616C 6C007669 65776D6F 64656C5F 6D656469 756D0076 6965776D 6F64656C 5F6C6172 67650077 6561705F 736D6F6B 65677265 6E616465 5F70696E 5F706C72 00776561 705F736D 6F6B6567 72656E61 64655F66 6972655F 706C7200 00000008 00000011 00000018 00000011 00000024 00000011 00000024 00000011 00000024 00000011 00000026 00000011 00000026 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000008 00000011 00000008 00000011 00000018 00000011 00000018 00000011 00000018 00000011 00000018 00000011 00000018 00000011 00000018 00000011 00000018 00000011 00000018 00000011 00000018 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 00000008 00000011 00000008 00000011 00000008 00000011 00000008 00000011 00000008 00000011 00000008 00000011 00000008 00000011 00000008 00000011 00000008 00000011 00000008 00000011 0000001B 00000011 0000001B 00000011 0000001B 00000011 0000001B 00000011 00000008 00000011 00000008 00000011 00000008 00000011 00000008 00000011 00000008 00000011 0000001B 00000011 0000001B 00000011 0000001B 00000011 00000023 00000011 2C326400 75695F6D 702F6D61 696E2E6D 656E7500 0000001D 0000001D ........
</syntaxhighlight>
</div>
</div>
=== Asset List ===
After the XFile header is the asset list. The asset list contains a list of script strings and a list of assets. The fastfile compiler creates a rawfile as the last asset which contains any compiler errors (as seen in french code_post_gfx_mp.ff).
<syntaxhighlight lang="cpp">
struct XAsset
{
  XAssetType type; //See enum below
  XAssetHeader * header;
};
struct XAssetList
{
  int scriptStringCount;
  const char * * scriptStrings;
  int assetCount;
  XAsset *assets;
};
</syntaxhighlight>
== General [[:Category:Assets|Asset]] Information ==
== General [[:Category:Assets|Asset]] Information ==
=== Asset Types ===
=== Asset Types ===
The types of assets loaded are determined by this enum.
The types of assets loaded are determined by this enum.
enum XAssetType : int
{| border="1" cellpadding="1" cellspacing="1" class="article-table" style="font-size:13px;line-height:21px;width:500px;height:500px;"
{
! scope="col"|Asset Type
  physpreset = 0x00,
! scope="col"|Xbox ID
  phys_collmap = 0x01,
! scope="col"|PS3 ID
  xanim = 0x02,
! scope="col"|PC ID
  modelsurfs = 0x03,
! scope="col"|Is Used
  xmodel = 0x04,
! scope="col"|Max Count
  material = 0x05,
! scope="col"|Asset Size (PC)
  pixelshader = 0x06,
|-
  techset = 0x07,            //On PS3, 0x07 is vertexshader, everything else follows starting with techset at 0x08.
|physpreset
  image = 0x08,
|0x00
  sound = 0x09,
|0x00
  sndcurve = 0x0A,
|0x00
  loaded_sound = 0x0B,
|True
  col_map_sp = 0x0C,
|0x40
  col_map_mp = 0x0D,
|0x2C
  com_map = 0x0E,
|-
  game_map_sp = 0x0F,
|phys_collmap
  game_map_mp = 0x10,
|0x01
  map_ents = 0x11,
|0x01
  fx_map = 0x12,
|0x01
  gfx_map = 0x13,
|True
  lightdef = 0x14,
|0x400
  ui_map = 0x15,              //Not Used
|0x48
  font = 0x16,
|-
  menufile = 0x17,
|xanim
  menu = 0x18,
|0x02
  localize = 0x19,
|0x02
  weapon = 0x1A,
|0x02
  snddriverglobals = 0x1B,
|True
  fx = 0x1C,
|0x1000
  impactfx = 0x1D,
|0x58
  aitype = 0x1E,              //Not Used
|-
  mptype = 0x1F,              //Not Used
|xmodelsurfs
  character = 0x20,          //Not Used
|0x03
  xmodelalias = 0x21,        //Not Used
|0x03
  rawfile = 0x22,
|0x03
  stringtable = 0x23,
|True
  leaderboarddef = 0x24,
|0x1000
  structureddatadef = 0x25,
|0x24
  tracer = 0x26,
|-
  vehicle = 0x27,
|xmodel
  addon_map_ents = 0x28
|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
|}

Latest revision as of 18:38, 22 June 2026


Main FastFile Structure

 #define MAX_DB_HEADER_ENTRIES 0x3800

 //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_Header
 {
   char magic[8];
   int version;
   bool allowOnlineUpdate;
   unsigned __int64 fileCreationTime;
   language_t languageMask;
   int entryCount;
   DbHeaderImageStreamEntry entries[]; //entryCount
   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

On PS3 Entries are the serialized source ranges and logical decode positions for streamed GfxImage payloads.

The serialized header row order is not the same as the runtime record order. The engine reads: DbHeaderImageStreamEntry, Then stores runtime records as: GfxImageStreamRecord.

public struct DbHeaderImageStreamEntry
{
    uint FileIndex;      // 0 = current fastfile, 1..4 = imagefile%d
    uint SourceStart;    // compressed/source offset in selected file
    uint SourceEnd;      // compressed/source end offset, not size
    uint BlockOffset;    // low 16-bit/intra-block logical stream offset
    uint StreamOffset;   // full logical uncompressed stream offset
}

public struct GfxImageStreamRecord
{
    uint SourceStart;
    uint BlockOffset;
    uint StreamOffset;
    uint SourceEnd;
    void* File;
}

Xbox 360

for (int32 i = 0; i < 0x0f; i++)
{
  if (((1 << i) & language) == 0)
    continue;
  else
    ReadBytes(((entryCount << 1) + entryCount) << 2);
}

PS3

The language selector comes from DB global/state storage: dbManager->selectedLanguageMask; // offset +0x46024 in the manager block

Behavior from the eboot:

  • If selectedLanguageMask == 0, the first header’s languageMask initializes it.
  • If it is already set, the header language mask must intersect it.
  • The entry table for the selected language bit is read.
  • Entry tables for other language bits are skipped with entryCount * 0x14.
    for (uint32_t i = 0; i < (language_t->MAX_LANGUAGES - 1); i++)
    {
        uint32_t bit = 1u << i;

        if ((DB_Header->languageMask & bit) == 0)
            continue;

        if (DB_Header->entryCount > MAX_DB_HEADER_ENTRIES)
            Com_Error("Too many DB header entries");

        uint32_t entryBytes = DB_Header->entryCount * 0x14;

        if (bit != db->selectedLanguageMask) //See notes above
        {
            SkipBytes(r, entryBytes);
            continue;
        }

        for (uint32_t entryIndex = 0;
             entryIndex < DB_Header->entryCount;
             entryIndex++)
        {
            DbHeaderImageStreamEntry *entry = &DB_Header->entries[entryIndex];

            entry->fileIndex    = ReadU32BE(r);
            entry->sourceStart  = ReadU32BE(r);
            entry->sourceEnd    = ReadU32BE(r);
            entry->blockOffset  = ReadU32BE(r);
            entry->streamOffset = ReadU32BE(r);
        }
    }

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, the last block being padded with zeroes if not 0x10000 bytes long. 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.

Header

The XFile header is loaded first. It contains XBlock sizes to be allocated for g_streamBlocks.

enum
{
 XFILE_BLOCK_TEMP	= 0,
 XFILE_BLOCK_PHYSICAL	= 1,
 XFILE_BLOCK_RUNTIME	= 2,
 XFILE_BLOCK_VIRTUAL	= 3,
 XFILE_BLOCK_LARGE	= 4,
 XFILE_BLOCK_CALLBACK	= 5,
#if defined(PC) || defined(PS3)
 XFILE_BLOCK_VERTEX	= 6,
 #ifdef PC
 XFILE_BLOCK_INDEX	= 7,
 #endif
#endif
 MAX_XFILE_COUNT
};
 
struct XFile
{
  int size;
  int externalSize;
  int blockSize[MAX_XFILE_COUNT];
};

g_streamBlocks

Remember that g_streamBlocks are loaded as the zone is read. Here are some examples. The raw dumps are collapsed by default to keep the page readable:

Temp

Temp block dump

0000000B 40000001 000001AF 400000F5 40153A79 00000000 00000000 40153A82 401537C1 42820000 00000000 00000000 00000001 00000000 00000168 00000000 00000000 00000000 00000000 4000844B 00000000 00000000 00000085 00000085 0000016E 000001F4 00000001 00000000 00000000 00000000 00000000 00000000 00000000 40153A59 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 40000E89 4012CA4D 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

Large

Large block dump

00000000 4000002D 4000003E 40000052 40000066 4000007A 4000008F 4000009F 400000B0 400000C0 400000DA 6D656C65 655F6B6E 6966655F 73746162 00776561 705F6D31 3838375F 6C696674 5F706C72 00776561 705F6D31 3838375F 6F70656E 5F706C72 00776561 705F6D31 3838375F 6C6F6F70 5F706C72 00776561 705F6D31 3838375F 636C6F73 655F706C 72007669 65776D6F 64656C5F 736D616C 6C007669 65776D6F 64656C5F 6D656469 756D0076 6965776D 6F64656C 5F6C6172 67650077 6561705F 736D6F6B 65677265 6E616465 5F70696E 5F706C72 00776561 705F736D 6F6B6567 72656E61 64655F66 6972655F 706C7200 00000008 00000011 00000018 00000011 00000024 00000011 00000024 00000011 00000024 00000011 00000026 00000011 00000026 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000023 00000011 00000008 00000011 00000008 00000011 00000018 00000011 00000018 00000011 00000018 00000011 00000018 00000011 00000018 00000011 00000018 00000011 00000018 00000011 00000018 00000011 00000018 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 0000001A 00000011 00000008 00000011 00000008 00000011 00000008 00000011 00000008 00000011 00000008 00000011 00000008 00000011 00000008 00000011 00000008 00000011 00000008 00000011 00000008 00000011 0000001B 00000011 0000001B 00000011 0000001B 00000011 0000001B 00000011 00000008 00000011 00000008 00000011 00000008 00000011 00000008 00000011 00000008 00000011 0000001B 00000011 0000001B 00000011 0000001B 00000011 00000023 00000011 2C326400 75695F6D 702F6D61 696E2E6D 656E7500 0000001D 0000001D ........

Asset List

After the XFile header is the asset list. The asset list contains a list of script strings and a list of assets. 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;
};

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