Skip to content

Play overlay (FPS, TURBO, volume, save states) and savestates over the link (1.1) - #3

Merged
TechnicallyComputers merged 2 commits into
mainfrom
feat/runtime-overlay
Sep 27, 2026
Merged

TechnicallyComputers merged 2 commits into
mainfrom
feat/runtime-overlay

Conversation

@TechnicallyComputers

Copy link
Copy Markdown
Member

What

retro_overlay (overlay/) is what a host draws over a running core. It looks and behaves the same whichever core is running.

  • FPS, top left. It counts emulated frames over the time they span, not a mean of 1/dt, which reads high when frames arrive unevenly.
  • >> TURBO, top right.
  • Volume meter on the right edge, for 1.5 s after a change.
  • Toasts.
  • Save-state browser, centre: twelve slots with thumbnails.
    • Opened by SELECT+R1 or the host's hotkey.
    • Face buttons are read and drawn by position, not one console's letters.
  • It depends on no SDL, GL or clock. place() puts every layer in the same spot on every host.
  • The font, boxes and browser layout are the ones psxrecomp, snesrecomp and n64lle already share.

retro_state (state/) implements the savestate envelope CORE_ABI.md "Savestates" specifies.

  • check_state() is its load rule, applied in order. It names both values of the first mismatch.
  • The thumbnail is inside the envelope.

Link 1.1 adds SaveState / LoadState / StateDone, taken between frames.

  • The runner's StateKeeper writes and checks envelopes, and hashes content on a background thread.
  • --load-state checks an envelope and still accepts bare states (n64lle's gates).
  • as_msg now implements the minor rule: it ignores a longer packet's tail and zero-fills a shorter one. LINK_TRANSPORTS.md §10 required that fix before the first minor bump.
  • A 1.0 runner never receives the new messages: CoreLink::states_supported() checks first.

Design and hotkeys: docs/OVERLAY.md. The consumer is Retro Launcher PR (hub feat/runtime-overlay).

Checked

  • ctest: 13/13.
    • New overlay test: FPS method, layers, place(), the browser, InputGuard, every load-rule mismatch, corruption, truncation.
    • New link_savestates test (fake core, which now has a 12-byte state): save after frame 4, load after frame 8, last picture 6; refused on other content; headless load.
  • The hub's real PlaySession, driven offscreen with injected keys against n64lle 0.375.0 / Pokémon Stadium, with framebuffers read back:
    • overlay layers drawn in place;
    • a 2.97 MB state saved in about 40 ms, with a thumbnail of the game frame, and loaded back;
    • events.tsv empty.

Not checked

A real screen, a real controller (the chord, stick repeat), sound and volume by ear. Those verdicts are Alex's.

🤖 Generated with Claude Code

retro_overlay (overlay/): what a host draws over a running core, the same
for every core. FPS (top left, emulated frames over the time they span),
>> TURBO (top right), the volume meter (right edge), toasts, and the
save-state browser: twelve slots with thumbnails, input read by pad position,
requests the host carries to the runner. No SDL, GL or clock; place() puts
every layer in the same spot on every host. The font, boxes and browser are
the ones psxrecomp, snesrecomp and n64lle already share.

retro_state (state/): the savestate envelope CORE_ABI.md specifies, and
check_state(), its load rule in order, naming both values of the first
mismatch. The thumbnail is inside the envelope.

Link 1.1: SaveState / LoadState / StateDone, between frames. The runner's
StateKeeper writes and checks the envelope, hashing the content on a
background thread so the first save does not wait. --load-state checks an
envelope and still takes a bare state. as_msg now ignores a longer packet's
tail and zero-fills down to a pre-append size: the minor rule, fixed before
this first minor bump as LINK_TRANSPORTS.md §10 required.

Tests: retro-overlay-test (FPS method, layers, place(), the browser,
InputGuard, every load-rule mismatch, corruption, truncation); the fake core
gains a 12-byte savestate; link_savestates saves after frame 4, loads after
frame 8 and sees picture 6, is refused on other content, and loads headless.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
OVERLAY.md: the overlay, the browser, the envelope, the hub's hotkeys and how
it was checked (unit tests, the link test, and the hub's PlaySession driven
offscreen against n64lle Pokemon Stadium; a real screen and controller are
not checked). CORE_LINK: the minor rule as the code keeps it, 1.1's messages,
savestates off the not-built list, the Direct-mode keys. LINK_TRANSPORTS §10:
resolved. CORE_RUNNER: the keeper and --load-state. HOST_LIFECYCLE: no State
block (superseded); where hotkeys stand. CORE_ABI: the envelope is
implemented. README: overlay/, state/, link 1.1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@TechnicallyComputers
TechnicallyComputers merged commit d5146fa into main Sep 27, 2026
6 checks passed
TechnicallyComputers added a commit that referenced this pull request Sep 27, 2026
… 1.1) and #2 (build-local)

runner_main.cpp: keep main's pkg_sha (declared outside the package block,
for the state keeper) and --describe's exemption from the package
requirement. build-local.sh --test: 18/18; --describe on n64lle's generic
core with the Pokemon Stadium package prints 76 options and 16 inputs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant