RIOv4_3rc1 candidate: wedge fix + E0 threshold + check-display repaint; archive prior images

New edit 6 (--checkrepaint, requires --e0thresh): hooks the CheckRequest
handler's final notify ($C5E4) through a 10-byte cave at $E020 that
repaints F0000000 after the self-test and re-renders the E0 readout only
when a counter is at/over threshold — no more stale 04000000 after
status checks. Candidate = 9600 native-game-compatible base + edits
1-2/5/6, 68 bytes vs stock, disassembly-verified, awaiting burn; on
verification it will be christened RIO 4.3.

All prior patched generations (wedge-only, 31250/31250v2, 62500/125000
science builds, e0t5 pair) moved to rio-firmware/archive/ with their
disassemblies; RIOv4_2.bin stays at top level as the pristine patch
source.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-19 16:13:13 -05:00
co-authored by Claude Fable 5
parent a9ae6ff0c8
commit c29a9d5343
19 changed files with 13214 additions and 22 deletions
+24
View File
@@ -47,6 +47,11 @@ for a in sys.argv:
E0T = int(a.split("=", 1)[1]) if "=" in a else 5
assert E0T is None or 1 <= E0T <= 255, f"--e0thresh out of range: {E0T}"
# --checkrepaint: repaint the display after the CheckRequest self-test (edit 6).
CHECKREPAINT = "--checkrepaint" in sys.argv
assert not CHECKREPAINT or E0T is not None, \
"--checkrepaint requires --e0thresh (it re-renders E0 via the gated $D5F2)"
args = [a for a in sys.argv[1:] if not a.startswith("--")]
SRC = args[0] if len(args) > 0 else "RIOv4_2.bin"
if len(args) > 1:
@@ -59,6 +64,8 @@ else:
DST = "RIOv4_2_patched.bin"
if E0T is not None and len(args) <= 1:
DST = DST[:-4] + f"_e0t{E0T}.bin"
if CHECKREPAINT and len(args) <= 1:
DST = DST[:-4] + "_ckr.bin"
d = bytearray(open(SRC, "rb").read())
assert len(d) == 0x10000, f"expected 64KB image, got {len(d)}"
@@ -141,6 +148,23 @@ if E0T is not None:
0x7E, 0xD5, 0xF7] # $E01B JMP $D5F7 (resume render)
patch(0xE000, [0xFF] * len(cave), cave)
# --- edit 6 (--checkrepaint): repaint the display after the check self-test --
# The CheckRequest handler ($C5A6) renders its five-channel encoder sweep to
# the cockpit display (it sets the test-display flag $2421 for the duration)
# and returns without repainting, leaving a stale '04 00 <ch4 count>' frame
# (idle: 04000000) after every status check. Hook its final TestModeChange
# notify ($C5E4 JSR $C70E) through a cave that also repaints F0000000
# ($CB7C) and then re-renders the E0 error readout via $D5F2 — which, with
# the edit-5 gate, paints only when a counter is at/over threshold. Display
# after any check: F0000000 when healthy, E0... when not.
if CHECKREPAINT:
patch(0xC5E4, [0xBD, 0xC7, 0x0E], [0xBD, 0xE0, 0x20]) # JSR $C70E -> JSR $E020
cave6 = [0xBD, 0xC7, 0x0E, # $E020 JSR $C70E (original notify, kept)
0xBD, 0xCB, 0x7C, # $E023 JSR $CB7C (repaint F0000000)
0xBD, 0xD5, 0xF2, # $E026 JSR $D5F2 (E0 readout iff >= threshold)
0x39] # $E029 RTS
patch(0xE020, [0xFF] * len(cave6), cave6)
open(DST, "wb").write(d)
new_sha = hashlib.sha256(d).hexdigest()
# byte-diff report