Cidb
CIDB is the collision-data container embedded in many Link's Awakening room-model BFRES files. It stores one or more triangle meshes, each with raw per-triangle surface IDs and a serialized PhysX R-tree used for broad-phase collision queries.
This page documents the current state of reverse engineering, not an official specification. Fields are labelled **verified** only where they have been decoded from the retail RomFS and exercised by round-trip checks.
Location in BFRES
CIDB is embedded rather than stored as a separate regular ROMFS file.
1. Open a room model in "region_common/map".
2. Search for the ASCII magic CIDB (43 49 44 42).
3. The lossless container ends at the BFRES relocation-table offset stored in the BFRES header at `0x18`. The CIDB magic must occur before that relocation table.
Conventions
Unless a table says otherwise, integer and float fields are little-endian.
| Type | Meaning |
|---|---|
u8, u16, u32
|
unsigned integer, little-endian |
| be_u32 | unsigned 32-bit integer, big-endian |
| f32 | IEEE-754 single-precision float, little-endian |
| be_f32 | IEEE-754 single-precision float, big-endian |
Raw CIDB vertices use `(X, Y, Z)`. `X` and `Z` form the floor plane; `Y` is the vertical/gravity axis.
CIDB container
All decoded map containers start with this little-endian header.
| Offset | Type | Description |
|---|---|---|
0x00
|
char[4]
|
Magic: CIDB
|
0x04
|
u32
|
Header size. Observed value: 0x10.
|
0x08
|
u32
|
Unknown. Observed as 0 in the sampled map files.
|
0x0C
|
u32
|
Section count. Observed as 5.
|
0x10
|
u32[section_count]
|
Offsets of CIDB sections, relative to the CIDB start. |
The exact meaning of every container section has not been established. The safe way to find collision is to search the CIDB payload for NXS\x01MESH, not to assume a particular section number.
NXS/MESH collision record
Every decoded collision mesh starts with the eight-byte magic 4E 58 53 01 4D 45 53 48 (NXS\x01MESH). The mesh's variable data immediately follows this 28-byte header.
Outer descriptor and contact-code table
In the retail CIDBs examined so far, an NXS\x01MESH record is immediately preceded by a 0x2C-byte outer descriptor. This is not merely alignment data:
| Descriptor-relative offset | Type | Established meaning |
|---|---|---|
+0x04
|
u32
|
NXS/MESH payload length, beginning at the following NXS magic.
|
+0x08
|
u32
|
Byte length of the following material/contact-code table; divisible by four. |
+0x10
|
u32
|
Still not fully named; observed values include 0xFFFFFF01 and 0xFFFFFF02.
|
The contact-code table begins at nxs_offset + descriptor[+0x04] and consists of descriptor[+0x08] / 4 little-endian u32 values. The table is followed by padding until the next CIDB descriptor. It is part of the CIDB, not BFRES render-material metadata or a value invented by the executable at load time.
For example, TownWell mesh 1 serializes the four words 0x00000029, 0x00000017, 0x0000004B, 0x0008000B directly after its NXS payload. Its material-table-index 1 resolves to 0x17, the observed shallow water contact code. The high bits are meaningful state bits in at least some entries, so tools must preserve every full u32 unchanged.
| Offset | Type | Description |
|---|---|---|
0x00
|
char[8]
|
Magic: NXS\x01MESH
|
0x08
|
u32
|
PhysX mesh serialization version. Observed value: 0x0E.
|
0x0C
|
u32
|
PhysX midphase ID. Observed value: 0, consistent with the following RTRE R-tree midphase.
|
0x10
|
u32
|
PhysX serialization flags. 0x07 = material-index array + face-remap array + u8 indices; 0x0B = material-index array + face-remap array + u16 indices.
|
0x14
|
u32
|
Vertex count (V).
|
0x18
|
u32
|
Triangle count (T).
|
0x1C
|
f32[3 × V]
|
Vertex positions in raw (X, Y, Z) order.
|
Triangle index width
The retail map archive has two observed index forms:
| Condition observed | Triangle index type | Bytes per triangle |
|---|---|---|
V <= 255
|
u8[3]
|
3 |
V > 255
|
u16[3]
|
6 |
Triangle indices follow the vertex array and are ordered [a, b, c]. The reader verifies that all indices are below V. Collision is one-sided; a custom floor must have its normal facing raw +Y, and a wall's normal must face the playable volume.
Per-triangle material-table indices
The triangle-index array is followed by exactly T little-endian u16 values. Entry i belongs to triangle i.
surface_ids_offset = 0x1C + (V * 12) + (T * 3 * index_width)
surface_id[i] = u16(surface_ids_offset + i * 2)
These values are PhysX PxMaterialTableIndex entries: per-triangle indices into the CIDB mesh's immediately following u32 contact-code table. They are not BFRES render-material names and are not, by themselves, a global gameplay material enum. A complete scan of the retail map archive found values 0 through 10.
This is why the same raw value can legitimately result in different footsteps in two rooms: the mesh stores an index, while each CIDB mesh serializes its own contact-code table. The runtime resolves a hit's triangle material index through that per-mesh table.
The field order and flags match the public PhysX 3.4 triangle-mesh serializer, which writes mMaterialIndices as a u16 array, and its shape material resolver, which obtains the hit triangle's material index then resolves it through the shape material array.
Material name table (48 entries, index = low6). Built by a static initialiser at 0xE5099C into a bss table at 0x1CC1C40 (40-byte entries), so it does not exist as a literal in the file. Index: name.
| Idx | Name | Idx | Name | Idx | Name | Idx | Name |
|---|---|---|---|---|---|---|---|
| 0 | GRASS | 12 | MARBLE | 24 | SWAMP | 36 | SAND |
| 1 | GRASS | 13 | MARBLE | 25 | MARBLE | 37 | SAND |
| 2 | TURF | 14 | STONE | 26 | CARPET | 38 | DIRT |
| 3 | GRASS | 15 | MUD | 27 | WOOD2CR | 39 | DIRT |
| 4 | GRASS | 16 | MARBLE | 28 | CARPET | 40 | GRASS |
| 5 | SAND | 17 | STONE | 29 | STONE | 41 | DIRT |
| 6 | GRAVEL | 18 | STONE | 30 | STONE | 42 | DIRT |
| 7 | DIRT | 19 | CARPET | 31 | MUD | 43 | DIRT |
| 8 | DIRT | 20 | MARBLE | 32 | DIRT | 44 | SAND |
| 9 | WOOD | 21 | WATER | 33 | CARPET | 45 | DIRT |
| 10 | WOOD3HO | 22 | SWAMP | 34 | STONE | 46 | DIRT |
| 11 | STONE | 23 | WATER | 35 | CARPET | 47 | WATER |