Skip to content

v2.9.0 "Full Circle"

Choose a tag to compare

@doublegate doublegate released this 03 Jul 00:00

Rusty2600 v2.9.0 "Full Circle"

Sixth release of the RustyNES gap-closure arc — closes the remaining
wasm-winit capability gap against RustyNES's own wasm demo: a
share-link feature, PWA install, and a wasm32-safe debugger overlay —
plus a real, not re-deferred, investigation into in-browser Lua
scripting that concluded honestly deferred.

Shipped through PR #19, reviewed by GitHub Copilot and Gemini Code
Assist — 2 findings, both fixed.

?settings= share-link

Round-trips the whole Config (region, video, audio, both players' key
bindings) through a hand-rolled, URL-safe base64 codec — pure and
target-agnostic, so the encode/decode logic is exercised by 7 new native
unit tests without touching a single browser API. Applied on boot,
overriding Config::load()'s persisted localStorage value when a
?settings= parameter is present in the URL. Deliberately settings-only
(no ROM reference) — neither the native rfd file dialog nor the wasm
<input type=file> picker has a URL a share link could carry, so a
recipient still picks their own ROM file.

A wasm32-safe debugger overlay

debug-hooks is now confirmed wasm32-safe for wasm-winit: the CPU/
TIA/RIOT/Memory panels plus nearly every other native debugger panel
(Watch, Callstack, Events, Player-Missile-Ball, Access, Compare,
TAStudio's jump-to-frame) work identically in-browser. The one
exception — TAStudio's "Save branch" action, which needs rfd's
native-only save-file dialog — is scoped out specifically
(MenuAction::TastudioSaveBranch is not(target_arch = "wasm32")-gated)
rather than excluding all of debug-hooks from the wasm build.

PWA install

A web app manifest plus a service worker (web/manifest.json,
web/sw.js) make the deployed build installable ("Add to Home Screen" /
desktop install prompt) and usable offline after a first visit. Since
Trunk hashes build filenames per release, a static precache manifest
would go stale every rebuild — instead the service worker runtime-caches
same-origin GETs: cache-first-then-revalidate for sub-resources (wasm,
JS glue, CSS, icons, manifest), network-first for the app-shell
navigation request (see the PR review fix below for why that split
matters).

In-browser Lua scripting — investigated for real, deferred with a confirmed reason

This crate's own module doc has flagged a piccolo-backed wasm fallback
as a "genuine, scoped follow-up" since it was first built. This release
actually did that follow-up investigation rather than re-deferring on
the same old reasoning:

  • mlua on wasm32 is confirmed, again, a hard wall. A direct
    build attempt (cargo check --target wasm32-unknown-unknown -p rusty2600-script) fails inside lua-src's build script: "don't know
    how to build Lua for wasm32-unknown-unknown." The vendored C build
    genuinely cannot target that toolchain — not a bug to work around.
  • piccolo is not yet a workable substrate either, for two
    compounding reasons: its only crates.io-published release (0.3.3)
    implements almost none of Lua's string/table stdlib — per its own
    README, ruling out exactly the kind of ordinary script this crate's
    emu API invites (string.format for a debug label, table.insert
    for per-frame state tracking); and its Executor-based "stackless"
    VM architecture (a gc-arena-rooted, Send-incompatible design) has
    no equivalent to engine.rs's "keep the VM around, call into it once
    per real frame" pattern without building real gc-arena/Rootable!
    plumbing from scratch — a genuine engine rewrite, not a parallel
    engine_piccolo.rs sibling. Its more-complete unpublished master
    branch is explicitly labeled pre-1.0-unstable by its own maintainer.

Native's mlua backend is completely unchanged — same crate, same
version pin, same feature gating. Documented in crates/rusty2600- script/src/lib.rs's module doc and docs/scripting.md; revisit once
piccolo publishes a crates.io release with real string/table
coverage — an upstream milestone, not one this project controls or can
schedule against.

PR review, for real

PR #19 was reviewed by GitHub Copilot and Gemini Code Assist — 2
findings, both genuine, both fixed:

  • A real cache-safety bug (Copilot): the service worker's
    activate handler deleted every cache except its own CACHE_NAME
    but Cache Storage is origin-wide, not scoped to one service worker, so
    this could have wiped a sibling GitHub Pages project's caches sharing
    the same origin. Fixed by filtering on a CACHE_PREFIX instead, so
    only a previous Rusty2600 shell cache is ever evicted.
  • A real offline-breaking race condition (Gemini Code Assist, high
    priority): stale-while-revalidate on the index.html navigation
    request, combined with Trunk's hashed sub-resource filenames, could
    leave a later offline visit with HTML referencing hashed assets that
    were never actually fetched (if the background revalidate silently
    updated the cached HTML to a newer version before those new hashed
    assets were ever cached). Fixed by switching navigation requests to
    network-first; sub-resources keep cache-first-then-revalidate, since
    they're effectively immutable-by-hash.

Test count

349 tests passing on default features (353 with --features test-roms)
— up from 342/346, the 7 new tests covering the share-link base64 codec
and its encode/decode round-trip. 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 the new
--features wasm-winit,debug-hooks combination (the wasm debugger
overlay) both clean; --features wasm-canvas (the other wasm build)
unaffected.

Honest verification boundary

Live in-browser verification (the share-link actually round-tripping
via a real browser URL bar, the service worker actually caching
offline, the debugger overlay actually rendering) remains blocked by
the same sandboxed-headless-Chromium GPU limitation documented since
v2.5.0 — this sandbox can't render wasm-winit at all. Everything
verifiable without live browser GPU access (unit tests, wasm32 compile +
clippy checks) has been confirmed.

What's next

v2.10.0 "Prism" — Shader Stack Expansion: a higher-quality NTSC
composite demodulation pass, hqNx/xBRZ upscaling, and a constrained
RetroArch .slangp/.cgp preset importer, growing
rusty2600-gfx-shaders beyond its current CRT scanline + composite-
artifact approximation. See to-dos/ROADMAP.md for the complete
v2.4.0 -> v3.0.0 roadmap.