<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://zeldamods.org/w_la/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Adoky</id>
	<title>ZeldaMods (Link&#039;s Awakening) - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://zeldamods.org/w_la/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Adoky"/>
	<link rel="alternate" type="text/html" href="https://zeldamods.org/las/Special:Contributions/Adoky"/>
	<updated>2026-10-09T01:10:59Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.9</generator>
	<entry>
		<id>https://zeldamods.org/w_la/index.php?title=Cidb&amp;diff=732</id>
		<title>Cidb</title>
		<link rel="alternate" type="text/html" href="https://zeldamods.org/w_la/index.php?title=Cidb&amp;diff=732"/>
		<updated>2026-10-04T16:16:30Z</updated>

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