MDX Format (Vertex Data)
The .mdx format is a companion file that always pairs tightly with a .mdl model. While the .mdl file handles the complex math, skeletal hierarchy, and animation logic, the .mdx file acts as bulk storage; holding the massive lists of raw 3D coordinates (vertices) that make up the physical shape of the model.
Architecturally, the swkotor.exe engine treats these two files as a single combined asset: the .mdl dictates where and how the model moves, and the .mdx provides the points to physically draw on the screen.
At a Glance
| Property | Value |
|---|---|
| Extension(s) | .mdx |
| Magic Signature | Raw binary stream (No explicit signature block) |
| Type | Interleaved Vertex Payload Array |
| Rust Reference | View rakata_formats::Mdx in Rustdocs |
Data Model Structure
Rakata safely consumes the unindexed byte sequences into a typed geometry definition mapped within rakata_formats::Mdx.
At the raw binary level, .mdx data is strictly an interleaved buffer. Variables (like positional 3D XYZ vectors, Texture Parameter UV planes, and light-calculating Normals) are sequentially woven directly across the byte stream.
Engine Audits & Decompilation
Deep Dive: For an exhaustive archive of the Ghidra decompilation notes detailing the exact byte-level layout of the binary MDL/MDX format and engine loading pipeline, refer to the MDL & MDX Deep Dive.
The following documents the engine’s exact load sequence and structure for .mdx interleaved data pipelines mapped from swkotor.exe.
(Decompilation logic for this section was entirely audited and verified via native Ghidra pipeline against swkotor.exe, explicitly pulling from InputBinary::Read (0x004a1230) and InputBinary::ResetMdlNode (0x004a0900).)
Loading and Lifecycle
| Pipeline Event | Ghidra Provenance & Engine Behavior |
|---|---|
| Memory Wrapping | Triggered immediately alongside the .mdl. The wrapper dynamically outlines the exact byte-count of .mdx data required (wrapper + 0x08). |
| Buffer Liberation | MDX arrays are entirely stateless. Once InputBinary::ResetMdlNode computes the geometry arrays and translates the buffer directly into the OpenGL hardware render-pools during loading, the engine immediately calls free() wiping the MDX byte arrays from physical memory entirely. |
TriMesh Structural Addressing
The KOTOR Engine avoids parsing the MDX data by scanning through it block-for-block. Instead, traversing the actual MDL hierarchy drives vertex payload requests explicitly.
| Mapped Property | Ghidra Provenance & Engine Behavior |
|---|---|
| Array Slicing | Every distinct TriMesh instantiated in the parent MDL tree explicitly registers an mdx_data_offset pointer (TriMesh + 0x144). This dictates exactly where the engine explicitly seeks within the interleaved .mdx payload array to fetch this mesh’s native points. |
| Node Alignment Constraints | Vanilla assets maintain extremely strict alignment formats. Meshes are dynamically sorted prior to hardware parsing: static rendering models fall to the top of the index chain, whereas dynamic procedural meshes (like character .Skin nodes) are specifically dumped sequentially to the rear of the .mdx. |
Note
Ghost Payload Sentinels During memory extraction, the engine implicitly pads geometric mesh payloads out to distinct 16-byte aligned boundaries using Terminator Rows. Any mesh vertex iteration falling slightly out of stride will be explicitly back-filled with ghost/sentinel float arrays (
[0.0, 0.0, 0.0]) to ensure OpenGL buffer calculations remain strictly uniform without overflowing pointer indexes during hardware streaming.
Proposed Linter Rules (Rakata-Lint)
Incorrectly calculated .mdx offset spans or payload array lengths can cause the engine to read misaligned bytes or overflow data bounds. Providing a linter rule to validate these payload alignments helps prevent geometry corruption and potential engine/gpu crashes.
While rakata-lint currently only evaluates GFF formats and does not yet parse .mdx buffers dynamically, the engine behaviors above hint at the foundational requirements for .mdx stability:
Planned Lint Diagnostics:
- Mesh Slice Verification: Enforces explicit iteration seeking. Validates
.mdxvector boundaries by explicitly jumping pointers down the file according to individualmdx_data_offsetassignments mapped on explicitly boundTriMeshheaders, rather than assuming unverified sequential payload lengths.