Files
Going-Commando/docs/formats/core-data-regions.md
T
ReaperOfVeriod cb38b8c279 Compute core_data region bounds once, from successor boundaries
Region spans were being re-derived per format while probing, usually
running from one known offset to the next with the last span running to
core_data.len(). On level 0 that gave the final shrub class a 925,008-byte
span absorbing most of the lump's tail, and every aggregate computed over
it -- record counts, value distributions, "this looks random" -- was
silently wrong. Nothing errored, which is what made it survive two
commits and a correction.

core_layout computes the layout once: each region ends where the next one
begins, class regions start at the lowest non-zero geometry offset in their
table, and a region whose successor is unknown gets end: None rather than a
clamped guess. Zero class entries mean absent, not position zero -- the
same trap occlusion and collision each fell into separately.

The disc test asserts what the module is actually for: that the unknown is
visible. Shrub's end is unresolved on the 24 levels that have a shrub
region, and that is asserted rather than hidden.

It also found that not every level has every region -- level 10 has neither
occlusion nor shrub -- so the test checks ordering against the canonical
sequence instead of demanding an identical set.

Still open: where the shrub region ends. Texture texels cannot bound it;
they sit before moby, not after shrub. See docs/formats/core-data-regions.md.
2026-10-11 03:02:02 +02:00

51 lines
2.1 KiB
Markdown

# core_data region bounds
How a level's `core_data` lump divides up, and how each region is bounded.
## The rule
A region's end is the **next region's start**, never `core_data.len()`. The
last region in a layout is the exception, and when its successor is unknown the
end is `None` rather than a guess.
This exists because region bounds were being re-derived per format during
probing, usually by running from one known offset to the next with the last
span running to the end of the lump. On level 0 that made the final shrub class
a 925,008-byte span absorbing most of the lump's tail. Every aggregate computed
over it -- record counts, value distributions, "this data looks random" -- was
silently wrong, and nothing errored.
`gc_formats::regions::core_layout` computes these once. Callers use it rather
than inventing their own.
## Layout
| region | start | end |
|------------|----------------|----------------------|
| `tfrags` | 0 | `occlusion` |
| `occlusion`| `occlusion` | `sky` |
| `sky` | `sky` | `collision` |
| `collision`| `collision` | first moby class |
| `moby` | first moby | first tie class |
| `tie` | first tie | first shrub class |
| `shrub` | first shrub | **unknown** |
Class regions start at the lowest non-zero geometry offset in their class
table. A zero entry means *absent*, not position zero -- the same trap the
occlusion and collision headers each fell into separately.
Not every level has every region: level 10 has no occlusion and no shrub.
## Open: where shrub ends
The offset ending the shrub region is not in the core index.
Texture texels do **not** bound it. They sit before moby, not after shrub: on
level 0 the texel range is 3539328..5326208 while the last shrub class starts
at 16044288, leaving ~925 KB of real, non-zero data after the last shrub class
that nothing yet accounts for.
`core_layout` reports `end: None` for shrub on the 24 levels that have one, and
the disc test asserts it, so the gap stays visible rather than being papered
over by clamping to the end of the lump.