File Formats - OpenJPOG/org.equinoxscripts.ojpog.io GitHub Wiki

Common Data Formats

Null-terminated string: ASCII string terminated with a zero-byte.

Fixed length string: An ASCII string encoded in a fixed number of bytes. Respect null termination.

Quaternion: Four 32-bit floats laid out as X,Y,Z,W.

Matrix: Sixteen 32-bit floats laid out in row-major order.

Vector3: Three 32-bit floats laid out as X,Y,Z

Vector2: Two 32-bit floats laid out as X,Y

Notes

An offset of ~~ means assume tight packing; this element starts after the previous one.

Toshi Model Driver (.TMD)

The TMD format starts with an 8 byte fixed length string. Magic is "TMDL".

TMD Header

The TMD header starts at byte 8 and is made of 52 bytes.

Offset Type Meaning
+0 uint32 Remaining bytes in file
+4 8 byte fixed string Category / lookup table for animations.
+12 uint64 Magic Value. Typically one of a couple values.
+20 uint32 lodDataOffset = value + 60
+24 uint32 Salt used to encrypt file offsets.
+28 uint32 Unknown value.
+32 uint32 Unknown value.
+36 zero*16 16 zeroes

Address encryption

To convert an encrypted address to an offset from the beginning of the file take: fileAddress = 60 + encryptedAddress - saltUsedForEncryptingOffsets

Scene Block

The scene block starts at byte 60+4, and has a size of the uint32 located at +60 from the beginning of the file.

Offset Type Meaning
+0 uint16 Number of nodes
+2 uint16 Unknown
+4 uint16 Number of animations
+6 uint16 Unknown
+8 zero*44 44 zeroes
+52 uint32 Encrypted address of the auxiliary node data
+56 (Optional) uint32 Encrypted address of the node data block *
+56 / +60 uint32 Encrypted address of the animation pointer block*

* If the decrypted address of the auxiliary node data is 0x7C it is assumed that there is no auxiliary node data. Then the decrypted address of the node data is assumed to be 0x7C also, and the encrypted address of the animation pointer table is located at +56 instead of +60.

Node Auxiliary Data (Optional)

Starting from the decrypted address of the auxiliary node data read one int32 for each node.

Node Data Block

The node data block starts at the decrypted address from the scene block, and extends for 0xB0 * numNodes bytes. Node 0 is then located at +0, and node 1 at +0xB0 inside the block. The node ID is the node's position in the zero-indexed array.

Node Format

Offset Type Meaning
+0 quaternion Fallback rotation, used when the animation doesn't provide one
+16 matrix Bind pose of the node, in world space
+80 matrix Inverse of the bind pose of the node, in world space
+144 byte Length of the name string
+145 15 byte fixed string Node name
+160 int16 ID of parent node, -1 if no parent exists
+162 uint16 If non-zero this node can ignore updates. Non-updated bones may only appear after all updated bones.
+164 vector3 Fallback translation, used when the animation doesn't provide one

Animation Pointer Block

The node data block starts at the decrypted address from the scene block, and extends for 4 * numAnimations bytes. Read one uint32 for each animation; this is the encrypted address of that animation.

Animation Data Block

Starting at a decrypted animation address from the animation pointer block read 0x20 + numNodes*4 bytes.

Offset Type Meaning
+0 byte Name length
+1 15 byte fixed string Animation Name
+16 uint32 Composite animation (added on top of others)
+20 uint32 Is sound played?
+24 uint32 Number of channels in animation
+28 32 bit float Duration in seconds
+32 uint32[numNodes] Encrypted address for each node's channel in this animation. Channel zero is for node zero.

Animation Channel Block

Starting at a decrypted animation channel address from a animation data block read an unknown number of bytes.

Offset Type Meaning
+0 uint16 (value&1) == UseTranslation, (value&2) == UseChannel
+2 uint16 Frame count
+4 frame[frameCount] Keyframes in this animation

Keyframe

Offset Type Meaning
+0 32 bit float Timestamp
+4 uint16 Translation key used in the lookup table
+6 uint16 Rotation key used in the lookup table

Levels-of-Detail Block

The levels of detail block starts at the offset specified in the header and extends for an undefined number of bytes.

Offset Type Meaning
+0 uint32 Number of levels
+4 uint32 Unknown value
+8 level[numLevels] LOD Level Data

Level-of-Detail

Offset Type Meaning
+0 uint32 Number of meshes in this level
+4 32 bit float Level of detail distance?
+8 4x 32 bit float Unknown
+24 mesh[numMesh] Mesh Data

Mesh Data

Offset Type Meaning
+0 uint32 Number of pieces in this mesh
+4 uint32 Total number of indices in the triangle strip for all pieces
+8 uint32 Total number of vertices
+12 32 byte fixed string Material name
+44 meshPiece[numPieces] Piece Data

Mesh Piece

Offset Type Meaning
+0 uint32 Total number of indices in this piece's triangle strip.
+4 uint32 Total number of vertices store in this piece's data.
+8 uint32 Total number of nodes this mesh is skinned to.
+12 uint32 Highest vertex number this piece references.
+16 vector3 Center of the bounding box for this piece. (max+min)/2
+28 vector3 Extent of the bounding box for this piece. (max-min)/2
+40 uint32[numNodesSkinnedTo] The IDs of the nodes that this mesh is skinned to. Element zero is the node ID of bone zero, etc.
~~ vertex[numVertices] The vertices defined in this piece. This accumulate inside the mesh, not in the mesh piece.
~~ int16[numIndices] The indices that make this piece's triangle strip. Note these reference the mesh's vertices and are numbered accordingly.

Mesh Vertex

Offset Type Meaning
+0 vector3 Position
+12 vector3 Normal
+24 byte[4] Each byte is a boneWeight = value / 0xFF
+28 byte[4] Each byte is a boneID = value / 3
+32 vector2 Texture Coordinate

Toshi Keyframe Library (.TKL)

Offset Type Meaning
+0 4 byte fixed string Must be "TPKL"
+4 byte[4] Always empty
+8 uint32 Remaining bytes in file (=bytes in LUT + 44)
+12 6 byte fixed string The name of this keyframe table/lookup table.
+18 byte[10] Unknown
+28 uint32 Number of position values
+32 uint32 Number of rotation values
+36 byte[16] Unknown
+52 uint32 Number of bytes in the LUT
+56 vector3[numPosValues] Position lookup table
~~ quaternion[numRotValues] Rotation lookup table

Toshi Material Library (.TML)

Offset Type Meaning
+0 4 byte fixed string Must be "TML1"
+4 uint32 Unknown
+8 uint32 Number of textures
+12 texture[numTextures] Textures
~~ uint32 Number of materials
~~ 32 byte fixed string[numMaterials] LUT for material names
~~ material[numMaterials] Materials

TML Material

Offset Type Meaning
+0 uint32 Index in the material name LUT for this materials' name.
+4 uint16 Unknown
+6 uint16 Number of textures that make up this material
+8 uint32[numTextures] The texture IDs of the textures that make up this texture.

TML Texture

Offset Type Meaning
+0 uint32 Texture ID
+4 uint32 Data size
+8 byte[8] Unknown
+16 tmlFormat Texture format
+18 uint16 texture width
+20 uint16 texture height
+22 byte[6] Unknown
+28 byte[dataSize] Image data according to the tmlFormat; raster formats use row-major order.

TML Texture Format

Value Description
0 RGBA_8888
2 ARGB_1555
6 DDS File
7 ARGB_4444
9 ARGB_2222

Notes

  • The order of the materials and textures seems extremely finicky so any solution shouldn't mess with it too much.