Summary
I've reverse-engineered the D3DMESH Version 1 (ERTM) format, which is currently listed as UNSUPPORTED in the version table of TelltaleGames_D3DMesh.ms. This covers:
- Tales of Monkey Island (2009) — all 5 episodes
- Back to the Future: The Game (2010-2011)
- Sam & Max Season 3: The Devil's Playhouse (2010)
- CSI: Deadly Intent / Fatal Conspiracy (2009-2010)
- Poker Night at the Inventory (2010)
- Wallace & Gromit Episode 4 (2009)
The format sits between V0.5 (Strong Bad/W&G Ep. 1-3, EarlyGameFix 4-9) and V2 (Jurassic Park). It uses the MTRE header with version byte 0x01.
What's documented
I've written a complete format specification covering:
- TriangleSet structure — CRC hash blocks, geometry fields (mStartIndex, mNumPrimitives, mMinVertIndex, mMaxVertIndex), bounding boxes, material block, multi-texture references
- Face index delta compression — the bitstream algorithm for
T3IndexBuffer::Decompress, cross-validated PC↔iOS on multiple meshes
- Vertex buffer chain — 16-byte headers (count + stride + type + flags), 6 buffer types (positions, normals, weights, bone IDs, UVs, tangents), raw float32 on PC
- Multi-texture materials — first texture = diffuse, subsequent textures classified by naming convention (bmap_bump → normal, mapspec → specular, adv_meshes → lightmap)
- D3DTX textures — DXT1/DXT3/DXT5 + RGBA8 (for normal maps), mipmap count field, pixel data at end of file
- Triangle strip/fan extras — mTriStrips field, extra indices beyond nprim*3 encoded as strip within the same submesh
Key differences from V0.5
| Feature |
V0.5 (Strong Bad/W&G) |
V1 (ToMI/BttF/S&M3) |
| Submesh name blocks |
String names or hashes by EarlyGameFix |
Always CRC64 hashes (12 bytes × 3) |
| Material texture slots |
5-7 conditional slots |
Sequential name_len + name references |
| Vertex buffer headers |
Flag byte + count + length + type |
count(u32) + stride(u32) + type(u32) + flags(u32) = 16 bytes |
| Face data |
Raw face point indices |
Delta-compressed bitstream (always on PC) |
| Vertex compression |
CompressionCheck + optional |
None on PC (raw float32) |
Verification
- 358/358 meshes from Tales of Monkey Island EP1 parse and export correctly
- 356/358 exact submesh count match with file header
- 70/70 triangle match between PC compressed and iOS raw indices (fx_bubble)
- Full vertex coverage (5639/5639 for sk20_guybrush, zero topological anomalies)
Resources
The full specification document (written in RTB script terminology), MaxScript pseudocode for the delta decompressor and bit reader, and a Python reference implementation are available here:
Format spec: CONTRIBUTION_RTB.md
Reference implementation (Python, pure stdlib):
export_mesh_glb.py — self-contained D3DMESH parser + glTF exporter with embedded textures
decode_d3dtx.py — DXT1/3/5 + RGBA8 texture decoder
Repository: https://github.com/coccofresco/telltale-explorer
Delta decompression pseudocode
The core algorithm that was missing — face index delta compression:
accumulator = ReadU16() -- first index (seed)
bodySize = ReadU32()
body = ReadBytes(bodySize)
indices = [accumulator]
bitPos = 0
while bitPos + 11 <= bodySize * 8 AND #indices < FaceCount:
deltaWidth = ReadBits(body, bitPos, 4); bitPos += 4
groupCount = ReadBits(body, bitPos, 7); bitPos += 7
if groupCount == 0: break
for j = 1 to groupCount:
sign = ReadBits(body, bitPos, 1); bitPos += 1
magnitude = ReadBits(body, bitPos, deltaWidth); bitPos += deltaWidth
delta = if sign then -magnitude else magnitude
accumulator = (accumulator + delta) AND 0xFFFF
append(indices, accumulator)
Bit reader is LSB-first within little-endian bytes.
Happy to help integrate this into the MaxScript if useful.
Summary
I've reverse-engineered the D3DMESH Version 1 (ERTM) format, which is currently listed as UNSUPPORTED in the version table of
TelltaleGames_D3DMesh.ms. This covers:The format sits between V0.5 (Strong Bad/W&G Ep. 1-3, EarlyGameFix 4-9) and V2 (Jurassic Park). It uses the MTRE header with version byte
0x01.What's documented
I've written a complete format specification covering:
T3IndexBuffer::Decompress, cross-validated PC↔iOS on multiple meshesKey differences from V0.5
Verification
Resources
The full specification document (written in RTB script terminology), MaxScript pseudocode for the delta decompressor and bit reader, and a Python reference implementation are available here:
Format spec: CONTRIBUTION_RTB.md
Reference implementation (Python, pure stdlib):
export_mesh_glb.py— self-contained D3DMESH parser + glTF exporter with embedded texturesdecode_d3dtx.py— DXT1/3/5 + RGBA8 texture decoderRepository: https://github.com/coccofresco/telltale-explorer
Delta decompression pseudocode
The core algorithm that was missing — face index delta compression:
Bit reader is LSB-first within little-endian bytes.
Happy to help integrate this into the MaxScript if useful.