Two separate problems, one of which was hiding the other.
1. The diagnostics were unreadable. do_netboot() printed them and returned,
and the caller's draw_main() redrew immediately and wiped the screen -- so
two consecutive failures were reported only as "a short flash" with no
detail, and the error code alone was not enough to act on. nb_pause() now
holds the screen until a button is pressed, on every failure path.
This cost two blind round trips, each of which needs a hand copy of the
.dol to the SD card. Printing a diagnosis and then erasing it is worse
than not printing one.
2. The default block was 1024 bytes, making ~1050-byte frames that span FIVE
of the SPRAM ring's 15 pages. The only multi-page frame ever proven on
this hardware is the 342-byte DHCP broadcast from bring-up, which spans
two. Five-page frames are untested territory, and a transfer is the wrong
place to discover a wrap bug.
Default is now 256 bytes -> ~296-byte frame -> two pages, deliberately
close to the proven case. --block raises it once small blocks work; the GC
still caps at NB_BLOCK_MAX = 1024.
ring_next() also keeps the four raw descriptor bytes and the page it read
them from, and the error path prints them. When a length is rejected those
bytes ARE the diagnosis: 00 00 xx xx tells us the assembler wrote a
descriptor and the length is simply unexpected, whereas garbage tells us we
are reading the wrong page.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>