Add gc-extract probe to dump structures through the real parser

Reading these formats by unpacking raw offsets out of core_index.bin has
cost real time. The index interleaves single-word region offsets with
count/offset pairs, so miscounting one shifts every field after it: that
produced a page of implausible collision headers on all 27 levels, sent
me chasing a tie-breakoff that turned out not to exist, and nearly had me
"fix" a stride bug in code that was already right.

probe dumps a level's core header and all three class tables through
LevelCoreHeader, so a field name printed is the field name the parser
uses. It also reports how many entries carry geometry inside core_data,
which is what pins the class table strides rather than guessing at them:
shrub reads 7/7 sane at 0x30 against 4/7 read at 0x20.

Reading a structure by hand in a shell still works; this just stops it
being the default, and stops the offset arithmetic being re-derived every
time a new region is investigated.
This commit is contained in:
2026-10-11 02:36:37 +02:00
parent c4ba84232a
commit f6bbbf8d5f
4 changed files with 270 additions and 0 deletions
+9
View File
@@ -870,6 +870,15 @@ plausible floats varies from 1 to 6 across spans, with 822 spans having 6,
455 having 1 and 373 having 2. So there is more header past `0x48`, and it
is not a single array of distances.
### Probe tool
`gc-extract probe <unpacked-dir> <level> [max-rows]` dumps the core header and
all three class tables through `LevelCoreHeader`, which is the point. The
table above and the shrub offset below were both established by hand first and
one of them nearly sent me to fix a bug that was not there. The tool also
reports how many entries carry geometry inside `core_data`, which is how the
shrub stride was pinned: 7/7 at 0x30 against 4/7 read at 0x20.
Note the LOD distances already decoded sit *before* this point (12.0, 25.0,
40.0 at `+0x10`), and the floats after `0x48` are a different population --
negative values, and a repeated leading 40.0.