Skip to content

FORMAT: .TMD

TheStolenBattenberg edited this page Dec 7, 2020 · 7 revisions

.TMD File Format

The .TMD file format is a general use 3D format used in many PlayStation 1 games. It is part of the SN Systems Psy-Q Library (specifically, libGS) and used extensively in early From Software games.

Sections are in the order they appear unless it is stated otherwise.

Header:

struct Header {
    unsigned int ID;
    unsigned int flags;
    unsigned int numObject;
};

'ID' is always equal to 0x41000000 in all known examples of the .TMD format.

Object:

struct Object {
    unsigned int offVertex;
    unsigned int numVertex;
    unsigned int offNormal;
    unsigned int numVertex;
    unsigned int offPrimitive;
    unsigned int numPrimitive;
    signed int scale;
};

'offVertex', 'offNormal' and 'offPrimitive' are the offsets of each objects vertices, normals and primitives. Their value may change based on the value of 'flags' inside the Header.

'num X' are the counts of each element at the given offset above them.

'scale' is a byproduct of .TMD models being represented with integer coordinates and is usually 0 in game files. It is for reversing the scaling required for representing floating point data as an integer (e.g - the integer vertex coordinates would be divided by scale in order to return them to floating point vertex coordinates).

There are as many Object structures as the value of 'numObject' in the header, and they are stored back to back like so: object0, object1, ..., objectN.

Vertex Data:

Vertex data is not a structure, but a list of SVECTOR elements. This data can possibly appear anywhere in the file, as it is pointed to by the value 'offVertex' in an Object structure.

The SVECTOR structure is defined as such:

struct SVECTOR {
    signed short x;
    signed short y;
    signed short z;
    signed short pad;
};

Be weary! Vertex coordinates are technically not considered fixed point due to the PS1's use of integer coordinates.

Normal Data:

Like Vertex Data, Normal data is not a structure but a list of SVECTOR elements. The data can appear anywhere in the file, as it is pointed to by 'offNormal' in a Object structure.

See Vertex Data for the definition of SVECTOR

Normal vectors are fixed point numbers, with 4 bits for the integer component and 12 for the fractional component. You must divide each element of the SVECTOR by 4096 in order to retrieve the correct values.

Primitive Data:

Like Vertex Data, and Normal Data, Primitive data is a list pointed to by 'offPrimitive' in an Object structure.

Each primitive is proceeded by a small header which declares what types of data will follow, and the size of the data that follows.

struct PrimitiveHeader {
    unsigned byte oLen;
    unsigned byte iLen;
    unsigned byte flags;
    unsigned byte mode;
};

'oLen' is the length of the primitive created by libGS in PS1 memory.

'iLen' is the length of the following primitive data, divided by four.

'flags' is a bitwise field, used to say how this primitive is rendered. The bit field description is as follows:

Bits Name Description
0 LGT A value of 1 means that the primitive does not use light source calculation.
1 FCE A value of 1 means that the primitive is rendered without backface culling.
2 GRD A value of 1 means each vertex has its own colour, achieving a gradient effect.
3-7 N/A Reserved - Should be 0

'mode' is a bitwise field, used to say what this primitive contains. The bit field description is as follows:

Bits Name Description
0 TGE Texture Brightness Calculation
1 ABE Translucency processing (ABE = Alpha Blend Enable?)
2 TME A value of 1 means the primitive has textures.
3 Quad A value of 1 means the polygon is a quad
4 IIP A value of 1 means the polygon uses gouraud shading
5-7 Code The Primitive type

The value of 'code' in the bitfield above can be 0 for a Polygon, 1 for a Line or 2 for a Sprite (No examples have been found, but this is believed to be like a billboarded quad).

Primitive Configurations: A Primitive Configuration refers to a known primitive type in the TMD Model. There are more undocumented primitive configurations but the ones that follow are known to work.

There are also two more bit fields used within primitive packets CBA and TSB which will be explained first.

'CBA'

Bits Name Description
0-5 VramX X Location of texture CLUT in VRAM, shifted right by 4
6-14 VramY Y Location of texture CLUT in VRAM
15 N/A Reserved. Should be 0

'TSB'

Bits Name Description
0-4 TPG Texture Page ID
5-6 ABR Transparency Blend Method
7-8 TPF Texture Colour Mode
9-15 N/A Reserved. Should be 0

The 'TPF' value is the type of texture expected. It can be a value of 0 for 4bpp, 1 for 8bpp and 2 for 16bpp.

The 'ABR' value will control blending between what is currently on the display buffer and the primitive that is going to be drawn. 0 is 50% + 50%, 1 is 100% + 100%, 2 is 100% - 100% and 3 is 100% + 25%.