Repository navigation
RustyNES v3.0.0 — "Cornerstone" (the API major: every break since v2.x in one place, a core timing epoch for movies and netplay, the last MMC3 timing gap closed in both cores, and a release-candidate MiSTer core)
RustyNES v3.0.0 — "Cornerstone"
The first release of the v3 line, and the API major the v2.9.x releases prepared for: the save, movie, netplay and Rust API changes made on the way here (most of them in v2.9.8 and v2.9.9, which were preparation for this release) are listed together below. It closes the last MMC3 timing difference against blargg's tests in both the emulator and the MiSTer core, guards movies and netplay against a version that emulates differently, and ships the MiSTer core's bitstreams as a release candidate, not hardware-verified. If you are upgrading from any v2.x release, read "Breaking changes since v2.x" first.
Breaking changes since v2.x
RustyNES refuses a file it cannot read correctly, with a message, rather than reading it on a guess. That rule is why most of these exist.
If you play games
- Your existing saves, save states, cheats and movies are not found for cartridge games (v2.9.8). A game's identity is now the ROM's contents without its 16-byte header, so a dump whose header is later corrected keeps its saves. On the desktop and the web this also re-keys HD-pack assignments, RetroAchievements progress files and browser battery saves. There is no automatic carry-over on the desktop and the web. FDS disks and NSF files are unaffected. Per-game settings on the desktop are unaffected.
- Save states from earlier versions are refused:
- states from v2.9.7 or earlier (v2.9.8);
- states from v2.9.8 (v2.9.9: the audio, MMC3 and MMC5 sections changed);
- states from v2.9.9 (v3.0.0: the PPU section changed for the MMC3 fix).
A refused state leaves the running game untouched, and the message now says it was saved by an older release. Re-create it from the game or an in-game save.
- Movies from earlier versions are refused. v2.9.8 made a movie record the machine it ran on (the emulation options and the cartridge board), v2.9.9 recorded the board in full, and v3.0.0 records which emulator behaviour it was recorded under (the emulation epoch). Every movie made before v3.0.0 is refused; re-record it. A movie that plays applies its recorded options, whatever your settings are, and restores yours when it stops. Movies imported from other emulators (
.fm2,.bk2,.fcm,.fmv,.vmv) still import. - Netplay peers must emulate identically. They must match on the game, every emulation option (v2.9.8), and, from v3.0.0, the emulation epoch: a number that rises only when a release changes what the emulator produces, so two releases with the same epoch still play together. A v3.0.0 player is told when the other side emulates differently or runs an older RustyNES, instead of the connection timing out; an older RustyNES cannot be changed, so on its side it still times out. Between two v3.0.0 players both sides are told the reason, in a mesh session too.
- The game database's corrections now apply everywhere (v2.9.8): Android, iOS, RetroArch and the web as well as the desktop. A game with a wrong header can now run as a different board, region or mirroring than before (for example Pin Bot (E) and Sidewinder run at PAL timing).
- During a movie or a netplay session, Reset, Power Cycle, disk swaps and state loads are refused on every route, including the hotkeys (v2.9.9).
If you use RetroArch
- RetroArch save states use the same container, so the same refusals apply: states from v2.9.9 and earlier are refused, and the core logs the reason and keeps the game running.
- RetroArch netplay between different core versions will not agree.
- The
platform=libnx(Switch) build was dropped in v2.9.8. .srmbattery saves and the core options are unchanged.
On Android and iOS
- Your saves moved once, in v2.9.9, to the game's identity: battery saves, suspend and state slots, library entries, per-game settings, RetroAchievements progress and box art, each copy checked before the original was removed. Cloud copies are re-created by the next upload.
- The apps now carry the release's version number (they had stayed at 2.0.4 and 2.0.8).
If you build on the Rust crates
The SemVer surface is the rustynes-core public API (including the chip-crate types it re-exports) and the .rns / .rnm formats.
- Removed (v2.9.8): the 18
rustynes_cpu::Busmethods deprecated since 2.7.5 (usenmi_level/irq_level), theApuBustrait,Bus::take_dma_mc_consumed,oam_dma_overlap_cycle,current_m2_phase,tick_one_cpu_cycle,Apu::snapshot_restored_parity, andserialize_header(useserialize_header_preserving;canonical_headeris private). - Renamed:
LockstepBusisSystemBus(v2.9.8);MapperError::TruncatedisMapperError::WrongLength(v3.0.0). #[non_exhaustive](build with the constructors, not by literal or struct update):HeaderandFrameInput(v2.9.8);Cartridge(parse,Cartridge::synthetic),BoardDescription(capture),HardwareOptions(default,capture) andMovie(Movie::new) (v3.0.0).- Changed:
Headergained fields andprg_ram_sizenow holds only the volatile RAM (the old sum isprg_ram_window());vs_dual_systemisis_vs_dual_system();vs_db::lookuptakes&Nes;Moviegainedoptions,boardandepoch; restores accept only the current layout;BoardDescription::captureandMovieRecorder::power_onare no longerconst; themmc3-m2-phase-irqfeature is gone (its behaviour is the default). - New:
rustynes_core::EMULATION_EPOCH; netplay'sSessionIdentity::epoch,IdentityMismatch::Emulator, theEmulatorMismatchvariants andemulator_mismatch_text.
File formats
| Format | v2.9.7 | v3.0.0 |
|---|---|---|
.rns save-state container |
2 | 3 (v2.9.8; older refused) |
.rns BUS / PPU / APU sections |
1 / 11 / 4 | 2 / 12 / 5 |
.rnm movie |
2 | 5 (minimum 5) |
| Netplay protocol | 4 ("RNES") |
6 ("RNE6") |
What v3.0.0 adds
- MMC3 interrupts with the background at
$1000are exact. Two PPU details from the NESdev pages: the background's A12 at the MMC3 page's "PPU cycle 324", and a visible line's dot 0 driving the background's CHR address, except the dot the odd-frame skip replaces. blargg's4-scanline_timingpasses all 13 sub-tests in the emulator and on the MiSTer core. One staged commercial game changed, and it is a fix: the fighting game on Super New Year Cart 15-in-1 draws its status bar whole. - Two mapper 45 multicart menus show up. Famicom Yarou 54 booted to a blue screen and Famicom Yarou Vol.5 7-in-1 drew font tiles over its scenery. Both menus draw before they program the board, and the board's power-on value is undocumented. A trace of the cartridges' own code showed what it must allow, and the board now powers on with every MMC3 CHR bank reaching the CHR-ROM. Vol.1 (a CHR-RAM cart) is still wrong, for a separate reason that stays open.
- The emulation epoch (ADR 0045), described above.
- A netplay spectator's buffer is bounded: at most about 18 minutes of input past the frame it shows, and shown frames are released. A spectator further behind than that plays what it kept, then says the stream was lost, instead of freezing.
- CI cannot pass without testing. A GitHub runner outage once left every gate skipped while
CI successreported a pass; it now fails unless the change detection ran.
The MiSTer core
- Release candidate, not hardware-verified. No hardware has run either bitstream. Verification on the SuperStation One moves to a later v3.x release.
- blargg's MMC3
4-scanline_timingpasses all 13 sub-tests on the core. The PPU drives the background's CHR address on a visible line's dot 0, as the NESdev PPU rendering page documents, except on the dot the odd-frame skip replaces. That one rule was all the core needed: its bus already presented the background pattern at the moment the MMC3 page's "PPU cycle 324" describes. - Its reference moved to this release. Every one of the 614 reference artifacts regenerated identically.
- The co-simulation ladder is 199 passed, 0 failed, 1 expected failure on-die and 200 passed, 0 failed, 1 expected failure off-die, each from one run of a frozen tree, with nothing skipped.
- The release-candidate bitstreams. Both builds are compiled at fitter seed 5, chosen from eight seeds swept on one build date (261006), every one of which closes on both builds. Each was compiled twice to the same bytes:
- on-die
RustyNES_MiSTer-v3.0.0.rbf, md53cfeb9683482d81418429af10c1c69dd(timing margin +0.408 ns setup, +0.116 ns hold); - off-die
RustyNES_MiSTer-v3.0.0-offdie.rbf, md5834f468169c41f441a70178212b512f2(+0.221 / +0.109 ns; the SDRAM read +0.439 / +1.181 ns, assuming zero board delay).
- on-die
Verification
--features test-roms: 3,223 passed, 0 failed, 11 ignored, on the released code.- The local commercial suites:
external_real_games60/0,external_extended137/0,external_coverage6/0 over every staged ROM. - AccuracyCoin 144/144, nestest 0-diff.
- Every moved baseline attributed; every fix has a test that failed before it.
Install
- Download the pre-built binaries for Linux, macOS, and Windows below.
- The MiSTer core bitstreams are attached below, as a release candidate, not hardware-verified. The on-die build is
RustyNES_MiSTer-v3.0.0.rbf, also attached under its datecoded nameRustyNES_20261006.rbf, and the off-die build isRustyNES_MiSTer-v3.0.0-offdie.rbf. - 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.
- Decisions: ADR 0043 (what v3.0.0 is) and ADR 0045 (the emulation epoch).
- Licensed under GPL-3.0-or-later.