Firmware: RIOv4_2_patched_31250.bin — wedge fix + SCI retuned to 31250 baud
make_patch.py gains --baud31250: one byte beyond the wedge patch — the SCI init operand at $D62B ($30 -> $02). BAUD $30 = /13 prescale, /1 divider (2MHz E / 208 = 9615); $02 = /1, /4 -> 31250 exactly, 3.3x faster. The init write also confirms the 8MHz crystal, which is why 19200/38400 are unreachable and why 62500/125k are left alone pending an ISR cycle count. - 24 bytes changed vs original (sha256 9f866cf3...); re-disassembly diff vs the classic patched image shows exactly the one operand line, and the classic build still reproduces 3fc8170c... (script regression-safe). - PC side: SerialPortTransport takes an optional baudRate (default 9600, runtime untouched); RioSerialMonitor + --mash accept --baud 31250. - Caveats documented in README/ANALYSIS: non-standard rate (FTDI-class adapters only, no 16550s); native games still speak 9600 so this chip is bench/RIOJoy-only; validate the wedge patch at 9600 first. 275 tests green; mash --selftest regression unchanged (FAIL/exit-1). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -40,3 +40,13 @@ 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`.
|
||||
|
||||
@@ -148,6 +148,31 @@ three regions with no downstream desync:
|
||||
Flash `RIOv4_2_patched.bin` directly to the W27C512 (DIP-28). This is
|
||||
static verification only; dynamic proof still needs the burned chip.
|
||||
|
||||
### 31250-baud variant (2026-07-17) — `RIOv4_2_patched_31250.bin`
|
||||
|
||||
`make_patch.py --baud31250` adds **one byte** to the wedge patch: the SCI
|
||||
init at `$D62A` (`LDAA #$30 ; STAA $102B BAUD`) becomes `LDAA #$02`.
|
||||
BAUD `$30` = prescale ÷13, divider ÷1 → 2 MHz E-clock / (16·13) = 9615
|
||||
("9600"); `$02` = prescale ÷1, divider ÷4 → 2 MHz / (16·4) = **31250
|
||||
exactly** (3.3× faster; analog exchange ~15 ms → ~4.6 ms; 96-lamp burst
|
||||
~0.4 s → ~0.12 s; every collision window shrinks 3×). The BAUD write
|
||||
confirms the 8 MHz crystal / 2 MHz E-clock — 19200/38400 are unreachable.
|
||||
|
||||
sha256 `9f866cf353d04906e1d3e3847b6375eaae251c987b656f68f093e61ba1bd545b`,
|
||||
24 bytes changed (the 23 wedge bytes + `$D62B: 30→02`). Re-disassembly
|
||||
diff vs the classic patched image shows exactly the one operand line.
|
||||
|
||||
**Caveats:** 31250 is non-standard — FTDI-class USB adapters make it
|
||||
exactly, classic 16550 UARTs cannot; the **native games still speak
|
||||
9600**, so a 31250 chip is bench/RIOJoy-only until Firestorm/Red Planet
|
||||
get BTL4OPT-style baud patches; and the 2 MHz HC11's RX ISR has ~640
|
||||
cycles/byte at this rate (fine) — do NOT be tempted to `$01`/62500 or
|
||||
`$00`/125 k without cycle-counting the `$D630` ISR worst path first.
|
||||
PC side: `SerialPortTransport` takes a baud parameter and the
|
||||
monitor/mash tools accept `--baud 31250`. Validate the wedge patch at
|
||||
9600 FIRST (one variable at a time), then A/B this chip with
|
||||
`--mash COM1 300 --label patched-31250 --baud 31250`.
|
||||
|
||||
### Validation plan (when a chip is available)
|
||||
Burn the two edits to a W27C512, socket it (preserve the original AMD
|
||||
chip), then run the `RIO_TAP` two-handed 8-button mash test. Expect: no
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
+22
-2
@@ -8,13 +8,25 @@ EVERY reply teardown, not just the $2522-gated success path.
|
||||
that clears $2521/$2522 then continues to $DA2F.
|
||||
2. Success path: make $DA00's clear of $2521/$2522 unconditional.
|
||||
|
||||
With --baud31250, additionally retune the SCI from 9600 to 31250 baud
|
||||
(-> RIOv4_2_patched_31250.bin): the init at $D62A loads BAUD ($102B) with
|
||||
$30 (prescale /13, divider /1 -> 2MHz E / (16*13) = 9615). $02 selects
|
||||
prescale /1, divider /4 -> 2MHz / (16*4) = 31250 exactly. One operand
|
||||
byte at $D62B. NOTE: 31250 is a non-standard rate — FTDI-class USB
|
||||
adapters produce it exactly; classic 16550 UARTs cannot. The native
|
||||
games still expect 9600, so a 31250 chip is bench/RIOJoy-only until the
|
||||
games are patched.
|
||||
|
||||
Each edit asserts the exact original bytes first, so a wrong assumption
|
||||
aborts instead of corrupting the image. Address == file offset.
|
||||
"""
|
||||
import sys, hashlib
|
||||
|
||||
SRC = sys.argv[1] if len(sys.argv) > 1 else "RIOv4_2.bin"
|
||||
DST = sys.argv[2] if len(sys.argv) > 2 else "RIOv4_2_patched.bin"
|
||||
BAUD31250 = "--baud31250" in sys.argv
|
||||
args = [a for a in sys.argv[1:] if not a.startswith("--")]
|
||||
SRC = args[0] if len(args) > 0 else "RIOv4_2.bin"
|
||||
DST = args[1] if len(args) > 1 else (
|
||||
"RIOv4_2_patched_31250.bin" if BAUD31250 else "RIOv4_2_patched.bin")
|
||||
|
||||
d = bytearray(open(SRC, "rb").read())
|
||||
assert len(d) == 0x10000, f"expected 64KB image, got {len(d)}"
|
||||
@@ -52,6 +64,14 @@ patch(0xDA21,
|
||||
[0x7F,0x25,0x21, 0x7F,0x25,0x22, 0x01,0x01,0x01,0x01,0x01,0x01,0x01])
|
||||
assert d[0xDA2E] == 0x39, "RTS at $DA2E must be intact"
|
||||
|
||||
# --- edit 3 (--baud31250 only): SCI 9600 -> 31250 --------------------------
|
||||
# $D62A 86 30 LDAA #$30 (SCP=/13, SCR=/1) -> 86 02 (SCP=/1, SCR=/4)
|
||||
# then STAA $102B (BAUD). 2MHz E-clock: 2e6/(16*13)=9615 -> 2e6/(16*4)=31250.
|
||||
if BAUD31250:
|
||||
assert d[0xD62A] == 0x86 and bytes(d[0xD62C:0xD62F]) == bytes([0xB7,0x10,0x2B]), \
|
||||
"expected LDAA #imm ; STAA $102B at $D62A"
|
||||
patch(0xD62B, [0x30], [0x02])
|
||||
|
||||
open(DST, "wb").write(d)
|
||||
new_sha = hashlib.sha256(d).hexdigest()
|
||||
# byte-diff report
|
||||
|
||||
Reference in New Issue
Block a user