Skip to content

v2.1.0 — storage on SdFat, and src/cpu + src/machines de-picoed

Choose a tag to compare

@jedgarpark jedgarpark released this 09 Sep 05:56
· 5 commits to main since this release
4067965

The firmware really is different this time. Unlike v2.0.0, which was a pure packaging release, every .uf2 here differs from the previous one — the SD card layer was replaced. Behaviour should be identical, and was verified on hardware across five games, but these are new binaries rather than the same bytes under a new name.

Two changes, both answering a review of the project's hardware dependencies.

Storage now uses SdFat

The vendored copy of FatFs and a hand-rolled SPI SD driver are gone — 24,102 lines deleted, 79 added. SdFat - Adafruit Fork is declared in library.properties, so Library Manager installs it for you.

Nothing above the board layer changed: game code still sees the same six storage functions, and still touches the card exactly once, at boot.

Three things were kept deliberately rather than re-derived:

  • 12.5 MHz SPI, the speed the old driver settled on — a number this project has actually run cards at.
  • Long filenames. The ROM loaders sort the names the card reports, so quietly switching to 8.3 names would have changed which ROM lands at which address — a booting machine running scrambled ROM, which looks like a corrupt dump rather than a storage bug.
  • The two-slot file pool, so no dynamic allocation.

The card-detect pin is no longer used; the old driver configured it and then never read it, and a missing card already surfaces as a failed mount. This library's private SD pin defines are also gone in favour of the ones the arduino-pico Fruit Jam variant already exports.

Cost: about +12 KB of program space and +1.7 KB of RAM per game. The tightest, Burger Time, goes from 62.0% to 62.4% of RAM with 197 KB still free.

src/cpu and src/machines are no longer Pico-specific

A CPU interpreter and a game's memory map have no business naming a vendor SDK. Both layers now contain zero executable references to the Pico SDK; a single new header, src/arcade_portability.h, is the only file outside src/boards/ that knows which chip this is. It provides code placement and two time sources, with arms for RP2040/RP2350, ESP32 and a portable fallback.

Adding a platform is now an arm in that header plus a board backend, rather than a hunt through two layers. The ESP32 arm is written but untested — no ESP32 port exists yet.

This is a refactor with no functional effect: every game is byte-identical across it.

Verified

Five games flashed and confirmed on real Fruit Jam hardware, each exercising a different storage path: Donkey Kong (ROMs, PROMs and the sound-CPU ROM), Galaga (its own 3-CPU ROM checksum passing, and a 14-file directory listing), Ms. Pac-Man (four different filename shapes in one sorted listing, plus the encrypted aux-board decode), Space Invaders (two directories and 88 KB of WAV samples — the only large sequential reads here), and Burger Time (the RAM ceiling, under gameplay, with its AY-3-8910 audio correct).

Also: 13/13 examples build, all 8 host harnesses build, reuse lint 178/178, arduino-lint --library-manager submit reports 0 errors, and invaders_host's 6000-frame scripted-play digest is bit-identical to the stored reference.

Also recorded

extras/DEVNOTES.md #103 documents a measurement that came out of this work and contradicted an existing assumption: moving a CPU interpreter into SRAM, listed in PORTING.md as the project's biggest performance lever, made Space Invaders 5.0% faster and Lunar Rescue 2.5% slower — same core, same one-line change, both results above 8 sigma. It was reverted, and PORTING.md no longer states that lever as an unqualified win. A technique proven on one machine here is not thereby proven for the next.

Flashing

Hold BOOT while connecting USB (or hold BOOT and tap RESET), then copy the .uf2 onto the RP2350 drive. The binaries contain no ROM data — you still need a microSD card with legally-obtained ROMs, laid out as each game's README describes.