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:
2026-10-10 14:06:04 +02:00
parent 4a455bbe88
commit 147ef8fcfc
4 changed files with 155 additions and 29 deletions
+13 -8
View File
@@ -1340,14 +1340,19 @@ Known differences between this implementation and what real GC software
expects, with the evidence for each, are tracked in
**`docs/bba_compat_todo.md`**. Summary of what is still OPEN:
1. **No hardware RX filtering** — we take every frame on the segment; the real
BBA delivers own-MAC + broadcast. Causes the ring pressure already seen on
hardware. Needs a decision, not just code.
2. **Ring geometry hardcoded** — `RHBP`/`BP`/`TLBP` writes ignored; a game
using a smaller RX ring corrupts silently.
3. **`NCRB` (0x01) not decoded** — filtering and interrupt-coalescing bits.
4. **Registers reading `0x00` that have non-zero hardware defaults** —
`NWAYC` `0x84`, `MISC` `0x3C`, and the rest of the map.
1. **No hardware RX filtering** — ⚠️ STILL OPEN. We take every frame on the
segment; the real BBA delivers own-MAC + broadcast. Causes the ring
pressure already seen on hardware. Needs a decision, not just code: the
W5100's MF bit filters against `SHAR`, which we write only at init, so a
driver that writes PAR0–5 would leave it stale and MF would drop
everything.
2. ✅ **Ring geometry** — `BP`/`RHBP` are honoured, with garbage rejected and
`geom_honoured` exposed. A ring must still be larger than
`_MAX_FRAME_PAGES` (6) or the worst-case reservation drops every frame.
3. ✅ **`NCRB` (0x01)** — decoded, stored and exported as `reg.ncrb`.
4. ✅ **Hardware defaults** — every register libogc2 writes now stores and
reads back (`NWAYC` `0x84`, `MISC` `0x3C`, …). Status registers
(`LTPS`/`LRPS`/`TWP`/`TRP`/`TXFIFOCNT`) still read `0x00` deliberately.
Keep that file updated in the same commit whenever one is closed.