TRAOD Formats

Tomb Raider: angel of darkness features a brand new game engine. That means new file formats had to be made. While the first engine had files with 1 big structure, with the new game engine the level files are split up into smaller parts. This means there are a lot of pointers inside the files. This way just a part where you are playing can be loaded, which means less memory is needed and a level loads faster. However, a single level is shorter this way which causes the game to load a new (part of a) level more often.

 

 

1. GMX Files

The .gmx files are big files containing a full level. They include all textures, animations, meshes and the rooms. But these are seperated from each other. The gmx files contains some smaller files for animations, characters and rooms.

struct GMXFile_Pointer
{
  long ID;
  long
Pointer;
  long
Size;
};

struct
GMXFile
{
  long Version;                 // 0x40666666
  int NumPointers;
  int Unknown1;
  GMXFile_Pointer *Pointers;
};
Each pointer in the GMXFile_Pointer gives you another file. They appear to be in random order. The ID field is unknown. It seems to be a unique ID for each filename.


1.1 Character files

One of the files that you can find are characters files (.chr).

struct CHRFile_TextData
{
  char Format[4];               // 'DXT1', 'DXT3' or 0x00000015 (B8G8R8A8).
  long Unknown1;                // Mostly set to 2 or 4
  long Unknown2;                // Always 1?
  long Levels;
  long XSize;
  long YSize;
  long DataSize;
  char *Data;
}; 

struct
CHRFile_TextInfo
{
  long Unknown1;
  long Unknown2;
  long Unknown3;
  long Unknown4;
  long Unknown5;
  long Unknown6;
};

struct
CHRFile_Textures
{
  long NumTextInfo;
  long Unknown1;
  CHRFile_TextInfo *TextInfo;
  CHRFile_TextData *TextData;
};

struct
CHRFile_Mesh
{
  long Unknown1;
  char Name[64];
  char Unknown2[380];           // Lots unknown data
};

struct CHRFile_MeshData_Unk2 {
   unsigned short Unknown1;
   unsigned short Unknown2;
   unsigned long Unknown3;
   unsigned long Unknown4;
};

struct CHRFile_MeshData_Vertex {
    char Unknown[19];           // (first
CHRFile_MeshData structure has 38 bytes per Vertex)
};

struct CHRFile_MeshData {
  long Unknown1[3];

  long NumVertices;
  CHR_MeshData_Vertex *Vertices;
 
  long NumIndex;
  short *Index;

  long NumUnknown2;
  CHR_MeshData_Unk2 *Unknown2;

  long Unknown3;
  long Unknown4;
};

struct
CHRFile
{
  long Unknown1;                // Seems to be always 0
  long TexturePointer;          // Pointer to the textures
  long MeshPointer;             // Pointer to the beginning of the first CHRFile_Mesh structure
  long Unknown1;                // Pointer to the something
  long MeshDataPointer;         // A pointer to first CHRFile_MeshData structure
  long NumMeshes;               // Number of CHRFile_Mesh you must read at the MeshPointer offset
};

 

1.2 Map files

Map files contain (part of) a level. Big levels are split in multiple maps. At some placed the screen goes black and a new map is loaded. This is done to reduce the size of textures and vertex/index buffers.

// First structure looks like some room definition, not sure however

struct
MAP_Rooms
{
  long NumRooms;
  MAP_RoomPointer *Rooms;
};

struct MAP_RoomPointer
{
  long Unknown1;
  long Pointer;
};

struct MAP_Room
{
  long Unknown1;
  long Unknown2;
  long Pointer1;
  long Pointer2;
};

// Textures in Direct3D Format. Can be simply loaded to a surface, included mipmaps.

struct MAP_Textures
{
  long NumTextInfo;
  long Unknown1;
  long NumTextData;
  long Unknown2;
  MAP_TextInfo *TextInfo;
  MAP_TextDataHeader *TextDataHeader;
  MAP_TextData *TextData;
};

struct MAP_TextInfo
{
  long Unknown1;
  long Unknown2;
  long Unknown3;
  long Unknown4;
  long Unknown5;
  long Unknown6;
};

struct MAP_TextDataHeader
{
  char Format[4]; // 'DXT1', 'DXT3' or 0x15000000. Last one is uncompressed A8R8G8B8 format.
  long Unknown1;  // 2 or 4
  long Unknown2;  // Always 1
  long Unknown3;  // Always 30
  long Levels;    // Number of levels in this texture. 7 for 256x256 textures, 2 for 8x8 textures.
  long XSize;
  long YSize;
  long DataSize;  // Size of this texture.
  long Unknown4;  // Always 0?
  long Unknown5;  // Always 0?
};

struct MAP_TextData
{
  char *Data;
};

struct MAPFile
{
  long RoomPointer;
  long TexturePointer;
  long UnknownPointer1;
  long UnknownPointer2;
  long UnknownPointer3;
};

 

2. DB Files

The data folder from aod contains 3 .db files and have all their own format. These files contain important data for the game. The actor.db file contains a lot of information about all friends and enemies in the game. The function of the other 2 files, weapon.db and invent.db, is not known yet. But the weapon.db must have something to do with the guns and ammo and invent seems to be about pickups.


2.1 Actor.db

As said before, actor.db is all about the NPCs (Non Player Characters). It's a easy format, which can be explained with just 2 structures:

struct ActorDB
{
  long NumActors;
  ActorDB_Item *Actors;
};

struct ActorDB_Item
{
  long ActorID;
  long HitPoints;
  long Type;
  long BaseID;
  long Flags;
};
The ActorID is an unique number for each actor. You cannot have 2 actors with the same id. Some actors can have shared animations. An enemy takes the animations from the base actor. This is set by the BaseID. If an enemy has it's own animations, BaseID must be set to it's own id. Else it points to the actor where the animations are used from.
Different from the other TR games, the main actor data is no longer hardcoded. The hit points of an enemy can be set using the HitPoints field. It's not clear to say how much time you must shoot an enemy to kill based on the hit points. It depends on the type of gun you use and the distance to the enemy. For example, a rat far away can take more shots then a guard right in front of you.
The Type value can be set to 4 values. If an character is playable, it has a type of 1. Friendly characters that cannot be shot have the type set to 2. Enemies which can be fired at have type 3. Finally there is a type 4 which seems to be used for animating objects.
The last value, Flags, can be set to 0, 1 and 3. The meaning of it is still unknown, but proberly it has something to do with the type of actor.