The console¶
Three numbers matter to a game more than any other on this page: the composition budget per scanline (a line too busy shows stale, and the budget is per line, not per screen), the display list of 256 entries per frame, and the 320 KiB pool of resident art. All the limits a game lives with are gathered in Constants and limits.
640 × 480 at 60 Hz, 8-bit palettised, 3 000 opaque sprite-pixels per scanline measured, across three genlocked RP2350B running at 252 MHz.
Video¶
| Resolution | 640 × 480 at 60 Hz (4:3), 18.4 Mpx/s active |
| Output | HDMI / DVI |
| Depth | 8 bits per pixel, palettised: index → blend table → RGB565 → RGB888 on the wire |
| Palette | one palette of 256 indices, no banks. Default partition — a per-game setting of the bundle, not wiring: index 0 reserved (transparent), 190 opaque colours (1-190), one system ink (191, the white of the built-in 8×8 arcade font) and 64 effect rows (192-255) ; a game can trade effect rows for opaque colours |
| Blend table | 65 536 × RGB565, 128 KB, rebuilt on the chip from the palette: one lookup per pixel resolves transparency, opacity, translucency, additive, shadow and front/behind priority, no branch |
| Sprites | 3 000 opaque sprite-pixels per scanline measured on the board, about 2 200 blended, roughly 90 opaque sprites of 32 px width per line |
| Sizes | arbitrary and animated; no fixed tile grid |
| Resident art | a 320 KiB pool in RP2's SRAM (450 KB target), owned by RP1: 64-byte pages, bitmaps streamed from RP2's NOR flash on demand by load orders carried in the display list packet, no tearing by a three-frame quarantine |
| Display list | 256 entries of 16 bytes per frame, sent by RP1 over SPI at VSYNC with the palette, the background camera and tile-map writes, and up to 16 load orders (6 928-byte packet, 2.22 ms) |
| Overlay bus | 16-bit at 42 MHz between the sprite engine and the mixer; 484 lines per frame: 480 pixel lines plus four control blocks carrying the palette and camera, the blend modes, the tile-map writes, and one reserved |
| Planes | sprite overlay over background, front/behind priority per pixel |
| Background | 8 × 8 tile map scrolled by the mixer from its NOR flash, or a 128 × 64 toroidal map owned by the game: the background camera and tile-map writes are driven by the game and travel with the display list, a text mode at no display-list cost |
| Latency | two frames plus scan-out, deterministic; no tearing by construction |
For comparison, a Neo Geo manages 1 536 sprite-pixels per line, about half.
Compute¶
| Processors | 3 × RP2350B, dual Cortex-M33 each, six cores total |
| Clock | 252 MHz on all three |
| Synchronisation | genlock from a shared 12 MHz MEMS oscillator on the XIN pins |
| SRAM | 520 KB per chip, 1.5 MB total |
Storage¶
| NOR flash | 3 × 16 MB, one per chip on its dedicated XIP port: sprite atlas, background, code |
| Measured throughput | 33 MB/s, i.e. 550 KB reloadable per frame |
| Removable | micro-SD card on RP1 (FAT32), with card detect: games live in papydeck/games/<name>/, one folder each, hot-plugged |
Launching a game compiles its art bundle into RP2's and RP3's NOR flash: a few seconds the first time, about two seconds from the card's cache, and nothing at all once the NOR flash already holds it. This is a cartridge model, not a loading-screen model.
Audio¶
Designed, not implemented yet: the mixer runs in DVI mode for now.
| Digital | HDMI data islands generated by RP3, no extra components |
| Analogue | I2S DAC on RP1: 4-pole jack and a 2.5 W class-D amplifier into 4 Ω |
| Sample rate | 48 kHz, from an exact PIO divider off 252 MHz |
Both paths exist because many PC monitors have neither speakers nor a headphone output.
Connectivity¶
| Wireless | Wi-Fi (station, network chosen and remembered on the console; HTTPS to the project's server), Bluetooth Classic (BR/EDR) and BLE |
| Gamepads | DualShock 4, DualSense, Switch Pro, 8BitDo… through Bluepad32 |
| Wired | USB-C 2.0 on RP1, the only chip carrying USB: console, firmware updates of all four chips |
| Debug | three SWD connectors, one per chip |
Bluetooth Classic is not a bonus feature: it is what living-room gamepads speak. BLE-only modules will not do.
The board¶
Dimensions¶
60 × 60 mm, four screw holes.
Connectors¶
HDMI type A, USB-C 2.0, micro-SD with card detect, 4-pole audio jack with switch, speaker connector, gamepads/keyboard/mouse on Bluetooth.
One user button.
Power¶
5 V from the USB-C input.
USB power alone is not enough for the nominal case
A USB port advertises 500 mA by default, and the board negotiates nothing on its CC lines. Either the firmware measures those lines to find out what is available, or power comes from elsewhere.
Status¶
Running on the V1 alpha board: genlocked HDMI output; the sprite engine with its pool owned by RP1 and its opaque intervals (3 000 sprite-pixels per line measured); the tile background, a world scrolled from the mixer's NOR flash, or a local text mode driven by the game; games from the micro-SD card, each with its art bundle compiled on the console and installed in the NOR flashes (cached on the card); a game engine (fixed-point actors, collision mask, animations) shared to the byte with the browser simulator; Bluetooth gamepads with pairing from the console's menu, rumble and player LEDs; Wi-Fi with an on-screen keyboard; the published games listed and downloaded onto the card over HTTPS. Watchdogs on the three chips and a universal exit (B or the console button held 3 s).
Still open: audio, pool compaction, an identity for the console (an ATECC608 on the V1 board, signing towards the server), scores sent to the leaderboard.