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