From 28e066be6abbf0ba558d6ca0525edc517fc1f7eb Mon Sep 17 00:00:00 2001 From: DoubleGate Date: Sun, 12 Jul 2026 03:56:38 -0400 Subject: [PATCH] =?UTF-8?q?release:=20cut=20v2.1.9=20"Fathom"=20(presentat?= =?UTF-8?q?ion=20and=20signal=20=E2=80=94=20"Aperture")?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cuts the v2.1.9 release — the presentation-and-signal step of the v2.1.5 → v2.2.0 "deepen the existing project" run, a marquee display release. Bumps the workspace version 2.1.8 → 2.1.9, renames CHANGELOG `[Unreleased]` → `[2.1.9]`, refreshes Cargo.lock, syncs the README badge / current-release paragraph / BibTeX, and authors `.github/release-notes/v2.1.9.md`. v2.1.9 (PR #283) is all opt-in / default-off display work, so the shipped default presentation stays byte-identical (AccuracyCoin 141/141, nestest 0-diff, visual_regression byte-identical): - Marquee CRT shader stack: WGSL ports of CRT-Royale, crt-guest-advanced, and Sony Megatron (HDR), selectable with mask/scanline/curvature controls + per-game presets. - Raw NTSC composite signal-decode path: a new rustynes-ppu::raw_signal un-decoded 2C02 composite model + a signal_decode.wgsl demodulator (rotating oscillator, edge-consistent phase) for artifact-accurate color. - GIF + WAV capture (extending av-record) + a generated-NTSC palette editor with a live preview. No default-build behavior change. Co-Authored-By: Claude Opus 4.8 --- .github/release-notes/v2.1.9.md | 31 ++++++++++++++++++++++++++++ CHANGELOG.md | 2 ++ Cargo.lock | 36 ++++++++++++++++----------------- Cargo.toml | 2 +- README.md | 27 +++++++++++-------------- 5 files changed, 64 insertions(+), 34 deletions(-) create mode 100644 .github/release-notes/v2.1.9.md diff --git a/.github/release-notes/v2.1.9.md b/.github/release-notes/v2.1.9.md new file mode 100644 index 00000000..54b05630 --- /dev/null +++ b/.github/release-notes/v2.1.9.md @@ -0,0 +1,31 @@ +# RustyNES v2.1.9 — Fathom (presentation and signal — Aperture) + +The **presentation-and-signal** step of the v2.1.5 → v2.2.0 "deepen the existing project" run — a marquee display release. Every shader / signal / capture / editor path is **opt-in and default-off**, so the shipped default presentation stays **byte-identical**: **AccuracyCoin 141/141 (100.00%)**, nestest 0-diff, `visual_regression` byte-identical. Landed in PR #283. + +## Added + +### Marquee CRT shader stack (B6) + +WGSL ports of three reference slang CRT shaders, first-class `BuiltinPass` variants selectable in **Settings → Shaders**, each with `#pragma parameter` sliders wired to the uniform slots: + +- **CRT-Royale** — the aperture/shadow/slot-mask + scanline + convergence classic. +- **crt-guest-advanced / guest-dr-venom** — mask type, scanline weight, beam, glow, curvature. +- **Sony Megatron** — the HDR CRT model (mask/gamma/HDR controls). + +Plus **per-game shader presets** (`PerGameConfig.shader_preset`, resolved on ROM load via `ShaderPresetBank::resolve`; `None`/unknown = byte-identical default) and five showcase built-in presets. All four new shaders parse and validate under the exact naga-29 validator wgpu uses. + +### Raw NTSC composite signal-decode path (P4) + +A new `rustynes-ppu::raw_signal` module generates the **un-decoded 2C02 composite waveform** (the Bisqwit `nes_ntsc` / Mesen2 "raw palette" model — a 512×12 chroma/level/emphasis table, `no_std`, transcendental-free with a `GOLDEN_SIGNAL` const-eval lock), and a new `signal_decode.wgsl` pass reconstructs the true two-level chip square wave from the index framebuffer and demodulates it — giving **signal-accurate artifact color** (waterfall dithering, transparency tricks) alongside the existing generated-palette + shader ladder. The demodulator uses a rotating-oscillator (3 transcendentals/pixel, not per-tap `sin`/`cos`) and a non-negative modulo so edge pixels stay phase-consistent. + +### Capture + palette editor + +- **GIF + WAV export** (`Container::{Gif,Wav}`) extending the `av-record` capture pipeline — video-only palettegen/paletteuse GIF at 25 fps, audio-only `pcm_s16le` WAV, with save-dialog filters. The recorder is unchanged (read-only taps; the emulation timeline is never perturbed). +- **Generated-NTSC palette editor** with a **live 16×4 preview** that regenerates from the current hue/sat/contrast/brightness/gamma params via `generate_base_palette` as you drag. + +## Notes + +- Version: workspace `2.1.8 → 2.1.9` (Cargo.lock refreshed). No dependency or mobile changes (the mobile apps re-release at v2.3.0). +- **No default-build behavior change.** All shaders, the raw-composite path, capture, and the palette editor are opt-in; the default presentation and the deterministic core are untouched. AccuracyCoin stays **141/141 (100.00%)**, nestest 0-diff, `visual_regression` byte-identical, save-state and the 60-ROM commercial oracle unchanged. +- Docs updated in-change: `docs/frontend.md` (the CRT stack, capture, palette editor), `docs/ppu-2c02.md` (raw-composite output), `CHANGELOG.md`. +- Full host gate green: fmt · clippy (native all-targets + feature combos incl. `av-record` + wasm32) · rustdoc (`-D warnings`) · `no_std` cross-compile (`thumbv7em`) · markdownlint (pinned v0.39.0) · the new-shader naga validation + `shader_pass` / `raw_signal` / `per_game` suites · AccuracyCoin 141/141 + `visual_regression` byte-identical · version consistency. diff --git a/CHANGELOG.md b/CHANGELOG.md index a8209cef..a49e70cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ cycle-accurate core later replaced. ## [Unreleased] +## [2.1.9] - 2026-07-12 - "Fathom" (presentation and signal — marquee CRT shader stack (CRT-Royale / guest-advanced / Sony Megatron) + raw NTSC composite signal-decode path + GIF/WAV capture + generated-palette editor — "Aperture") + ### Added - **Marquee CRT shader stack + raw NTSC composite signal (v2.1.9 "Presentation diff --git a/Cargo.lock b/Cargo.lock index 051054b2..150eda2b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4248,7 +4248,7 @@ dependencies = [ [[package]] name = "rustynes-android" -version = "2.1.8" +version = "2.1.9" dependencies = [ "android-activity", "android_logger", @@ -4266,7 +4266,7 @@ dependencies = [ [[package]] name = "rustynes-apu" -version = "2.1.8" +version = "2.1.9" dependencies = [ "bitflags 2.13.0", "criterion", @@ -4279,7 +4279,7 @@ dependencies = [ [[package]] name = "rustynes-cheevos" -version = "2.1.8" +version = "2.1.9" dependencies = [ "cc", "ureq", @@ -4287,7 +4287,7 @@ dependencies = [ [[package]] name = "rustynes-core" -version = "2.1.8" +version = "2.1.9" dependencies = [ "bitflags 2.13.0", "criterion", @@ -4304,7 +4304,7 @@ dependencies = [ [[package]] name = "rustynes-cpu" -version = "2.1.8" +version = "2.1.9" dependencies = [ "bitflags 2.13.0", "criterion", @@ -4315,7 +4315,7 @@ dependencies = [ [[package]] name = "rustynes-frontend" -version = "2.1.8" +version = "2.1.9" dependencies = [ "anstyle", "arboard", @@ -4369,11 +4369,11 @@ dependencies = [ [[package]] name = "rustynes-gfx-shaders" -version = "2.1.8" +version = "2.1.9" [[package]] name = "rustynes-hdpack" -version = "2.1.8" +version = "2.1.9" dependencies = [ "lewton", "png", @@ -4384,7 +4384,7 @@ dependencies = [ [[package]] name = "rustynes-ios" -version = "2.1.8" +version = "2.1.9" dependencies = [ "bytemuck", "cpal", @@ -4398,7 +4398,7 @@ dependencies = [ [[package]] name = "rustynes-libretro" -version = "2.1.8" +version = "2.1.9" dependencies = [ "libc", "rust-libretro", @@ -4407,7 +4407,7 @@ dependencies = [ [[package]] name = "rustynes-mappers" -version = "2.1.8" +version = "2.1.9" dependencies = [ "bitflags 2.13.0", "criterion", @@ -4419,7 +4419,7 @@ dependencies = [ [[package]] name = "rustynes-mobile" -version = "2.1.8" +version = "2.1.9" dependencies = [ "rustynes-core", "rustynes-hdpack", @@ -4434,14 +4434,14 @@ dependencies = [ [[package]] name = "rustynes-monetization" -version = "2.1.8" +version = "2.1.9" dependencies = [ "uniffi", ] [[package]] name = "rustynes-netplay" -version = "2.1.8" +version = "2.1.9" dependencies = [ "futures-util", "js-sys", @@ -4457,7 +4457,7 @@ dependencies = [ [[package]] name = "rustynes-ppu" -version = "2.1.8" +version = "2.1.9" dependencies = [ "bitflags 2.13.0", "criterion", @@ -4469,14 +4469,14 @@ dependencies = [ [[package]] name = "rustynes-ra" -version = "2.1.8" +version = "2.1.9" dependencies = [ "rustynes-cheevos", ] [[package]] name = "rustynes-script" -version = "2.1.8" +version = "2.1.9" dependencies = [ "mlua", "piccolo", @@ -4487,7 +4487,7 @@ dependencies = [ [[package]] name = "rustynes-test-harness" -version = "2.1.8" +version = "2.1.9" dependencies = [ "insta", "png", diff --git a/Cargo.toml b/Cargo.toml index cb377f46..8546cdc3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ members = [ ] [workspace.package] -version = "2.1.8" +version = "2.1.9" edition = "2024" rust-version = "1.96" license = "MIT OR Apache-2.0" diff --git a/README.md b/README.md index 6dfbe55d..a6ab3c34 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,19 +775,16 @@ and the Material-for-MkDocs documentation handbook at ## Current Release -RustyNES's current release is **v2.1.8 "Fathom" ("Tempo")**, the performance step of the -v2.1.5 → v2.2.0 "deepen the project" run — it adds a **specialized visible-scanline fast -PPU dot path** (a straight-line renderer for clean dots that drops to the exact 2-cycle-ALE -loop the instant any sub-scanline disturbance occurs; **~12% faster** on rendering-heavy -frames), a set of **SIMD-validated software palette→RGBA blitter paths** (scalar / `wide` / -wasm `+simd128`, all proven byte-identical — but the conversion is a **memory-bound LUT -gather**, so no SIMD path clears the >3% bar and **scalar stays the default**; the vector -paths are validated and available, not a shipped speedup), and a **wasm size/startup pass** -(`wasm-opt -O4` → 3.99 MiB gzip, comfortably under budget). The fast dot path is -**default-off** and **differential-tested bit-identical** to the exact path across the -corpus (framebuffer + audio + cycles + snapshot) — so the shipped build stays byte-identical: -**AccuracyCoin stays 141/141 (100.00%)**, nestest 0-diff, `visual_regression` / -`pal_apu_tests` unchanged. +RustyNES's current release is **v2.1.9 "Fathom" ("Aperture")**, the presentation-and-signal +step of the v2.1.5 → v2.2.0 "deepen the project" run — it adds a **marquee CRT shader stack** +(WGSL ports of **CRT-Royale**, **crt-guest-advanced**, and **Sony Megatron** HDR, selectable +in Settings → Shaders with mask/scanline/curvature controls and per-game presets), a +**raw NTSC composite signal-decode path** (a new `rustynes-ppu::raw_signal` un-decoded 2C02 +composite model plus a `signal_decode.wgsl` pass that reconstructs and demodulates the real +signal for artifact-accurate color), **GIF + WAV capture** (extending `av-record`), and a +**generated-NTSC palette editor** with a live preview. Every shader / signal / capture path +is **opt-in and default-off**, so the shipped default presentation stays byte-identical: +**AccuracyCoin stays 141/141 (100.00%)**, nestest 0-diff, `visual_regression` byte-identical. The v2.1.x line opened with **v2.1.0**, the accuracy-remediation release (a display-only PPU palette-backdrop-override fix, 86 mapper families promoted BestEffort → Curated, and @@ -913,7 +910,7 @@ If you use RustyNES in academic research, please cite: author = {RustyNES Contributors}, title = {RustyNES: A Cycle-Accurate NES Emulator in Rust}, year = {2026}, - version = {2.1.8}, + version = {2.1.9}, url = {https://github.com/doublegate/RustyNES}, note = {Cycle-accurate NES emulator on a master-clock-precise scheduler; AccuracyCoin 100\% (141/141), nestest 0-diff; 172 mapper families,