Created
September 16, 2025 16:43
-
-
Save eliasdaler/939537a03d518ebfc15f080c5c9fe4dc to your computer and use it in GitHub Desktop.
TMD ImHex parser (unfinished)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import std.io; | |
| import std.core; | |
| import std.sys; | |
| #include <math.hexpat> | |
| struct Vec3Pad { | |
| FixedPoint<s16> x, y, z; | |
| u16 pad [[hidden]]; | |
| } [[sealed, format("format_vec3")]]; | |
| // Only flat shaded triangles are properly parsed | |
| struct Primitive { | |
| u8 olen; | |
| u8 ilen; | |
| u8 flag; | |
| u8 mode; | |
| if (mode == 32) { | |
| u8 r; | |
| u8 g; | |
| u8 b; | |
| u8 md; | |
| u16 normal; | |
| u16 v0; | |
| u16 v1; | |
| u16 v2; | |
| } else { | |
| $ += ilen * 4; | |
| } | |
| }; | |
| u32 objOffset; | |
| struct Object { | |
| objOffset = $; | |
| u32 vertTopAddr; | |
| u32 numVert; | |
| u32 normalTopAddr; | |
| u32 numNormal; | |
| u32 primitiveTopAddr; | |
| u32 numPrimitives; | |
| u32 scale; | |
| $ = vertTopAddr + objOffset; | |
| Vec3Pad vertices[numVert]; | |
| $ = primitiveTopAddr + objOffset; | |
| Primitive prims[numPrimitives]; | |
| $ = normalTopAddr + objOffset; | |
| Vec3Pad normals[numNormal]; | |
| }; | |
| struct TMDFile { | |
| u32 id; | |
| std::assert(id == 0x41, "Invalid TMD id"); | |
| u32 flags; | |
| u32 numObj; | |
| Object objects[numObj]; | |
| }; | |
| TMDFile file @ 0x0; | |
| struct VertexFloat { | |
| float x, y, z; | |
| }; | |
| u16 objToInspect in; | |
| u16 numObjects out; | |
| const u16 numVerts = file.objects[objToInspect].numVert; | |
| const u16 numIndices = file.objects[objToInspect].numPrimitives * 3; | |
| struct Model { | |
| VertexFloat vertices[numVerts]; | |
| float colors[numVerts * 4]; | |
| u32 indices[numIndices]; | |
| } [[hex::visualize("3d", vertices, indices, null, colors)]]; | |
| std::mem::Section section = std::mem::create_section("Section"); | |
| std::mem::set_section_size(section, sizeof(Model)); | |
| Model model @ 0x00 in section; | |
| fn main() { | |
| numObjects = file.numObj; | |
| Object obj @ addressof(file.objects[objToInspect]); | |
| for (u32 i = 0, i < numVerts, i= i + 1) { | |
| model.vertices[i].x = fixedX12_to_float(obj.vertices[i].x); | |
| // flip Y and Z for visualization | |
| model.vertices[i].y = -fixedX12_to_float(obj.vertices[i].y); | |
| model.vertices[i].z = -fixedX12_to_float(obj.vertices[i].z); | |
| } | |
| for (u32 i = 0, i < numIndices / 3, i = i + 1) { | |
| Primitive prim @ addressof(obj.prims[i]); | |
| model.indices[i * 3 + 0] = prim.v0; | |
| model.indices[i * 3 + 1] = prim.v1; | |
| model.indices[i * 3 + 2] = prim.v2; | |
| model.colors[4 * prim.v0 + 0] = float(prim.r) / 255.0; | |
| model.colors[4 * prim.v0 + 1] = float(prim.g) / 255.0; | |
| model.colors[4 * prim.v0 + 2] = float(prim.b) / 255.0; | |
| model.colors[4 * prim.v0 + 3] = 1.0; | |
| model.colors[4 * prim.v1 + 0] = float(prim.r) / 255.0; | |
| model.colors[4 * prim.v1 + 1] = float(prim.g) / 255.0; | |
| model.colors[4 * prim.v1 + 2] = float(prim.b) / 255.0; | |
| model.colors[4 * prim.v1 + 3] = 1.0; | |
| model.colors[4 * prim.v2 + 0] = float(prim.r) / 255.0; | |
| model.colors[4 * prim.v2 + 1] = float(prim.g) / 255.0; | |
| model.colors[4 * prim.v2 + 2] = float(prim.b) / 255.0; | |
| model.colors[4 * prim.v2 + 3] = 1.0; | |
| } | |
| };model.colors[4 * prim.v2 + 3] = 1.0; | |
| } | |
| }; v1i + 3] = 1.0; | |
| model.colors[4 * v2i + 0] = float(file.objects[0].prims[x].r)/ 255.0; | |
| model.colors[4 * v2i + 1]= float(file.objects[0].prims[x].g)/ 255.0; | |
| model.colors[4 * v2i + 2] = float(file.objects[0].prims[x].b)/ 255.0; | |
| model.colors[4 * v2i + 3] = 1.0; | |
| } | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment