Skip to content

Additional runtime roadmap

Research snapshot: 2026-09-15. The accepted baseline on main is 0.1.7GQ, built from 6b91dcae09bf2dd3bc291d4301edc79edd8b7f0d. The operator confirms walking, CAPS fast-forward and save/reload on the Q. No returned 0.1.7GQ SD diagnostics or measured frame rate have been collected.

The earlier 0.1.6GQ card recorded two clean game returns, 64 ROM banks verified without retries, and no runtime bank retry or fault in its last recorded session. The operator confirmed loading a save after a full power-off/reboot on that version; the latest report does not explicitly repeat that check for 0.1.7GQ.

  1. Preserve accepted 0.1.7GQ and the backed-up save generations. Remaining hardware checks include resident-room startup without SD, the CAPS LED, recovery Cancel, failed-save power handling and an explicit full-reboot save load on 0.1.7GQ.
  2. Collect 0.1.7GQ diagnostics and measure normal and fast-forward play in the same scene before further speed changes. The earlier 0.1.6GQ last-60-frame sample was 50.1 emulated FPS, native 16.6 ms and one LCD update per four emulated frames. It is not a session average or a 0.1.7GQ result. Display smoothness and game speed need separate measurements.
  3. Continue from the completed DOOM host experiment: qualify mutable PSRAM access and measure a combined Q link before integrating the engine. Keep CGB qualification as a later runtime milestone.

The Q display accepts RGB565: 65,536 colors. GameQ now uses four amber shades for DMG games and a full-screen room. The palette change needs no new emulator. The original Game Boy picture is 160×144; scaling and palette selection are display work independent of cartridge compatibility.

The pinned Peanut-GB revision 8e656982f08663785794b84823d3e27f856fdb7f explicitly supports DMG only. Its README points to preliminary CGB work; changing the display palette does not add Game Boy Color emulation. See the pinned README and upstream CGB issue.

Add a later M4: Game Boy Color qualification milestone:

  1. Keep the working DMG runtime as the reference. Compare pinned candidates in the host harness before replacing it. Peanut’s CGB branch and Walnut-CGB are candidates, not selected dependencies. Walnut documents CGB support, RGB565 output options, and changes to ROM callbacks and instruction dispatch.
  2. Measure linked code/state size, bank-cache behavior, frame time, and the display conversion path. Preserve the verified SRAM ROM cache and aligned PSRAM accesses. Multi-byte ROM callbacks must handle bank boundaries.
  3. Run CGB hardware test ROMs, DMG Red regression playback, and save/reload checks; then qualify individual color games on the Q. Confirm supported ROM size, mapper, RAM, and RTC per title before advertising compatibility.

No CGB emulator is added by this roadmap note. A .gbc filename can already be used for a DMG-compatible image; the file extension does not establish Game Boy Color compatibility.

The completed feasibility experiment runs a real Freedoom level for 700 game tics with a 2 MiB host zone and measures a 329,267-byte standalone ARM flash load. It identifies the next gates: qualify mutable PSRAM accesses and measure a combined Q link. No DOOM engine is in the accepted 0.1.7GQ firmware. The original prototype contract below remains a guide to the remaining Q integration.

Use the real native DOOM engine with Freedoom data. Keep it separate from the Game Boy emulator and enter it through the Pokémon hub’s native-game action. The instrumented host replay and standalone ARM link-size report are complete. The Q runtime memory layout remains undecided pending the two gates above.

  • Engine: doomgeneric, candidate pin dcb7a8dbc7a16ce3dda29382ac9aae9d77d21284 (public master observed on the research date). It exposes initialization, frame drawing, timing, input, and one-tick entry points suitable for a small platform adapter.
  • Data: Freedoom 0.13.0, the release linked by the project’s current download page. Begin with Phase 1 and one reproducible level/replay. Record the downloaded archive and WAD hashes as recorded by the feasibility experiment; the initial research downloaded no assets. Its release notes describe improved vanilla compatibility but remaining save-buffer overflow cases, so all-level/save compatibility must be tested separately.
  • Keep the WAD on SD and implement seek/read through FatFs. Upstream’s WAD file interface already supports reading individual ranges; the whole WAD need not live in RAM.
