v2.5.0 "Web Awakens"
Rusty2600 v2.5.0 "Web Awakens"
Second release of the RustyNES gap-closure arc — the headline item here is
the single largest capability gap the whole gap analysis found: a real
winit+wgpu+egui rendering build on the web, replacing the bare
canvas-2D bootstrap that's carried the GH-Pages demo since it first shipped.
Shipped through PR #14, reviewed by GitHub Copilot and Gemini Code Assist —
7 findings, all genuine, all fixed (including a real memory leak in the new
wasm ROM-loading path and a latent wasm32 feature-gate compile-error risk).
Real winit+wgpu+egui rendering on wasm32 (the headline gap)
The GH-Pages demo has always been a bare canvas-2D requestAnimationFrame
bootstrap — a real winit+wgpu+egui build matching the native binary was
explicitly never attempted, honestly documented as such throughout this
project's history. This release makes the real attempt.
The SAME App/Gfx/shader_pass/emu_thread shell the native build uses
now compiles for wasm32-unknown-unknown behind a real wasm-winit
feature (previously an empty placeholder). The hard architectural problem —
Gfx::new_async's adapter/device acquisition can't block the browser's
single JS thread the way native's pollster::block_on does — is solved via
wasm_bindgen_futures::spawn_local, populating a shared
Rc<RefCell<Option<Active>>> cell once ready; every ApplicationHandler
callback already had to treat a not-yet-resumed Active as a no-op, so
this needed no further changes elsewhere. ROM loading routes through a
hidden <input type=file> instead of rfd (a native-only dependency).
Honest status, stated plainly: it compiles cleanly, and a real trunk build produces a working bundle — confirmed loading in headless Chromium,
with run_winit() executing and logging correctly. But the wgpu
adapter-request step itself could not be verified actually rendering a
frame: this sandbox's headless-Chromium-with-SwiftShader environment has no
navigator.gpu and, in this specific setup, wgpu 29's adapter request also
failed to fall back to the compiled-in GL/WebGL2 backend (gl support not compiled in / webgpu found no adapters) — independently reproduced
twice, once during implementation and once during coordinator verification
on a fresh build. This is a likely wgpu-internal webgpu-vs-wgpu_core
backend-dispatch limitation for this target, not something fixable from
this project's own Cargo.toml alone (egui-wgpu's own unconditional
wgpu dependency reintroduces the webgpu feature via Cargo's per-crate
feature unification regardless of what this crate's own Cargo.toml
requests). Real desktop browsers with genuine GPU access — real WebGPU
support, or a real hardware-accelerated GL driver instead of SwiftShader —
may well work where this sandboxed environment could not; that's a real,
open question for a future session with real browser access to confirm.
wasm-canvas (the proven, complete canvas-2D bootstrap) stays the actual
GH-Pages-deployed build for now. wasm-winit is real, committed, and
available to build — just not promoted to the live demo until rendering is
confirmed in a real browser.
GH Pages /api/ rustdoc hosting — already done
Checked before starting any new work: this was already live (confirmed via
a direct HTTP check against the deployed site). No code needed.
Debugger Lua console panel
Lua's print() previously went nowhere useful — real stdout, invisible in
a GUI app. crates/rusty2600-script's Lua VM now overrides the print
global to route into a new capped ScriptLog ring buffer (500 lines,
oldest dropped first), matching real Lua semantics (arguments tab-joined,
re-resolving the global tostring on every call so a script that
overrides tostring still sees that reflected). onFrame runtime errors
are captured into the same log automatically. A new Debug -> Lua Console
panel renders the captured history live, errors in red, with a Clear
button. Output-only — not an interactive REPL (would need to respect the
same WritesLocked determinism gate the normal onFrame tick already
enforces; real additional design work deliberately out of scope here).
Keyboard Controller / Trak-Ball — researched, not modeled
A documentation-only decision, no code change. Checked Stella's own
implementation and properties database rather than assumption: the
Trak-Ball has zero official Atari 2600 releases (only 2 homebrew ROMs in
Stella's database); the Keyboard/Keypad Controller has 40 ROMs including
one real official release (Brain Games, 1978) but remains niche relative
to the whole catalogue. Neither is modeled this arc — deliberately
deprioritized, not a permanent "never."
PR review, for real
7 findings from GitHub Copilot and Gemini Code Assist, all genuine, all
fixed — none dismissed:
- A real memory leak (Gemini, high priority): the wasm ROM
FileReader's
on_loadcallback leaked its heap allocation on every single ROM load
(Closure::<dyn FnMut()>::new+.forget()instead of the
once-per-read-appropriateClosure::once_into_js). - A latent wasm32 feature-gate mismatch (Gemini):
app.rs'sshell.render
call site gatedcheevos/scriptarguments on bare feature flags while
shell.rsgates the matching parameters onall(not(wasm32), feature = "...")— a wasm32 build with either feature enabled would have failed
to compile. - Lua's
print()now re-resolvestostringon every call instead of
capturing it once at install time, matching real Lua semantics. - The wasm ROM-picker
<input>now clears its value before.click(), so
re-selecting the same file reliably fireschangeagain. - A stale doc comment (
log_errorno longer needs to be called by a host
aftertick_frame— it already calls it internally) and two doc/comment
drift fixes (claimingweb/index.htmlbuildswasm-winitwhen it
actually buildswasm-canvas).
Test count
333 tests passing on default features (337 with --features test-roms),
up from 327/331 at v2.4.0. Full CI green — Linux/macOS/Windows, the perf
regression gate, and the no_std gate.
What's next
v2.6.0 "Rollback Bridge" — netplay's WebRTC transport, starting with an
explicit ADR on how far the async-runtime surface it needs can stay
contained to the netplay-feature-gated, wasm-target code path. See
to-dos/ROADMAP.md for the complete v2.4.0 -> v3.0.0 roadmap.