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.