The first live run aligned on the game's periodic Getstat poll -- every
30 frames, identical everywhere -- and reported a fork between native
mid-scene and the oracle still at boot (its tail showed lbas 304, 2864,
12422: boot loads; the scene had not been played there yet).
Anchor on Setlocs into the palette file's LBA range instead, compare the
two LBA request sequences positionally, and print each side's full
command window around the file with the first diverged request marked.
A side with no palette-file Setlocs in its history is told to play the
scene there rather than diffed against unrelated traffic.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The complete slot map exhausted single-emulator analysis: the tail load
is several interleaved streams (header-included and content DMAs to
scattered destinations, plus a final 113..117 chunk), and reconstructing
the game's bookkeeping from one side means simulating game internals --
exactly the guessing that has been wrong repeatedly here.
So measure the divergence itself. The oracle patch gains a CD command
history mirroring psx-runtime's (RecordCdCommand hooked at DuckStation's
CDROM::ExecuteCommand before handlers consume the param FIFO; cd_history
TCP command; flood-immune, 4096 entries). The oracle is rebuilt and the
patch regenerated from the checkout.
cd_diff.py pulls both histories, aligns on the longest common command
run, and prints the first diverged request on each side. The game
computes requests from what the emulator tells it, so the traffic just
before that fork is the runtime bug -- located by diff, not by theory.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>