Add on-console GameCube test suite + devkitPPC in the devcontainer
gc_bba_test/ builds a .dol that drives the adapter over raw EXI from the
console and reports pass/fail per test on the TV, navigable with the pad.
Uses libogc's EXI API against EXI0:2 (Serial Port 1) rather than its bba
network driver: driving the register file directly gives each check its own
verdict, so a failure points at a specific register instead of at
'networking'. Six suites - identity, registers, reset/control, EXI link
integrity (including an EXI clock-index sweep), ethernet TX/RX, SPRAM/DMA
streaming.
Encodes the hardware lessons from bring-up so the app cannot mislead:
* the device ID is a one-shot cleared by the first NCRA reset, so it is
reported SKIP on a re-run rather than FAIL
* TI means the frame reached the W5100, NOT the wire - the TX test says so
* register reads clock exactly the requested length (over-clocking
desynchronises the next transaction)
* TXDATA is written one byte per transaction (eff_addr auto-increments)
.devcontainer/Dockerfile gains the devkitPro gamecube-dev group. devkitPro
publishes no .deb on GitHub, so this uses their installer script against
apt.devkitpro.org -- which is 403 from inside the running container's egress
but reachable from a host-side docker build. Rebuild the container to get it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
/* bba.h — raw EXI transport to the re-bba-rb adapter in Serial Port 1.
|
||||
*
|
||||
* Deliberately NOT libogc's bba network driver: this talks to the register
|
||||
* file directly so every check gets its own pass/fail and a failure points at
|
||||
* a specific register rather than at "networking".
|
||||
*/
|
||||
#ifndef BBA_H
|
||||
#define BBA_H
|
||||
|
||||
#include <gccore.h>
|
||||
|
||||
/* Serial Port 1 == EXI channel 0, device 2. */
|
||||
#define BBA_EXI_CHAN EXI_CHANNEL_0
|
||||
#define BBA_EXI_DEV EXI_DEVICE_2
|
||||
|
||||
/* Register map (see CLAUDE.md "Key Registers"). */
|
||||
#define REG_NCRA 0x00
|
||||
#define REG_IMR 0x08
|
||||
#define REG_IR 0x09
|
||||
#define REG_RWP_LO 0x16
|
||||
#define REG_RWP_HI 0x17
|
||||
#define REG_RRP_LO 0x18
|
||||
#define REG_PAR0 0x20
|
||||
#define REG_PAR4 0x24
|
||||
#define REG_NWAYS 0x31
|
||||
#define REG_TWD_LO 0x34
|
||||
#define REG_TWD_HI 0x35
|
||||
#define REG_HIPR 0x3A
|
||||
#define REG_TXDATA 0x48
|
||||
#define SPRAM_BASE 0x0100
|
||||
|
||||
/* NCRA bits */
|
||||
#define NCRA_RESET 0x01
|
||||
#define NCRA_ST0 0x02
|
||||
#define NCRA_SR 0x08
|
||||
|
||||
/* IR bits */
|
||||
#define IR_RI 0x02
|
||||
#define IR_TI 0x04
|
||||
|
||||
/* Expected constants */
|
||||
#define NWAYS_LINKUP 0x17
|
||||
#define HIPR_PRESENT 0x01
|
||||
|
||||
/* EXI clock index, EXI_SPEED1MHZ(0) .. EXI_SPEED32MHZ(5). The nominal 32 MHz
|
||||
* index is really ~27 MHz on hardware (see CLAUDE.md); the capture domain
|
||||
* oversamples it 2x at 54 MHz. Settable so the suite can sweep it. */
|
||||
extern u32 bba_speed;
|
||||
|
||||
/* All return 0 on success, negative on an EXI-layer failure. */
|
||||
|
||||
/* Immediate read of `len` (1..4) bytes from `addr`.
|
||||
* Clocks EXACTLY `len` bytes: over-clocking a register read leaves stale
|
||||
* prefetched bytes queued in the gateware and desynchronises the NEXT
|
||||
* transaction (hardware-confirmed 2026-09-30). Never pad this. */
|
||||
int bba_read(u16 addr, void *buf, u32 len);
|
||||
|
||||
/* Immediate write of `len` (1..4) bytes to `addr`. */
|
||||
int bba_write(u16 addr, const void *buf, u32 len);
|
||||
|
||||
/* Convenience single-byte helpers. bba_r8 returns the byte, or <0 on error. */
|
||||
int bba_r8(u16 addr);
|
||||
int bba_w8(u16 addr, u8 val);
|
||||
|
||||
/* SPRAM / DMA-style read: any address >= 0x0100 streams until CS deasserts,
|
||||
* so `len` may exceed 4 and the header's 2-bit length field is ignored. */
|
||||
int bba_stream(u16 addr, void *buf, u32 len);
|
||||
|
||||
/* Stream `len` bytes into the TXDATA port. One byte per EXI transaction:
|
||||
* the register file's effective address auto-increments per data byte, so a
|
||||
* multi-byte write to 0x48 would spill into 0x49+ instead of the FIFO. */
|
||||
int bba_tx_bytes(const u8 *buf, u32 len);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user