DISCLAIMER: This file comes with no guarantee as to its accuracy, and must not be used to break the law in any way. I accept no responsibility for any problems relating to this document, use at your own risk.

JPOG File Formats

A selection of file formats for Jurassic Park Operation Genesis. Written and researched by Andres.

  Material Library (.tml) 
  Model file (.tmd)

Material Library (.tml)

Contain a bunch of textures. Textures can be 16bit or 32bit RGBA, or DirectX Texture (DXT) compressed. Files named "*16.tml" contain only 16bit textures (data_format=2,7), others have data_format=0,2,6 (maybe 7 too?).

struct TMLFile {
  char[4] magic = "TML1";
  uint    unknown = 0x00;

  uint    num_textures;
  array of struct {

    uint texture_id;   // numbered in reverse order ie. texture[n].texture_id = num_textures-1-n
    uint data_size;    // see data_format below
    uint unknown1;
    uint unknown2;
    short data_format; // 0 = RGBA 8888 (rgba order), data_size = width*height*4
                       // 2 = RGBA 5551 (rgba order), data_size = width*height*2

                       // 6 = Raw DDS file. Either DXT3 or 5 compressed (brga order, as per DXT specs).
                       //     data_size = size of DDS file, as per DDS/DXT specification
                       // 7 = RGBA 4444 (rgba order), data_size = width*height*2
    short width;
    short height;
    short unknown3;    // = 0xFFFF always?

    uint unknown4;     // = 0x43000000 always?
    byte data[data_size];
  } texture[num_textures];

  uint num_strings;
  char[32] strings[num_strings];
  array of struct {

    uint string_num; // index into strings array
    short unknown;
    short num_refs;
    uint texture_id[num_refs]; // list of texture_id of textures with this name

  } string_table[num_strings];
}

Model file (.tmd)

Contains a scene graph (including meshes) for a single model. Scene graph nodes have a standard transformation matrix, children nodes, and optional mesh. A mesh is stored conveniently for rendering, each using a single material, with triangles stored as a triangle strip.

struct TMDFile {
  char[4] magic = "TMDL";
  uint unknown1 = 0x00;
  uint data_size;   // = filesize - 12

  char[8] catagory; // eg. "STRUCT", "MISC", "FLORA"
  uint unknown2;
  char[4] unknown3 = "IX2",0x00;
  uint graph_size;  // same as graph_size2

  uint unknown4;    // this is position 0x20 in file. Related to
                    // FirstPart.unknown2 at file position 0x74
  uint unknown5;
  uint unknown6;
  uint unknown7[4]; // = {0,0,0,0} always?

  uint graph_size2; // same as graph_size
}

// The SceneGraphBlock starts at file position 0x40.
// sizeof(SceneGraphBlock) = TMDFile.graph_size
struct SceneGraphBlock {
  short numNodes;
  short N;           // 

  short P;           // 
  short Q;           // 
  uint unknown1[11]; // always = {0x00, 0x00, ...}?

  uint unknown2;    // related to TMDFile.unknown4 (at file position 0x20)

  array of struct Node { // sizeof(Node) = 0xB0
    float4  rotation;      // quaternion

    float16 transform;     // position float3 starts at transform[12]
    float16 invtransform;
    byte node_name_length; // number of non-zero chars
    char node_name[15];
    short parent;          // index of parent node

    short no_mesh;         // 0 if node has a mesh, or if a child has a mesh
                           // 1 otherwise 
    float3 pivot_offset;   // usually equals transform.position
  } nodes[num_nodes];

  uint unknown3;    // related to TMDFile.unknown4 (at file position 0x20)

  uint unknown4;    // = 0x71655340 always? 
  uint unknown5;    // = 0x10 always? 
  uint unknown6[4]; // = {0,0,0,0} always? 

  uint O;           // 

  uint unknown7;    // = 0x3D088889 always? 
  uint unknown8[num_nodes]; // related to TMDFile.unknown4? (at file position 0x20) 

  uint unknown9[3];    // = {0x00200000, 0, 0} always? 
  uint unknown7;    // = 0x3D088889 always? 

  // Kiosk.tmd has two sets of these tables, and has P = Q = 2 instead of 1
  array[O] of struct {

    uint block_num;    // numbered in reverse order
    ...
  }
}

// MeshBlock starts at immediately after the ScenGraph Block
// ie. at file position 0x40+TMDFile.graph_size
struct MeshBlock {
  uint unknown1;
  uint num_meshes;
  uint unknown2 = 0x00;
  uint unknown3[4]; // last two sometimes floats


  array of struct Mesh {
    uint unknown1;      // = 0x01 always?
    uint tri_strip_size;
    uint num_verts;
    char material_name[32];
    uint A;
    uint B;
    uint num_nodes;
    uint B2;           // = B always

    float unknown2[6];
    uint nodes[num_nodes]; // indexes of scene graph nodes using this mesh

    array of struct Vertex {
      float3 position;
      float3 unknown1; // normal?

      float2 unknown2;
      float2 texpos;
    } verts[num_verts];

    // Indexed triangle strip. If any two vertex indicies for a triangle
    // are the same, skip it. Eg. vertex indicies for triangles are in:
    // {tri_strip[0,1,2], tri_strip[3,2,1], tri_strip[2,3,4],
    //  tri_strip[5,4,3], tri_strip[4,5,6], tri_strip[7,6,5], ...}
    short tri_strip[tri_strip_size];

  } meshes[num_meshes];
}

Page created: 11-Aug-2003