Skip to content

PR #89 split 3/4: BRK vectors architecturally - #145

Merged
mstan merged 3 commits into
mainfrom
split89/brk-vector
Oct 3, 2026
Merged

mstan merged 3 commits into
mainfrom
split89/brk-vector

Conversation

@mstan

@mstan mstan commented Oct 3, 2026

Copy link
Copy Markdown
Member

Part 3 of 4 of the split of #89 (@TechnicallyComputers): BRK vectors architecturally instead of being swallowed. The commit is the contributor's 4e3ac80, cherry-picked with -x, unchanged.

Nothing plants BRK markers any more, so a main-CPU BRK is one the guest really reached. Swallowing it as a one-byte no-op let an off-rails run slide through $00 bytes into real code before anything trapped. The BRK now reports (at most 8 per process) and takes the hardware vector. Main's control-flow edge ring (#143) records it as a vector edge, so the jump that led there stays queryable.

Evidence: main (097a355) vs this commit

Default (shipped) config, headless scripted runs:

  • attract: no input, 6000 frames.
  • play: menus, then gameplay input, 6021 frames.
title frames frame CRC mismatches final state [brk] main / branch exit
MMX, MMX2, MMX3, Super Metroid, Yoshi's Island, BS F-Zero 2 6000 + 6021 each 0 WRAM/VRAM/CGRAM/OAM and run report identical 0 / 0 0 / 0
SMW, StarFox 6000 per-frame WRAM 0 (no pixel log in these hosts) run report identical 0 / 0 0 / 0
Zelda, Gundam W 6000 per-frame WRAM 0 — (killed at frame cap) 0 / 0 —
SMRPG, F-Zero (own headless harness) 6000 / 6021 final frame identical final WRAM identical 0 / 0 0 / 0
SMK, DKC2 (frame-capped hosts) 6000 final frame identical — 0 / 0 0 / 0
Illusion of Gaia 100 s smoke — — 0 / 0 —

No title vectors on these workloads, and every outcome is identical. The path only fires once a guest is already off the rails.

Evidence is in F:/Projects/snesrecomp/_wt-pr89-builds/evidence/<game>/<workload>/summary.json.

🤖 Generated with Claude Code

`brkHookEnabled` dates from a bridge that bounced through PLANTED BRK markers,
where executing one had to be inert. Nothing plants them any more -- the
bridge says so outright: "The bounce is via explicit JSR/JSL interception
below, not via planted BRKs" -- so the only BRK the main CPU can now execute
is one the guest really reached, which means it is off the rails.

Swallowing it was actively harmful. Hardware vectors on the FIRST $00; this
continued one byte at a time, so an off-rails run slid through blank memory,
crossed back into real code and corrupted the stack before anything trapped.
A Super Metroid fault executed 240 such bytes and only stopped on an unrelated
COP some 9,000 steps later, by which point the instruction ring held nothing
but the slide and the original bad jump was unrecoverable.

Now it reports (capped at 8 per run, with PC and mode bits) and takes the
architectural vector. The flag is kept for callers that set it explicitly --
SA-1 clears it -- and no longer suppresses the vector.

It paid for itself immediately: the same fault moved from ~9,000 steps
downstream to the instruction beside its cause, and the diagnosis followed in
one run. A 900-frame trace is byte-identical and no BRK executes in a healthy
run, so this only bites where the guest is already lost.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
(cherry picked from commit 4e3ac80)
@mstan

mstan commented Oct 3, 2026

Copy link
Copy Markdown
Member Author

Not mergeable yet: CI fails tests/interp816 S7 (second rc=0 exp 1, return S=0188 exp 01FF). After the poll's RTS the test returns into zeroed memory, where main's inert-BRK swallow ends the run; vectoring slides through the BRK vector instead. Something in the bridge still depends on the swallow. Find what, before this lands.

@mstan
mstan merged commit 88a9f7f into main Oct 3, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants