TR5 file format


Note:

            items in blue are described in the TRosettaStone document.

            items in red are unique/different and are described, if known,

            in this document.


Disclaimer:  This document is at a very early stage and all attempts to verify this information have been made.

                   HOWEVER, I do not guarantee any of the information to be correct. If you find something wrong, or better, if you find something new, please share it. 


                   This document describes a possible file format. It does not contain any algorithims. It does not contain any computer program  source code. As such this document and it's contents cannot be copyrighted and cannot be considered a copyright infringement. HOWEVER, I am not a lawyer.


                   Thanks,

                   Roy




Note: Structures are NOT C++ structures.

          Terminology for consistency with TRosettaStone document: 

bit8 char

bitu8 unsigned char

bit16 short int

bitu16 unsigned short int

bit32 long

bitu32 unsigned long

       

*********************************************************************

bitu32 Version; // version "TR4",0 (4 bytes)

bitu16 NumRoomTextiles; // number of room texture tiles (2 bytes)

bitu16 NumObjectTextiles; // number of object texture tiles (2 bytes)

bitu16 NumBumpMapTextiles; // number of bump map texture tiles (2 bytes)

bitu32 Textile32UncompressedSize; // 32 bit textures uncompressed size

bitu32 Textile32CompressedSize; // 32 bit textures compressed size

bitu8  Textile32[Textile32CompressedSize]; // data bytes for the 32 bit textures (ZLIB compressed data)

bitu32 Textile16UncompressedSize; // 16 bit textures uncompressed size

bitu32 Textile16CompressedSize; // 16 bit textures compressed size

bitu8 Textile16[Textile16CompressedSize]; // data bytes for the 16 bit textures (ZLIB compressed data)

bitu32 Textile32MiscUncompressedSize; // 32 bit misc. (lettering, sky, etc) textures uncompressed size

bitu32 Textile32MiscCompressedSize; // 32 bit misc.textures compressed size

bitu8 Textile32Misc[Textile32MiscCompressedSize]; // data bytes for the 32 bit misc textures (ZLIB compressed data)

32*bit8 Seperator; // 32 bytes of 0x00 (Late Note: Michiel has discovered the first 4 bytes here are 2 bitu16 flags

for Lara type and weather, msg posted on the 'F*cking Pop Ups'  board somewhere )

bitu32 LevelDataSize1; // size of level data (count after LevelDataSize2 bitu32)

bitu32 LevelDataSize2; //  repeat of above

bitu32 Seperator; // 4 bytes of 0x00

bitu32 NumRooms; // number of rooms (maximum 255 rooms (0-254)) (4 bytes)

tr5 room Rooms[NumRooms]; // the actual room data

bitu32 NumFloorData; // number of floor data bitu16's to follow (4 bytes)

bitu16 FloorData[NumFloorData]; // floor data (NumFloorData * 2 bytes)


bitu32 NumMeshData; // number of bitu16's of mesh data to follow (=Meshes[]) (4 bytes)

struct {

tr2_vertex Centre; // relative coordinates of mesh centre (6 bytes)

bitu8 Unknown1[4]; // unknown (4 bytes)

bit16 NumVertices; // number of vertices to follow (2 bytes)

tr2_vertex Vertices[NumVertices]; // list of vertices (NumVertices * 6 bytes)

bit16 NumNormals; // number of normals to follow (2 bytes)

tr2_vertex Normals[NumNormals]; // list of normals (NumNormals * 6 bytes) (becomes Lights if NumNormals < 0; 2 bytes)

bit16 NumTexturedRectangles; // number of textured rectangles to follow (2 bytes)

tr5_face4 TexturedRectangles[NumTexturedRectangles]; // list of textured rectangles (NumTexturedRectangles * 12 bytes)

bit16 NumTexturedTriangles; // number of textured triangles to follow (2 bytes)

tr5_face3 TexturedTriangles[NumTexturedTriangles]; // list of textured triangles (NumTexturedTriangles * 10 bytes)

} Meshes[NumMeshPointers]; // note that NumMeshPointers comes AFTER Meshes[]



bitu32 NumMeshPointers; // number of mesh pointers to follow (4 bytes)

