At a glance

What it is
A negative finding: the RAM window 0x80108EA4..0x80109550 is a renderer scratch buffer, not a navmesh table
Where the real pathing data is
The per-scene walkability grid (field locomotion), the MAN region boxes, and the tile-board grid for the puzzle mode - table below
Parser
none (nothing to parse); reproduction via mednafen-state extract + scripts/mednafen/pointer-hunt.py
Confidence
Inferred - zero pointers into the window across three save states; the contents match GP0 packet shapes

Falsified readings across the whole project are collected on do-not-re-walk; this page keeps the full reasoning for the one that looked most like real data.

The decisive test: nothing points at it

A real navmesh table would be consulted through a stable base-pointer cell somewhere in RAM. A pointer-hunt over the full 2 MiB of main RAM, for any u32 pointing into the window, returns zero hits in all three save states (mc1 field, mc2 battle, mc3 field). No overlay slot, SCUS data segment, kernel stack or runtime heap holds the table base. The buffer is consumed by code that knows its address as a compiled-in constant (a MIPS LUI+ADDIU immediate pair inside the renderer), not via indirection.

rest of main RAM (2 MiB scanned) adjacent structures sprite-batcher data "navmesh" window 0x80108EA4..0x80109550 6 pointers 0 pointers renderer code LUI+ADDIU constant
Only compiled-in constants reach the window; the six real pointers target its neighbours.

What the bytes actually are

Three shapes appear across the captures, none matching a record table:

  • Repeating constant runs. In the map01 field state, the window holds a uniform u16 sequence (0c 00 repeated, then 0d 00, then 0e 00) with no record structure.
  • GPU-packet shapes. In the other two states, 12-byte runs mirror the GP0 packet header + RGB-colour + delta-position layout the PSX renderer emits (GP0 packets are the raw draw commands sent to the PlayStation GPU): the canonical TMD primitive flag/mode/code/ilen quartet, RGB colour triplets, and signed byte deltas at the i16 positions.
  • Overwritten wholesale. All three states show different shapes at the same offset. Stable per-scene records would persist; a working buffer is refilled on scene entry.

Where the pathing data really lives

SystemDataDetails
Town / field locomotion + collisionPer-scene walkability tile grid: one byte per 128-unit tile, 4 sub-cell wall bits, reached through a scratchpad base pointerField locomotion
Puzzle / board minigameTile-board grid (cell 2 = wall), installed inline by field-VM op 0x49Field/event VM
Per-scene region / zone boxes18-byte records in the MAN control block, queried by player tile; the payload is a camera preset, not pathing dataCamera-region table
Encounter armingRecord pointer in the actor slot +0x94Encounter record, world map

How we know

EvidenceInstrumentWhat it shows
Zero inbound pointerspointer-hunt.py into-window over three save statesNo RAM cell holds the window's base - a table nobody indexes is not a table.
Six adjacent pointersSame hunt widened to 0x80108000..0x8010A000Pointers target neighbouring offsets (0x80108398, 0x80108BC8, 0x80108C2C, 0x80108C38) - the sprite-batcher's own structures, not the scratch region.
Byte shapesmednafen-state extract RAM dumpsContents match GP0 draw-packet layout, and differ wholesale across scenes.
Reproducing the negative finding
./target/release/mednafen-state extract <mc1.mc1> --start 0x80000000 --end 0x80200000 --out /tmp/ram_mc1.bin
./target/release/mednafen-state extract <mc3.mc3> --start 0x80000000 --end 0x80200000 --out /tmp/ram_mc3.bin

python3 scripts/mednafen/pointer-hunt.py into-window /tmp/ram_mc1.bin \
    --target-lo 0x80108EA4 --target-hi 0x80109550 --exclude-self
python3 scripts/mednafen/pointer-hunt.py into-window /tmp/ram_mc3.bin \
    --target-lo 0x80108EA4 --target-hi 0x80109550 --exclude-self

Both invocations return zero hits. The narrow bounds match the original navmesh reading; widen to 0x80108000..0x8010A000 to surface the adjacent sprite-batcher pointers.

History: how the navmesh reading arose

The cluster was spotted by diffing two area-load save states: 1700 bytes differed, which is how scene-resident data shows up - but also how any working buffer repopulated on scene entry shows up. A leading id / kind record interpretation fit one state's bytes and broke on the other two. Structural inference from a single diff pair is the trap; the pointer hunt is the test that settles it.

See also