Honour the GC's ring geometry (BP / RHBP) instead of hardcoding it
Compat TODO item 2, the last silent-corruption risk. RXFrameAssembler took the RX ring as a compile-time constant (pages 1-15), so a driver configuring a SMALLER ring was ignored and we kept writing pages it would never read, with nothing reporting an error. The bounds now come from bp/rhbp, wired in BBATop from the GC's BP (0x0A/0B) and RHBP (0x1A/1B) registers, and both the page wrap and the free-space calculation use them. Garbage is rejected rather than obeyed: the driver's values are used only when bp >= 1 (page 0 is the TX buffer), rhbp <= 0x0F and rhbp > bp. Otherwise the hardcoded layout stands and geom_honoured goes low, so a mismatch is observable. Without that check BP=0 or an RHBP below BP gives a zero or negative ring size and the assembler writes outside it. ⚠️ Recorded as a known limitation: a ring must be LARGER than _MAX_FRAME_PAGES (6) or nothing is ever stored, because a frame's length is unknown until EOF so the worst case (1518+4 = 6 pages) is reserved up front. Found the honest way -- the test was written with RHBP=4 first and passed VACUOUSLY, storing nothing at all. Making that work needs a length-aware reservation, which is a bigger change than this one. T7 (8-page ring honoured, frames only in pages 1-8, and at least one actually stored) and T7b (all three garbage cases rejected, fallback still stores). Mutation-tested: wrapping at the hardcoded page 15 writes pages 9-11 and fails T7; removing the sanity check fails all four T7b assertions. Item 1 (RX filtering) remains the only open gap. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+29
-9
@@ -59,17 +59,37 @@ nothing is ever lost but the ring fills with other hosts' traffic.
|
||||
|
||||
## 2. Ring geometry is hardcoded — silent corruption risk
|
||||
|
||||
**Status: OPEN.**
|
||||
**Status: ✅ DONE 2026-10-10.** `RXFrameAssembler` takes the ring bounds from
|
||||
`bp`/`rhbp`, wired from the GC's `BP` (0x0A/0B) and `RHBP` (0x1A/1B) registers
|
||||
in `BBATop`. The wrap and the free-space calculation both use them, so a
|
||||
driver's smaller ring is respected instead of ignored.
|
||||
|
||||
We fix TX = page 0 and RX = pages 1–15 (`_RX_PAGE_FIRST`, `_RX_PAGE_LAST`,
|
||||
`_PAGES_TOTAL`). libogc2 writes `TLBP = 0x0000`, `BP = 0x0001`,
|
||||
`RHBP = 0x000F`, which matches us exactly — but **we ignore those writes.**
|
||||
**Garbage is rejected, not obeyed.** The bounds are used only when
|
||||
`bp >= 1` (page 0 is the TX buffer), `rhbp <= 0x0F` and `rhbp > bp`;
|
||||
otherwise the hardcoded pages 1–15 stand and `geom_honoured` goes low, so a
|
||||
mismatch is observable rather than silent. Without that check, `BP = 0` or an
|
||||
`RHBP` below `BP` gives a zero or negative ring size and the assembler writes
|
||||
outside it.
|
||||
|
||||
A game choosing a smaller RX ring (`RHBP < 0x0F`) would read pages the
|
||||
assembler is still writing, with nothing reporting an error. The minimum
|
||||
honest fix is to honour `RHBP`/`BP`, or failing that to detect a value that
|
||||
disagrees with our layout and surface it (a status bit, or at least the UART
|
||||
console) rather than corrupt silently.
|
||||
⚠️ **A ring must be LARGER than `_MAX_FRAME_PAGES` (6) or nothing is ever
|
||||
stored.** A frame's length is unknown until EOF, so the assembler reserves the
|
||||
worst case (1518 + 4 bytes = 6 pages) before accepting one. With a 4-page ring
|
||||
`free` can never reach 6, so RBFI drops every frame — correct, conservative,
|
||||
and useless. This was found by writing the test with `RHBP = 4` first, where it
|
||||
passed **vacuously** because nothing was stored at all. If a real driver ever
|
||||
configures a ring that small, the reservation has to become length-aware
|
||||
(accept a frame whose actual length fits), which is a bigger change than this
|
||||
one.
|
||||
|
||||
Tests: `rx_frame_assembler` **T7** (an 8-page ring is honoured, frames land
|
||||
only in pages 1–8) and **T7b** (all three garbage cases rejected, and the
|
||||
fallback layout still stores). Mutation-tested: wrapping at the hardcoded page
|
||||
15 writes pages 9–11 and fails T7; removing the sanity check fails all four
|
||||
T7b assertions.
|
||||
|
||||
For the record, libogc2 writes `TLBP = 0x0000`, `BP = 0x0001`,
|
||||
`RHBP = 0x000F` — exactly the old hardcoded layout, which is why this never
|
||||
showed up in practice.
|
||||
|
||||
## 3. `NCRB` (0x01) is not decoded at all
|
||||
|
||||
|
||||
Reference in New Issue
Block a user