From d5c812e56e80e98c984972950390aa429ea0245e Mon Sep 17 00:00:00 2001 From: DoubleGate Date: Wed, 15 Jul 2026 01:40:02 -0400 Subject: [PATCH] release: cut v2.2.1 (housekeeping patch) Bumps the workspace version 2.2.0 -> 2.2.1 to ship everything merged to main since the v2.2.0 "Capstone" tag: PR #304 (Game Genie re-key research tooling archived to scripts/gg/), PR #305 (six Dependabot bumps consolidated with zero source changes -- pollster 0.4->1.0, wide 0.7->1.5, tungstenite+tokio-tungstenite 0.29->0.30, bytemuck/cc patch, actions/setup-python v5->v6), PR #306/#307 (their CHANGELOG records), PR #308 (the 2A03-revision DMA-divergence probe archived to scripts/probes/), and PR #309 (four gitignored, RUSTYNES_FDS_BIOS-gated smoke tests against TakuikaNinja's FDS $4023/mirroring/audio-register/ DRAM-watchdog hardware-verification probes). This is a pure housekeeping patch: zero accuracy, feature, or core changes. The deterministic #![no_std] chip stack, save-state/TAS/ netplay-replay formats, and every golden vector are untouched -- AccuracyCoin holds 141/141 (100.00%), unchanged from v2.2.0. Version bump scope (workspace Cargo.toml `[workspace.package] version` is the single source of truth; every crate inherits via `version.workspace = true`, confirmed via `cargo clippy --workspace` reporting v2.2.1 for all 18 crates): - Cargo.toml / Cargo.lock: 2.2.0 -> 2.2.1 - CHANGELOG.md: renamed [Unreleased] -> [2.2.1] - 2026-07-15, added a fresh empty [Unreleased] above it - docs/STATUS.md, README.md (badge + "Current Release" section), AGENTS.md (canonical -- CLAUDE.md/GEMINI.md are symlinks to it): updated "current release" narrative to v2.2.1, reframing v2.2.0 "Capstone" as the prior release this patch sits on top of - .github/release-notes/v2.2.1.md: authored for release-auto.yml's override path (preferred over the CHANGELOG-section fallback) Deliberately NOT touched: the Android app's versionCode/versionName and the iOS app's MARKETING_VERSION -- these track their own host-only release cadence (frozen at their v2.0.x readiness points) and are decoupled by design from the desktop/core version until the joint mobile store launch at v2.3.0. Also not touched: to-dos/ ROADMAP.md's "Current release" line, which was already stale (citing v2.1.0) before this patch and is a pre-existing narrative-staleness issue orthogonal to this release's scope. Full gate green: cargo fmt --all --check, cargo clippy --workspace --all-targets -- -D warnings (all 18 crates confirm v2.2.1), cargo test --workspace (exit 0, zero failures), markdownlint on every touched doc. Co-Authored-By: Claude Opus 4.8 --- .github/release-notes/v2.2.1.md | 29 ++++++++++++++++++++++++++ AGENTS.md | 8 +++++--- CHANGELOG.md | 11 +++++++--- Cargo.lock | 36 ++++++++++++++++----------------- Cargo.toml | 2 +- README.md | 15 ++++++++++++-- docs/STATUS.md | 17 +++++++++++++++- 7 files changed, 90 insertions(+), 28 deletions(-) create mode 100644 .github/release-notes/v2.2.1.md diff --git a/.github/release-notes/v2.2.1.md b/.github/release-notes/v2.2.1.md new file mode 100644 index 00000000..d4c8d3cc --- /dev/null +++ b/.github/release-notes/v2.2.1.md @@ -0,0 +1,29 @@ +# RustyNES v2.2.1 — Housekeeping patch + +A **housekeeping patch** on top of v2.2.0 "Capstone": dev-tooling archival, a zero-source-change dependency consolidation, and a new gitignored FDS test corpus. **Zero accuracy, feature, or core changes** — the deterministic `#![no_std]` chip stack, save-state / TAS / netplay-replay formats, and every golden vector are untouched: **AccuracyCoin holds 141/141 (100.00%)**, unchanged from v2.2.0. + +## Added + +### Game Genie re-key research tooling archived + +Preserved the six intermediate research / verification scripts behind the header-robust Game Genie code re-key (which shipped in #262) beside the generator in `scripts/gg/`: `crc_combine.py` (a pure-Python `zlib.crc32_combine` implementation, self-tested against 2000 random synthetic trials, underpinning the `rom_crc32 == crc32_combine(prgCRC, chrCRC, chrLen)` identity), `alias_resolve.py` (long-tail title-alias CRC resolution), `coverage.py` / `coverage2.py` (name-join coverage accounting), `inspect.py`, and `verify.py` (which now proves the combine identity over every standard nes20db cart dump). Dev / research tooling only — touches no crate, no build, no core. + +### 2A03-revision DMA-divergence probe archived + +`scripts/probes/probe_rev.rs`, a diagnostic test probe behind the already-shipped v2.1.7 "Stepping" DMA-frontier work (ADR 0033) — snapshot-hashes DMA test ROMs under `Cpu2A03Revision::Rp2A03G` vs `Rp2A03H`. Kept for reference; not wired into CI. + +### `TakuikaNinja` FDS hardware-verification probes (gated, gitignored) + +Four `RUSTYNES_FDS_BIOS`-gated smoke tests (`crates/rustynes-test-harness/tests/fds_takuikaninja.rs`) against `FDS-Mirroring-Test`, `FDS-4023-Test`, `FDS-Audio-Registers`, and `FDS-4030D1-Addr` — real hardware-verified probes of `$4023` / mirroring / audio-register behavior and the FDS DRAM-refresh-watchdog IRQ. None of the four carries an explicit permissive license, so they're staged gitignored under `tests/roms/external/fds-takuikaninja/` rather than committed, mirroring the existing commercial-ROM convention; every test skips cleanly when the BIOS or a probe disk is absent. The underlying `$4023` and mirroring behaviors these probes exercise are already implemented and unit-tested independently in `crates/rustynes-mappers/src/fds.rs` — this is regression insurance against a second, hardware-verified oracle, not a fix for a gap. The `$4030.D1` DRAM-watchdog probe tracks a known, honest residual (not yet modeled by RustyNES or, per upstream, by most current FDS emulators) — see `docs/accuracy-ledger.md`. + +## Changed + +### Dependency consolidation (closes Dependabot #298–#303) + +Rolled all six open Dependabot bumps into one reviewed change, each verified against the code and gates; all landed with **no source changes** and the deterministic `#![no_std]` core untouched: **pollster 0.4 → 1.0** (frontend / android / iOS `block_on` for wgpu/Metal init), **wide 0.7 → 1.5** (the desktop `u32x8` SIMD blitter — the SIMD-vs-scalar byte-identity gate still passes), **tungstenite + tokio-tungstenite 0.29 → 0.30** (netplay + mobile signaling; `default-features = false` + `handshake` + `rustls-tls-webpki-roots` retained for clean pure-rustls cross-compiles), **bytemuck 1.25.0 → 1.25.1** and **cc 1.2.66 → 1.2.67** (patch), and CI **actions/setup-python v5 → v6** (MkDocs step). + +## Notes + +- Version: workspace `2.2.0 → 2.2.1`. No mobile app version change (`versionCode`/`versionName` on Android and `MARKETING_VERSION` on iOS stay frozen at their v2.0.x host-only release points; the joint mobile store launch remains v2.3.0). +- **No accuracy/oracle number moves.** AccuracyCoin 141/141, nestest 0-diff, `blargg_apu_2005` / `pal_apu_tests` (10/10) / `visual_regression` / the 60-ROM commercial oracle all unchanged. Save-state / TAS / netplay-replay formats untouched. +- Full host gate green: fmt · clippy (all feature combos + wasm32) · rustdoc (`-D warnings`) · `no_std` cross-compile (`thumbv7em`) · markdownlint · `cargo deny check`. diff --git a/AGENTS.md b/AGENTS.md index cf89a914..26bda11f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -26,7 +26,9 @@ RustyNES is a cycle-accurate Nintendo Entertainment System emulator written in pure Rust. The accuracy bar is Mesen2 / higan / ares: tight lockstep scheduling at PPU-dot resolution on a master-clock-precise timebase, sub-instruction PPU events visible to subsequent CPU code, and a lookup-table non-linear audio mixer with band-limited synthesis. The frontend is pure Rust (`winit` + `wgpu` + `cpal` + `egui`). -**Current release: v2.2.0 "Capstone"** (2026-07-12) — the **milestone cut** that **closes the v2.1.5 → v2.2.0 "deepen the existing project"** run, landing its two remaining marquees — the **netplay matchmaking / lobby** stack and the **FDS medium model** — atop a peripherals + quality/security pass, all sitting on the v2.0.0 "Timebase" one-clock / every-cycle-bus-access scheduler rewrite + Vs. `DualSystem` dual-console support. Every v2.2.0 change is **additive or default-off**, so the deterministic core is untouched on the shipped default — **AccuracyCoin holds 141/141 (100.00%)**, nestest is 0-diff, and `blargg_apu_2005` / `pal_apu_tests` (10/10) / `visual_regression` / the 60-ROM commercial oracle / the `#![no_std]` chip stack are all unchanged, and save-state / TAS / netplay replay stay bit-identical. It lands (PRs #290, #291; cut #297): a **netplay lobby + matchmaking** stack over the existing room-code / TURN transport (`ListRooms`/`RoomList` browse-and-join room directory + a server-side `QuickMatch`/`Matched` quick-play path, both **signaling only** with the `room-list` frame parsed by a brace-depth walk bounded at `MAX_ROOM_LIST` = 256); **delayed-stream spectators** (`SpectatorConfig.delay_frames`, clamped to `MAX_DELAY_FRAMES` = 512 — a pure presentation hold that cannot perturb the match); a **hardened desync + peer-liveness surface** (a graded `DesyncStatus` with a hysteresis threshold of 3 ≈ 1.5 s + a graded `PeerLink` / terminal `DisconnectReason::PeerTimeout` on multi-second 2 s / 5 s RTT timeouts — telemetry only, the rollback/determinism contract untouched); the **FDS medium model completion** (F4.3, a marquee — a per-block **CRC-16/KERMIT** re-emitted on every BIOS write via `resynth_block_crc` over a synthesized gap/mark wire image, an opt-in default-OFF continuous analog head-seek / velocity model `Fds::set_analog_head_seek` replacing the flat `HEAD_RESEEK_CYCLES`, and a BIOS-free synthetic write-verify oracle `Fds::medium_write_verify` as the CI-verifiable half — the real-BIOS write-CRC path stays gitignored/local; an additive **v4** FDS save-state tail, byte-identical with the model off); **peripherals** (a Famicom `$4016`-bit-2 **microphone** `Nes::set_microphone` — `$4016`-only, never `$4017` — and a 3×3-aperture Zapper light-timing model `ZAPPER_APERTURE_*`, both additive / default-off); and a **quality / security** pass (cargo-fuzz targets grown **3 → 8** — `ppu_reg_io` / `apu_reg_io` / `netplay_message` / `save_state` / `movie` — the `movie` target finding and fixing **two real OOM-DoS paths** in `Movie::deserialize`, byte-identical for valid input; a read-only **Tools → ROM Info** browser over `&Nes` that never mutates; and four new MkDocs handbook pages). The prior step — **v2.1.10 "Fathom" ("Loom")** (2026-07-12) — was the **creator-tools & web-parity** step (TAStudio greenzone depth + Lua API breadth + a browser RetroAchievements auth-proxy deploy stack (ADR 0015) + Vs. `DualSystem` presentation in the libretro core; the wasm desktop-style dual present remains deferred). The intervening steps: **v2.1.6 "Timbre"** (2026-07-11) expansion-audio fidelity (a decibel oracle asserting measured level ratios vs Mesen2 / hardware targets, hardware/Mesen2 channel-level calibration incl. the Namco 163 ~12 dB fix, VRC7 patch-set verification vs Nuke.YKT, a frontend Audio Mixer panel — base 2A03 NTSC output byte-identical) → **v2.1.7 "Stepping"** (2026-07-12) hardware revisions & DMA frontier (opt-in `PpuRevision` / `Cpu2A03Revision` die-revisions + power-on RAM/palette models; the DMA "unexpected read" frontier proven a **documented no-op on every oracle**, ADR 0033 — honest, not faked) → **v2.1.8 "Tempo"** (2026-07-12) performance (a default-OFF specialized fast PPU dot path, `Nes::set_fast_dotloop` — ~+12.3% rendering-heavy, differential-tested bit-identical; a SIMD-validated software blitter where scalar stays default; a wasm 3.99 MiB-gzip size pass) → **v2.1.9 "Aperture"** (2026-07-12) presentation & signal (a raw NTSC composite `rustynes-ppu::raw_signal` core; a marquee CRT shader stack — CRT-Royale / CRT Guest Advanced / Sony Megatron — all naga-validated WGSL; GIF/WAV capture; a live generated-palette preview). Now on the shipped default the Fathom line keeps the deterministic core byte-identical and layers accuracy + display + quality-of-life work atop the v2.0.0 core: **v2.1.0** accuracy remediation (PPU palette backdrop-override, the mapper-tier completion to **51 Core / 95 Curated / 26 BestEffort of 172**, the MMC3 R1/R2 residual closed by-design-permanent) → **v2.1.1** the Wizards & Warriors game-DB mirroring freeze fix → **v2.1.2 "Prism"** display fidelity (Vs. `DualSystem` desktop second-screen, the NTSC composite-shader ladder, an in-core generated NTSC palette, NSF non-60 Hz + NSFe) → **v2.1.3 "Codex"** quality-of-life (an APU audio filter-model selector, Game Genie code nomination + a full / header-robust code database, a Material-for-MkDocs handbook served at `/docs/` on GitHub Pages) → **v2.1.4 "Caliper"** accuracy hardening (opt-in default-OFF OAM decay modeled on Mesen2, a CI boot-smoke sweep of all 26 BestEffort mapper families, a shared MMC3-clone A12/IRQ timing oracle) → **v2.1.5 "Vernier"** the regression-net & residual step → **v2.1.6 "Timbre"** expansion-audio fidelity → **v2.1.7 "Stepping"** hardware revisions & DMA frontier → **v2.1.8 "Tempo"** performance → **v2.1.9 "Aperture"** presentation & signal → **v2.1.10 "Loom"** creator tools & web parity → **v2.2.0 "Capstone"** the milestone cut closing the run (this release). v2.0.0 "Timebase" remains RustyNES's designated MAJOR-boundary release — see "Timebase (v2.0.0)" below. RustyNES is now a multi-platform emulation suite, all on the one byte-identical cycle-accurate core — **`docs/STATUS.md` is the authoritative current-state record.** What ships beyond the desktop app: +**Current release: v2.2.1** (2026-07-15) — a **housekeeping patch** on top of v2.2.0 "Capstone" (next paragraph): archives two batches of dev/research tooling (the Game Genie header-robust re-key's six research/verification scripts in `scripts/gg/`, and the 2A03-revision DMA-divergence probe in `scripts/probes/`), consolidates six open Dependabot PRs with **zero source changes** (`pollster` 0.4→1.0, `wide` 0.7→1.5, `tungstenite`/`tokio-tungstenite` 0.29→0.30, `bytemuck`/`cc` patch, `actions/setup-python` v5→v6), and wires four gitignored, `RUSTYNES_FDS_BIOS`-gated smoke tests against `TakuikaNinja`'s FDS `$4023` / mirroring / audio-register / DRAM-watchdog hardware-verification probes (regression insurance for behavior RustyNES already models correctly, not a fix — the `$4030.D1` DRAM-refresh-watchdog probe tracks a known, honest residual RustyNES does not model, per `docs/accuracy-ledger.md`). **Zero accuracy, feature, or core changes** — the deterministic `#![no_std]` chip stack, save-state / TAS / netplay-replay formats, and every golden vector are untouched; **AccuracyCoin holds 141/141 (100.00%)**, unchanged from v2.2.0. + +The prior release, **v2.2.0 "Capstone"** (2026-07-12), was the **milestone cut** that **closes the v2.1.5 → v2.2.0 "deepen the existing project"** run, landing its two remaining marquees — the **netplay matchmaking / lobby** stack and the **FDS medium model** — atop a peripherals + quality/security pass, all sitting on the v2.0.0 "Timebase" one-clock / every-cycle-bus-access scheduler rewrite + Vs. `DualSystem` dual-console support. Every v2.2.0 change is **additive or default-off**, so the deterministic core is untouched on the shipped default — **AccuracyCoin holds 141/141 (100.00%)**, nestest is 0-diff, and `blargg_apu_2005` / `pal_apu_tests` (10/10) / `visual_regression` / the 60-ROM commercial oracle / the `#![no_std]` chip stack are all unchanged, and save-state / TAS / netplay replay stay bit-identical. It lands (PRs #290, #291; cut #297): a **netplay lobby + matchmaking** stack over the existing room-code / TURN transport (`ListRooms`/`RoomList` browse-and-join room directory + a server-side `QuickMatch`/`Matched` quick-play path, both **signaling only** with the `room-list` frame parsed by a brace-depth walk bounded at `MAX_ROOM_LIST` = 256); **delayed-stream spectators** (`SpectatorConfig.delay_frames`, clamped to `MAX_DELAY_FRAMES` = 512 — a pure presentation hold that cannot perturb the match); a **hardened desync + peer-liveness surface** (a graded `DesyncStatus` with a hysteresis threshold of 3 ≈ 1.5 s + a graded `PeerLink` / terminal `DisconnectReason::PeerTimeout` on multi-second 2 s / 5 s RTT timeouts — telemetry only, the rollback/determinism contract untouched); the **FDS medium model completion** (F4.3, a marquee — a per-block **CRC-16/KERMIT** re-emitted on every BIOS write via `resynth_block_crc` over a synthesized gap/mark wire image, an opt-in default-OFF continuous analog head-seek / velocity model `Fds::set_analog_head_seek` replacing the flat `HEAD_RESEEK_CYCLES`, and a BIOS-free synthetic write-verify oracle `Fds::medium_write_verify` as the CI-verifiable half — the real-BIOS write-CRC path stays gitignored/local; an additive **v4** FDS save-state tail, byte-identical with the model off); **peripherals** (a Famicom `$4016`-bit-2 **microphone** `Nes::set_microphone` — `$4016`-only, never `$4017` — and a 3×3-aperture Zapper light-timing model `ZAPPER_APERTURE_*`, both additive / default-off); and a **quality / security** pass (cargo-fuzz targets grown **3 → 8** — `ppu_reg_io` / `apu_reg_io` / `netplay_message` / `save_state` / `movie` — the `movie` target finding and fixing **two real OOM-DoS paths** in `Movie::deserialize`, byte-identical for valid input; a read-only **Tools → ROM Info** browser over `&Nes` that never mutates; and four new MkDocs handbook pages). The prior step — **v2.1.10 "Fathom" ("Loom")** (2026-07-12) — was the **creator-tools & web-parity** step (TAStudio greenzone depth + Lua API breadth + a browser RetroAchievements auth-proxy deploy stack (ADR 0015) + Vs. `DualSystem` presentation in the libretro core; the wasm desktop-style dual present remains deferred). The intervening steps: **v2.1.6 "Timbre"** (2026-07-11) expansion-audio fidelity (a decibel oracle asserting measured level ratios vs Mesen2 / hardware targets, hardware/Mesen2 channel-level calibration incl. the Namco 163 ~12 dB fix, VRC7 patch-set verification vs Nuke.YKT, a frontend Audio Mixer panel — base 2A03 NTSC output byte-identical) → **v2.1.7 "Stepping"** (2026-07-12) hardware revisions & DMA frontier (opt-in `PpuRevision` / `Cpu2A03Revision` die-revisions + power-on RAM/palette models; the DMA "unexpected read" frontier proven a **documented no-op on every oracle**, ADR 0033 — honest, not faked) → **v2.1.8 "Tempo"** (2026-07-12) performance (a default-OFF specialized fast PPU dot path, `Nes::set_fast_dotloop` — ~+12.3% rendering-heavy, differential-tested bit-identical; a SIMD-validated software blitter where scalar stays default; a wasm 3.99 MiB-gzip size pass) → **v2.1.9 "Aperture"** (2026-07-12) presentation & signal (a raw NTSC composite `rustynes-ppu::raw_signal` core; a marquee CRT shader stack — CRT-Royale / CRT Guest Advanced / Sony Megatron — all naga-validated WGSL; GIF/WAV capture; a live generated-palette preview). Now on the shipped default the Fathom line keeps the deterministic core byte-identical and layers accuracy + display + quality-of-life work atop the v2.0.0 core: **v2.1.0** accuracy remediation (PPU palette backdrop-override, the mapper-tier completion to **51 Core / 95 Curated / 26 BestEffort of 172**, the MMC3 R1/R2 residual closed by-design-permanent) → **v2.1.1** the Wizards & Warriors game-DB mirroring freeze fix → **v2.1.2 "Prism"** display fidelity (Vs. `DualSystem` desktop second-screen, the NTSC composite-shader ladder, an in-core generated NTSC palette, NSF non-60 Hz + NSFe) → **v2.1.3 "Codex"** quality-of-life (an APU audio filter-model selector, Game Genie code nomination + a full / header-robust code database, a Material-for-MkDocs handbook served at `/docs/` on GitHub Pages) → **v2.1.4 "Caliper"** accuracy hardening (opt-in default-OFF OAM decay modeled on Mesen2, a CI boot-smoke sweep of all 26 BestEffort mapper families, a shared MMC3-clone A12/IRQ timing oracle) → **v2.1.5 "Vernier"** the regression-net & residual step → **v2.1.6 "Timbre"** expansion-audio fidelity → **v2.1.7 "Stepping"** hardware revisions & DMA frontier → **v2.1.8 "Tempo"** performance → **v2.1.9 "Aperture"** presentation & signal → **v2.1.10 "Loom"** creator tools & web parity → **v2.2.0 "Capstone"** the milestone cut closing the run → **v2.2.1** this housekeeping patch (this release). v2.0.0 "Timebase" remains RustyNES's designated MAJOR-boundary release — see "Timebase (v2.0.0)" below. RustyNES is now a multi-platform emulation suite, all on the one byte-identical cycle-accurate core — **`docs/STATUS.md` is the authoritative current-state record.** What ships beyond the desktop app: - **Timebase (v2.0.0)** — the scheduler substrate is rewritten from a five-counter dot-lockstep model to a single canonical cycle counter, every CPU cycle a real bus access, and a split-around-the-access `start_cycle`/`end_cycle` PPU catch-up (ADR 0002 / ADR 0029), now the *only* scheduler path. This is a MAJOR-boundary breaking change (ADR 0003): `.rns` save-state and `.rnm` movie format epochs bump (ADR 0028) — a pre-v2.0.0 `.rns` slot now fails to load with a clear error instead of silently misinterpreting stale bytes. Landed across five betas + rc.1 (PRs #217–223). Also new: core-level **Vs. `DualSystem`** dual-console support (`Emu::Dual`, `crates/rustynes-core`) for the four Vs. arcade cabinet boards — core-and-test-harness-only, frontend wiring deferred. The R1/R2 MMC3 IRQ-timing residual is by-design-deferred beyond this release with a mechanism-level finding recorded in ADR 0002 (not closed, not silently dropped). **AccuracyCoin now measures 141/141 (100.00%)**: the v2.0.1 upstream AccuracyCoin re-sync grew the catalog to 146 rows / 141 assigned tests and briefly opened two new PPU gaps ("ALE + Read" $0491, "Hybrid Addresses" $0492), which **v2.0.3** closed by promoting the 2-cycle-ALE PPU fetch model to the unconditional default (both experimental flags retired; additive `PPU_SNAPSHOT_VERSION` v5 tail). AccuracyCoin held 100% (139/139) throughout the v2.0.0 betas and final cut, dipped to 139/141 under the v2.0.1 re-sync, and is back to a full 141/141 from v2.0.3 onward. @@ -36,7 +38,7 @@ RustyNES is a cycle-accurate Nintendo Entertainment System emulator written in p - **Mapper breadth → 172 families** (up from 168 at the v1.7.x tag), Core / Curated / BestEffort behind the CI accuracy-honesty gate. - **Release automation** — `.github/workflows/release-auto.yml`: when a new version goes final-green on `main`, it auto-tags + publishes the GitHub Release (body from a maintainer-authored `.github/release-notes/vX.Y.Z.md` override, else the CHANGELOG `[X.Y.Z]` section; title codename parsed from the CHANGELOG header) and builds + attaches the desktop binaries by invoking `release.yml` via `workflow_call` (a tag pushed by `GITHUB_TOKEN` can't trigger `on: push: tags`, hence the direct call). The v1.8.0–v1.9.9 GitHub Releases are all published with comprehensive notes + Linux / macOS-aarch64 / Windows binaries. -Platform additions through v1.10.0 were **host-only and additive**: the deterministic `#![no_std]` chip stack was untouched and byte-identical on ARM. **v2.0.0 "Timebase" is different by design** — it rewrites the scheduler substrate itself (still `#![no_std]`-clean, AccuracyCoin now back at a full **141/141 (100%)** from v2.0.3 — see above, but the save-state / movie format epochs deliberately bump per ADR 0028, so cross-version `.rns`/`.rnm` round-trip is a v1.x-only guarantee, not a v1.x⇄v2.x one). Forward path: the **v2.0.x "Harbor" mobile-finalization re-port train** onto the v2.0.0 core has fully shipped — v2.0.1 (first Android re-port + AccuracyCoin oracle re-sync), v2.0.2–v2.0.3 (the 2-cycle-ALE accuracy closure to 141/141), v2.0.4 (Android release candidate), v2.0.5–v2.0.8 (iOS finalization), and v2.0.9 (both-apps readiness) — followed by the **v2.1.x "Fathom" accuracy line** (v2.1.0 → v2.1.10) capped by the **v2.2.0 "Capstone"** milestone cut, the current release; see the "Current release" paragraph above. The **v2.1.5 → v2.2.0** line is a **"deepen the existing project"** run (accuracy / performance / features / quality); **v2.1.5 "Vernier"** opened it (the tepples Holy Mapperel mapper bank-reachability / IRQ regression net, the first PAL-region APU oracle at `pal_apu_tests` 10/10, the MMC3 R1/R2 F5.0 A12-phase study, a measured fat-LTO A/B, and a real TURN NAT-traversal retransmit production fix — all NTSC-byte-identical), **v2.1.6 "Timbre"** continued it (the expansion-audio decibel oracle, the hardware/Mesen2 channel-level calibration incl. the Namco 163 ~12 dB fix, VRC7 patch-set verification vs Nuke.YKT, and a frontend Audio Mixer panel — base 2A03 NTSC output byte-identical), **v2.1.7 "Stepping"** added opt-in PPU / 2A03 die-revisions + power-on RAM/palette hardware models (the DMA "unexpected read" frontier proven a documented no-op on every oracle, ADR 0033 — honest, not faked), **v2.1.8 "Tempo"** the default-OFF specialized fast PPU dot path (~12% rendering-heavy, differential-tested bit-identical) + a SIMD-validated software blitter + a wasm size pass, **v2.1.9 "Aperture"** the marquee CRT shader stack + a raw NTSC composite signal-decode path + GIF/WAV capture + a palette editor, **v2.1.10 "Loom"** the TAStudio greenzone + Lua API breadth + the browser-RA auth-proxy deploy stack + Vs. `DualSystem` libretro presentation, and **v2.2.0 "Capstone"** the milestone cut closing the run (the netplay matchmaking / lobby stack + the FDS medium model + a peripherals & quality/security pass — fuzz targets 3 → 8, a `Movie::deserialize` OOM-DoS fix, a read-only Tools → ROM Info browser) — all NTSC-byte-identical, AccuracyCoin 141/141 throughout; the v2.1.5 → v2.2.0 run is now closed. The **joint Google Play + Apple App Store + AltStore PAL + F-Droid launch** — with it the `rustynes-monetization` activation — is the future **v2.3.0** (moved from the earlier v2.1.0 / v2.2.0 targets). +Platform additions through v1.10.0 were **host-only and additive**: the deterministic `#![no_std]` chip stack was untouched and byte-identical on ARM. **v2.0.0 "Timebase" is different by design** — it rewrites the scheduler substrate itself (still `#![no_std]`-clean, AccuracyCoin now back at a full **141/141 (100%)** from v2.0.3 — see above, but the save-state / movie format epochs deliberately bump per ADR 0028, so cross-version `.rns`/`.rnm` round-trip is a v1.x-only guarantee, not a v1.x⇄v2.x one). Forward path: the **v2.0.x "Harbor" mobile-finalization re-port train** onto the v2.0.0 core has fully shipped — v2.0.1 (first Android re-port + AccuracyCoin oracle re-sync), v2.0.2–v2.0.3 (the 2-cycle-ALE accuracy closure to 141/141), v2.0.4 (Android release candidate), v2.0.5–v2.0.8 (iOS finalization), and v2.0.9 (both-apps readiness) — followed by the **v2.1.x "Fathom" accuracy line** (v2.1.0 → v2.1.10) capped by the **v2.2.0 "Capstone"** milestone cut, then the **v2.2.1** housekeeping patch, the current release; see the "Current release" paragraph above. The **v2.1.5 → v2.2.0** line is a **"deepen the existing project"** run (accuracy / performance / features / quality); **v2.1.5 "Vernier"** opened it (the tepples Holy Mapperel mapper bank-reachability / IRQ regression net, the first PAL-region APU oracle at `pal_apu_tests` 10/10, the MMC3 R1/R2 F5.0 A12-phase study, a measured fat-LTO A/B, and a real TURN NAT-traversal retransmit production fix — all NTSC-byte-identical), **v2.1.6 "Timbre"** continued it (the expansion-audio decibel oracle, the hardware/Mesen2 channel-level calibration incl. the Namco 163 ~12 dB fix, VRC7 patch-set verification vs Nuke.YKT, and a frontend Audio Mixer panel — base 2A03 NTSC output byte-identical), **v2.1.7 "Stepping"** added opt-in PPU / 2A03 die-revisions + power-on RAM/palette hardware models (the DMA "unexpected read" frontier proven a documented no-op on every oracle, ADR 0033 — honest, not faked), **v2.1.8 "Tempo"** the default-OFF specialized fast PPU dot path (~12% rendering-heavy, differential-tested bit-identical) + a SIMD-validated software blitter + a wasm size pass, **v2.1.9 "Aperture"** the marquee CRT shader stack + a raw NTSC composite signal-decode path + GIF/WAV capture + a palette editor, **v2.1.10 "Loom"** the TAStudio greenzone + Lua API breadth + the browser-RA auth-proxy deploy stack + Vs. `DualSystem` libretro presentation, and **v2.2.0 "Capstone"** the milestone cut closing the run (the netplay matchmaking / lobby stack + the FDS medium model + a peripherals & quality/security pass — fuzz targets 3 → 8, a `Movie::deserialize` OOM-DoS fix, a read-only Tools → ROM Info browser) — all NTSC-byte-identical, AccuracyCoin 141/141 throughout; the v2.1.5 → v2.2.0 run is now closed. The **joint Google Play + Apple App Store + AltStore PAL + F-Droid launch** — with it the `rustynes-monetization` activation — is the future **v2.3.0** (moved from the earlier v2.1.0 / v2.2.0 targets). --- @@ -178,7 +180,7 @@ These cross-cutting decisions span multiple files. Reading individual chip docs - `ref-docs/` is immutable. Research updates go in dated supplemental files. - ADRs go in `docs/adr/` (Michael Nygard format). - `rustynes-core` re-exports the public types from the chip crates; downstream consumers (`rustynes-frontend`, `rustynes-test-harness`) should depend on `rustynes-core` rather than the chip crates directly. -- When relabeling old engine "v2.x" narrative for users, present it as upstream lineage/history — **never as a current RustyNES release version.** The current release is **v2.2.0 "Capstone"** (2026-07-12, the milestone cut that closes the v2.1.5 → v2.2.0 "deepen the existing project" run — its two remaining marquees the netplay matchmaking / lobby stack and the FDS medium model, atop a peripherals + quality/security pass (Famicom `$4016`-bit-2 microphone + 3×3-aperture Zapper; cargo-fuzz targets 3 → 8 finding + fixing two `Movie::deserialize` OOM-DoS paths; a read-only Tools → ROM Info browser); every change additive or default-off, AccuracyCoin 141/141) on the v2.0.0 "Timebase" one-clock / every-cycle-bus-access scheduler rewrite + Vs. `DualSystem` dual-console support. The v2.0.x "Harbor" mobile-finalization train (v2.0.1→v2.0.9) and the entire v2.1.x "Fathom" line (v2.1.0→v2.1.10) plus the v2.2.0 "Capstone" milestone have all shipped — the run's steps being v2.1.5 "Vernier" (regression-net & residual) → v2.1.6 "Timbre" (expansion-audio fidelity) → v2.1.7 "Stepping" (opt-in PPU/2A03 die-revisions + power-on RAM/palette models; the DMA "unexpected read" frontier a documented no-op on every oracle, ADR 0033) → v2.1.8 "Tempo" (a default-OFF fast PPU dot path + SIMD blitter + wasm size pass) → v2.1.9 "Aperture" (a marquee CRT shader stack + raw NTSC composite signal-decode + GIF/WAV capture + palette editor) → v2.1.10 "Loom" (TAStudio greenzone + Lua API breadth + browser-RA auth-proxy deploy stack + Vs. `DualSystem` libretro presentation) → v2.2.0 "Capstone" (this release) — preceded by v1.10.0 "Arcade" the native Libretro / RetroArch core, the v1.9.0→v1.9.9 iOS TestFlight train, the v1.8.0→v1.8.9 "Android" train, and the desktop-feature lineage v1.1.0→v1.7.1, all on the v1.0.0 production core (see the top "Current release" block + `docs/STATUS.md`). **Never claim any version *later* than v2.2.0 is released** — in particular the joint mobile app-store launch (Google Play + Apple App Store + AltStore PAL + F-Droid) is the future **v2.3.0** (NOT v2.1.0 or v2.2.0 — the entire v2.1.x line and the v2.2.0 "Capstone" milestone have all already shipped, closing the "deepen the existing project" run; the store launch moved out to v2.3.0 — see `to-dos/ROADMAP.md`). Two distinct "v2.0"s exist and must not be conflated, **both now shipped, at different times, for different reasons**: the **engine-lineage v2.0** master-clock work shipped as the **v1.0.0** production core (2026-06-13) — it was the *only* scheduler through v1.10.0. RustyNES's own **v2.0.0 "Timebase"** release (2026-07-03) is a *different* milestone that *replaces* that same dot-lockstep scheduler outright: the **one-clock + every-cycle-bus-access collapse** (a single canonical cycle counter + a split-around-the-access `start_cycle`/`end_cycle` PPU catch-up, mirroring Mesen2's structure), full Vs. `DualSystem` dual-console emulation (core-and-harness-only; frontend wiring deferred), and the breaking save-state / cross-version changes it entailed (ADR 0002 / ADR 0028 / ADR 0029) — the one release that broke byte-identity / save-state compatibility, by design. The R1/R2 hard-tier MMC3 IRQ-timing residual was investigated under a bounded-effort campaign and is by-design-deferred beyond v2.0.0, not closed — see ADR 0002's decision-update section for the mechanism-level finding. +- When relabeling old engine "v2.x" narrative for users, present it as upstream lineage/history — **never as a current RustyNES release version.** The current release is **v2.2.1** (2026-07-15, a housekeeping patch — dev-tooling archival, a zero-source-change dependency consolidation, and a gitignored FDS test-corpus addition, zero accuracy/feature/core changes — on top of **v2.2.0 "Capstone"** [2026-07-12], the milestone cut that closes the v2.1.5 → v2.2.0 "deepen the existing project" run — its two remaining marquees the netplay matchmaking / lobby stack and the FDS medium model, atop a peripherals + quality/security pass (Famicom `$4016`-bit-2 microphone + 3×3-aperture Zapper; cargo-fuzz targets 3 → 8 finding + fixing two `Movie::deserialize` OOM-DoS paths; a read-only Tools → ROM Info browser); every change additive or default-off, AccuracyCoin 141/141) on the v2.0.0 "Timebase" one-clock / every-cycle-bus-access scheduler rewrite + Vs. `DualSystem` dual-console support. The v2.0.x "Harbor" mobile-finalization train (v2.0.1→v2.0.9) and the entire v2.1.x "Fathom" line (v2.1.0→v2.1.10) plus the v2.2.0 "Capstone" milestone have all shipped — the run's steps being v2.1.5 "Vernier" (regression-net & residual) → v2.1.6 "Timbre" (expansion-audio fidelity) → v2.1.7 "Stepping" (opt-in PPU/2A03 die-revisions + power-on RAM/palette models; the DMA "unexpected read" frontier a documented no-op on every oracle, ADR 0033) → v2.1.8 "Tempo" (a default-OFF fast PPU dot path + SIMD blitter + wasm size pass) → v2.1.9 "Aperture" (a marquee CRT shader stack + raw NTSC composite signal-decode + GIF/WAV capture + palette editor) → v2.1.10 "Loom" (TAStudio greenzone + Lua API breadth + browser-RA auth-proxy deploy stack + Vs. `DualSystem` libretro presentation) → v2.2.0 "Capstone" (the milestone cut closing the run) → **v2.2.1** this housekeeping patch (this release) — preceded by v1.10.0 "Arcade" the native Libretro / RetroArch core, the v1.9.0→v1.9.9 iOS TestFlight train, the v1.8.0→v1.8.9 "Android" train, and the desktop-feature lineage v1.1.0→v1.7.1, all on the v1.0.0 production core (see the top "Current release" block + `docs/STATUS.md`). **Never claim any version *later* than v2.2.1 is released** — in particular the joint mobile app-store launch (Google Play + Apple App Store + AltStore PAL + F-Droid) is the future **v2.3.0** (NOT v2.1.0 or v2.2.0 — the entire v2.1.x line and the v2.2.0 "Capstone" milestone have all already shipped, closing the "deepen the existing project" run; the store launch moved out to v2.3.0 — see `to-dos/ROADMAP.md`). Two distinct "v2.0"s exist and must not be conflated, **both now shipped, at different times, for different reasons**: the **engine-lineage v2.0** master-clock work shipped as the **v1.0.0** production core (2026-06-13) — it was the *only* scheduler through v1.10.0. RustyNES's own **v2.0.0 "Timebase"** release (2026-07-03) is a *different* milestone that *replaces* that same dot-lockstep scheduler outright: the **one-clock + every-cycle-bus-access collapse** (a single canonical cycle counter + a split-around-the-access `start_cycle`/`end_cycle` PPU catch-up, mirroring Mesen2's structure), full Vs. `DualSystem` dual-console emulation (core-and-harness-only; frontend wiring deferred), and the breaking save-state / cross-version changes it entailed (ADR 0002 / ADR 0028 / ADR 0029) — the one release that broke byte-identity / save-state compatibility, by design. The R1/R2 hard-tier MMC3 IRQ-timing residual was investigated under a bounded-effort campaign and is by-design-deferred beyond v2.0.0, not closed — see ADR 0002's decision-update section for the mechanism-level finding. - **Forward plans + roadmap live in `to-dos/`.** `to-dos/ROADMAP.md` (updated in #129) is the planning entry point and frames the release line + "the path to v2.0.0 and beyond"; `to-dos/plans/` holds the per-release plan docs (through `v1.7.0-forge-plan.md` on `main`, plus the staged-forward `v1.8.0-android-plan.md` / `v1.9.0-ios-plan.md` / `v2.0.0-master-clock-plan.md`) + the `to-dos/plans/engine-lineage/` history archive + a `to-dos/plans/research/` reference-mining archive. - The v1.0.0 release + GitHub Pages/CI + post-release record is in `docs/v1.0.0-synthesis-handoff-2026-06-13.md` — read it before touching CI, Pages, or release tooling. Full per-release history is in `CHANGELOG.md`. - **Markdownlint is a CI gate** (pre-commit, pinned `markdownlint-cli v0.39.0`). The local `markdownlint` binary is a newer version that reports rules v0.39.0 lacks (e.g. MD060) — those are NOT gated; verify with `pre-commit run markdownlint --all-files`, not the bare binary. `.markdownlint.json` keeps `MD013`/`MD033`/`MD041` disabled by design (long technical tables, the README HTML banner/``, the HTML-led README). `.markdownlintignore` exempts `ref-docs/`, `ref-proj/`, the vendored `tricnes/` + upstream READMEs, and the frozen `docs/archive/` + `to-dos/archive/` trees — don't lint or reformat those. diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d024646..53cc332b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,12 @@ cycle-accurate core later replaced. ## [Unreleased] +## [2.2.1] - 2026-07-15 - Housekeeping patch (dev-tooling archival + dependency consolidation + FDS test corpus) + +Zero accuracy, feature, or core changes — the deterministic `#![no_std]` chip +stack, save-state / TAS / netplay-replay formats, and every golden vector are +untouched. AccuracyCoin holds **141/141 (100.00%)**, unchanged from v2.2.0. + ### Added - **Game Genie re-key research tooling archived (PR #304).** Preserved the six @@ -41,9 +47,8 @@ cycle-accurate core later replaced. absent, keeping CI clean by default. The underlying `$4023` and mirroring behaviors these probes exercise are already implemented and unit-tested independently in `crates/rustynes-mappers/src/fds.rs` — this is regression - insurance against a second, hardware-verified oracle, not a fix for a - gap. The - `$4030.D1` DRAM-watchdog probe tracks a known, honest residual (not yet + insurance against a second, hardware-verified oracle, not a fix for a gap. + The `$4030.D1` DRAM-watchdog probe tracks a known, honest residual (not yet modeled by RustyNES or, per upstream, by most current FDS emulators) — see `docs/accuracy-ledger.md`. diff --git a/Cargo.lock b/Cargo.lock index 6e44963c..e65eb940 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4290,7 +4290,7 @@ dependencies = [ [[package]] name = "rustynes-android" -version = "2.2.0" +version = "2.2.1" dependencies = [ "android-activity", "android_logger", @@ -4308,7 +4308,7 @@ dependencies = [ [[package]] name = "rustynes-apu" -version = "2.2.0" +version = "2.2.1" dependencies = [ "bitflags 2.13.0", "criterion", @@ -4321,7 +4321,7 @@ dependencies = [ [[package]] name = "rustynes-cheevos" -version = "2.2.0" +version = "2.2.1" dependencies = [ "cc", "ureq", @@ -4329,7 +4329,7 @@ dependencies = [ [[package]] name = "rustynes-core" -version = "2.2.0" +version = "2.2.1" dependencies = [ "bitflags 2.13.0", "criterion", @@ -4346,7 +4346,7 @@ dependencies = [ [[package]] name = "rustynes-cpu" -version = "2.2.0" +version = "2.2.1" dependencies = [ "bitflags 2.13.0", "criterion", @@ -4357,7 +4357,7 @@ dependencies = [ [[package]] name = "rustynes-frontend" -version = "2.2.0" +version = "2.2.1" dependencies = [ "anstyle", "arboard", @@ -4411,11 +4411,11 @@ dependencies = [ [[package]] name = "rustynes-gfx-shaders" -version = "2.2.0" +version = "2.2.1" [[package]] name = "rustynes-hdpack" -version = "2.2.0" +version = "2.2.1" dependencies = [ "lewton", "png", @@ -4426,7 +4426,7 @@ dependencies = [ [[package]] name = "rustynes-ios" -version = "2.2.0" +version = "2.2.1" dependencies = [ "bytemuck", "cpal", @@ -4440,7 +4440,7 @@ dependencies = [ [[package]] name = "rustynes-libretro" -version = "2.2.0" +version = "2.2.1" dependencies = [ "libc", "rust-libretro", @@ -4449,7 +4449,7 @@ dependencies = [ [[package]] name = "rustynes-mappers" -version = "2.2.0" +version = "2.2.1" dependencies = [ "bitflags 2.13.0", "criterion", @@ -4461,7 +4461,7 @@ dependencies = [ [[package]] name = "rustynes-mobile" -version = "2.2.0" +version = "2.2.1" dependencies = [ "rustynes-core", "rustynes-hdpack", @@ -4476,14 +4476,14 @@ dependencies = [ [[package]] name = "rustynes-monetization" -version = "2.2.0" +version = "2.2.1" dependencies = [ "uniffi", ] [[package]] name = "rustynes-netplay" -version = "2.2.0" +version = "2.2.1" dependencies = [ "futures-util", "js-sys", @@ -4499,7 +4499,7 @@ dependencies = [ [[package]] name = "rustynes-ppu" -version = "2.2.0" +version = "2.2.1" dependencies = [ "bitflags 2.13.0", "criterion", @@ -4511,14 +4511,14 @@ dependencies = [ [[package]] name = "rustynes-ra" -version = "2.2.0" +version = "2.2.1" dependencies = [ "rustynes-cheevos", ] [[package]] name = "rustynes-script" -version = "2.2.0" +version = "2.2.1" dependencies = [ "mlua", "piccolo", @@ -4529,7 +4529,7 @@ dependencies = [ [[package]] name = "rustynes-test-harness" -version = "2.2.0" +version = "2.2.1" dependencies = [ "insta", "png", diff --git a/Cargo.toml b/Cargo.toml index 8c263c95..08d52d29 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ members = [ ] [workspace.package] -version = "2.2.0" +version = "2.2.1" edition = "2024" rust-version = "1.96" license = "MIT OR Apache-2.0" diff --git a/README.md b/README.md index ba5244d3..0abd8767 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@