Resource Current evidence Consequence
Firmware payload 1,220,608 of 1,441,792 bytes; 216 KiB free A combined Q link must be measured before adding the engine to the main image.
Internal heap address span 0x20038dc0–0x20097ff8, 389,688 bytes This is the maximum heap span before live MicroPython objects, not available DOOM memory.
GameQ PSRAM ownership Lower 4 MiB; upper 4 MiB reserved for stock RAM disk/recovery Stop/unload the GB session before reusing its lower-half ROM region. Do not assume all 8 MiB are available.
PSRAM writes Existing wrapper and verified loader require word alignment A normal C heap doing byte/halfword writes cannot simply be placed here.
Upstream DOOM zone Defaults and minimum both 6 MiB Upstream defaults exceed current PSRAM ownership. -mb can request less, but level viability must be measured.
Display 320×240 RGB565, requested 60 MHz SPI A 320×200 RGB565 transfer alone takes about 17.1 ms; full-screen 320×240 takes 20.5 ms, before rendering/overhead.

Local evidence: build/firmware/verification.json, build/firmware/gameq-q1.map, third_party/coldcard-firmware/shared/psram.py, and the memory-ownership section of architecture.md. DOOM’s zone defaults and -mb override are in i_system.c.

The current mapped-memory timing fix is a prerequisite to preserve. The DOOM experiment must establish a safe mutable-memory strategy; reducing a constant from 6 MiB to 4 MiB does not solve write width or actual allocation demand. Possible follow-up work is a smaller internal mutable arena plus explicitly managed external asset caches, or a separately verified PSRAM access strategy. Neither is proven by the successful read-heavy Game Boy ROM cache.

  1. Pin the engine and Freedoom archive, preserve notices, and create a host adapter with deterministic controls, frame checksums, allocation high-water marks, largest allocation, and WAD read totals. Run the same first-level replay with constrained zone sizes, starting at 4 MiB.
  2. Disable sound/network backends initially. Render a 320×200 indexed frame (64,000 bytes) and convert palette indices into one RGB565 scanline at a time. Explicitly remove redundant display buffers: upstream doomgeneric.c allocates four bytes per output pixel even when CMAP256 is selected. Merely selecting indexed output does not reduce that allocation. The engine also owns I_VideoBuffer in i_video.c.
  3. Compile the same engine with the existing Cortex-M4 toolchain and export flash/BSS/stack estimates. The minimal SD updater and wallet-module removal shipped in 0.1.5GQ, so that space saving is already reflected in the budget above. Preserve the working update path when assessing further size changes.
  4. Once memory and link gates pass, add the Q adapter: arrows to move/turn, Z to fire, X to use/open, a run modifier, number keys for weapons, and Cancel back to the hub. Return control to the shell between bounded engine ticks for keyboard/power handling; contain quit/fault paths rather than calling a process-wide exit().
  5. Physical acceptance: enter a level, move/fire/open doors, record frame time and memory high-water marks, exit/re-enter from the hub, then verify a DOOM save and restore. Keep this distinct from Pokémon cartridge saves.

The Q implementation is not yet present. The host replay and standalone ARM link are measured; Q performance and a safe complete memory layout are not. The constraints support a concrete porting experiment, not a claim that a full Freedoom campaign already fits or runs at a given FPS.

doomgeneric identifies its engine as GPL-2.0; source headers permit version 2 or later. Freedoom’s license permits source/binary redistribution with its notices retained. The current Coldcard tree’s COPYING-CC is MIT with the Commons Clause. Record these separately and resolve combined-image redistribution compatibility before publishing a DOOM-containing firmware; private implementation research can proceed without changing the working firmware’s licensing declaration.