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:
@@ -41,22 +41,37 @@ the SCI state machine (protocol constants FC=ACK FD=NAK FE=RESTART
|
||||
FF=IDLE, idle-reload-4 patterns), patch the early-ACK/error wedge path or
|
||||
widen its window, burn a new EPROM, keep this original safe.
|
||||
|
||||
## Patched images (built by make_patch.py; see RIOv4_2-ANALYSIS.md)
|
||||
## Current work candidate — `RIOv4_3rc1.bin`
|
||||
|
||||
- **`RIOv4_2_patched.bin`** — the reply-latch wedge fix, 23 bytes changed.
|
||||
sha256 `3fc8170caf60e2580641724ff995176c93c4f2e706f31487beded8233142493f`.
|
||||
- **`RIOv4_2_patched_31250.bin`** (`make_patch.py --baud31250`) — wedge fix
|
||||
+ SCI retuned 9600 → 31250 baud (one more byte, `$D62B: 30→02`).
|
||||
sha256 `9f866cf353d04906e1d3e3847b6375eaae251c987b656f68f093e61ba1bd545b`.
|
||||
Bench/RIOJoy-only until the native games get baud patches; needs an
|
||||
FTDI-class adapter (16550s can't make 31250). Test tools take `--baud 31250`.
|
||||
- **Speed-ladder variants** (`_31250v2`, `_62500`, `_125000`) and bench
|
||||
verdicts: see RIOv4_2-ANALYSIS.md — 31250v2 is the certified FastRIO
|
||||
build; 62500/125000 were science runs (CPU is the wall).
|
||||
- **`RIOv4_2_patched_e0t5.bin` / `RIOv4_2_patched_31250v2_e0t5.bin`**
|
||||
(`--e0thresh=5`) — adds a threshold to the cockpit display's `E0`
|
||||
serial-error readout, which stock firmware paints on the *first*
|
||||
counter event (`E0000001` forever after one benign give-up). Display
|
||||
stays `F0000000` until any error counter reaches 5; counters still
|
||||
accumulate. 30-byte cave at `$E000`, disassembly-verified, **not yet
|
||||
burned/bench-verified**. Details in RIOv4_2-ANALYSIS.md.
|
||||
Built by `make_patch.py --e0thresh=5 --checkrepaint RIOv4_2.bin
|
||||
RIOv4_3rc1.bin`; sha256
|
||||
`dc59bd51cae34781cf42f338e44a020b249a4030acc3c584af916aee9ca881e3`
|
||||
(68 bytes changed vs stock). 9600 baud, native-game compatible. On the
|
||||
stock v4.2 base it carries:
|
||||
|
||||
1. **Reply-latch wedge fix** (edits 1-2) — bench-certified.
|
||||
2. **E0-display threshold, N=5** (edit 5) — bench-certified 2026-07-19
|
||||
(held `F0000000` sub-threshold, flipped to `E0000105` at the 5th
|
||||
teardown; mash regression clean).
|
||||
3. **Check self-test display repaint** (edit 6, NEW) — the CheckRequest
|
||||
handler previously left a stale `04000000` frame on the display; a
|
||||
10-byte cave at `$E020` now repaints `F0000000` after every check,
|
||||
then re-renders the `E0` readout only if a counter is at/over
|
||||
threshold. **Needs on-hardware verification**: after a burn, any
|
||||
version+check exchange (tray connect, monitor, mash start) must
|
||||
leave the display reading `F0000000`, not `04000000`; then re-run
|
||||
`--e0test` (expect the certified behavior unchanged) and a mash
|
||||
spot-check.
|
||||
|
||||
Once edit 6 is verified on the cockpit, this image is christened
|
||||
**RIO 4.3**.
|
||||
|
||||
## Archive
|
||||
|
||||
All prior generations live in [`archive/`](archive/) with their
|
||||
disassemblies: `RIOv4_2_patched` (wedge fix only), `_31250`/`_31250v2`
|
||||
(FastRIO speed builds), `_62500`/`_125000` (speed-ladder science runs),
|
||||
and the `_e0t5` pair (threshold without check-repaint; the 9600 one is
|
||||
in the socket as of 2026-07-19 until rc1 is burned). Bench verdicts and
|
||||
per-edit history: RIOv4_2-ANALYSIS.md. The pristine dump `RIOv4_2.bin`
|
||||
stays at top level — it is the source every patch builds from.
|
||||
|
||||
+9
-4
@@ -516,7 +516,12 @@ last thing rendered), enqueues the fault reports, clears the flag
|
||||
(`$C5E1`), notifies `0x8C` again — and **returns without repainting the
|
||||
display**. Every status check therefore leaves a stale
|
||||
`04 00 <ch4 count>` snapshot (idle: `04000000`) on the digits. The
|
||||
board is fully healthy afterwards; no reset is needed. Proper fix, if
|
||||
the cosmetic bothers: a ~10-byte cave off `$C5E4` that repaints `F0`
|
||||
(`JSR $CB7C`) and re-renders the E0 readout when over threshold
|
||||
(`JSR $D5F2`) — candidate for the next burn, not yet built.
|
||||
board is fully healthy afterwards; no reset is needed. Proper fix:
|
||||
**edit 6** (`make_patch.py --checkrepaint`) — a 10-byte cave at `$E020`
|
||||
hooked from the handler's final notify (`$C5E4`): `JSR $C70E` (original
|
||||
notify), `JSR $CB7C` (repaint `F0000000`), `JSR $D5F2` (re-render the
|
||||
E0 readout, which the edit-5 gate suppresses below threshold), `RTS`.
|
||||
Built into **`RIOv4_3rc1.bin`** (with edits 1-2 and 5; sha256
|
||||
`dc59bd51cae3…`) — awaiting burn + on-hardware verification, after
|
||||
which the image is christened RIO 4.3. Prior generations moved to
|
||||
`archive/`.
|
||||
|
||||
File diff suppressed because one or more lines are too long
+13109
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user