Repository navigation
RustyNES v3.5.0 — "Chorus" (creator tools: the full movie input stream, Lua WebSockets and shared memory, an MCP server, speedrun timing and dump checks; and the MiSTer core's MMC5, VRC6, Namco 163, VRC7 and Bandai FCG boards, off the die)
LatestRustyNES v3.5.0 — "Chorus"
Movies recorded before v3.5.0 are refused, and so are movies and netplay peers from v3.4.x. Movies are .rnm format 7, which records every input the core takes; a format-6 movie is refused with the reason ("re-record it"). The MMC5 scanline fix moves frames and audio of MMC5 games, so the emulation epoch is 6: a movie or netplay peer from epoch 5 is refused with both epochs named. On the MiSTer core, v3.4.x save states are refused on both builds.
v3.5.0 is a creator-tools release. Movies record the Zapper and the other expansion devices, the microphone, Vs. coins, FDS disk swaps and Datach barcode scans. Lua scripts gain a real WebSocket client and real OS shared memory. A new binary, rustynes-mcp, serves the headless core to a Model Context Protocol client, with reproducible fork-and-diff experiments. Speedruns can be timed in master-clock cycles from RAM conditions, with a fixed-layout memory interface for splitters, and rustynes dump-check reports whether a ROM file is the dump it claims to be. The desktop gains an A/V sync offset for recordings, Multi-Disk bundles and rebindable peripheral keys; the browser gains drag-and-drop, and its lightweight embed runs Vs. DualSystem cabinets. The MMC5's scanline IRQ came a whole line early; it now follows the NESdev page. The hosted TURN relay is switched back on. On the MiSTer core, the off-die headline build adds the MMC5, the VRC6 and Namco 163 with their audio, the VRC7's banking (silent), the Bandai FCG boards, and the Famicom keyboard, P2 microphone and Power Pad; the on-die RustyNES_Lite keeps v3.4.x's boards.
Breaking changes
.rnmmovies are format 7; a format-6 movie (v3.1.0 to v3.4.x) is refused with the reason.rustynes verifyattestations are version 3.TAStudioprojects are written as.rnmprojversion 2, which a v3.4.x build refuses as too new; version-1 projects still load.- The emulation epoch is 6 (ADR 0045), for the MMC5 scanline fix below: a movie or netplay peer from epoch 5 is refused with both epochs named. An MMC5 save state from v3.4.x is refused; other boards' states load. Netplay protocol 9 is unchanged.
rustynes-coreAPI:FrameInput::apply_toandFrameInput::held_onare no longerconst fn;FrameInputgainsextra: Option<ExtraInput>. Additive:Mapper::snoops_ppu_reads/notify_ppu_readandPpuBus::notify_ppu_read, each with a default.- MiSTer core: a v3.4.x save state is refused on both builds (the layout fingerprint moved: on the die
0CF5891F, 4,097 bits; off the dieF27C2FF4, 4,736 bits), and the OSD's Controllers option moved to status bits 23:21, so an older saved configuration reads as Gamepads.
Added
- Movies record every input the core takes besides the controllers: each port's expansion device (Zapper, Vaus, Power Pad, Family Trainer, SNES mouse, the Family BASIC and Subor keyboards, both Hyper Shots), the microphone, both Vs. coin acceptors and the service button, FDS disk swaps and Datach barcode scans. Recorders read them off the machine, so the desktop, browser, Android and iOS record them with no change of their own. A recording allows a disk swap, a scan and a coin; playback and netplay still refuse them.
TAStudioprojects keep players 3 and 4 and these inputs. - Lua WebSockets (
comm.ws_open/ws_send/ws_close,ws://andwss://) and real shared memory (comm.mmfWrite/mmfReadover a per-user, owner-only OS region another program can open by name), both in thescript-ipcfeature. Destinations follow the HTTP rule;docs/scripting.mdhas the layout and the threat model. - An MCP server,
rustynes-mcp(ADR 0048,docs/mcp-server.md): one ROM served over stdio with 25 tools — pause, stepping, breakpoints, side-effect-free reads, a work-RAM-only write, the frame as a PNG, nametables as tile text, OAM, sandboxed read-only Lua, andfork_create/fork_run/fork_diff. Every fork records its inputs as an.rnm, andmovie_verifyreplays it byte for byte. No network listener. - Speedrun auto-timing: a splits file names start, splits and reset as RetroAchievements-style RAM conditions, and the run is timed in master-clock cycles, so a movie gives the same splits on every machine.
rustynes speedruntimes a movie headlessly;--splitstimes a live session; with thememiffeature,--memifpublishes a fixed-layout memory block every frame for LiveSplit-style tools (docs/memory-export-interface.md, ADR 0047). rustynes dump-check: hashes, a match against a No-Intro DAT you supply, the header against an NES 2.0 database you supply and against RustyNES's own corrections, a suspected overdump, truncation or trailing data, and the header against what the program does when run. RustyNES ships no DAT or database.- Desktop: an A/V sync offset for recordings (Settings → Recording), Multi-Disk bundles (
.rnbundle: an FDS game dumped one file per disk plays as one disk set; a bundle of cartridges adds an Emulation → Multicart menu), and rebindable microphone, Power Pad and Family BASIC keyboard keys (Settings → Input → Device keys). - Browser: drop a ROM, a movie or (full build) the FDS BIOS onto the page to load it, and the lightweight canvas embed runs both consoles of a Vs. DualSystem cabinet side by side, with
F10inserting a coin.
Changed
- The hosted TURN relay is on again. It was held off in v3.4.1 and v3.4.2 because Cloudflare kept relaying for expired and revoked credentials. A stricter test found it still relays for them but never bills that traffic, so the cost is bounded by credentials within their three-hour lifetime, which the per-address and daily limits already bound. Players whose networks cannot connect directly can play online through the relay again. The privacy policy says what is kept while the relay is on.
- The emulation thread runs at a raised priority on Windows and macOS too, one step above normal on Windows and the
USER_INTERACTIVEclass on macOS, below the audio thread; Linux was already elevated. - The host warning codes live in the emulation core, so every frontend takes a warning's code and wording from one place. The apps show no change.
- Provenance: the Power Pad's serial layout is recorded as derived from Mesen2 (a
// Provenance:header, a row indocs/originality-and-provenance.mdand aNOTICEline), the conservative reading of a v1.1.0 comment citing it. No code changes.
Fixed
- The MMC5's scanline IRQ came a whole line early, and counted with rendering off. The chip now watches the PPU's reads as the NESdev page describes: the read after three consecutive reads of one nametable address is the detection (the attribute fetch, dot 4), line N reads N, and "in frame" clears when reads stop, on a
$2001write with rendering off, and on a$FFFA/$FFFBread. Uchuu Keibitai SDF's playfield grid now has an even 8-pixel pitch; Castlevania III, Gemfire and L'Empereur change in audio only. No test ROM measures MMC5 IRQ timing: the fix rests on the NESdev page, blargg's 2005 hardware timings (line resolution) and that grid. The page's pseudocode detects two dots earlier than its prose; both cores take the prose, and the question is recorded for hardware. - RetroAchievements on the desktop and mobile apps read the wrong memory for cartridge RAM. RetroAchievements addresses NES memory as the CPU bus, but the native client put cartridge RAM at
0x0800, so a condition on a cartridge-RAM address read nothing and one on a RAM mirror read cartridge RAM. Addresses now pass through unchanged, as the browser build and the RetroArch core already did. - The browser builds kept every file they opened in memory, a whole buffer per ROM or movie for the rest of the session; each read now frees itself when it ends.
- Netplay: the Vs. coin hotkey inserted a coin on one peer only; inserting a coin is now refused during netplay and movie playback. On Android and iOS a disk swap or a coin no longer desyncs online play: both are refused during netplay and playback, with the reason shown.
- Android and iOS check a custom relay address with the core's own parser, which also refuses a non-numeric, out-of-range or empty port at connect time instead of dialling the default port.
- A recorded Vs. coin is held for the frames it ran with; the history timeline survives a disk swap or a barcode scan; hosted TURN credentials with an empty username or password are refused; browser RetroAchievements reads its proxy address when a session starts (browser RetroAchievements stays off on the public demo).
Not changed, and why
- Netplay carries none of the new inputs (protocol 9): a session exchanges one controller byte per player per frame and refuses disk swaps, scans and coins, so nothing diverges.
- Reset and Power Cycle are still not recorded; foreign movie imports still carry controllers only.
- The MiSTer core's VRC7 is silent: its FM synthesis moves to v3.8.0, because the public documentation does not determine it and the oracle's
opll.rsis a derived region. The Namco 163 does not answer a CHR-ROM page as a nametable (Mappy Kids after its title screen). No Miracle Piano on either core.
The MiSTer core
- Release candidate, not hardware-verified. No hardware has run either bitstream, and the SDRAM pin constraints are still provisional.
- The Lite tier.
RustyNES_Lite(on the die) keeps exactly the boards it carried in v3.4.x; every board added from v3.5.0 on is in the off-die headlineRustyNESonly, and the Lite build refuses it as an unsupported mapper.tier-gatechecks the RTL's own decision for every mapper and submapper at both builds against the published table. - New boards, off the die only: the MMC5 (5) with ExRAM, extended attributes, split screen, the multiplier, its pulses and PCM, and the scanline IRQ, which detects scanlines from PPU reads as the oracle now does; the Konami VRC6 (24, 26) with its audio; the Namco 163 (19) with its wavetable audio; the Konami VRC7's (85) banking, WRAM and IRQ, silent; the Bandai FCG boards (16, 153, 159) with their serial EEPROMs. Each has bus, checkpoint and save-state gates against the oracle, and commercial frame gates, among them Castlevania III's frame 440. Where the oracle departs from the NESdev pages or the EEPROM data sheets, a module gate grades the page and the ladder records the disagreement as an expected failure.
- The Famicom peripherals: the Family BASIC keyboard from a PS/2 keyboard, the Power Pad on port 2, and the second controller's microphone, gated against the NESdev pages.
- Provenance disclosures (the sibling's
docs/provenance.md, "Disclosures"): three reads that touched derived regions of the oracle while this release was written, none of them used: the oracle's Power Pad region, read before it carried its header (the RTL follows the NESdev page and is gated against it); the comment above the oracle's EEPROM model (the data sheets were followed); and the Namco 163's output level, seen in a search result (the RTL's level comes from the NESdev page's measurements, and the audio comparison is blind to a uniform scale). They are recorded for outside review, not certified clean. - The MMC5 detector was checked by mutation: six deliberate defects, three caught at once; one (the 241st-line exit) is unreachable, since line 240 makes no reads, and the other two were caught after a new stimulus that reads the IRQ status by hand (
mapper5irqack406). - The oracle pin moves to v3.5.0 (this release's merge,
5d441f44):VERIFY=1reproduces all 256 stems and 1,156 artifacts byte for byte. - The co-simulation ladder: on the die 315 passed, 0 failed, 4 expected failures; off the die 365 passed, 0 failed, 10 expected failures. The four on both are
chrram-fetch(18 of 185,725 fetches), Mississippi Satsujin Jiken frame 140, Micro Machines frame 71 and the Sunsoft 5B timed gate; of the six off the die only, five are where the oracle departs from the NESdev pages or the EEPROM data sheets (two Bandai EEPROM stimuli, the VRC7's WRAM enable, and the VRC6 and MMC5 audio timing), each graded both ways, and one is v3.4.0's Ganbare Goemon Gaiden frame 25, eight pixels lost to the SDRAM's CHR latency. - New bitstreams at seed 2, BUILD_DATE 2026-10-23, each byte-identical across two clean compiles: the off-die
RustyNES_MiSTer-v3.5.0.rbf(md5737048b65de5c712cc5d40fc26b906fa, setup +0.380 / hold +0.081 ns, SDRAM read capture +0.436 / +1.176 ns over all four corners) and the on-dieRustyNES_MiSTer-v3.5.0-lite.rbf(md53db762d73bdc3d685638121cd0ee360b, setup +0.231 / hold +0.074 ns). They replace a seed-3 pair attached for a few hours on 2026-10-23: seed 3 followed an outdated reading of the seed rule (found in the MiSTer release review), and the rebuild also carries that review's fixes, among them two Family BASIC keys held across their twin's release and the off-die OSD's ROM-size message.
Verification
cargo test --workspace --features test-roms,commercial-roms --no-fail-fast: 3,920 passed, 0 failed, 19 ignored, with the commercial suites at 60/0, 169/0 and 6/0.cargo fmt --check;cargo clippy --workspace --all-targets -D warnings, and again withscripting,scripting,hd-pack,retroachievementsandfull, for both browser builds, and for the excludedrustynes-cosim;cargo docwith-D warnings; thethumbv7emno_stdbuild; markdownlint. All clean.- MiSTer: the co-simulation ladders above;
VERIFY=1at5d441f44(256 stems, 1,156 artifacts);release-rbf.sh v3.5.0 --no-buildpassed every check against the compile date; both release assets downloaded back match the md5 above.
Install
- Download the pre-built binaries for Linux, macOS, and Windows below.
- The MiSTer bitstreams are attached below as a release candidate, not hardware-verified:
RustyNES_MiSTer-v3.5.0.rbf(off-die, needs SDRAM) andRustyNES_MiSTer-v3.5.0-lite.rbf(on-die). - The WebAssembly build is live at doublegate.github.io/RustyNES.
- The RetroArch core is in RetroArch's Online Updater on the platforms the libretro buildbot publishes to.
- Licensed under GPL-3.0-or-later.