diff --git a/docs/re/structures/mcol-collision.md b/docs/re/structures/mcol-collision.md index e9102f0..0f2f909 100644 --- a/docs/re/structures/mcol-collision.md +++ b/docs/re/structures/mcol-collision.md @@ -47,13 +47,44 @@ tables. six section pointers at `0x70`; `MCOL` has a large value, two mid-range values and `112` at `0x50`, mostly zeros at `0x60`, and `0x05050501` at `0x70`). The headers agree on the spatial prefix and diverge after it. -* **My `POF0` delta decoder is wrong here** — it emits eight leading zero deltas - before plausible offsets, so either the stream has a preamble I am not - skipping or my 6/14/22-bit reading is off. The working decoder is - `tools/re-capture/regn_decode.py` on branch `auto/regn-reader`; **use that - rather than re-deriving it**, which is the mistake I made here. +* **Everything past `0x40`** — but see below; the pointer layout is now known. -**First step for whoever continues**: run the known-good `POF0` reader over an -`MCOL`, list which words are relocated, and read the header slots those pointers -occupy. That is exactly the move that turned `REGN` from twenty failed -correlations into a decode. + +## ✅ The pointer layout, from `POF0` + +**2026-08-26.** Running the known-good decoder (`regn_decode.py` on +`auto/regn-reader`) rather than my own broken one. Sanity check first: on `REGN` +it returns header slots `0x70`–`0x84` exactly — the six section pointers — so the +tool and my use of it are right. + +On `MCOL`, over all **11** objects: + +| | | +|---|---| +| header-region relocated slots are **exactly `0x54`, `0x58`, `0x5C`, `0x74`** | **11 / 11** | +| slot `0x5C` resolves to **`0x80`** — the first byte after the header | **11 / 11** | +| slot `0x74` resolves to **(first array pointer − 8)** | **10 / 11** | + +So `MCOL` has **four** top-level pointers where `REGN` has six, and one of them +(`0x5C`) always addresses the data immediately following the header. + +**The bulk of the relocations form record arrays.** 92.7 % of the gaps between +consecutive relocated words are **32 bytes**, arranged in 7–127 contiguous runs +per object. Combined with `0x74` landing 8 bytes before the first of them, the +reading is an array of **32-byte records each carrying one pointer at `+8`**. + +What the four targets look like: + + 0x5C -> 0x80 c685620b 4596789d 4694b3b5 44a9a634 floats + 0x54 -> … c6826964 456b1aa4 469ab065 c685cfe8 floats + 0x58 -> … 00000001 00020003 00040005 00050004 small ints / u16 pairs + 0x74 -> … 00000001 00000001 00007710 00000000 counts, then the array + +Two float blocks, an index block and a record array is the shape of a mesh — +which is what a name like `MCOL` beside a navigation mesh would suggest. 🟡 That +is a reading of the shape; none of the four blocks has been decoded. + +❔ Still open: the record layout, what the index block indexes, the **one object +in eleven** where `0x74` does not land 8 before the array, and the 7.3 % of gaps +that are not 32 (they are the boundaries between runs, but that has not been +checked). \ No newline at end of file