Commit Graph

2 Commits

Author SHA1 Message Date
Alex Vanderveen 106845956f scale_within_frame: refuse the constant-within-frame test for scratch regs
Run with --reg v0 it reported 'varies-within-frame' for a colour
computation that is provably correct. The probe arms a WINDOW of block
leaders rather than one instruction, so the six values it counted came
from six different PCs -- and they decode exactly right for source
(248,136,8) at $s6=80: 248*80>>7 = 155, 136*80>>7 = 85, 8*80>>7 = 5, and
the assembled word 939873691 = 0x3805559B carries precisely those bytes
under command 0x38. 136 and 8 are the source bytes mid-load.

The test is only meaningful for a value that should be fixed for the
whole frame -- the callee-saved fade scale it was written for. For a
scratch register, counting across PCs measures the program running.
Scratch registers now return not-applicable, and --per-pc breaks values
down by instruction so each can be read on its own.

The oracle's source table also came back byte-identical to psx-runtime's:
same 3 words, same counts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 12:55:58 -04:00
Alex Vanderveen 85bb9304db scale_within_frame: check the fade scale is constant across one frame
packet_writers named the guilty code. Six PCs write the additive quads'
colour words, all running the same idiom:

    lbu ,64() ; mult , ; mflo  ; sra ,,7 ; sb ...

$s6 is the fade level, one value per frame, so every vertex in a frame
must see the same $s6 and the 64 quads should carry a handful of
colours. psx-runtime carries ~153 where DuckStation carries 3. A $s6
that changes WITHIN a frame explains that exactly: same source colours,
same arithmetic, a different scale per vertex.

Unlike every other comparison here this needs no oracle and no phase
lock -- 'constant within a frame' is checkable against one emulator on
its own, which is why it is worth a tool of its own after so many runs
lost to synchronising two.

$s6 is callee-saved and stays live across the swc2/NCLIP at
0x800684C4..0x800684D8, which is where a recompiled routine could lose it.

Ruled out first, by reading the implementations: mult computes eagerly
into cpu->lo and mflo reads it (no deferred-evaluation hazard), sb and
lw both handle scratchpad byte-exactly, and the lwl/lwr/swl/swr tables
are correct for little-endian R3000A.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 12:55:58 -04:00