# RIO board firmware - **`RIOv4_2.bin`** — RIO cockpit I/O board firmware **v4.2**, dumped 2026-07-04 from one of our own boards' EPROM: an **AMD AM27C512-150** (64K x 8 UV EPROM, 150ns — the image fills it exactly). sha256 `60a88718835c654b6135dbec7721c40ef99dca07df2ad4b57eedeb24037a5f73`. For the eventual patched burn: a pin-compatible Winbond W27C512 (electrically erasable, TL866-friendly) drops straight into the socket; the original AMD chip gets labeled and preserved unmodified. ## First-look analysis (from the image alone, confirmed on hardware) - MCU: **Toshiba TMP68HC11** (read off the chip; the code fingerprint agrees — 6800-family opcodes with writes into the 68HC11 internal register block at `$10xx`). - Memory map: image is FF up to **0xC000**; 16KB of code occupies `$C000-$FFFF` (EPROM mapped at the top of the HC11 address space). - Startup at `$C000`: `SEI; LDS #$8000; STAA $1024 (TMSK2); STAA $1022 (TMSK1); ...` then a long `JSR` init chain — textbook HC11 bring-up. - Vector table (`$FFD6-$FFFF`, big-endian): - `$FFFE` RESET → `$C000` - **`$FFD6` SCI (serial) → `$D630`** — the entry point of the board's receive/protocol interrupt handler. The suspected board-side DISABLE_AND_DIE-style wedge (see RIO-NOTES.md: the board mirrors the game's PCSPAK state machine, and mash-stress leaves the reply path dead while the button/event path stays alive) is reachable from here. - `$FFE4` → `$C1B2`, `$FFE6` → `$C18E` (timer output-compares); most other vectors → `$DB07..$DB3D` stubs. ## Why this exists The remaining RIO reliability issue is board-side: under button-mash stress the board's reply/analog state machine wedges (RX dead, TX alive; a button press or power cycle revives it), reproduced identically on two different USB serial adapters. The game-side half of the protocol was binary-patched for tolerance (BTL4OPT patches v2-v4); the board firmware is the other half. Plan (RIO-NOTES.md "Board firmware patch plan"): disassemble as 68HC11 from `$C000` with the vector entries as roots, find 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) - **`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.