TR4 file format

Contributors: Rgbold, Turbo Pascal, Yuri Zhivago, Dr. Willard, TRWad, Popov, others ?
Compiled by Popov

This document describes only differences between TR3 and TR4 file format. Please, refer to the TRosetta Stone document to get informations about TR1 / TR2 and TR3 file format.
This document is not complete, there are yet some unknowns. Feel free to fill in the blanks and let us know that we can modify this document.

Types used

bit8a signed 8 bits
bitu8an unsigned 8 bits
bit16a signed 16 bits
bitu16an unsigned 16 bits
bit32a signed 32 bits
bitu32an unsigned 32 bits
floata 4 bytes float

Other types can be used: if it's the case, refer to the TRosetta Stone document to have their definitions (for eg: tr2_color)

General format of a .TR4 file

bitu16Number of non bumped room tiles 
bitu16Number of tiles for objects 
bitu16Number of bumped room tiles 
bitu32Uncompressed size of texture 1 
bitu32Compressed size of texture 1 
bitu8[](compressed) Texture 1 (32 bits texture) 
bitu32Uncompressed size of texture 2 
bitu32Compressed size of texture 2 
bitu8[](compressed) Texture 2 (16 bits texture) 
bitu32Uncompressed size of texture 3 
bitu32Compressed size of texture 3 
bitu8[](compressed) Texture 3 (32 bits texture)-> a 256x512 texture with the font & sky
bitu32Uncompressed size of geometry 
bitu32Compressed size of geometry 
bitu8[](compressed) Geometry 
num_sounds * struct TR4_TrailingSound
bitu32UncompSize;// Uncompressed sound size
bitu32CompSize;// Compressed sound size -> compression is ADPCM (WAV format)
bitu8sound_data[];// data of the sound - size is CompSize bitu8


Format of the geometry block

-> same structures than in TR3 format, except:

Room Lights

// Follows a D3D light structure, I think, could be wrong (46 bytes)
typedef struct
bit32Xposition;// world coords
bit32Yposition;// world coords
bit32Zposition;// world coords
tr2_colourColor;// three bytes rgb values
bitu8LightType;// same as D3D (i.e. 2 is for spotlight)
bitu8unknown;// always 0xff?
floatX,Y,Z;// direction??
} tr4_room_light;

Tri & Quad polys in mesh objects

// Triangle surface (10 bytes)
typedef struct
bitu16Vertices[3];// The 3 vertices of a tri
bitu16Texture;// Object-texture index
bitu16Lighting;// transparency flag & strength of the hilight
} tr4_face3;

// Quadrangle surface (12 bytes)
typedef struct
bitu16Vertices[4];// The 4 vertices of a quad
bitu16Texture;// Object-texture index
bitu16Lighting;// transparency flag & strength of the hilight
} tr4_face4;

The new field Lighting has this layout:

Bit 0if set, alpha channel = intensity (same meaning that when the Attribute field of tr2_object_texture is 2. Cf TRosetta stone document)
Bits 1->7strength of the hilight. In TR4, objects can exhibit some kind of light reflection when seen from some particular angles. These bits give the strength of this effect: the more bigger the value is, the more visible is the effect.


Flyby cameras

Before SoundSources (cf. TRosetta stone document) is a new field for Flyby_Camera data:

// Data for a flyby camera (40 bytes)
typedef struct
bit32pos[6];// Positions ? (x1,y1,z1,x2,y2,z2)
bitu8index[2];// A pair of indices
bitu16Unknown[5];// ??
bit32ID;// Index of something
} tr4_extra_camera;

Cinematic frames replaced by AI data

There are no cinematic frames in TR4. Instead of that, there is the following structure:

bitu32num_AIData;// this field replaces the bitu16 NumCinematicFrames of TR1/2/3 levels
// Data for a AI object (24 bytes)
typedef struct
bitu16ObjectID;// the objectID from the AI object (AI_FOLLOW is 402)
bitu16Flags;// The trigger flags (button 1-5, first button has value 2)
bit32Angle;// rotation
} tr4_AI_object;

Changes in tr2_sprite_texture

This structure has the same size than before but some of its fields have changed of meaning:

// Data for a sprite (16 bytes)
typedef struct
bitu8unknown1;// ??
bitu8unknown2;// ??
bit16Width;// = (real_width-1) * 256
bit16Height;// = (real_height-1) * 256
bit16x1,y1;// top-left corner of the texture
bit16x2,y2;// bottom-right corner of the texture
} tr4_sprite_texture;

In addition, the NumSpriteTextures field (see TRosetta stone) is preceeded by the 3 ASCII bytes 'SPR'

Mesh objects

Meshes have no longer colored tris / quads. So, NumColoredRectangles, ColoredRectangles[], NumColoredTriangles, ColoredTriangles[] no longer exist in the tr2_mesh structure (cf. TRosetta stone document for the tr2_mesh_structure).

Object textures

The NumObjectTextures field (see TRosetta stone) is now preceeded by \0TEX (4 bytes -> \0 is the bitu8 value 0). The structure tr2_object_texture itself has changed:

// Data for an object texture (38 bytes vice 20 in TR1/2/3)
typedef struct
bitu16Attribute;// same meaning than in TR3
bitu16Tile;// same meaning than in TR3
bitu16Flags;// new in TR4
tr2_object_texture_vertVertices[4];// same meaning than in TR3
bitu32Unknown1,Unknown2;// new in TR4: x & y offset in something ?
bitu32XSize,YSize;// new in TR4: width-1 & height-1 of the object texture
} tr4_object_texture;

Meaning of Flags:

Bits 0->2mapping correction. It seems that these bits change the way the texture is applied...
Bit 11->122 bits giving the bump mapping type. Can be 0x01 or 0x10. It's 0x00 if not bump mapped. Only textures for room or animated textures can be bump mapped, not meshes
Bit 15if set, the texture is for a tri/quad from a room or animated texture. If not set, the texture is for a mesh



The tr2_animation structure has changed a little:

// Data for an animation structure (40 bytes vice 32 in TR1/2/3)
typedef struct
bitu32dwFrameOffset;// same meaning than in TR3
bitu8bFrameRate;// same meaning than in TR3
bitu8bFrameSize;// same meaning than in TR3
bitu16wStateId;// same meaning than in TR3
bit16Unknown;// same meaning than in TR3
bit16sSpeed;// same meaning than in TR3
bitu16wAccelLo;// same meaning than in TR3
bit16sAccelHi;// same meaning than in TR3
bitu8Unknown2[8];// new in TR4
bitu16wFrameStart;// same meaning than in TR3
bitu16wFrameEnd;// same meaning than in TR3
bitu16wNextAnimation;// same meaning than in TR3
bitu16wNextFrame;// same meaning than in TR3
bitu16wNumStateChanges;// same meaning than in TR3
bitu16wStateChangeOffset;// same meaning than in TR3
bitu16wNumAnimCommands;// same meaning than in TR3
bitu16wAnimCommand;// same meaning than in TR3
} tr4_animation;