Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/release-notes/v2.1.9.md
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
36 changes: 18 additions & 18 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
27 changes: 12 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</p>

<p align="center">
<a href="https://github.com/doublegate/RustyNES/actions"><img src="https://github.com/doublegate/RustyNES/workflows/CI/badge.svg" alt="Build Status"></a> <a href="#license"><img src="https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg" alt="License: MIT OR Apache-2.0"></a> <a href="https://github.com/doublegate/RustyNES/releases"><img src="https://img.shields.io/badge/version-v2.1.8-blue.svg" alt="Version"></a> <a href="rust-toolchain.toml"><img src="https://img.shields.io/badge/rust-1.96-orange.svg" alt="Rust: 1.96"></a><br>
<a href="https://github.com/doublegate/RustyNES/actions"><img src="https://github.com/doublegate/RustyNES/workflows/CI/badge.svg" alt="Build Status"></a> <a href="#license"><img src="https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg" alt="License: MIT OR Apache-2.0"></a> <a href="https://github.com/doublegate/RustyNES/releases"><img src="https://img.shields.io/badge/version-v2.1.9-blue.svg" alt="Version"></a> <a href="rust-toolchain.toml"><img src="https://img.shields.io/badge/rust-1.96-orange.svg" alt="Rust: 1.96"></a><br>
<a href="#compatibility-and-accuracy"><img src="https://img.shields.io/badge/AccuracyCoin-100%25%20(141%2F141)-brightgreen.svg" alt="AccuracyCoin"></a> <a href="#compatibility-and-accuracy"><img src="https://img.shields.io/badge/nestest-0--diff-brightgreen.svg" alt="nestest"></a> <a href="https://doublegate.github.io/RustyNES/"><img src="https://img.shields.io/badge/play-in%20browser-success.svg" alt="Try in browser"></a><br>
<a href="#platform-support"><img src="https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS%20%7C%20Web%20%7C%20Android%20%7C%20iOS-lightgrey.svg" alt="Platform"></a>
</p>
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
Loading