bitu32 MeshPointers[NumMeshPointers]; // mesh pointer list (NumMeshPointers * 4 bytes)

bitu32 NumAnimations; // number of animations to follow (4 bytes)

tr5_animation Animations[NumAnimations]; // animation list (NumAnimations * 40 bytes)

bitu32 NumStateChanges; // number of state changes to follow (4 bytes)

tr2_state_change StateChanges[NumStateChanges]; // state-change list (NumStructures * 6 bytes)

bitu32 NumAnimDispatches; // number of animation dispatches to follow (4 bytes)

tr2_anim_dispatch AnimDispatches[NumAnimDispatches]; // animation-dispatch list list (NumAnimDispatches * 8 bytes)

bitu32 NumAnimCommands; // number of animation commands to follow (4 bytes)

tr2_anim_command AnimCommands[NumAnimCommands]; // animation-command list (NumAnimCommands * 2 bytes)

bitu32 NumMeshTrees; // number of MeshTrees to follow (4 bytes)

tr2_meshtree MeshTrees[NumMeshTrees]; // MeshTree list (NumMeshTrees * 4 bytes)

bitu32 NumFrames; // number of words of frame data to follow (4 bytes)

bitu16 Frames[NumFrames]; // frame data (NumFrames * 2 bytes)

bitu32 NumMoveables; // number of moveables to follow (4 bytes)

tr5_moveable Moveables[NumMoveables]; // moveable list (NumMoveables * 20 bytes)

bitu32 NumStaticMeshes; // number of StaticMesh data records to follow (4 bytes)

tr2_staticmesh StaticMeshes[NumStaticMeshes]; // StaticMesh data (NumStaticMesh * 32 bytes)

4*bitu8  SPR; // "SPR" (4 bytes)

bitu32 NumSpriteTextures; // number of sprite textures to follow (4 bytes)

tr2_sprite_texture SpriteTextures[NumSpriteTextures]; // sprite texture list (NumSpriteTextures * 16 bytes)

bitu32 NumSpriteSequences; // number of sprite sequences records to follow (4 bytes)

tr2_sprite_sequence SpriteSequences[NumSpriteSequences]; // sprite sequence data (NumSpriteSequences * 8 bytes)

bitu32 NumCameras; // number of camera data records to follow (4 bytes)

tr2_camera Cameras[NumCameras]; // camera data (NumCameras * 16 bytes)

bitu32 NumFlyByCameras; // number of fly by camera data records to follow (4 bytes)

tr5 fly by camera FlyByCameras[NumFlyByCameras];// fly by camera data (NumFlyByCameras * 40 bytes)

bitu32 NumSoundSources; // number of sound source data records to follow (4 bytes)

tr5_sound_source SoundSources[NumSoundSources]; // sound source data (NumSoundSources * 16 bytes)

bitu32 NumBoxes; // number of box data records to follow (4 bytes)

tr2_box Boxes[NumBoxes]; // box data (NumBoxes * 8 bytes)

bitu32 NumOverlaps; // number of overlap records to follow (4 bytes)

bitu16 Overlaps[NumOverlaps]; // overlap data (NumOverlaps * 2 bytes)

10*bit16 Zones[NumBoxes]; // zone data (NumBoxes * 20 bytes)

bitu32 NumAnimatedTextures; // number of animated texture records to follow (4 bytes)

bitu16 AnimatedTextures[NumAnimatedTextures]; // animated texture data (NumAnimatedTextures * 2 bytes)

5*bitu8 TEX; "TEX" (5 bytes)

bitu32 NumObjectTextures; // number of object textures to follow (4 bytes) 

tr5_object_texture ObjectTextures[NumObjectTextures]; // object texture list (NumObjectTextures * 40 bytes)

bitu32 NumItems; // number of items to follow (4 bytes)

tr2_item Items[NumItems]; // item list (NumItems * 24 bytes)

bitu32 NumCinematicFrames; // number of cinematic frame records to follow (4 bytes)

tr5_cinematic_frame CinematicFrames[NumCinematicFrames]; // (NumCinematicFrames * 24 bytes)

bitu16 NumDemoData; // number of demo data records to follow (2 bytes)

bitu8 DemoData[NumDemoData]; // demo data (NumDemoData bytes)

