The oracle's $s4 reads 0x800E2C04; psx-runtime's covers
0x800E260C..0x800E2664, about 1.4 KB away. That is suggestive but not
conclusive on its own: the samples came from different moments, and if
$s4 walks a larger table across the effect then a phase difference alone
produces it.
What decides it is whether the CONTENTS differ. --diff-span reads one
range from both emulators and compares the bytes, which is
phase-independent while the table is static: identical data means a
differing $s4 is just a different offset into the same table, while
differing data is a fault upstream of the colour routine entirely.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
psx-runtime's $s4 covers 0x800E260C..0x800E2664 and reads a table of
exactly 3 colour words, identical on both emulators -- so this routine
can only ever emit 3 colours. Yet native's packets carry (117,0,0),
(106,0,0), (94,0,0), which cannot come from source (248,136,8) at any
scale: R=117 would force G=63, not 0. Something is reading a different
table.
DuckStation has pc_break (which captures every GPR) but no pc_probe, so
--oracle-pointer breaks once and reports which table its $s4 names. One
hit answers it: same range means the source cannot explain the packet
difference; a different range means psx-runtime is reading the wrong
table, which would be the bug itself.
Uses OracleBreak so the breakpoint cannot outlive the tool -- tested.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Native's source table is UNIFORM: 3 distinct colour words --
(248,136,8), (248,248,176), (0,0,0). Those are the oracle's
(147,80,4)/(147,147,104)/(4,4,4) at a different fade level: 248*147/248
is exactly 147, and 136 and 8 scale to 80 and 4. Source correct, scale
correct (constant per frame, measured), packets carrying ~153 colours --
so the corruption is between the table and the packet.
The oracle run failed with 'unknown command: pc_probe_clear': DuckStation
has pc_break but no pc_probe, so it cannot be probed this way. It does
not need to be -- the table is at the same address in both emulators, so
--span LO:HI reads it directly. The failure path now says so instead of
telling the user to replay an animation that would never have worked.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
$s6 is measured constant within each frame and ramping smoothly
(128,124,120,116,112,108), so the fade scale is not the source of
psx-runtime's ~153 distinct vertex colours against DuckStation's 3. That
also sharpens the target: at neutral scale the routine takes
'beq $s6,$t3' and copies the source word verbatim, so those 153 values
ARE the source table.
This probes $s4 to locate the table, reads it, counts the distinct
colour words actually in it, and can trace which code wrote it. Run
against --port 4371 to read the oracle's copy of the same table.
Either answer narrows: a uniform table means the fault is between the
table and the packet; a varied one means the wrong data is already there
before the colour routine runs, and the filler is the culprit.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>