Commit Graph

5 Commits

Author SHA1 Message Date
Alex Vanderveen af7b6f379e read the whole reply, and tell "not running" apart from "not a block leader"
The multi-line fix did not work, because I fixed the read loop and left the
parse. raw() kept reading until the JSON document was complete and then still
did split(b"\n", 1)[0] before parsing it — so pc_probe_dump was truncated in
exactly the same place, and the error still named the server. Verified against
the live runtime this time rather than reasoned about: 843 bytes, 6 newlines,
parses.

The whole buffer is parsed now (JSON treats the embedded newlines as
whitespace), with the first line kept as a fallback for a peer that sends more
than one document down a connection.

Underneath that, the probe was reporting the wrong cause. Every candidate came
back with count 0, and the message offered two possibilities: the addresses are
mid-block, or the code did not run. It was the second — the effect was not on
screen at all — and that is checkable rather than guessable. class_on_screen()
walks the display list and says which it is:

  "PolyG4+semi is not being drawn, so this code never ran and no candidate
   could fire. Currently drawing: PolyFT4 x576, PolyF4+semi x184, PolyFT3 x1."

Several tools depend on a routine actually running — a write trace over its
packets, a block probe at one of its instructions — and each reports its own
symptom when it is not: no writes recorded, no candidate fired, no table found.
All three are now one plain statement.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 12:55:58 -04:00
Alex Vanderveen 88fedc3694 parity: align BOTH emulators, and stop inventing display-state differences
Two bugs, both visible in every parity run so far.

Alignment only ever steered DuckStation. It read psx-runtime's frame, drove the
oracle at it, then took screenshots -- while the native run kept going. So the
two images were of different frames essentially always, and the tool printed
that as a warning to read past rather than as the reason the comparison was
void. It also failed outright whenever the oracle had already passed the target,
because run_to_frame cannot go backwards ("target frame already passed").

Neither side can rewind, but both can move FORWARD: psx-runtime by stepping
(pause/step are real again -- the "native run cannot be paused" in that warning
had been stale since they were restored), DuckStation by run_to_frame. The
target is therefore whichever emulator is further ahead, and the one behind
catches up. Both are parked for the screenshots, and the game is handed back
afterwards rather than left relying on the park's silence timeout.

The display-state block was pure noise. The two servers name the same facts
differently -- display_x/width/height against display_area_x/disp_w/disp_h --
so comparing raw keys reported native=None for every field. That reads as the
runtime failing to report its display state and is really a vocabulary
mismatch: a difference invented by the tool, printed under a heading saying the
emulators diverged. Names are now normalised, display_disable is inverted
rather than merely renamed onto display_enable (or every frame would differ),
and a field only one side reports is marked one_sided instead of counted as
disagreement.

Studio leads with the alignment verdict, because every other number in the
report is conditional on it.

Also: the resume-on-error patch first landed in align_frames() instead of
main(), referencing an `args` that does not exist there -- caught by extending
the undefined-global bytecode guard to gpu_parity, packet_writers and gte_check.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 12:55:57 -04:00
Alex Vanderveen 4f8a2edf86 dlist: re-read the list parked; refuse lopsided colour verdicts
Both changes come from reading a real native-vs-oracle pair.

The good news in that pair: all 64 additive quads carry BIT-IDENTICAL vertices
on the two emulators, and every (opcode, blend) class count matches. Whatever
the render bug is, the geometry the guest builds is not it.

The bad news was in how the oracle's half was captured. Reading 2 MB from a
running emulator takes ~128 round trips, and the game rebuilds its ordering
table underneath -- that walk spanned 6 frames and came back with a whole frame
of additive quads carrying just 4 distinct colour values across 768 channels.
A torn read that looks exactly like data, and I nearly read it as evidence that
the runtime's colours were corrupt.

The fix is cheap now that the scan reports the list's span: the first pass finds
WHERE the list is, then the emulator is parked and only that span (a few KB) is
re-read, so the decoded list comes from ONE instant. A few KB is affordable even
at the 1 Hz the oracle drops to while parked, which is what made this impossible
when the read was the whole of RAM. Walks now report whether they are coherent,
and say THIS WALK MAY BE TORN when they are not.

gpu_colour_parity refuses a verdict past a 4x sample imbalance. It had reported
"differ" from 3328 vertices against 256 -- roughly thirteen frames of an
animating effect against a single one. Those differ by construction and say
nothing about the emulators.

Also fixes two tests that encoded the old ping-based frame(): one mock answered
every command with a frame field, so it answered `frame` too and quietly robbed
the test of the ping fallback it existed to check.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 12:55:57 -04:00
Alex Vanderveen 0e5d463356 duckstation linux build + frame capture diagnostics 2026-08-20 11:26:37 -04:00
Alex Vanderveen 1f65200e6f bump 2026-08-19 23:35:17 -04:00