Find a 64-byte collision record stride in RAM, and record a savestate search pitfall

Searching the savestates for the collision grid dimensions as a u32 pair -- level
0's 11 x 33 and level 1's 24 x 16 -- puts level 1's at several RAM addresses and
level 0's nowhere. So the grid dimensions are not held in RAM as adjacent u32s,
and the collision payload is reshaped on load, as the shrub packet tables are.

A nearby region of level 1's RAM does show structure. At 0x12e048c and
0x12e04cc, 64 bytes apart:

  28 01 00 00 | 92 ff 00 00 | 04 00 a0 41 | ...
     296        -110        20.0f

Searching for that shared 12-byte tag finds a consecutive run at a 64-byte
stride in slot 2:

  0x12df390
  0x12df3d0   +0x40
  0x12df410   +0x40

plus scattered singles elsewhere. Slot 1 has the tag at four addresses not on a
64-byte stride, so the two levels lay it out differently.

What this is: a 64-byte record carrying two small signed values and a float
reading exactly 20.0 -- the shape of a per-cell entry with coordinates and a
radius or half-extent, which is what the collision grid would hold.

What this is not: it is not decoded. Three consecutive records is not enough to
establish a stride, the tag matches only a few records rather than a whole grid,
and 20.0 may be coincidence. Level 1's grid is 384 cells; nothing here has been
shown to count to 384.

Method note: savestates are compressed on disk, so a byte scan of the file finds
nothing. All RAM search must go through gc-trace find --state, which decompresses
first -- scanning the file directly reports zero hits for a sequence that
demonstrably exists in memory.
This commit is contained in:
2026-10-12 03:27:14 +02:00
parent d3e1475f64
commit bd012efe71
+38
View File
@@ -671,3 +671,41 @@ at load, so the disc parser can bound it and check its signature but cannot read
it as either RAM form. Decoding it means reversing the expansion, not
re-describing what the loader produced. That is a larger job than the framing
work so far, and it is the honest boundary of what is currently known.
## Collision: a 64-byte record stride in RAM
Searching the savestates for the collision grid dimensions as a `u32` pair --
level 0's `11 x 33` and level 1's `24 x 16` -- puts level 1's at several RAM
addresses and level 0's nowhere. So the grid dimensions are **not held in RAM as
adjacent `u32`s**, and the collision payload is reshaped on load, as the shrub
packet tables are.
A nearby region of level 1's RAM does show structure worth recording. At
`0x12e048c` and `0x12e04cc`, 64 bytes apart:
28 01 00 00 | 92 ff 00 00 | 04 00 a0 41 | ...
296 -110 20.0f
Searching for that shared 12-byte tag finds a **consecutive run at a 64-byte
stride** in slot 2:
0x12df390
0x12df3d0 +0x40
0x12df410 +0x40
plus scattered singles elsewhere. Slot 1 has the tag at four addresses that are
*not* on a 64-byte stride, so the two levels lay it out differently.
**What this is.** A 64-byte record carrying two small signed values and a float
that reads exactly 20.0. That is the shape of a per-cell entry with coordinates
and a radius or half-extent, which is what the collision grid would hold.
**What this is not.** It is not decoded. Three consecutive records is not enough
to establish a stride, the tag matches only a few records rather than a whole
grid, and `20.0` may be coincidence. Level 1's grid is 384 cells; nothing here
has been shown to count to 384.
**Method note.** Savestates are compressed on disk, so a byte scan of the file
finds nothing. All RAM search must go through `gc-trace find --state`, which
decompresses first -- scanning the file directly reports zero hits for a
sequence that demonstrably exists in memory.