TR4 FILE FORMAT NOTES

         Recopilation notes from some peoples
                                  12-21-01
               Last Updated January-02-2002

Hi, This is my own recopilation about Tr4 file format notes from some peoples, this is not a complete byte-per-byte walktroug because the TR4 file format is almost the like the TR3 files, so once you have your TR3 reader working then  read the notes below to help you to known what you have to change/add to your Tr3 fileformat for be able to read/write TR4 levels.

The more important thing is that TR4 files are in compressed way, the method used is called ZLIB, and you can found on internet (search the word Zlib) a Zlib.dll and a Zlib.H file that will let you descompress zlib compressed data in your program.

For uncompress each chunk data, you will found in the file:

uncompressed_size : 4 bytes telling you how long the data is when is uncompressed, so you have to alloc a memory buffer
                                 with  this size where to store the chunk once uncompressed.

Compressed_size    : 4 bytes telling you how long the data is when is compressed.

Next come the compressed data, read compressed_size bytes data, and then use your zlib rutine to uncompress the chunk and store the data in your allocated buffer.

Turbo Pascal, 12-21-01.


Note #1,  By Yuri Zhivago

I don't have it in a nice neat form like the TRosettaStone;  in fact,  it's been so long now, I'm not at all sure where my notes on it are.

If you have the TRueView source, you have everything I know - TR2IO.C   is where all of the TR4 I/O occurs.  Search for "TombRaider_4" in  TR2IO.C to see the places where TR4 is different from the other versions.

Having written that, I just dug out my notes as of about five months  ago;  they're not current, but between these notes and the TR2IO.C source,  you should be able to figure things out...

--- TR4 Notes (written to myself):

The .TR4 format is similar to TR3, except (note that this list of exceptions is not intended to be complete at this point):

    *   The level data is zlib compressed (obviously)

   *     There is no 8-bit palette, nor are there any 8-bit textures,
        and LightMap is not present.

  *     Lara now comprises two ObjectIDs and two sets of meshes, one
        for most of her body and the other for her joints;
        this appears to be how she is "skinned."  All other
        meshes that I have observed are "normal" (e.g. are
        not "skinned" in this manner).

   *    struct tr2_room_light is now 46 bytes (no clues yet)

   *     struct tr2_animation has 8 extra bytes immediately
        before .FrameStart (no clues yet)

   *    Three bytes ("SPR") appear immediately before NumSpriteTextures

   *    struct tr2_sound_source is now 40 bytes (no clues yet)

   *    Between SoundSources and NumBoxes is a new element:
           bitu32 NumXYZ
           struct { bitu8 unknown[16]; } XYZ[NumXYZ];

Before SoundSources is a new field for Flyby_Camera data
bitu32 Number_of_FBCameras
followed by data for each camera. Data field is 40 bytes.
[Yury had previously stated NumXYZ as a new field incorrectly.
His NumXYZ field was the SoundSources in normal structure format],
    -Note from Roy Godbold.

        Four bytes ("TEX\0") appear immediately before NumObjectTextures

        struct tr2_object_texture is now 38 bytes.  The .Tile
        field is now bitu32, not bitu16;  the other 16 new bytes
        appear after the texture vertices (no clues yet)

        It appears that SoundMap is either larger or variable-length,
        although I'm not yet certain how the length would be inferred
        (there does not appear to be a NumSoundMap field).  This causes
        my parser to behave erratically, so I currently stop parsing at
        SoundMap.

Soundmap is a fixed 740 bytes  long, the problem was that  the num_cinematic fields is now 4 bytes long and the cinematic records is now 24 bytes long, so Yury was reading  incorrect that structure causing a later problem  in his reader.
    -Note from Turbo Pascal

      .PAK files are also zlib compressed;  the first four bytes of
      the file are the uncompressed size, while the compressed size
      is inferred as the file length - 4.  The logo files decompress
      to 512*256*24bits bitmaps.

      There is an unused level, JOBY1B.TR4, that looks like an abandoned
      effort - the only mesh is Lara, and there is a fair amount of
      landscape, but nothing to do, really...

      Things I've observed using the viewer:

        TR3-style alpha transparency doesn't work (water, rays of
           light, etc.) - in fact, it's completely wrong (there are
           cases where unintended transparency occurs).  This could
           conceivably be a bug in my viewer, but it works perfectly
           for all the TR3 levels, so I'm guessing there was a change.
           All the TR4 transparencies show up as opaque greyscale.

        AnimatedTextures don't seem to work;  in fact, I don't think
           they are actually used (my level dumping routine is broken
           at the moment, so I can't verify this, but a few judicious
           printf()s lead me to believe that this is the case.)

