Skip to content

v2.8.0 "Touchpoint"

Choose a tag to compare

@doublegate doublegate released this 02 Jul 22:46

Rusty2600 v2.8.0 "Touchpoint"

Fifth release of the RustyNES gap-closure arc — the first wave of
wasm-winit web parity, building real interactivity on top of v2.5.0's
bare wasm render.

Shipped through PR #18, reviewed by GitHub Copilot and Gemini Code
Assist — 6 findings, 5 fixed, 1 dismissed with documented evidence.

On-screen touch controls (the headline)

A D-pad + fire button + console-switch row for the wasm-winit build
(ShellState::render_touch_overlay, wasm32-only), since a browser user
on mobile Safari/Chrome has no physical keyboard. All plain egui
widgets, feeding the exact same InputState the keyboard path
populates, via a new input::TouchButton/TouchOverlayState pair:
pure, target-agnostic press/hold/release + latch-edge tracking, unit-
tested under the ordinary native cargo test --workspace run (not
gated to wasm32-only, so this logic is exercised on every CI platform).

Latching switches (Color/Difficulty) toggle exactly once per press
rather than re-toggling 60 times a second while held; momentary buttons
(joystick directions/fire, Select/Reset) emit a press/release edge
matching how a real key's keydown/keyup already drives them. Defaults
visible (a touch-only device has no other way to drive the emulator);
View -> Touch overlay toggles it off for a desktop-browser user who
does have a keyboard.

Honestly documented limitation: egui-winit's default touch handling
tracks one synthesized pointer, so true simultaneous multi-finger
combos (holding a direction while also tapping Fire) aren't guaranteed
to both register — a real egui/egui-winit constraint, unverifiable
either way in this project's sandbox (no real touchscreen), not
something this release introduces or works around.

Settings panel + console-switch buttons — verified, not built

Reviewed the Settings window tab-by-tab for wasm32-safety: the Video/
Audio/Input/System tabs are plain egui widgets with no native-only API
in the path (no rfd dialogs, no blocking file I/O), so the panel
already worked correctly on wasm32 structurally — no code needed there.
Console-switch buttons were likewise already reachable "for free" via
the shared Emulation -> Console switches menu on both native and
wasm32. The real gap this release closes is persistence (below) and the
touch-friendly on-screen row, for a user who can't easily reach a
dropdown menu with a finger.

Real localStorage config persistence

Config::save()/Config::load() now genuinely persist on wasm32 via
web_sys::window().local_storage(), replacing a previous no-op stub
(and a previously-nonexistent load()). Shares TOML (de)serialization
helpers with the native config.toml file path, so both backends are
covered by one set of native unit tests. Falls back to defaults on any
missing/corrupt/foreign stored value, never blocking launch.

Save-state SLOT persistence (v2.4.0's manual save slots) is
deliberately deferred — it needs per-slot localStorage keys, an
mtime substitute (localStorage has none), and real size budgeting
across 8 slots within the ~5-10MB origin quota, a distinctly bigger
lift than the single-key Settings value above. Documented in
docs/frontend.md rather than rushed alongside this release's headline
items.

PR review, for real

PR #18 was reviewed by GitHub Copilot and Gemini Code Assist — 6
findings:

  • Draggable touch-overlay Areas (Gemini Code Assist): egui::Area
    is movable by default, so the D-pad/fire/console-switch overlays
    could be accidentally dragged by a touch. Fixed with .movable(false)
    on all 3.
  • A wasted per-frame audio-sample allocation on wasm32 (Gemini Code
    Assist): the Vec collecting DC-blocked samples was allocated and
    populated every frame (60 times/sec) even on wasm32, where nothing
    reads it (audio_tx is native-only, wasm-winit audio being an
    explicitly deferred stretch goal). Fixed — now gated to native only;
    the DC-blocker filter state still advances every sample on both
    targets, since that state must stay correct for whenever wasm32 audio
    eventually gets wired up.
  • A misleading doc comment (Copilot): TouchOverlayState's doc
    comment claimed momentary buttons "emit their live level every
    frame" — the code was already correct (edge-based, matching
    keydown/keyup), only the comment was wrong. Corrected.
  • A false-positive claim (Gemini Code Assist, dismissed with
    evidence): that this project's && let chain syntax "will cause
    compilation to fail on stable Rust toolchains." This project's
    edition is 2024 (let-chains stabilized since Rust 1.88), the exact
    same pattern is already used in emu_thread.rs (merged in v2.7.0),
    and CI for this very PR had already passed on Linux/macOS/Windows
    with this exact syntax on stable rustc 1.96. Dismissed rather than
    "fixed" into a stylistic regression.

Test count

342 tests passing on default features (346 with --features test-roms) — up from 333/337, the 9 new tests covering
TouchButton/TouchOverlayState and the shared TOML (de)serialization
helpers. Full CI green — Linux/macOS/Windows, the perf regression gate,
and the no_std gate. Independently re-verified beyond the standard
gate: cargo check/cargo clippy --target wasm32-unknown-unknown --features wasm-winit and cargo check --target wasm32-unknown-unknown --features wasm-canvas (the other wasm build, confirming no
regression) both clean.

Honest verification boundary

Live in-browser interactive verification (touch input actually working
on a real touchscreen) remains blocked by the same sandboxed-headless-
Chromium GPU limitation v2.5.0 already documented — this sandbox
can't render wasm-winit at all, let alone drive it with touch.
Everything verifiable without live browser GPU access (unit tests,
wasm32 compile + clippy checks) has been confirmed.

What's next

v2.9.0 "Full Circle" — Web Parity Wave 2: in-browser Lua scripting, a
share-link feature, PWA install, and a wasm debugger overlay, closing
the remaining wasm-demo capability gap against RustyNES. See
to-dos/ROADMAP.md for the complete v2.4.0 -> v3.0.0 roadmap.