Skip to content

Physical Q test: 0.1.7GQ

Automated checks do not establish physical-Q acceptance. Record the GameQ commit and the DFU SHA-256 with the results below.

On September 15, 2026, the operator reported that the update was working well and explicitly confirmed walking, CAPS speed toggling, and save/reload. The staged firmware was built from 6b91dcae09bf2dd3bc291d4301edc79edd8b7f0d; its DFU SHA-256 is 1af09ded8f4e82b760d5a5b7b9b90d1bee30d8b303995b6a6a4897c27c07c303. This is the accepted gameplay baseline on main.

This confirmation is an operator report. The SD card has not been returned for 0.1.7GQ diagnostics, so no new FPS, load-retry or save-checksum measurements are claimed. Full power-off save loading was explicitly confirmed on 0.1.6GQ below; the 0.1.7GQ report did not specify a power cycle.

Remaining explicit hardware checks include the CAPS LED, no-SD room startup, complete redraws after dialogs, recovery Cancel, and the failed-save shutdown path. These remain separate from the confirmed gameplay and save/reload checks.

The clean firmware build passed 274 tests. Additional checks covered 54,000 matching host replay frames, 11 Cortex-M4 renderer cases and 180 Red frames, plus the final linked firmware’s 38 PSRAM-controller, 8 verifier and 17 display error-recovery cases. These do not measure physical peripheral timing.

The September 15, 2026 run used 0.1.6GQ at da619457e4332851c9ddc7b072f52516403db1ee. The preserved DFU matches SHA-256 9f4d56ee42c40def565f191bc42694f8efd8a163bcebf40c0a53ef08f660d08a. Evidence is preserved locally under build/reviews/physical-0.1.6-success-20260915-121105.

  • Operator report: Pokémon Red’s in-game SAVE and subsequent load worked both after returning to the room and after fully powering off and rebooting.
  • Save validation: both 32 KiB generations pass the pinned Red main checksum and CONTINUE saved-name presence check. The current and backup checksums are FE and A1; the files differ in 34 bytes and record play times of 00:05:51 and 00:05:17. These are two valid, distinct save generations.
  • Room trace: two Red launches in one boot, each followed by a clean return reporting cartridge RAM saved to SD.
  • Latest ROM load: 64 banks, 64 complete scans, zero retries and zero failures.
  • Retained game session: 3,057 frames; 63 bank loads, zero retries and no captured native fault. The final 60-frame window was normal-speed 50.1 emulated FPS / 16.6 ms native time, rendering one in four emulated frames (about 12.5 display updates per second). This is not a whole-session average. The session recorded zero fast-forward toggles.
  • Old error file: last-error.txt is byte-identical to the prior 0.1.5GQ PSRAM failure. It is retained history, not a new error from this run.

This run did not test fast-forward or its LED. It does not identify which verification/timing change resolved the earlier failures.

Terminal window
git checkout main
git pull --ff-only
make pokered hub
make firmware
make sd SD=/Volumes/GAMEQ
shasum -a 256 build/firmware/gameq-q1.dfu

When updating the Q running 0.1.6GQ, put for-version:0.1.6GQ in GameQ/system/recovery on the card. The installed version enters GameQ recovery; 0.1.7GQ ignores this older version’s marker after installation.

Eject the card, insert it in slot A, and reboot with USB power connected. In GameQ recovery, use Left/Right to select gameq-q1.dfu and Enter to load and verify it. Enter the existing PIN if requested, then confirm Install this new firmware?. Keep power connected through the immutable developer warning and update. For older installed versions, see build.md.

Confirm the 0.1.6GQ-scoped marker reaches GameQ recovery and the update completes. Check that Cancel returns to the room before starting the update. For a later recovery test on 0.1.7GQ, use for-version:0.1.7GQ.

An empty GameQ/system/recovery file instead keeps recovery active across versions until removed. A valid but crashing application does not automatically enter bootloader recovery; see build.md.

The renderer sends only changed LCD rows and forces a redraw after clearing, width changes and display faults. Diagnostics add selected frames, source rows seen/sent, pixel bytes and window counts. Walking and CAPS speed toggling passed the operator test; quantitative physical speed and smoothness have not been measured for this version.

A failed save during a power-button hold now keeps the game paused in memory. Enter retries saving and shuts down after success; Cancel returns to the same game; X opens a separate discard-and-shutdown confirmation. Emulation remains paused while the dialog is open.

First compare normal and CAPS play in the same scene, then return to the room and relaunch to check complete redraws and save continuity. After that, an optional failure-path check is to remove the SD during play and hold Power: the game must remain paused, and reinserting the card must allow saving before shutdown. Cancel must resume the same game with its RAM intact.

Load verification fetches each PSRAM word once and allows three read-only scans per bank. A complete scan must match; failed scans are never pieced together. Source fingerprints distinguish changed SD reads from PSRAM mismatch. The runtime selects 30 MHz PSRAM and shares a 4-microsecond pause between 64-byte bursts. Failed loads now record their own verification status and retry/mismatch telemetry. The physical run above passed without retries; the cause of the earlier failures is not isolated.

The full-screen resident room, metadata filtering, fast-forward LED and authenticated recovery updater remain. Gameplay retains 266×240 amber output, ten verified cache slots, adaptive display cadence and uncapped fast-forward. The physical timing sample above covers normal mode only.

  1. Power off, remove the SD card, and boot. Confirm GameQ opens a walkable Red-engine room covering all 320×240 pixels. Walk and open the clerk’s desk.
  2. Insert the game card in slot A and use Rescan SD card. A card containing only Pokémon Red plus the legacy hub and macOS metadata should report one game. Walk with arrows and press Z facing each shelf or the clerk. Empty shelves should explain that they are empty. The clerk opens controls, rescan and system info.
  3. At a populated shelf, confirm the filename with Enter. Pokémon should load without a PSRAM error and use four amber shades at 266×240, with narrow side bars. Return with Cancel and repeat the load three times, including once after a reboot. Preserve diagnostics if any load fails.
  4. Check held arrows, and Z/X while holding a direction. Z = A, X = B, Enter = Start, Backspace = Select.
  5. Press the physical SHIFT/CAPS key once for fast-forward, again for normal. Holding it must toggle only once. Confirm the NFC activity LED follows the mode and turns off when leaving play. Speed is uncapped; no fixed multiplier is promised.
  6. Use Pokémon’s SAVE menu and confirm it with Z. Leave the SD inserted. Press Cancel to return to the room and flush cartridge RAM.
  7. Confirm the player returns to the same shelf. Relaunch Pokémon, select CONTINUE, and verify the saved location/name. Then repeat after a reboot.
  8. Open the clerk’s System info to record the last game’s mode, FPS/native time and save result. Compare a normal-speed play with a fast-forward play.
  9. Check room collision, all shelf positions, settings return, Cancel, power handling and a short battery-powered run. DOOM is not installed in this build.

Keep the card inserted during saving. The firmware cannot make an arbitrary FAT filesystem immune to power loss; test normal save/relaunch before fault injection. Previous-save recovery is covered by host tests, but SD power-loss behavior still requires the device. .sav.bak retains the previous generation; emulator faults write a separate .crash.sav without replacing the normal save.

If a step fails, record the last screen and exact error, power source, SD slot, card format, and commit. If a shelf unexpectedly opens GameQ desk, record which shelf and key did it and preserve the card diagnostics before another attempt. Use the recovery marker to enter the updater. See build.md for its limits.

Before emulation, GameQ compares the ROM in PSRAM against a second SD read or a second decode of the resident room. It verifies every bank admitted to the internal SRAM cache against its recorded fingerprint, with bounded retries. A persistent mismatch stops startup or emulation with its offset or bank number. These checks remain enabled in 0.1.7GQ.

After leaving a game with Cancel or encountering an emulator fault, inspect these files in GameQ/system:

  • diagnostic.txt: version and cartridge, CPU/memory state, speed mode, emulated FPS, display cadence, native timing, free heap, bank loads/retries, cache fingerprints and early samples from frames 1, 10 and 60.
  • last-frame.pgm: the 160×144 grayscale source image before scaling and SPI, useful for separating emulator faults from display faults.
  • rom-check.txt: this transfer’s success or failure, PSRAM timing, requested banks, full scans, retries, rejected checks and last mismatch. A recovered mismatch remains visible even when verification eventually passes. Source mismatch values are fingerprints; PSRAM mismatch values are bytes.
  • diagnostic.txt also records LCD transfer counts: selected frames, source rows seen/sent, pixel bytes and windows. Counts reset at cartridge start; compare the rows seen and sent to measure avoided work.
  • bank0.bin: the internal SRAM copy of ROM bank zero.
  • hub-trace.txt: the last 16 room boundaries, including the native command, mailbox, raw keyboard matrix and returned result before/after display cleanup.
  • last-error.txt: the latest startup or session exception, kept separately so successful room interactions do not erase it.

Room boundaries also capture the native command, full mailbox, Game Boy button mask and raw Q key matrix before display cleanup. This distinguishes a settings mailbox request from a raw Cancel exit. The captured outcome also preserves a shelf request if an async return unexpectedly becomes empty. The 0.1.5GQ captures all matched their returns; the earlier desk behavior’s cause remains unknown.

For canonical Red, a trap at the first opcode fetch from 0x0038 preserves the fault state before its runaway RST38 loop can overwrite RAM. Faults also write wram.bin, vram.bin and hram-io.bin. Those raw files may remain after a later clean run; diagnostic.txt states whether they belong to its run. Other ROMs retain normal RST38 behavior.

Return the card to the computer after a normal exit and power-off. Preserve both save generations and the diagnostic files before another test.

  • 0.1.1GQ: intermittent PSRAM mismatch at 0x017a8f; retries sometimes reached Red’s title and Oak dialogue. That run reported 22.6 FPS / 34.9 ms native time. Its written SRAM buffer did not establish a valid in-game save.
  • 0.1.2GQ: aligned word transfers passed ROM readback, but gameplay still became blank. The late state at frame 463 showed a RST38 loop that had already overwritten emulated RAM, so it did not identify the first fault.
  • 0.1.3GQ: verified bank caching, PSRAM chip-select timing and first-fault trapping accompanied successful naming and walking, plus an in-game save interaction. The retained run reached 12,231 frames at a final 20.1 FPS / 40.9 ms native sample, with 185 bank-copy retries. That copied save was not valid, and reload was not tested. This version used four switchable cache slots and the smaller green image. The evidence does not isolate which change resolved the earlier corruption.
  • 0.1.4GQ: the full-screen room appeared, but its interactions opened GameQ desk. The card contained one game and two hidden .gb metadata files that the old catalog incorrectly counted. A first-boot “Yikes” did not recur.
  • 0.1.5GQ: two shelf-zero requests reached cartridge loading and failed PSRAM verification at 0x0a1029 (b1 != e7) and 0x0a58a9 (a8 != b7). The resident room recovered, all 12 captured mailboxes matched their returns, and saves were unchanged. Earlier desk requests had no captured initiating input. The old rom-check.txt still showed a 0.1.4GQ success because failed transfers did not update that file; last-error.txt and hub-trace.txt captured the failures.

To check the compiled PSRAM timing helper against modeled controller states, run python tests/arm_psram.py build/firmware/gameq-q1.elf with unicorn and pyelftools installed. It covers completion flags, mode and DMA guards, stuck transfers, readback failures and interrupt restoration. It does not simulate electrical timing or replace the physical tests above.