bit16 SoundMap[450]; // sound map (900 bytes)

bitu32 NumSoundDetails; // number of sound-detail records to follow (4 bytes)

tr2_sample_info SoundDetails[NumSoundDetails]; // sound-detail list (NumSoundDetails * 8 bytes)

bitu32 NumSampleIndices; // number of sample indices to follow (4 bytes)

bitu32 SampleIndices[NumSampleIndices]; // sample indices (NumSampleIndices * 4 bytes)


//////////////////////////////////////////////////////TR5 ROOMS///////////////////////////////////////////////////////////////////////////////////////////


In TR5 the room format was drastically changed. The room itself is made up of 'sections'. These sections

encompass a 3 block by 3 block grid (actually 3069 pixels by 3069 pixels ). I will refer to these sections as layers.

Some 'rooms' do not actually contain visible mesh data. I will refer to these rooms as null rooms



tr5 room structure [ FIRST NUMBER IS OFFSET IN BYTES FROM START OF ROOM STRUCTURE]

{

0    bitu32 XELA; // "XELA" (4 bytes)

4    bitu32 RoomDataSize; // size of the following data ( use this vice 'walking thru' to get next room) (4 bytes)

8    bitu32 Seperator; // 0xCDCDCDCD (4 bytes)

12  bitu32 EndSDOffset; // usually this number +  216 will give you the offset from the start of the room data to the end

                                    of the Sector Data. HOWEVER have seen where this bitu32 is equal to -1 so it is better

                                    to use the following bitu32 and + 216 + ((NumXSectors * NumZSectors)*8) if you need

                                    to obtain this information. (4 bytes)

16   bitu32 StartSDOffset; // this number + 216 will give you the offset from the start of the room to the start of the                                                                                 sector data. (4 bytes)

20   bitu32 Seperator; // will either be 0x00000000 or 0xCDCDCDCD (4 bytes)

24   bitu32 EndPortalOffset; // this number + 216 will give you the offset from the start of the room to the end of the                                               portal data. (4 bytes)

28   bit32 x; // X position of room ( world coordinates) (4 bytes)

32   bit32 Seperator; // 0x00000000 (4 bytes)

36   bit32 z; // Z position of room (world coordinates) (4 bytes)

40   bit32 yBottom; // lowest point in room (4 bytes)

44   bit32 yTop; // highest point in room (4 bytes)

48   bitu16 NumZSectors; // sector table width (2 bytes)

50   bitu16 NumXSectors; // sector table height (2 bytes)

52   bitu32 RoomColor; // ARGB format (blue is least significant byte) (4 bytes)

56   bitu16 NumRoomLights; // number of lights in this room (2 bytes)

58   bitu16 NumRoomStaticMeshes; // number of static meshes in this room (2 bytes)

60   bitu16 UnknownR1; // usually 0x0001 however high byte is sometimes non zero (2 bytes)

62   bitu16 UnknownR2; // usually 0x0000 however low byte is sometimes non zero (2 bytes)

64   bitu32 Filler; // always 0x00007FFF (4 bytes)

68   bitu32 Filler2; // always 0x00007FFF (4 bytes)

72   bitu32 Seperator; // 0xCDCDCDCD (4 bytes)

76   bitu32 Seperator; // 0xCDCDCDCD (4 bytes)

80   6*bitu8 Seperator; // 6 bytes 0xFF

86   bitu16 RoomFlag; // 0x01 = water, 0x20 = wind, others unknown (2 bytes)

88  bitu16 UnknownR5; // unknown (2 bytes)

90  10*bitu8 Seperator; // 10 bytes 0x00

100 bitu32 Seperator; // 0xCDCDCDCD (4 bytes)

104 bitu32 UnknownR6; // unknown (4 bytes)

108  float RoomX; // X position of room in world coordinates * If  null room then this data will be 0xCDCDCDCD (4                                bytes)

112  bitu32 Seperator; // 0x00000000 or 0xCDCDCDCD if null room. (4 bytes)

116  float RoomZ; // Z position of room in world coordinates * If null room then will be bitu32 0xCDCDCDCD (4                                bytes)

120  bitu32 Seperator; // 0xCDCDCDCD (4 bytes)

124  bitu32 Seperator; // 0xCDCDCDCD (4 bytes)

128  bitu32 Seperator; // 0xCDCDCDCD (4 bytes)

132  bitu32 Seperator; // 0xCDCDCDCD (4 bytes)

136  bitu32 Seperator; // 0x00000000 unless null room then 0xCDCDCDCD (4 bytes)

140  bitu32 Seperator; // 0xCDCDCDCD (4 bytes)

144  bitu32 NumRoomTriangles; // total number of triangles this room (4 bytes)

148  bitu32 NumRoomRectangles; // total number of rectangles this room (4 bytes)

152  bitu32 Seperator; // 0x00000000 (4 bytes)

156  bitu32 LightSize; //  size of light data (number of lights * 88) (4 bytes)

160  bitu32 NumRoomLights; // total number of lights this room (4 bytes)

164  bitu32 UnknownR7; // unknown, usually equals 0, 1, 2, or 3 (4 bytes)

168  bit32 UnknownR8; // usually equals room yTop. Sometimes a few blocks off. If null room then 0xCDCDCDCD

172  bit32 lyBottom; // equals room yBottom. If null room then 0xCDCDCDCD (4 bytes)

176  bitu32 NumLayers; // number of layers (pieces) this room (4 bytes)

180  bitu32 LayerOffset; // this number + 216 will give you an offset from the start of the room data to the start of the                                         layer data (4 bytes)

184  bitu32 VerticesOffset; // this number + 216 will give you an offset from the start of the room data to the start of the

                                     verex data (4 bytes)

188  bitu32 PolyOffset; // this number + 216 will give you an offset from the start of the room data to the start of the 

                                rectangle/triangle data (4 bytes)

192  bitu32 PolyOffset2; // same as above ? (4 bytes)

196  bitu32 VerticesSize; // size of vertices data block (4 bytes)

200  bitu32 Seperator; // 0xCDCDCDCD (4 bytes)

204  bitu32 Seperator; // 0xCDCDCDCD (4 bytes)

208  bitu32 Seperator; // 0xCDCDCDCD (4 bytes)

212  bitu32 Seperator; // 0xCDCDCDCD (4 bytes)

216  tr5 lights[LightSize]; // data for the lights (88 bytes * NumRoomLights)

tr2 SectorData[(NumXSectors * NumZSectors) * 8]; // normal sector data structure

bitu16 NumDoors; // number of portals (2 bytes)

tr2 room door[NumDoors]; // normal portal structure (32 bytes * NumDoors)

bitu16 Seperator; // 0xCDCD (2 bytes)

tr2 room static mesh[NumStaticMeshes]; // normal room static mesh structure (20 bytes * NumRoomStaticMeshes)

tr5 room layer[NumLayers]; // data for the room layers (pieces) (56 bytes * NumLayers)

tr5 room polygons[NumRoomRectangles + NumRoomTriangles]; // data for the room polys (face4 and face3).                              Structured as

                             first layers rectangles then triangles, followed by the next layers rectangles and triangles,

                             etc., until all layers are done. (12 bytes each rectangle. 10 bytes each triangle)

tr5 room vertices[VerticesSize]; // data for the room vertices. Structured as vertices for the first layer, then

                                                    vertices for the second layer, etc., until all layers are done. (28 bytes each

                                                    vertex.


}tr5 room


tr5 room layer structure (56 bytes)

{

0   bitu32 NumLayerVertices; // number of vertices in this layer (4 bytes)

4   bitu16 UnknownL1; // unknown (2 bytes)

6   bitu16 NumLayerRectangles; // number of rectangles in this layer (2 bytes)

8   bitu16 NumLayerTriangles; // number of triangles in this layer (2 bytes)

10 bitu16 UnknownL2; // appears to be the number of 2 sided textures in this layer, however is sometimes 1 off (2 bytes)

12 bitu16 Filler; // always 0 (2 bytes)

14 bitu16 Filler2; // always 0 (2 bytes)


///////  The following 6 floats (4 bytes each) define the bounding box for the layer //////////

16 float LayerBoundingBoxX1;

20 float LayerBoundingBoxY1;

24 float LayerBoundingBoxZ1;

28 float LayerBoundingBoxX2;

32 float LayerBoundingBoxY2;

36 float LayerBoundingBoxZ2;


40 bitu32 Filler3; // always 0 (4 bytes)

44 bitu32 UnknownL6; // unknown (4 bytes)

48 bitu32 UnknownL7; // unknown (4 bytes)

52 bitu32 UnknownL8; // unknown. Always the same throughout the level. (4 bytes)

}tr5 room layer


tr5 face4 structure (12 bytes)

{

bitu16 Vertices[4]; // the values are the indices into the appropriate layer vertice list. (2 bytes each)

bitu16 Texture; // the texture number for this face. Needs to be masked with 0xFFF as the high 4 bits are flags.(2 bytes)

bitu16 UnknownF4; // unknown (2 bytes)

}tr5 room rectangle


tr5 face3 structure (10 bytes)

{

bitu16 Vertices[3]; // the values are the indices into the appropriate layer vertice list (2 bytes each)

bitu16 Texture; // the texture number for this face. Needs to be masked with 0xFFF as the high 4 bits are flags (2 bytes)

bitu16 UnknownF3; // unknown (2 bytes)

}tr5 room triangle


tr5 vertex structure (28 bytes)

{

float x; // x of vertex (4 bytes)

float y; // y of vertex (4 bytes)

float z; // z of vertex (4 bytes)

float nx; // x of vertex normal (4 bytes)

float ny; // y of vertex normal (4 bytes)

float nz; // z of vertex normal (4 bytes)

bitu32 vColor; // vertex color ARGB format (4 bytes)

}tr5 vertex



tr5 light structure (88 bytes)

{


// The following is preliminary info. Appears to be correct, however I'm having strange findings

// on some early testing. Proceed at your own risk on this one.


// The first three floats specify the position of the light in world coordinates

// The sun type light should not use these but seems to have a large x value (9 million, give or take)

// a zero y value, and a small z value (4 - 20) in the original TR5 levels


float x; // x position of light (4 bytes)

float y; // y position of light (4 bytes)

float z; // z position of light (4 bytes)


// The next three specify the color of the light


float Red; // color of red spectrum (4 bytes)

float Green; // color of green spectrum (4 bytes)

float Blue; // color of blue spectrum (4 bytes)


// Another 'filler'


bitu32 Seperator; // not used 0xCDCDCDCD (4 bytes)


// At this point the following info diverges dependant on which type of light being used:

// 0 = sun,  1 = light,  2 = spot,  3 = shadow


//   The sun type doesn't use the next two.

//   For the spot type these are the hotspot and falloff angle cosines

//   For the light and shadow types these are the TR units for the hotspot/falloff (1024=1sector)


float Input; // cosine of the IN value for light / size of IN value (4 bytes)

float Output; // cosine of the OUT value for light / size of OUT value (4 bytes)


//  The next two are only used by the spot type light


float RadInput; // (IN radians) * 2 (4 bytes)

float RadOutput; // (OUT radians) * 2 (4 bytes)


//  The next is also only used by the spot type light


float Range; // Range of light (4 bytes)


// The final 3 floats are used only by the 'sun' and 'spot' type lights.

// They describe the directional vector of the light.

// This can be obtained by :

//   if both x and y LightDirectionVectorX = cosX * sinY

//     LightDirectionVectorY = sinX

//     LightDirectionVectorZ = cosX * cosY

//


float DirectionVectorX; // light direction (4 bytes)

float DirectionVectorY; // light direction (4 bytes)

float DirectionVectorZ; // light direction (4 bytes)


//  The next six values repeat some of the previous information in long data types vice floats


bit32 x; // x position of light (4 bytes)

bit32 y; // y position of light (4 bytes)

bit32 z; // z position of light (4 bytes)


//  16384 = 1.0 for the rotations ( 1/16384 )


bit32 DirectionVectorX;  // light direction (4 bytes)

bit32 DirectionVectorY; // light direction (4 bytes)

bit32 DirectionVectorZ; // light direction (4 bytes)


//  The next char specifies the type of light as specified above


bitu8 LightType; // type of light. (1 byte)


//  Another filler


3*bitu8 Seperator; // 0xCDCDCD (3 bytes)

}tr5 light


tr5_object_texture structure (40 bytes)

{

bitu16 Attribute; //0, 1, or 2 (2 means 2 sided) (2 bytes)

bitu32 Tile; // need to mask with 0xFF as other bits are flags. ie bit15 seems to indicate triangle (4 bytes)

tr5 object texture vert; // Vertices[4] (16 bytes)

bitu32 UV1; // unknown how used (4 bytes)

bitu32 UV2; // unknown how used (4 bytes)

bitu32 Xsize; // unknown how used, x size (4 bytes)

bitu32 Ysize; // unknown how used, y size (4 bytes)

bitu16 Seperator; // always 0x0000 (2 bytes)

}tr5_object_texture


tr5 object texture vert structure (4 bytes)

{

bitu8 Xcoordinate; // 0 if Xpixel is the low value, 255 if Xpixel is the high value in the object texture (1 byte)

bitu8 Xpixel; // (1 byte)

bitu8 Ycoordinate; // 0 if Ypixel is the low value, 255 if Ypixel is the high value in the object texture (1 byte)

bitu8 Ypixel; // (1 byte)

}tr5 object texture vert



tr5 fly by camera structure (40 bytes)

{

bit32 CameraX; // x position of camera in world coordinates (4 bytes)

bit32 CameraY; // y position of camera in world coordinates (4 bytes)

bit32 CameraZ; // z  position of camera in world coordinates (4 bytes)


bit32 TargetX; // x position of aiming point in world coordinates (4 bytes)

bit32 TargetY; // y position of aiming point in world coordinates (4 bytes)

bit32 TargetZ; // z  position of aiming point in world coordinates (4 bytes)


bit8  Sequence; // sequence # of camera (1 byte)

bit8  CameraNumber; // camera # (1 byte)


bitu16 FOV; // fov of camera ( .0054945 for each degree ) (2 bytes)

bitu16 Roll; // roll of camera ( .0054945 for each degree ) (2 bytes)


bitu16 Timer; // timer number (2 bytes)

bitu16 Speed; // ( .000015259 each ) (2 bytes)

bitu16 Flags; // ( see your handy TRLE manual for the specs ) (2 bytes)

bitu32 Room; // room number (4 bytes)

}tr5 fly by camera



tr5 moveable structure ( 20 bytes ) ( same as old structure but has bitu16 filler at the end )

{

    bitu32 ObjectId; // object identifier ( matched in Items[] )

    bitu16 NumMeshes; // number of meshes in this object 

    bitu16 StartingMesh; // starting mesh ( offset into MeshPointers[] ) 

    bitu32 MeshTree; // offset into MeshTree[] )

    bitu32 FrameOffset; // byte offset into Frames[] ( divide by 2 for Frames[i] )

    bitu16 Animation; // offset into Animations[]

    bitu16 Filler; // always equal to 65519 ( 0xFFEF )

}tr5 moveable


tr5 animation structure ( 40 bytes ) ( same as old structure but has 8 bytes before FrameStart )

{

    bitu32  FrameOffset; // byte offset into Frames[] ( divide by 2 for Frames[i] )

    bitu8    FrameRate; // Engine ticks per frame

    bitu8    FrameSize; // number of bit16's in Frames[] used by this animation

    bitu16  StateId; // 

    bit16    Unknown;

    bit16    Speed; // Evengi Popov found this but I never seen what he said it was for

    bitu16  AccelLo; // same as above

    bit16    AccelHi; // same as above

    bitu8    AUnknown[8]; // Unknown

    bitu16  FrameStart; // first frame in this animation

    bitu16  FrameEnd; // last frame in this animation ( numframes = ( End - Start) + 1 )

    bitu16  NextAnimation;

    bitu16  NextFrame;

    bitu16  NumStateChanges;

    bitu16  StateChangeOffset; // offset into StateChanges[]

    bitu16  NumAnimCommands; // how many of them to use

    bitu16  AnimCommand; // offset into AnimCommand[]

}tr5 animation




/////////////////////////// The following structures have changed from the TR3 version //////////////////////


tr5_cinematic_frame now 24 bytes vice 16 bytes. Unknown how format was changed.