Decode the overlay's load base, from its own profiler table

Range measured: all 27 levels' overlays.

The overlay carries the game's profiler menu definition -- a run of 8-byte
padded names (normal, camera, cam+chr, volume, bars, render, mobys, ties,
shrubs, cpu/gpu, occl, ...) followed by runs of absolute RAM addresses that
point back at those same names. On every level the four addresses after
normal/camera/cam+chr/volume, each minus its target name's overlay offset, give
the same number: 1,735,792.

That is field_00 - 16, where field_00 is the header word that read 1,735,808 on
all 27 levels with nothing attached to it. The overlay is loaded with its
16-byte header stripped, so overlay offset X sits at RAM X + 1,735,792.
OverlayHeader::ram_address carries it, and the disc test asserts the derivation
holds on all 27 levels.

Confirmed, not only derived: level 0's RAM 0x1acf80 holds
"normal\0camera\0cam+chr\0volume\0", byte-identical to overlay 0x5310, and
0x5310 + 1735792 == 0x1acf80. All four names land where the overlay's own table
says. `gc-trace verify-overlay-base` runs that check, savestate-gated the same
way as the tie and tfrag ones.

The overlay is relocated, not copied: only 37.67% of level 0's is
byte-identical at the base, and the 256-entry sine table -- at overlay 0xb650c
-- is not at 0xb650c + base. So the base locates the overlay's image, but
individual tables inside it move. That is the shape of a loader applying
relocations, and it means the base is necessary but not sufficient for reading
the game's tables.

The value of the base is that any overlay offset can now be carried to a RAM
address, which is the prerequisite for reading the game's live level state --
the thing the tie relocation and tfrag lighting checks had to work around.

Two things get deleted rather than finished. The collision u16 table was probed
four ways -- magnitude distribution, level-independence, run starts, run
lengths -- and every one came back level-dependent: the run-start pattern is
identical on 1 of 19 levels. So the first 1024 bytes of the collision payload
are data, not a fixed table, and nothing was decoded. Recorded as the negative
it is rather than left as four half-findings.
This commit is contained in:
2026-10-13 13:22:50 +02:00
parent 55ea619b4c
commit 4abce518e5
7 changed files with 381 additions and 1 deletions
+37
View File
@@ -2322,6 +2322,43 @@ What would settle it, and none of these are cheap:
whose name is a volume trigger, that would be decisive. No class name
containing "volume" exists on the disc, which is why this is not available.
## The overlay's load base, from its own profiler table (2026-10-11)
**Range measured:** all 27 levels' overlays.
**Method:** the overlay carries the game's **profiler menu definition** -- a run
of 8-byte-padded names (`normal`, `camera`, `cam+chr`, `volume`, `bars`,
`render`, `mobys`, `ties`, `shrubs`, `cpu/gpu`, `occl`, ...) followed by runs of
absolute RAM addresses that point **back at those same names**. On every level
the four addresses after `normal`/`camera`/`cam+chr`/`volume`, each minus its
target name's overlay offset, give the same number: **1,735,792**.
That number is `field_00 - 16`, where `field_00` is the header word that
previously read 1,735,808 on all 27 levels with no meaning attached. So the
overlay is loaded with its 16-byte header stripped: overlay offset `X` sits at
RAM `X + 1,735,792`. `OverlayHeader::ram_address` carries it.
**Confirmed, not only derived.** The same bases were checked in PCSX2's RAM:
level 0's `0x1acf80` holds `"normal\0camera\0cam+chr\0volume\0"`, byte-identical
to overlay `0x5310`, and `0x5310 + 1735792 == 0x1acf80`. All four names land
where the overlay's own table says. `gc-trace verify-overlay-base` runs the
check.
**The overlay is relocated, not copied.** Only **37.67%** of level 0's overlay
is byte-identical at the predicted base, and the 256-entry sine table -- at
overlay `0xb650c` -- is *not* at `0xb650c + base`. So the base locates the
overlay's image, but individual tables inside it move. That is the shape of a
loader applying relocations, and it means the base is necessary but not
sufficient for reading the game's tables.
The value of the base is that any overlay offset can now be carried to a RAM
address, which is the prerequisite for reading the game's live level state --
the thing the tie relocation and the tfrag lighting checks had to work around.
Note the profiler table's own vocabulary, since it is the first named structure
in the overlay: `volume` is one of the game's profiling categories, so volumes
are a real subsystem. It does not locate the data.
## Chunk records: what the stride table settles, and one signature it does not
Walked every chunk on all 27 levels and grouped by its six-byte header signature: