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
32 changes: 32 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -237,3 +237,35 @@ WARP.md

# Antigravity PR reviewer: large-diff on-disk handoff (transient, removed by the script).
/.agy-review-work/

# --- Frontend capture / telemetry output (`v1.25.0`, T-FP-B / T-FP-G1) ---
# These land in the user's data directory by default, but the emulator can be pointed anywhere and
# is routinely run straight out of a checkout — so a stray capture must not become a commit
# candidate.
#
# Each pattern's breadth was checked against what is actually COMMITTED rather than assumed. The
# extensions below have zero tracked files, so they are safe to match recursively:
**/*.y4m
**/*.wav
**/rustysnes-perf-*.csv

# Screenshots are the exception, and the reason the rest of this block is not simply `*.png`.
# `screenshot::file_stem` writes `<sanitized-rom-title>-NNNN.png`, defaulting to `rustysnes-NNNN`
# — but the repo tracks **712** PNGs, 30 of them named `rustysnes-*.png` (the branding banners),
# and `assets/RustySNES_Icon_Pack/transparent/icon/rustysnes-icon-transparent-1024.png` even
# matches a generic `*-NNNN.png`. So:
# - the default-title form is exact enough to match recursively (zero tracked collisions);
# - the ROM-titled form stays ROOT-ANCHORED, since a recursive version would ignore real assets.
**/rustysnes-[0-9][0-9][0-9][0-9].png
/*-[0-9][0-9][0-9][0-9].png

# The recommended destination for captures — point the emulator here and nothing above has to be
# relied on at all. `**/` already covers the repo root, so no separate `/captures/` is needed.
**/captures/

# Shader presets and symbol maps a user drops in to try (inputs, never project files). Zero
# tracked files of any of these extensions, so recursive is safe.
**/*.slangp
**/*.cgp
**/*.sym
/presets/
44 changes: 44 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,50 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.25.0] "Workbench" - 2026-07-30

**The frontend catches up with the engine.** RustySNES's emulation core has been at the Mesen2/ares
bar for several releases while its egui shell lagged its own NES sibling; this release closes that
gap in ten reviewed increments (`T-FP-A` … `T-FP-G2`), taking the frontend from "boots games" to a
tool you can debug, profile, record, retime, and author a TAS with.

Everything here is **additive and default-off or default-inert**: `video.stack` defaults to `Off`,
the preset chain is empty, the debugger needs `debug-hooks`, GPU timing needs `gpu-timing`, and the
per-voice mixer's unity gain is a bit-exact bypass in the DSP. An existing `config.toml` renders and
sounds byte-identically, and no save-state format changed (`FORMAT_VERSION` stays at 10).

The five headline capabilities:

- **A real debugger** — conditional breakpoints over an expression evaluator, an instruction trace,
a control-flow event log, a WRAM access heat map, symbol maps, a memory editor with freezes, an
OAM viewer, a cart memory map, and an inline 65C816 assembler that assembles by *searching the
real disassembler* rather than carrying a second opcode table.
- **A multi-pass shader stack** with `RetroArch`-shaped per-pass semantics, richer CRT and an NTSC
composite pass, `.slangp`/`.cgp` preset parsing, and a best-effort GLSL→WGSL bridge through naga —
every untranslatable pass named rather than silently black. Verified by **offscreen GPU goldens**,
which is new infrastructure: the previous shader tests only checked that WGSL parsed.
- **Observability and honest pacing** — p50/p95/p99/max distributions over emulation, present, GPU
and audio-buffer time, an opt-in CSV session log, and `PacingMode` turned from a setting nothing
read into one resolved against the monitor's real refresh and the surface's real present-mode caps,
with any declined request **reported** rather than silently downgraded.
- **An 8-voice audio mixer** (gain, mute, solo, VU meters) plus **compressed rewind** — XOR-delta and
RLE with periodic keyframes, no new dependency, bit-identical round-trip.
- **TAStudio** — a piano roll, a greenzone that reuses the rewind compression, and invalidation as
the *default* consequence of an edit.

Plus the infrastructure the above plugs into: compile-time-checked localisation in five languages
wired through the whole menu bar and every Settings tab, a populated Help menu, and `Settings` split
into per-tab renderers.

### A recurring defect this release was written to remove

Five settings shipped in earlier versions that **round-tripped through `config.toml` while nothing
read them** — `gamepad`, `video.integer_scale`, `config.p2`, `audio.device`, and `PacingMode`. Each
looked functional and did nothing. All five are now live, and the pattern was explicitly hunted:
grep a setting's *readers*, not its definition. Two more instances were caught during review of this
very release — a shader preset path that persisted while nothing loaded it at startup, and an i18n
catalogue with sixty translated strings and eight consumers.

### Fixed

- **Soft-patching: a hostile BPS patch could panic instead of erroring.** Two arithmetic paths took
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 @@ -22,7 +22,7 @@ members = [
]

[workspace.package]
version = "1.24.0"
version = "1.25.0"
edition = "2024"
rust-version = "1.96"
license = "MIT OR Apache-2.0"
Expand Down
23 changes: 19 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
</p>

<p align="center">
<a href="https://github.com/doublegate/RustySNES/actions"><img src="https://github.com/doublegate/RustySNES/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/RustySNES/releases"><img src="https://img.shields.io/badge/version-v1.24.0-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/RustySNES/actions"><img src="https://github.com/doublegate/RustySNES/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/RustySNES/releases"><img src="https://img.shields.io/badge/version-v1.25.0-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/65C816%20oracle-0--diff-brightgreen.svg" alt="65C816 oracle: 0-diff"></a> <a href="#compatibility-and-accuracy"><img src="https://img.shields.io/badge/SPC700%20oracle-0--diff-brightgreen.svg" alt="SPC700 oracle: 0-diff"></a> <a href="https://doublegate.github.io/RustySNES/"><img src="https://img.shields.io/badge/pages-demo%20%2B%20rustdoc%20%2B%20docs-success.svg" alt="GitHub Pages"></a><br>
<a href="#platform-support"><img src="https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS%20%7C%20Web-lightgrey.svg" alt="Platform"></a>
</p>
Expand Down Expand Up @@ -623,9 +623,14 @@ Material-for-MkDocs documentation handbook at

## Current Release

RustySNES's current release is **v1.8.0 "Tracepoint"**. See [`docs/STATUS.md`](docs/STATUS.md)
and [`CHANGELOG.md`](CHANGELOG.md) for the full release history (`v0.1.0` through `v1.8.0`) and
per-release detail.
RustySNES's current release is **v1.25.0 "Workbench"** — the frontend release that brings the
egui shell up to the engine's level: a full debugger, a multi-pass shader stack with `.slangp`
support, performance distributions and hardware-resolved frame pacing, an 8-voice audio mixer with
compressed rewind, A/V capture, a virtual pad, and TAStudio. It is **additive throughout**: an
existing `config.toml` renders and sounds byte-identically, and no save-state format changed.

See [`docs/STATUS.md`](docs/STATUS.md) and [`CHANGELOG.md`](CHANGELOG.md) for the full release
history (`v0.1.0` through `v1.25.0`) and per-release detail.

- **Download:** the [GitHub Releases](https://github.com/doublegate/RustySNES/releases) page —
desktop binaries for Linux, macOS (aarch64), and Windows.
Expand Down Expand Up @@ -656,6 +661,16 @@ emulator, tracked in lockstep rather than a frozen snapshot
native 3x default.
- **`v1.8.0 "Tracepoint"`** — debugger depth II: a Memory Compare panel and an in-app Docs/glossary
panel.
- **`v1.9.0 "Marionette"` - `v1.20.0 "Aperture"`** — scripting reach, HD packs, RetroAchievements,
shaders and accessibility, the Android/iOS mobile ladder, a PGO/BOLT pipeline, and a UI/UX-parity
pass — all with the accuracy dashboard unchanged.
- **`v1.21.0 "Touchstone"` - `v1.24.0 "Ensemble"`** — the accuracy rungs: the per-dot PPU compositor
becomes the sole renderer, the DSP-1 Mode-7 floor is fixed and then the NEC-DSP host interface
made pin-exact, and DSP-3 + ST011 complete the NEC coprocessor family.
- **`v1.25.0 "Workbench"`** — the frontend catches up with the engine, in ten reviewed increments
(`T-FP-A`-`T-FP-G2`): debugger, shader stack + `.slangp`/GLSL bridge, observability + real pacing,
audio mixer + compressed rewind, A/V capture + virtual pad + databases, and TAStudio. Five
settings that had round-tripped through `config.toml` while nothing read them are now live.

The full roadmap lives in [`to-dos/ROADMAP.md`](to-dos/ROADMAP.md) (the phase spine) and
[`to-dos/VERSION-PLAN.md`](to-dos/VERSION-PLAN.md) (the named release ladder, including the
Expand Down
2 changes: 1 addition & 1 deletion crates/rustysnes-android/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "rustysnes-android"
description = "RustySNES: Android JNI presentation host (wgpu-on-Surface, no emulation logic)"
version = "1.24.0"
version = "1.25.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/rustysnes-apu/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rustysnes-apu"
version = "1.24.0"
version = "1.25.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/rustysnes-cart/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rustysnes-cart"
version = "1.24.0"
version = "1.25.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/rustysnes-cheevos/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "rustysnes-cheevos"
description = "Native-only RetroAchievements (rcheevos) FFI wrapper for RustySNES"
version = "1.24.0"
version = "1.25.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/rustysnes-core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rustysnes-core"
version = "1.24.0"
version = "1.25.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/rustysnes-cpu/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rustysnes-cpu"
version = "1.24.0"
version = "1.25.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/rustysnes-frontend/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "rustysnes-frontend"
description = "RustySNES: cross-platform SNES emulator binary (winit + wgpu + cpal + egui)"
version = "1.24.0"
version = "1.25.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/rustysnes-gfx-shaders/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "rustysnes-gfx-shaders"
description = "RustySNES: shared WGSL presentation-shader sources (blit + post-filters)"
version = "1.24.0"
version = "1.25.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/rustysnes-ios/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "rustysnes-ios"
description = "RustySNES: iOS Metal presentation host (wgpu-on-CAMetalLayer, no emulation logic)"
version = "1.24.0"
version = "1.25.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/rustysnes-mobile/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "rustysnes-mobile"
description = "RustySNES: UniFFI mobile bridge (Kotlin/Swift bindings over the emulation core)"
version = "1.24.0"
version = "1.25.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/rustysnes-monetization/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "rustysnes-monetization"
description = "RustySNES: dormant entitlement/ad-pacing policy scaffold (mobile-only, never a dependency of the deterministic core)"
version = "1.24.0"
version = "1.25.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/rustysnes-netplay/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "rustysnes-netplay"
description = "RustySNES: GGPO-style rollback netplay (UDP native, WebRTC browser)"
version = "1.24.0"
version = "1.25.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
Expand Down
Loading
Loading