MDB Format - KCreator/Earth-Defence-Force-Documentation GitHub Wiki
All offsets are relative to the beginning of their table entries.
Since the header is always at the beginning of the file, the offsets there are also absolute file offsets.
File format largely derived from EDF5, and EDF6. EDF4.1 might have unknown differences.
Header: 48 (0x30) bytes
| Offset | Size | Type | Description |
|---|---|---|---|
| 0x00 | 4 | char[4] | Magic, always MDB0 |
| 0x04 | 4 | uint32 | Version: 0x14 for EDF4.1/EDF5, 0x20 for EDF6 |
| 0x08 | 4 | uint32 | Name table count |
| 0x0C | 4 | uint32 | Name table offset (always 0x30) |
| 0x10 | 4 | uint32 | Bone count |
| 0x14 | 4 | uint32 | Bone table offset |
| 0x18 | 4 | uint32 | Object count |
| 0x1C | 4 | uint32 | Object table offset |
| 0x20 | 4 | uint32 | Material count |
| 0x24 | 4 | uint32 | Material table offset |
| 0x28 | 4 | uint32 | Texture count |
| 0x2C | 4 | uint32 | Texture table offset |
Name table: 4 (0x04) bytes
| Offset | Size | Type | Description |
|---|---|---|---|
| 0x00 | 4 | uint32 | UTF-16 string offset |
Bone table: 192 (0xC0) bytes
| Offset | Size | Type | Description |
|---|---|---|---|
| 0x00 | 4 | int32 | Bone index |
| 0x04 | 4 | int32 | Parent bone index (-1 for no parent) |
| 0x08 | 4 | int32 | Next sibling bone index (-1 for none) |
| 0x0C | 4 | int32 | First child bone index (-1 for none) |
| 0x10 | 4 | int32 | Bone name (name-table index) |
| 0x14 | 4 | int32 | Child bone count |
| 0x18 | 1 | uint8 | Unused bone participation metadata (exact original meaning unverified). |
| 0x19 | 1 | int8 | Unused Signed bone semantic/role metadata; no reader of the copied role integer has been found |
| 0x1A | 1 | uint8 (Boolean encoding) | Loader stores (raw value == 1), so only literal 1 becomes true. True when Bound box values are present, but not a confirmed relation found. |
| 0x1B | 5 | uint8[5] | Zero padding/alignment |
| 0x20 | 64 (0x40) | float32[16] | Local transformation matrix (4x4): position, rotation and scale in parent-bone space |
| 0x60 | 64 (0x40) | float32[16] | Inverse bind-pose matrix used for GPU skinning |
| 0xA0 | 16 (0x10) | float32[4] | Mesh bounding-box size; W is normally 1 |
| 0xB0 | 16 (0x10) | float32[4] | Mesh bounding-box offset; W is normally 1 |
Matrices are Y-up for the default world orientation.
The bounding box is a child of this bone and inherits its rotation and position. The offset + size interpretation has been independently validated in Blender: it exactly encloses the visible mesh of tested humanoid models. Bounds on ordinary models appear to be determined by vertices weight-painted to the bone. Some UI elements have bounding boxes without weight paint; a current hypothesis is that a mesh sharing the bone's name supplies the bounds in that case.
The loader retains 0x18 in the resource-bone record, but normal animation/render-bone construction does not copy it. It is copied only while allocating/resizing the resource-bone array, no comparison has been found, and controlled edits had no in-game effect. It should currently be treated as unused, legacy or authoring metadata rather than a runtime rendering flag. Observed: 3 throughout the ordinary deform/mesh-weighted hierarchy, 2 throughout a separate hierarchy rooted at A_under_geo, and 0 on nonessential/control/helper nodes. Controlled in-game edits produced no visible or functional change. The field is retained in the resource record but is not copied into standard animation-bone records, and no runtime consumer has been found.
0x19 is sign-extended and copied into every animation-bone record, but preservation alone does not prove consumption. High-level enemy, human, aim and weapon initialization resolves important bones through hashed name lookups using names supplied by configuration data. Identifiable IK setup uses CAS values such as v_weapon_grip_ik_target and configured lists such as ik_control_info; those paths do not select bones through 0x19. The executable also contains Havok Behavior foot-IK support, so an optional consumer cannot be completely excluded, but the signed left/right foot and helper patterns may simply be skeleton-semantic metadata generated for the animation toolchain. MOVSX during animation-bone construction proves that file values 250..255 become runtime values -6..-1. Observed examples: 0 on ordinary/sub-deform bones, 1 on aim_center, 4 on its child aim_target, -1 (file 255) on palm/weapon/IK-like helpers, and -5/-4 (file 251/252) on the right/left floor-contact feet. Editing hand and foot values produced no visible effect on the tested enemy.
0x1A Observed true on ordinary deform bones and the A_under_geo hierarchy; false on root, aim, and palm/helper nodes. The normalized flag is copied into animation-bone; its consumer and meaning have not yet been identified. Bounding float4s are copied independently.
Texture table: 16 (0x10) bytes
| Offset | Size | Type | Description |
|---|---|---|---|
| 0x00 | 4 | int32 | Texture index |
| 0x04 | 4 | uint32 | Texture name (UTF-16 string offset) |
| 0x08 | 4 | uint32 | Texture filename (UTF-16 string offset) |
| 0x0C | 4 | uint32 | Reserved, always zero |
Material table: 32 (0x20) bytes
| Offset | Size | Type | Description |
|---|---|---|---|
| 0x00 | 2 | uint16 | Material index |
| 0x02 | 1 | uint8 | Render priority (usually 0, often higher on transparent objects); exact ordering semantics unverified |
| 0x03 | 1 | uint8 | Render layer (normally 0; observed as 1 on loading-screen/tank_catapi assets and 2 on transparent/UI materials); exact semantics unverified |
| 0x04 | 4 | int32 | Material name (name-table index) |
| 0x08 | 4 | uint32 | Shader name (UTF-16 string offset) |
| 0x0C | 4 | uint32 | Material-parameter table offset |
| 0x10 | 4 | uint32 | Material-parameter count |
| 0x14 | 4 | uint32 | Material-texture/sampler table offset |
| 0x18 | 4 | uint32 | Material-texture/sampler count |
| 0x1C | 1 | uint8 | Engine render-participation flags. Bit 0 enables it as a shadow caster when true. Normally 3; value 2 is observed on UI and barrier (transparent) materials. Other bits have no confirmed readers |
| 0x1D | 3 | uint8[3] | Ignored/padding. |
Material Parameters: 32 (0x20) bytes
| Offset | Size | Type | Description |
|---|---|---|---|
| 0x00 | 4 | float32 | Value 1 / X |
| 0x04 | 4 | float32 | Value 2 / Y |
| 0x08 | 4 | float32 | Value 3 / Z |
| 0x0C | 4 | float32 | Value 4 / W |
| 0x10 | 4 | float32 | Value 5; not used by the known parameter types |
| 0x14 | 4 | float32 | Value 6; not used by the known parameter types |
| 0x18 | 4 | uint32 | Parameter name (ASCII string offset) |
| 0x1C | 1 | uint8 | Type: 0=Float, 1=Vector2, 2=RGB, 3=RGBA |
| 0x1D | 1 | uint8 | Component/value count |
| 0x1E | 2 | uint16 | Zero padding |
Some value slots can contain nonzero data even when the parameter type/component count does not use them.
Material Textures: 28 (0x1C) bytes
| Offset | Size | Type | Description |
|---|---|---|---|
| 0x00 | 4 | int32 | Texture-table index |
| 0x04 | 4 | uint32 | Shader texture-slot/type name (ASCII string offset) |
| 0x08 | 2 | uint16 | Sampler override flags; see bit assignments below |
| 0x0A | 2 | int16 | Filter selector used when flag 0x0001 is set |
| 0x0C | 1 | uint8 | Texture address mode U used when flag 0x0002 is set |
| 0x0D | 1 | uint8 | Texture address mode V used when flag 0x0002 is set |
| 0x0E | 1 | uint8 | Texture address mode W used when flag 0x0020 is set |
| 0x0F | 1 | int8 | Maximum anisotropy used when flag 0x0010 is set |
| 0x10 | 4 | float32 | Minimum LOD used when flag 0x0008 is set |
| 0x14 | 4 | float32 | Maximum LOD used when flag 0x0008 is set |
| 0x18 | 4 | float32 | Mipmap LOD bias used when flag 0x0004 is set |
Sampler override flag assignments:
| Flag | Overridden field(s) |
|---|---|
0x0001 |
Filter |
0x0002 |
Address U and V |
0x0004 |
Mipmap LOD bias |
0x0008 |
Minimum and maximum LOD |
0x0010 |
Maximum anisotropy |
0x0020 |
Address W |
These sampler meanings are confirmed end-to-end. The loader expands the compact values into the exact 52-byte D3D11_SAMPLER_DESC layout and passes it to ID3D11Device::CreateSamplerState.
Object table: 16 (0x10) bytes
| Offset | Size | Type | Description |
|---|---|---|---|
| 0x00 | 4 | int32 | Object index |
| 0x04 | 4 | int32 | Name (name-table index) |
| 0x08 | 4 | uint32 | Mesh count |
| 0x0C | 4 | uint32 | Mesh-info table offset |
Mesh info: 40 (0x28) bytes
| Offset | Size | Type | Description |
|---|---|---|---|
| 0x00 | 1 | uint8 | Topology selector: loader maps 0 to runtime value 4 and nonzero to 5. These match D3D11 triangle-list and triangle-strip enum values |
| 0x01 | 1 | uint8 | Is skinned mesh (value == 1) |
| 0x02 | 1 | int8 | Number of bone influences per vertex, normally 0-4. The runtime sign-extends this field |
| 0x03 | 1 | uint8 | Reserved/alignment, normally zero |
| 0x04 | 4 | int32 | Material index (-1 for none) |
| 0x08 | 4 | uint32 | Unknown/reserved, normally zero |
| 0x0C | 4 | uint32 | Vertex-layout table offset |
| 0x10 | 2 | uint16 | Vertex stride: total byte size of one vertex record |
| 0x12 | 2 | uint16 | Vertex-layout element count |
| 0x14 | 4 | uint32 | Vertex count |
| 0x18 | 4 | int32 | Mesh index |
| 0x1C | 4 | uint32 | Vertex-data offset |
| 0x20 | 4 | uint32 | Index count |
| 0x24 | 4 | uint32 | Index-data offset |
Vertex layout info: 16 (0x10) bytes
| Offset | Size | Type | Description |
|---|---|---|---|
| 0x00 | 4 | uint32 | Vertex storage type |
| 0x04 | 4 | uint32 | Byte offset within one vertex record |
| 0x08 | 4 | uint32 | Semantic channel/index, for example texcoord0 versus texcoord1 |
| 0x0C | 4 | uint32 | Semantic name (ASCII string offset) |
Vertex types:
| Type | Data type | Size |
|---|---|---|
| 1 | float32[4] | 16 bytes |
| 4 | float32[3] | 12 bytes |
| 7 | float16[4] | 8 bytes |
| 12 | float32[2] | 8 bytes |
| 21 | uint8[4] | 4 bytes |
Index data: 2 bytes per index
| Offset | Size | Type | Description |
|---|---|---|---|
| 0x00 | 2 | uint16 | Unsigned vertex index |
Vertex data: Variable length
| Offset | Size | Type | Description |
|---|---|---|---|
| 0x00 | Vertex count x vertex stride | byte[] | Interleaved vertex records. Element formats and offsets are described by the mesh's vertex-layout entries |
Strings: Variable length
| Offset | Size | Type | Description |
|---|---|---|---|
| 0x00 | Variable | char[] / UTF-16LE[] | Null-terminated ASCII and UTF-16LE strings referenced by the tables above |