- Build Status License: MIT OR Apache-2.0 Version Rust: 1.96
+ Build Status License: MIT OR Apache-2.0 Version Rust: 1.96
AccuracyCoin nestest Try in browser
Platform

@@ -775,7 +775,18 @@ and the Material-for-MkDocs documentation handbook at ## Current Release -RustyNES's current release is **v2.2.0 "Capstone"**, the milestone cut that **closes the +RustyNES's current release is **v2.2.1**, a **housekeeping patch** on top of +v2.2.0 "Capstone" (below): archives two batches of dev/research tooling (the +Game Genie header-robust re-key's research scripts and a 2A03-revision +DMA-divergence probe), consolidates six open Dependabot PRs with **zero +source changes** (pollster, wide, tungstenite/tokio-tungstenite, bytemuck, +cc, actions/setup-python), and wires four gitignored, BIOS-gated smoke tests +against `TakuikaNinja`'s FDS hardware-verification probes (regression +insurance for behavior RustyNES already models correctly). **Zero accuracy, +feature, or core changes** — AccuracyCoin holds **141/141 (100.00%)**, +unchanged from v2.2.0. + +It follows **v2.2.0 "Capstone"**, the milestone cut that **closes the v2.1.5 → v2.2.0 "deepen the existing project" run**, landing its two remaining marquees — the **netplay matchmaking/lobby** stack (a browse-and-join room directory + server-side quick-play over the existing room-code / TURN transport, delayed-stream spectators, a graded diff --git a/docs/STATUS.md b/docs/STATUS.md index dd5b7f04..2e5785e9 100644 --- a/docs/STATUS.md +++ b/docs/STATUS.md @@ -1,6 +1,21 @@ # RustyNES — Project Status Matrix -> **Current release: v2.2.0 "Capstone"** (2026-07-12) — the **milestone cut** that +> **Current release: v2.2.1** (2026-07-15) — a **housekeeping patch** on top of +> v2.2.0 "Capstone" (below): archives two batches of dev/research tooling (the +> Game Genie header-robust re-key's six research/verification scripts in +> `scripts/gg/`, and the 2A03-revision DMA-divergence probe in `scripts/probes/`), +> consolidates six open Dependabot PRs with **zero source changes** (`pollster` +> 0.4→1.0, `wide` 0.7→1.5, `tungstenite`/`tokio-tungstenite` 0.29→0.30, +> `bytemuck`/`cc` patch, `actions/setup-python` v5→v6), and wires four gitignored, +> `RUSTYNES_FDS_BIOS`-gated smoke tests against `TakuikaNinja`'s FDS `$4023` / +> mirroring / audio-register / DRAM-watchdog hardware-verification probes +> (regression insurance for behavior RustyNES already models correctly — not a +> fix). **Zero accuracy, feature, or core changes** — the deterministic +> `#![no_std]` chip stack, save-state / TAS / netplay-replay formats, and every +> golden vector are untouched; **AccuracyCoin holds 141/141 (100.00%)**, +> unchanged from v2.2.0. +> +> The prior release, **v2.2.0 "Capstone"** (2026-07-12), was the **milestone cut** that > **closes the v2.1.5 → v2.2.0 "deepen the existing project"** run on the v2.0.0 "Timebase" > core, landing its two remaining marquees — the **netplay matchmaking / lobby** stack and the > **FDS medium model** — atop a peripherals + quality/security pass (the joint iOS App Store /