Animated textures work exactly in the same way that TR1-Tr3, i don;t known what problem Yury had with this structure.
   -Note From Turbo Pascal

        While every other mesh/staticmesh works, pickups appear to be
           sunk into the floor (or whatever they're on top of).  In
           fact, they appear to be Y-centered at floor (or table) level.
        TR4 has a number of new (and cool) lighting and particle effects;
           interestingly, my viewer renders these as meshes.  There
           must be some interesting FloorData or hardcoded magic going
           on...
        Ropes do not appear as items or staticmeshes;  at present, my
           viewer can't find them at all.  They may be related to the
           new NumZZZ elements, although I have no evidence of that.
        I see the continuation of a trend that I first saw in TR3, that
           being the existence of detached rooms.  TR3 has a number of
           levels that have a cube off in space somewhere, which appears
           to me to be a "practice area" (to test out textures, etc.).
           In addition, at least one TR3 level (MINES.TR4) contains a
           completely detached "room" that actually appears in the
           level (when the submersible is lowered).  TR4 has quite a few
           detached areas that appear in the levels;  not only do they
           appear, but Lara enters and exits them.  The FloorData
           presumably now contains some "teleportation" code.  I assume
           that this is to avoid the "five-dimensional space" issues
           that can occur in densely overlapping areas.
        The mirrored rooms are interesting;  they really are mirror-imaged
           rooms that are bisected by two translucent planes that create
           the illusion of a mirror.  Again, I assume that there is some
           special FloorData that indicates one of these rooms and its centre
           plane;  that way, all the engine has to do is render Lara
           in mirror-image about that plane while following the normal
           FloorData rules.  Quite clever, really...
      --- end notes

      Good luck.

      Yuri Zhivago


Note #2,  By Roy Godbold
 

*******************************************************
      TR4 Possible File Format
rgbold March '01

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

---------------
Dword = 4 bytes
Int  = 2 bytes
--------------

Dword "TR4",0
Int   number of RoomTextures?
Int   number of OtherTextures?
Int   number of BumpMapTextures?
Dword UncompressedSize1
Dword CompressedSize1
TextureBlock1
Dword UncompressedSize2
Dword CompressedSize2
TextureBlock2
Dword UncompressedSize3
Dword CompressedSize3
TextureBlock3
Dword UncompressedSize4
Dword CompressedSize4
Rest_level_Block3    //The whole level data is in compressed mode in this block.

/// Once the level data is uncompressed then read the level as TR3 except  where noted

NOTES:
Texture needs to be masked with 0xfff (high 4 bits are flags)   //the textureID on each rectangle/triangle face.

Room Lights now 46 bytes:

TR4_RoomLight //
  //Follows a D3D light structure, I think, could be wrong

  Dword Xposition  // world coords
  Dword Yposition  // world coords
  Dword Zposition  // world coords
  TR2_Color        // three bytes rgb values
  bitu8 LightType  // same as D3D (i.e. 2 is for spotlight)
  bitu8 unknown    // always 0xff?
  byte  Intensity
  float In
  float Out
  float Length
  float Cutoff
  floats X,Y,Z    //direction??
 

Before SoundSources is a new field for Flyby_Camera data
bitu32 Number_of_FBCameras
followed by data for each camera. Data field is 40 bytes.
[Yury had previously stated NumXYZ as a new field incorrectly.
His NumXYZ field was the SoundSources in normal structure format]
 

Cinematic Frames now 24 bytes
* the field num_cinematic_frames is 4 bytes long for tr4-tr5
vice 2 bytes for tr1-tr3.

There are no colored rectangles or triangles in mesh data.
Mesh Rectangles and Triangles now
  MeshRects: v0,v1,v2,v3,texture,int unknown
  MeshTris:  v0,v1,v2,texture,int unknown
Texture Objects now preceeded by TEX/0 (4bytes)
Object Textures now 38 bytes vice 20
Tile is now a bitu32 vice bitu16 seems need to mask with 0xff as other
       bits are flags. Seems bit15 set means triangle.
In the texture coords now 0 is used for low value vice 1
The extra 16 bytes are at the end of ObjectTexture structure

Attributes using 1 or 2 for transparent. 2 used for 2 sided textures
               (water surface,etc)
 

Animation now 40 vice 32 bytes. extra 8 seem to be zero right before
/after the old 8 unknowns

"SPR"  3 byte ascii before sprite textures

There are no 8bit or 16 bit palettes (no colored rects or tris)
No lightmap
No 8bit textures

TR4 are 4 zlib compresed chunks, 3 for textures and 1 for rest level.
Following level data are Riff Wave Formats.
Lara 2 meshes , skin and joints.


Note # 3 From Michiel:

Go to trwad.tripod.com/download/TR5Manuel.htm for a small list from the OCB codes from TR5 objects. These codes set the password in the keypads, laser types and enemie opening animations.

These codes are includes in the item structure from TR4&5 and replaces the old intensity2 from TR2&3 data files.
This means TR4&5 don't have 2 intensity values, but only one.
The size of the structure is still the same.

-------------------------------------------

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

long NumAIData

followed by the following data for each object

int ObjectID ; the objectID from the AI object (AI_FOLLOW is 402)
int Room
long X
long Y
long Z
int OCB
int Flags ; The trigger flags (button 1-5, first button has value 2)
long Angle ; rotation

It's directly after the item data
---------------------------------------------------------------------

The underwater Current, like the doc sais, is not located in the fully in the floordata structure. The largest part is hidden in th tr2_camera structure. The floordata points to this structure. The difference ith a normal camera is that the room number is strenght of the current. The unknown int after this seems to be 0 for a camera, 1 for a fixed camera and for a current object it is different for every object.
 


Note #4 From E. POPOV

Here's my compilation of docs I have about TR4 file format augmented with infos I found when coding the TR4 support in TrViewer. I sent the HTML version to TP and I will add it to my web site.

Note: it's a lot better when seen in HTML format !,  Look from here!



Notes #5 By Baloneyman

This was lying around

////////////////////////////////////////////////////////////////////////////
//TR4 Room_Light
// EXAMPLE FOR SPOT LIGHT TYPE //

002A0000 ~ X world position dword
80FDFFFF ~ Y world position dword
007E0000 ~ Z world position dword
F0E0D0 ~ rgb colour byte[3]
02 ~ light type byte 0= sun, 1= light, 2= spot, 3= shadow,
FF ~ constant byte
13 ~ intensity byte [ 0-31 max (8 = .25) ]
B28F703F ~ in cosine float
CA03683F ~ out cosine float
00000045 ~ len float in 1024 units
00009F45 ~ cut float in 1024 units

//last 3 floats specify a directional vector

D91E7F3E ~ cosX * sinY (float)
411884BE ~ sinX (float)
E1F76E3F ~ cosX * cosY (float)

////////////////////////////////////////////////////////////////////////////

Sun -uses position of ff,ff,8 always
uses intensity
uses X and Y for directional vector

Light - uses position
uses intensity
uses OUT in 1024 units
uses IN in 1024 units

Spot - uses all fields as above

Shadow - uses position
uses intensity as -1 to 0 ( -.50 = 16 )
uses OUT in 1024 units
uses IN in 1024 units
 

///////////////////////////////////////////////////////////////////////////

// TR4LIGHT structure (46 bytes)

typedef struct
{

//        The first 3 values represent the position of the light in XYZ world coordinates
// NOTE: the SUN type light does not have a position and uses -1, -1, 8 for the XYZ.

long LightXposition
long LightYposition
long LightZposition
 

//        The next 3 bytes specify the RGB color values for the light

unsigned char LightRed
unsigned char LightGreen
unsigned char LightBlue

//        The next byte specifies the type of light. 0=sun, 1=light, 2=spot, 3=shadow
// NOTE: the 'effect' type light is not really a light but just changes the
// the vertex lighting.

char LightType

//        The following byte is a constant -1. Not used.

char LightConstant

//        The next byte is for the Intensity of the light.
// All lights but the 'shadow' type uses 0 minimum to 31 maximum. i.e. a value
// of .25 would be represented by 8.
//        NOTE: the shadow type light uses values of -1 to 0. a -.50 value would
// be represented by 16.

char LightIntensity

//        For the 'light' and 'shadow' type lights the following 2 floats
// represent the OUT and IN (falloff and hotspot) values in TR units (1024 = 1 sector)
//        For the 'spot' type light represent the cosine of the angle.
//        The 'sun' type light does not use these values.

float LightIN
float LightOUT

//        The following two floats are used only by the 'spot' type light
//        and represent the values in TR units (1024 = 1 sector)

float LEN
float CUT
 

//        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        x = cosX * sinY
//                                                y = sinX
//                                                z = cosX * cosY
//
//                        if only x                x = 0
//                                                y = sinX
//                                                z = cosX
//
//                        if only y                x = sinY
//                                                y = 0
//                                                z = cosY

float LightDirectionVectorX
float LightDirectionVectorY
float LightDirectionVectorZ

} TR4LIGHT;

///////////////////////////////////////////////////////////////////////////



 
 
 
Hosted by www.Geocities.ws

1