diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index f81a8e0f..f123d753 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -124,7 +124,7 @@ jobs:
stage="rustynes-${{ steps.tag.outputs.tag }}-${{ matrix.target }}"
mkdir -p "$stage"
cp "target/${{ matrix.target }}/release/${{ matrix.bin_name }}" "$stage/"
- cp README.md LICENSE-MIT LICENSE-APACHE NOTICE CHANGELOG.md "$stage/"
+ cp README.md LICENSE NOTICE CHANGELOG.md "$stage/"
echo "stage=${stage}" >> "$GITHUB_ENV"
- name: Create archive (tar.gz)
@@ -247,7 +247,7 @@ jobs:
cp pgo-bin/rustynes "$stage/rustynes"
chmod +x "$stage/rustynes"
strip "$stage/rustynes"
- cp README.md LICENSE-MIT LICENSE-APACHE NOTICE CHANGELOG.md "$stage/"
+ cp README.md LICENSE NOTICE CHANGELOG.md "$stage/"
tar -czf "${stage}.tar.gz" "$stage"
echo "asset=${stage}.tar.gz" >> "$GITHUB_ENV"
diff --git a/.gitignore b/.gitignore
index 05fb22a9..c75b0155 100644
--- a/.gitignore
+++ b/.gitignore
@@ -187,7 +187,17 @@ flamegraph.svg
# Large local NESdev wiki mirror (~208M, reference only).
/nesdev_wiki/
-# --- Reference projects (external cloned repos) ---
+# --- Reference projects (external cloned repos) — REFERENCE FIREWALL ---
+# ref-proj/ held local clones of reference emulators used ONLY as black-box
+# behavioral oracles. Their licenses are project-specific: Mesen2, puNES, FCEUX,
+# and GeraNES are copyleft (GPL), and reproducing that source makes RustyNES a
+# derivative work (which it now is, GPL-3.0-or-later); TriCNES is MIT. The
+# directory has been REMOVED from disk and stays ignored here as a firewall guard
+# so the copyleft source can never re-enter the working tree. Do NOT re-clone
+# reference-emulator source into the repo; implement hardware behavior from
+# docs/test ROMs. (The MIT TriCNES source is instead deliberately vendored, with
+# attribution, under crates/rustynes-test-harness/golden/tricnes/.) See
+# docs/ai-emulator-provenance-guardrails.md and the "MOST IMPORTANT RULE" of AGENTS.md.
/ref-proj/
# --- Temporary files ---
diff --git a/AGENTS.md b/AGENTS.md
index 0b056033..580102d0 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -23,11 +23,24 @@
> **New here since v0.8.x?** The emulation core was replaced with the cycle-accurate engine and the repo was re-cut as v1.0.0. Read `docs/v1.0.0-synthesis-handoff-2026-06-13.md` first — it explains what changed, the `rustynes-*` architecture, where everything moved, and the hard constraints. Then update this file + your memory as you work.
+## MOST IMPORTANT RULE — Provenance & license firewall (read first, applies to every task)
+
+**This rule outranks everything else in this file.** RustyNES exists because of a real, corrected provenance failure (GPL emulator code was reproduced despite a black-box instruction, then the honest "ported from" comments were scrubbed; the project was relicensed to **GPL-3.0-or-later** and every derived site re-attributed). The full account is `docs/provenance-failure-postmortem.md`; the preventive ruleset is **`docs/ai-emulator-provenance-guardrails.md`** (PDFs of both in `ref-docs/`). **Read the guardrails doc and treat it as binding.** The non-negotiable core:
+
+- **REFERENCE FIREWALL.** Reference emulators (Mesen2, puNES, FCEUX, Nestopia, higan, ares, GeraNES, TriCNES, tetanes, …) are **black-box oracles**. You may run them and read their *output* (framebuffers, traces, audio, logs). You **must not** open, read, quote, or reproduce their **source** (`.c`/`.cpp`/`.h`/`.cs`/`.rs`), constants, tables, variable names, code ordering, or comments — not "for reference," not once. **The local `ref-proj/` reference-emulator clone has been removed from disk and stays gitignored (`/ref-proj/`), so the source is out of reach by design. Do not re-clone it into the working tree.** If you find such source in reach, report that it should be removed; do not read it.
+- **IMPLEMENT FROM DOCS.** Write hardware behavior from public documentation (`nesdev_wiki/`, `ref-docs/`, datasheets, die studies) and pin it to public test ROMs / golden vectors. Hardware behavior is a fact; the specific *code expression* is copyrighted.
+- **IF YOU DERIVE, SAY SO — AND STOP.** If you do port/adapt/closely-model an external source, (1) it is a derivative work under that source's license; (2) attribute it at the site + in `docs/originality-and-provenance.md` §1 + in `NOTICE` + via an SPDX header; (3) the project license must stay compatible (GPL-3.0-or-later) — flag it to the maintainer before proceeding.
+- **NEVER LAUNDER.** Never reword or delete an honest "ported/derived from X" comment to make code look independent. Scrubbing provenance is the cardinal failure — worse than the original port. The response to "this says GPL code was incorporated" is relicense-and-attribute, never scrub-the-comment.
+- **NO OVER-ATTRIBUTION.** Do not tag a genuine oracle *comparison* ("matches Mesen2's behavior," "cross-checked against ares") as "derived from." Attribute real ports; leave genuinely-independent code independent.
+- **DO NOT SELF-CERTIFY.** Never assert "no third-party code is incorporated" / "license-clean" as a finished claim. Surface provenance status for human + expert review; state uncertainty. AI self-attestation of license compliance is not trustworthy — an outside NESdev reviewer, not the tooling, is what caught this.
+
+Enforcement lives alongside the prose: `/ref-proj/` is gitignored/`.dockerignore`d/`.markdownlintignore`d and excluded from CodeRabbit; `deny.toml` gates dependency licenses; every derived file carries an SPDX + provenance header. A rule the tooling enforces beats a rule you are merely asked to follow.
+
## What this is
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.8 "Aperture II"** (2026-08-04, a presentation-fidelity release — gamma-correct scanlines in linear light + a WebGL2 gamma fix + a sharper Gaussian scanline profile in the base `CRT_WGSL`; presentation-only, so the pre-shader framebuffer + AccuracyCoin 141/141 are byte-identical and the shipped native default is unchanged [the native sRGB surface passes `aux = 0`, which selects the exact pre-v2.2.8 output; the new linear-light + sharpness path is keyed on a non-zero `aux`, set on the WebGL2 non-sRGB path and when the scanline knob is raised]; the shader/appearance changes await on-display + browser visual verification), on top of **v2.2.7 "Timbre II"** (2026-08-04) — an **expansion-audio fidelity** release (of the v2.2.6 → v2.3.0 NESdev-remediation line), driven by a measure-first cross-reference of VRC6 and Sunsoft 5B against 11 reference emulators + the NESdev wiki (Mesen2-only comparison hides where Mesen2 is the outlier). **VRC6 recalibrated to ~1.0× a 2A03 pulse** (`VRC6_MIX_SCALE` 979 → 650; the NESdev/field consensus — rustico/tetanes/BizHawk encode 1.0× exactly; Mesen2's louder ~1.506× mixer weighting was the outlier a reviewer flagged; `db_vrc6a/b` oracle 1.506 → 1.0), and the **Sunsoft 5B envelope moved to the exact 5-bit 1.5 dB/step DAC** (`SUNSOFT5B_LOG_VOL32`, matching nestopia/rustico, replacing the 4-bit 3 dB approximation). **Expansion-only — base 2A03 byte-identical**, so **AccuracyCoin holds 141/141 (100.00%)** and nestest is 0-diff; the base BLEP is a verified 81.6 dB-SFDR band-limited decimator. Built on **v2.2.6 "Almanac"** (2026-08-04) — a **de-monetization + provenance** release opening the **v2.2.6 → v2.3.0** NESdev-remediation line. **RustyNES is permanently open-source and income-free (ADR 0035)**: all planned monetization is removed (the `rustynes-monetization` crate, `docs/monetization/`, and the Android/iOS billing / ad / freemium / paywall layers deleted) and the native apps are kept as **free FOSS apps** (no ads, no tracking, no paid unlock; the free Google-Play services + `foss`/`play` split retained). It also discloses (ADR 0030) that the PPU hybrid-address *timing* was calibrated to TriCNES (reproducing the Rad Racer mis-render), flagged for a documentation-derived rework in v2.3.0. **Zero emulation-core behavior changes**, so **AccuracyCoin holds 141/141 (100.00%)** and nestest is 0-diff by construction. On top of **v2.2.5 "Colophon"** (2026-08-03) — a **provenance, licensing, and documentation-integrity** release with **zero emulation-core behavior changes** (so **AccuracyCoin holds 141/141 (100.00%)** and nestest is 0-diff by construction). It reworded in-source comments that had mischaracterized publicly-documented hardware-behavior implementations as "ports of" copyleft emulators (Mesen2 GPLv3, puNES GPLv2) into the accurate oracle framing; rewrote `NOTICE` to disclose the behavioral-oracle use of GPL emulators (Mesen2/MesenCE, higan, GeraNES, ares, FCEUX, Nestopia, puNES — no code incorporated) and to attribute the genuinely-incorporated permissive components (emu2413, TriCNES, rcheevos — all MIT), the bundled fonts and test ROMs, and the CRT-shader/NTSC-filter visual influences as independent reimplementations; disclosed **GeraNES (GPL-3.0-only)** as an oracle; added `docs/originality-and-provenance.md`; and added an AI-assistance disclosure to the README (removing a misleading comparison graphic and fixing a mislabeled screenshot caption). On top of **v2.2.4 "Cartridge"** (2026-07-24) — a **libretro / RetroArch distribution** cut whose purpose is that the RustyNES core **builds and installs cleanly through the Libretro buildbot** () for in-RetroArch use. **Zero emulation-core changes** — the deterministic `#![no_std]` chip stack, save-state / TAS / netplay formats, and every golden vector are byte-identical to v2.2.3, so **AccuracyCoin holds 141/141 (100.00%)** and nestest is 0-diff by construction. `crates/rustynes-libretro` wraps `rustynes-core`, so it inherits every v2.2.3 change automatically (the fast-dot-path default; the `PPU_SNAPSHOT_VERSION` 8 / APU v4 save-state schema, transparent because `get_serialize_size` / `on_serialize` size and emit the *current* snapshot via `Nes::snapshot_core_into` rather than a fixed layout; the `Mapper::mix_audio` i32 widening; the Zapper model; the `mNNN_` mapper rename), and both buildbot cross-ABIs the CI early-warning gate models — `x86_64-pc-windows-gnu` and `aarch64-linux-android` — `cargo check --release -p rustynes-libretro` clean. The concrete change is a **`rustynes_libretro.info` metadata correction**: **`disk_control` `false` → `true`** (the real fix — the FDS multi-side Disk Control interface has been wired since the buildbot recipe landed but was advertised as absent, hiding multi-disk FDS swapping from RetroArch's Quick Menu), `display_version` `v1.0.0` → `v2.2.4`, and the description mapper count `168` → `172`. Libretro **core options** (region / overscan / palette / accuracy toggles) remain unexposed — `core_options = "false"` is accurate, a documented future enhancement rather than a v2.2.4 gap. The Antigravity PR reviewer standardization onto the shared template rides along. On top of **v2.2.3 "Datum"** (2026-07-23) — a **performance and accuracy-closure patch**, the product of a measure-first appraisal that profiled the emulator and acted on what the profile showed rather than on intuition. **Performance:** the specialized PPU fast dot path is promoted to the **default** and exposed to users for the first time — `Nes::set_fast_dotloop` had **no caller outside the core**, so a **−11.3%** frame-time win (fresh clean-host Criterion, reproducing v2.1.8's +12.3% by a different method; differential-tested bit-identical every frame since v2.1.8) shipped switched off and unreachable; release builds now ship **PGO-optimized** Linux binaries when the existing >3%-and-byte-identical gate passes; and CI gained a same-runner **relative** frame-time regression gate, closing a hole where a 2.5x slowdown passed the deliberately-loose absolute ceiling. **Two optimizations were measured and REJECTED** and are documented with their numbers per `docs/performance.md`'s convention — P3 (`emit_pixel` bounds-check elision) made the shipped default *slower* (+4.32% / +3.35% on the `_fast` workloads, p ≤ 0.02), and P4 (`cpu_clock`) found both textbook optimizations already implemented with the one remaining lever capped at **≤1.9%**. **Accuracy:** the **last two Holy Mapperel residuals are closed**, so all 17 ROMs report `detail=0000` (was 15/17) — MMC1's two software WRAM write-protect layers (`$E000` bit 4 + SNROM's CHR-register layer, gated on `chr_is_ram`) and FME-7's open bus on the RAM-selected-but-disabled window, both routed through the trait's existing `cpu_read_unmapped` contract. MMC1 is the change Holy Mapperel's README calls a game-compatibility hazard (FCEUX / PowerPak omit it), so it was validated before landing: **60/60** commercial ROMs including seven battery-backed MMC1 saves, plus **138/138** extended. The **Sunsoft 5B absolute level** is calibrated against Mesen2, which required widening `Mapper::mix_audio` to `i32` (the correct full-scale 5B tone `1882 * 18.471 = 34,761` does not fit `i16`). A **save-state schema gap** is fixed — `PPU_SNAPSHOT_VERSION` **8** carrying the sprite-eval FSM + OAM data-bus state, plus an APU **v4** tail — which is what made AccuracyCoin report **141/141 through run-ahead** as well as without it; a new standing field-vs-schema audit found it and the two APU gaps mechanically. A **Zapper beam-relative light model** lands opt-in / default-off (no pass-fail light-gun ROM exists to adjudicate it). **AccuracyCoin holds 141/141 (100.00%)**, nestest 0-diff. Also: the eleven `sprintN.rs` mapper modules (27,631 lines, ~110 boards) are renamed for the boards they emulate with `mNNN_` mapper-number prefixes, proven content-preserving by a byte-for-byte item comparison (930 items, 0 altered) and an identical 172-ID dispatch table.
+**Current release: v2.2.9 "Studio II"** (2026-08-04, a frontend quality-of-life release opening the second half of the v2.2.6 → v2.3.0 NESdev-remediation line — TAStudio piano-roll edits now drive the emulator [`handle_tas_requests` re-seeks the `Nes` after a `SetInput` batch, matching the scripting path], `.bk2` movies play back honoring their `LogKey` column order [`bk2_interop` parses the real column header instead of a fixed order, with parse errors surfaced on the status bar], and tool windows gain a **detach / pop-out** affordance (the shared `detachable_window` helper across 18 panels) [native-only, docked on wasm; **honest scope caveat:** the frontend is currently a single-viewport `egui_winit` integration, so `show_viewport_immediate` renders the panel *embedded in the main window*, NOT yet a separate OS window — so this does not yet fully resolve the Windows-10 trapped-window report; true OS-window detach needs multi-viewport render-loop wiring (`set_embed_viewports(false)` + per-viewport winit windows), tracked as follow-up]; frontend-only, so the deterministic core is untouched and **AccuracyCoin holds 141/141 (100.00%)** with nestest 0-diff), on top of **v2.2.8 "Aperture II"** (2026-08-04, a presentation-fidelity release — gamma-correct scanlines in linear light + a WebGL2 gamma fix + a sharper Gaussian scanline profile in the base `CRT_WGSL`; presentation-only, so the pre-shader framebuffer + AccuracyCoin 141/141 are byte-identical and the shipped native default is unchanged [the native sRGB surface passes `aux = 0`, which selects the exact pre-v2.2.8 output; the new linear-light + sharpness path is keyed on a non-zero `aux`, set on the WebGL2 non-sRGB path and when the scanline knob is raised]; the shader/appearance changes await on-display + browser visual verification), on top of **v2.2.7 "Timbre II"** (2026-08-04) — an **expansion-audio fidelity** release (of the v2.2.6 → v2.3.0 NESdev-remediation line), driven by a measure-first cross-reference of VRC6 and Sunsoft 5B against 11 reference emulators + the NESdev wiki (Mesen2-only comparison hides where Mesen2 is the outlier). **VRC6 recalibrated to ~1.0× a 2A03 pulse** (`VRC6_MIX_SCALE` 979 → 650; the NESdev/field consensus — rustico/tetanes/BizHawk encode 1.0× exactly; Mesen2's louder ~1.506× mixer weighting was the outlier a reviewer flagged; `db_vrc6a/b` oracle 1.506 → 1.0), and the **Sunsoft 5B envelope moved to the exact 5-bit 1.5 dB/step DAC** (`SUNSOFT5B_LOG_VOL32`, matching nestopia/rustico, replacing the 4-bit 3 dB approximation). **Expansion-only — base 2A03 byte-identical**, so **AccuracyCoin holds 141/141 (100.00%)** and nestest is 0-diff; the base BLEP is a verified 81.6 dB-SFDR band-limited decimator. Built on **v2.2.6 "Almanac"** (2026-08-04) — a **de-monetization + provenance** release opening the **v2.2.6 → v2.3.0** NESdev-remediation line. **RustyNES is permanently open-source and income-free (ADR 0035)**: all planned monetization is removed (the `rustynes-monetization` crate, `docs/monetization/`, and the Android/iOS billing / ad / freemium / paywall layers deleted) and the native apps are kept as **free FOSS apps** (no ads, no tracking, no paid unlock; the free Google-Play services + `foss`/`play` split retained). It also discloses (ADR 0030) that the PPU hybrid-address *timing* was calibrated to TriCNES (reproducing the Rad Racer mis-render), flagged for a documentation-derived rework in v2.3.0. **Zero emulation-core behavior changes**, so **AccuracyCoin holds 141/141 (100.00%)** and nestest is 0-diff by construction. On top of **v2.2.5 "Colophon"** (2026-08-03) — a **provenance, licensing, and documentation-integrity** release with **zero emulation-core behavior changes** (so **AccuracyCoin holds 141/141 (100.00%)** and nestest is 0-diff by construction). It reworded in-source comments that had mischaracterized publicly-documented hardware-behavior implementations as "ports of" copyleft emulators (Mesen2 GPLv3, puNES GPLv2) into the accurate oracle framing; rewrote `NOTICE` to disclose the behavioral-oracle use of GPL emulators (Mesen2/MesenCE, higan, GeraNES, ares, FCEUX, Nestopia, puNES — no code incorporated) and to attribute the genuinely-incorporated permissive components (emu2413, TriCNES, rcheevos — all MIT), the bundled fonts and test ROMs, and the CRT-shader/NTSC-filter visual influences as independent reimplementations; disclosed **GeraNES (GPL-3.0-only)** as an oracle; added `docs/originality-and-provenance.md`; and added an AI-assistance disclosure to the README (removing a misleading comparison graphic and fixing a mislabeled screenshot caption). On top of **v2.2.4 "Cartridge"** (2026-07-24) — a **libretro / RetroArch distribution** cut whose purpose is that the RustyNES core **builds and installs cleanly through the Libretro buildbot** () for in-RetroArch use. **Zero emulation-core changes** — the deterministic `#![no_std]` chip stack, save-state / TAS / netplay formats, and every golden vector are byte-identical to v2.2.3, so **AccuracyCoin holds 141/141 (100.00%)** and nestest is 0-diff by construction. `crates/rustynes-libretro` wraps `rustynes-core`, so it inherits every v2.2.3 change automatically (the fast-dot-path default; the `PPU_SNAPSHOT_VERSION` 8 / APU v4 save-state schema, transparent because `get_serialize_size` / `on_serialize` size and emit the *current* snapshot via `Nes::snapshot_core_into` rather than a fixed layout; the `Mapper::mix_audio` i32 widening; the Zapper model; the `mNNN_` mapper rename), and both buildbot cross-ABIs the CI early-warning gate models — `x86_64-pc-windows-gnu` and `aarch64-linux-android` — `cargo check --release -p rustynes-libretro` clean. The concrete change is a **`rustynes_libretro.info` metadata correction**: **`disk_control` `false` → `true`** (the real fix — the FDS multi-side Disk Control interface has been wired since the buildbot recipe landed but was advertised as absent, hiding multi-disk FDS swapping from RetroArch's Quick Menu), `display_version` `v1.0.0` → `v2.2.4`, and the description mapper count `168` → `172`. Libretro **core options** (region / overscan / palette / accuracy toggles) remain unexposed — `core_options = "false"` is accurate, a documented future enhancement rather than a v2.2.4 gap. The Antigravity PR reviewer standardization onto the shared template rides along. On top of **v2.2.3 "Datum"** (2026-07-23) — a **performance and accuracy-closure patch**, the product of a measure-first appraisal that profiled the emulator and acted on what the profile showed rather than on intuition. **Performance:** the specialized PPU fast dot path is promoted to the **default** and exposed to users for the first time — `Nes::set_fast_dotloop` had **no caller outside the core**, so a **−11.3%** frame-time win (fresh clean-host Criterion, reproducing v2.1.8's +12.3% by a different method; differential-tested bit-identical every frame since v2.1.8) shipped switched off and unreachable; release builds now ship **PGO-optimized** Linux binaries when the existing >3%-and-byte-identical gate passes; and CI gained a same-runner **relative** frame-time regression gate, closing a hole where a 2.5x slowdown passed the deliberately-loose absolute ceiling. **Two optimizations were measured and REJECTED** and are documented with their numbers per `docs/performance.md`'s convention — P3 (`emit_pixel` bounds-check elision) made the shipped default *slower* (+4.32% / +3.35% on the `_fast` workloads, p ≤ 0.02), and P4 (`cpu_clock`) found both textbook optimizations already implemented with the one remaining lever capped at **≤1.9%**. **Accuracy:** the **last two Holy Mapperel residuals are closed**, so all 17 ROMs report `detail=0000` (was 15/17) — MMC1's two software WRAM write-protect layers (`$E000` bit 4 + SNROM's CHR-register layer, gated on `chr_is_ram`) and FME-7's open bus on the RAM-selected-but-disabled window, both routed through the trait's existing `cpu_read_unmapped` contract. MMC1 is the change Holy Mapperel's README calls a game-compatibility hazard (FCEUX / PowerPak omit it), so it was validated before landing: **60/60** commercial ROMs including seven battery-backed MMC1 saves, plus **138/138** extended. The **Sunsoft 5B absolute level** is calibrated against Mesen2, which required widening `Mapper::mix_audio` to `i32` (the correct full-scale 5B tone `1882 * 18.471 = 34,761` does not fit `i16`). A **save-state schema gap** is fixed — `PPU_SNAPSHOT_VERSION` **8** carrying the sprite-eval FSM + OAM data-bus state, plus an APU **v4** tail — which is what made AccuracyCoin report **141/141 through run-ahead** as well as without it; a new standing field-vs-schema audit found it and the two APU gaps mechanically. A **Zapper beam-relative light model** lands opt-in / default-off (no pass-fail light-gun ROM exists to adjudicate it). **AccuracyCoin holds 141/141 (100.00%)**, nestest 0-diff. Also: the eleven `sprintN.rs` mapper modules (27,631 lines, ~110 boards) are renamed for the boards they emulate with `mNNN_` mapper-number prefixes, proven content-preserving by a byte-for-byte item comparison (930 items, 0 altered) and an identical 172-ID dispatch table.
The prior release, **v2.2.2 "Conduit"** (2026-07-21), was a **build, distribution, and CI-integrity patch**: the **libretro buildbot recipe from 1 of 10 jobs green to all ten building** (the last step before RustyNES lands in RetroArch's built-in core downloader), a **GitHub Actions supply-chain hardening** pass (`persist-credentials: false` on all 19 checkouts, a fail-closed release-tag check via `git/matching-refs`, `dtolnay/rust-toolchain` SHA-pinned off `@master`), and the toolchain **collapsed to one pinned source of truth** — no toolchain version literal anywhere under `.github/` and **no `nightly` on any build path**. **Zero emulation-core changes**, so AccuracyCoin held 141/141 by construction. Its one behavioural improvement in a shipped artifact: the libretro **tvOS** core built with `panic = "abort"` like every other platform.
@@ -47,7 +60,7 @@ Platform additions through v1.10.0 were **host-only and additive**: the determin
---
-**Release history → `CHANGELOG.md`.** The full per-release detail — features, the mapper-count growth (51 → **172 families**), ADRs, and PR trains for **v1.0.0 → v2.0.0** (plus the documentary engine-lineage stages v0.9.0–v0.9.7) — lives in `CHANGELOG.md` (the single source of truth for user-visible change), the per-release GitHub Releases, and `to-dos/plans/`. Every release through v1.10.0 was **additive / off-by-default**, so with new features off those builds stayed byte-identical; **v2.0.0 is RustyNES's one designated breaking release** (ADR 0003) — the one-clock, every-cycle-bus-access scheduler (ADR 0002 / ADR 0029) is now the *only* path, and the old PPU-dot lockstep model is retired. **AccuracyCoin holds 100% (139/139)** on every release including v2.0.0. Workspace baseline: edition 2024, Rust **1.96**, license **MIT OR Apache-2.0**, author **DoubleGate**; the WebAssembly / GitHub Pages build is live at .
+**Release history → `CHANGELOG.md`.** The full per-release detail — features, the mapper-count growth (51 → **172 families**), ADRs, and PR trains for **v1.0.0 → v2.0.0** (plus the documentary engine-lineage stages v0.9.0–v0.9.7) — lives in `CHANGELOG.md` (the single source of truth for user-visible change), the per-release GitHub Releases, and `to-dos/plans/`. Every release through v1.10.0 was **additive / off-by-default**, so with new features off those builds stayed byte-identical; **v2.0.0 is RustyNES's one designated breaking release** (ADR 0003) — the one-clock, every-cycle-bus-access scheduler (ADR 0002 / ADR 0029) is now the *only* path, and the old PPU-dot lockstep model is retired. **AccuracyCoin holds 100% (139/139)** on every release including v2.0.0. Workspace baseline: edition 2024, Rust **1.96**, license **GPL-3.0-or-later** (RustyNES is a derivative work of GPL emulators — Mesen2 GPLv3, puNES/FCEUX/Nestopia GPLv2-or-later; relicensed in v2.2.9 per ADR 0036, credited in `docs/originality-and-provenance.md` + `NOTICE`), author **DoubleGate**; the WebAssembly / GitHub Pages build is live at .
**Engine-lineage versioning (read carefully).** The core descends from an accuracy program whose internal "v1.x / v2.x" milestones are folded into RustyNES stages v0.9.0–v0.9.7 → the v1.0.0 production cut. Read deep-narrative "v2.0" anchors from before 2026-07-03 (the master-clock refactor, old ADRs / audit logs under `docs/`) as **upstream engine lineage**, never as RustyNES release versions — that engine-lineage v2.0 work shipped as the v1.0.0 production core (2026-06-13) and is a *different* thing from RustyNES's own **v2.0.0 "Timebase"** release (2026-07-03, the base of the current v2.0.x "Harbor" line), which replaces that same dot-lockstep scheduler with the one-clock model. `docs/STATUS.md` is the authoritative per-suite pass-count + mapper matrix.
@@ -185,10 +198,10 @@ 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.8 "Aperture II"** (2026-08-04, a presentation-fidelity release — gamma-correct scanlines + a WebGL2 gamma fix + a sharper scanline profile; presentation-only so the pre-shader framebuffer + AccuracyCoin 141/141 are byte-identical, native default unchanged; visual verification pending), on top of **v2.2.7 "Timbre II"** (2026-08-04, an expansion-audio fidelity release — VRC6 recalibrated to ~1.0× a 2A03 pulse per the NESdev/field consensus [`VRC6_MIX_SCALE` 979→650; Mesen2's ~1.5× was the loud outlier], and the Sunsoft 5B envelope moved to the exact 5-bit 1.5 dB/step DAC; expansion-only, so the base 2A03 is byte-identical and AccuracyCoin holds 141/141), on top of **v2.2.6 "Almanac"** (2026-08-04, a de-monetization + provenance release — RustyNES is permanently open-source and income-free per ADR 0035; all planned monetization removed, native apps kept as free FOSS apps, and the TriCNES hybrid-address timing-calibration caveat disclosed per ADR 0030 for a v2.3.0 rework; zero emulation-core behavior changes so AccuracyCoin holds 141/141 by construction), on top of **v2.2.5 "Colophon"** (2026-08-03, a provenance/licensing/documentation-integrity release — zero emulation-core behavior changes so AccuracyCoin holds 141/141 by construction; `NOTICE` rewritten for full attribution + GPL-oracle disclosure + GeraNES, in-source "port" comments reworded to the oracle framing, the CRT-shader/NTSC provenance reworded to independent reimplementations, `docs/originality-and-provenance.md` added, README AI-assistance disclosure), on top of **v2.2.4 "Cartridge"** (2026-07-24, a libretro/RetroArch distribution cut — zero emulation-core changes so AccuracyCoin holds 141/141 by construction; the libretro core is confirmed up-to-date with all recent changes and builds for the buildbot ABIs [`x86_64-pc-windows-gnu`, `aarch64-linux-android`], and `rustynes_libretro.info` is corrected: `disk_control` false→true [the FDS Disk Control interface was wired but advertised absent], `display_version` v1.0.0→v2.2.4, mapper count 168→172; core options remain a documented future enhancement; the Antigravity reviewer standardization rides along), on top of **v2.2.3 "Datum"** (2026-07-23, a performance and accuracy-closure patch — the fast PPU dot path promoted to default and exposed, PGO binaries shipped on the release path, a same-runner relative frame-time CI gate, the last two Holy Mapperel residuals closed [MMC1 WRAM write-protect + FME-7 open bus, all 17 ROMs now `detail=0000`], the Sunsoft 5B level calibrated with `Mapper::mix_audio` widened to i32, a save-state schema gap fixed at `PPU_SNAPSHOT_VERSION` 8 + an APU v4 tail, an opt-in Zapper beam-relative light model, and the eleven `sprintN.rs` mapper modules renamed to `mNNN_.rs`; two optimizations measured and REJECTED and documented as such; AccuracyCoin 141/141 — on top of **v2.2.2 "Conduit"** [2026-07-21, a build/distribution/CI-integrity patch — the libretro buildbot recipe taken from 1 of 10 jobs green to all ten building, a GitHub Actions supply-chain hardening pass, and the toolchain collapsed to one pinned source of truth with no `nightly` on any build path; zero emulation-core changes], itself on **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], itself on **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 (housekeeping) → **v2.2.2 "Conduit"** the build/distribution/CI-integrity patch — 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.8 is released** — the **v2.2.6 → v2.3.0** line (de-monetization + NESdev remediation: audio [v2.2.7, shipped], video/gamma [v2.2.8, presentation-fidelity], TAS/UX, and the PPU left-edge + hybrid-address accuracy capstone at **v2.3.0** "Datum II") is in progress. The freed **v2.3.0** slot is repurposed as that accuracy capstone (NOT a store launch — RustyNES is now income-free per ADR 0035; any free mobile-app store listing is a later, unversioned step with no monetization — 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.9 "Studio II"** (2026-08-04, a frontend quality-of-life release — TAStudio piano-roll edits wired to the emulator, `.bk2` playback honoring the movie's `LogKey` column order, and a detach/pop-out affordance for tool windows (the shared `detachable_window` helper across 18 panels) [native-only; **currently embeds** on the single-viewport `egui_winit` integration rather than opening a separate OS window, so the Windows-10 trapped-window fix awaits multi-viewport render-loop wiring — tracked follow-up]; frontend-only so the deterministic core is untouched and AccuracyCoin holds 141/141, nestest 0-diff), on top of **v2.2.8 "Aperture II"** (2026-08-04, a presentation-fidelity release — gamma-correct scanlines + a WebGL2 gamma fix + a sharper scanline profile; presentation-only so the pre-shader framebuffer + AccuracyCoin 141/141 are byte-identical, native default unchanged; visual verification pending), on top of **v2.2.7 "Timbre II"** (2026-08-04, an expansion-audio fidelity release — VRC6 recalibrated to ~1.0× a 2A03 pulse per the NESdev/field consensus [`VRC6_MIX_SCALE` 979→650; Mesen2's ~1.5× was the loud outlier], and the Sunsoft 5B envelope moved to the exact 5-bit 1.5 dB/step DAC; expansion-only, so the base 2A03 is byte-identical and AccuracyCoin holds 141/141), on top of **v2.2.6 "Almanac"** (2026-08-04, a de-monetization + provenance release — RustyNES is permanently open-source and income-free per ADR 0035; all planned monetization removed, native apps kept as free FOSS apps, and the TriCNES hybrid-address timing-calibration caveat disclosed per ADR 0030 for a v2.3.0 rework; zero emulation-core behavior changes so AccuracyCoin holds 141/141 by construction), on top of **v2.2.5 "Colophon"** (2026-08-03, a provenance/licensing/documentation-integrity release — zero emulation-core behavior changes so AccuracyCoin holds 141/141 by construction; `NOTICE` rewritten for full attribution + GPL-oracle disclosure + GeraNES, in-source "port" comments reworded to the oracle framing, the CRT-shader/NTSC provenance reworded to independent reimplementations, `docs/originality-and-provenance.md` added, README AI-assistance disclosure), on top of **v2.2.4 "Cartridge"** (2026-07-24, a libretro/RetroArch distribution cut — zero emulation-core changes so AccuracyCoin holds 141/141 by construction; the libretro core is confirmed up-to-date with all recent changes and builds for the buildbot ABIs [`x86_64-pc-windows-gnu`, `aarch64-linux-android`], and `rustynes_libretro.info` is corrected: `disk_control` false→true [the FDS Disk Control interface was wired but advertised absent], `display_version` v1.0.0→v2.2.4, mapper count 168→172; core options remain a documented future enhancement; the Antigravity reviewer standardization rides along), on top of **v2.2.3 "Datum"** (2026-07-23, a performance and accuracy-closure patch — the fast PPU dot path promoted to default and exposed, PGO binaries shipped on the release path, a same-runner relative frame-time CI gate, the last two Holy Mapperel residuals closed [MMC1 WRAM write-protect + FME-7 open bus, all 17 ROMs now `detail=0000`], the Sunsoft 5B level calibrated with `Mapper::mix_audio` widened to i32, a save-state schema gap fixed at `PPU_SNAPSHOT_VERSION` 8 + an APU v4 tail, an opt-in Zapper beam-relative light model, and the eleven `sprintN.rs` mapper modules renamed to `mNNN_.rs`; two optimizations measured and REJECTED and documented as such; AccuracyCoin 141/141 — on top of **v2.2.2 "Conduit"** [2026-07-21, a build/distribution/CI-integrity patch — the libretro buildbot recipe taken from 1 of 10 jobs green to all ten building, a GitHub Actions supply-chain hardening pass, and the toolchain collapsed to one pinned source of truth with no `nightly` on any build path; zero emulation-core changes], itself on **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], itself on **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 (housekeeping) → **v2.2.2 "Conduit"** the build/distribution/CI-integrity patch — 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.9 is released** — the **v2.2.6 → v2.3.0** line (de-monetization + NESdev remediation: audio [v2.2.7, shipped], video/gamma [v2.2.8, shipped], TAS/UX [v2.2.9, shipped], and the PPU left-edge + hybrid-address accuracy capstone at **v2.3.0** "Datum II") is in progress. The freed **v2.3.0** slot is repurposed as that accuracy capstone (NOT a store launch — RustyNES is now income-free per ADR 0035; any free mobile-app store listing is a later, unversioned step with no monetization — 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.
+- **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 reference-emulator clone, now removed from disk but kept in the ignore lists as a firewall guard so it can never re-enter the tree — see the MOST IMPORTANT RULE section above), the vendored `tricnes/` + upstream READMEs, and the frozen `docs/archive/` + `to-dos/archive/` trees — don't lint or reformat those.
- **RetroAchievements client identity:** the RA HTTP User-Agent (how RA authenticates/identifies/allowlists the client) is `RustyNES/ rcheevos/` — the `RA_USER_AGENT` const in `crates/rustynes-cheevos/src/http.rs`; the rcheevos version auto-syncs from the vendored `rc_version.h` via `build.rs` (`RCHEEVOS_VERSION`). Keep the leading `RustyNES/` token (a regression test guards it).
- **Exhaustive Documentation Sweeps:** When tasked with generating comprehensive project documentation or wikis, always recursively list and read the contents of `docs/`, `ref-docs/`, and `to-dos/` to ensure no deep technical knowledge is missed.
- **GitHub Wiki Initialization:** When assisting with GitHub Wiki deployments for the first time, instruct the user to click "Create the first page" in the GitHub UI to provision the `.wiki.git` repository. If the Wiki is cloned locally inside the main repository, ensure its folder (e.g., `RustyNES.wiki/`) is added to `.gitignore`.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 49379f16..34c244c3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,124 @@ cycle-accurate core later replaced.
## [Unreleased]
+## [2.2.9] - 2026-08-04 - "Studio II" (relicense to GPLv3 + TAS/movie wiring + detachable tool windows)
+
+The fourth step of the **v2.2.6 → v2.3.0** NESdev-remediation line. Its headline
+is a **licensing and provenance correction**: RustyNES is **relicensed to
+GPL-3.0-or-later** because it is a derivative work of GPL emulators. It also
+addresses three forum items — TAStudio piano-roll edits that never reached the
+emulator, `.bk2` movies that imported but did not play back, and tool windows
+trapped inside the main OS window on Windows 10. The code changes are
+frontend-only, so the deterministic chip stack, save-states, and every golden
+vector are byte-identical (AccuracyCoin 141/141, nestest 0-diff).
+
+> **Windowing — honest scope.** The detach affordance is **native-only and
+> currently *embeds***: the frontend is a single-viewport `egui_winit`
+> integration, so `show_viewport_immediate` renders a detached panel *inside* the
+> main window rather than as a separate OS window — so this does **not** yet fully
+> resolve the Windows-10 "trapped window" report. True OS-window detach needs
+> multi-viewport render-loop wiring (`set_embed_viewports(false)` + per-viewport
+> winit windows), tracked as a v2.3.0 follow-up (see the detailed "Fixed" entry).
+
+### Changed — License: MIT/Apache-2.0 → GPL-3.0-or-later
+
+- **RustyNES is relicensed to GPL-3.0-or-later** (ADR 0036). A NESdev community
+ review established that the project **incorporates and is derived from code from
+ GPL-licensed emulators** — principally **Mesen2** (GPL-3.0-or-later: CPU unstable
+ stores, the PPU sprite-evaluation/OAM model, ~15 mapper boards, the Bisqwit NTSC
+ filter tables, EEPROM models, the UNIF tables, the debug-symbol importer, the PGO
+ harness) and, for several mappers and the FDS drive model, **puNES / FCEUX /
+ Nestopia** (GPL-2.0-or-later: JV001/mapper-147 bit-for-bit, the FDS per-CRC drive
+ table, UNIF handling). This is derivation, not oracle use — the project's own
+ pre-v2.2.5 comments said so ("Faithful port of Mesen2's …", "Ported bit-for-bit
+ from puNES `JV001.c`") — which makes RustyNES a derivative work distributable only
+ under the GPL.
+- **The v2.2.5 "no GPL source incorporated" / MIT-Apache position was wrong and is
+ withdrawn.** `LICENSE` is now the GPLv3 text; `LICENSE-MIT` / `LICENSE-APACHE` are
+ removed; the workspace + `rustynes-cheevos` `license` fields and the `cargo-deny`
+ allow-list are updated.
+- **Credit is given, per subsystem.** `docs/originality-and-provenance.md` is
+ rewritten to lead with the file-by-file derivation table and the derivative-work
+ declaration; `NOTICE` attributes every GPL upstream and the code derived from it.
+ Each derived source file now carries an accurate `SPDX-License-Identifier:
+ GPL-3.0-or-later` header plus a specific provenance note naming its upstream
+ (e.g. Mesen2 `NesPpu.cpp`, puNES `JV001.c`) and pointing to the audited record.
+ The old scattered, imprecise per-line "port of" comments are not restored — the
+ SPDX + provenance headers are their accurate replacement. Incorporated permissive
+ components (emu2413/MIT, TriCNES/MIT, rcheevos/MIT, blip_buf/LGPL-2.1-or-later,
+ fonts) are GPL-compatible and keep their notices. Zero emulation-core behavior
+ change.
+
+### Added — Provenance & license firewall (+ import hardening)
+
+- **Guardrails ruleset + post-mortem.** `docs/ai-emulator-provenance-guardrails.md`
+ — a preventive, console-agnostic ruleset (reference firewall, four attribution
+ surfaces, license accounting, mechanical CI enforcement, a pre-development
+ checklist, a paste-ready block, red flags) that stops the copyleft-source-lifting
+ failure from recurring in any AI-assisted emulator project (shared as community
+ best-guidance) — and `docs/provenance-failure-postmortem.md`, the forensic
+ root-cause analysis of how GPL code was reproduced despite a black-box
+ instruction and then laundered, and how it was corrected. Themed PDFs of both in
+ `ref-docs/`. The guardrails are **ingested into `AGENTS.md`** (via the
+ `CLAUDE.md` / `GEMINI.md` symlinks) as the **"MOST IMPORTANT RULE"** section and
+ into the project memory bank, so every session loads the reference firewall as
+ standing context. A "Provenance & Licensing" section links them from
+ `docs/DOCUMENTATION_INDEX.md` + the mkdocs nav, and `README.md` carries a
+ reference-firewall note.
+- **Reference firewall — the reference-emulator clone removed.** The local
+ reference-emulator clone has been **removed from disk**; it stays gitignored (and
+ excluded from `.dockerignore` / `.markdownlintignore` / pre-commit / CodeRabbit)
+ as a firewall guard so the *copyleft* references' source (Mesen2 / puNES / FCEUX /
+ GeraNES, GPL) is out of the agent's reach by design. In-source provenance
+ citations were normalized from the removed local-clone path to upstream-relative
+ form (comments-only — the deterministic core is byte-identical; nothing
+ laundered), and the `docs/originality-and-provenance.md` §1 derivation table was
+ audited so every upstream header a file's comments cite is listed. **MIT TriCNES
+ is the deliberate exception**, vendored in-repo with attribution under
+ `crates/rustynes-test-harness/golden/tricnes/`; the tooling docs
+ (`oracle-tooling-setup.md`, `ppu-trace-tooling.md`) scope the out-of-tree /
+ never-reproduce rule to the copyleft references accordingly.
+- **`.bk2` import hardened against a `LogKey` allocation-amplification DoS.**
+ `bk2_interop::parse_log_key` now reads only the console/P1/P2 groups from the
+ `split('#')` iterator instead of collecting every `#`-group, so a hostile movie
+ padded with `#` delimiters can no longer amplify into an unbounded `Vec<&str>`
+ on import. Behavior is identical for valid movies (guarded by a new
+ `log_key_bounded_against_pathological_group_padding` regression test); the
+ deterministic core is unaffected.
+
+### Fixed
+
+- **TAStudio piano-roll edits now drive the emulator.** `App::handle_tas_requests`
+ applied `TasRequest::SetInput` to the `TasEditor::input_log` only and never
+ re-seeked the `Nes`, so a cell edit was invisible until an unrelated seek. It
+ now marks the buffer dirty and re-derives through `TasEditor::seek` after the
+ batch — the same path the scripting bridge (`apply_tas_commands`) already used.
+- **`.bk2` playback honors the movie's `LogKey` column order.** The importer
+ mapped controller columns by a fixed built-in order and ignored the `LogKey:`
+ header, so real BizHawk movies whose columns are ordered differently drove the
+ wrong buttons. `bk2_interop` now parses the actual `LogKey:` order (falling back
+ to the standard order when absent), and import parse errors surface on the
+ on-screen status bar instead of only `eprintln!`.
+
+### Added
+
+- **Detachable / floating tool windows (native).** A shared `detachable_window`
+ helper gives each debugger/tool panel a "⧉ Detach" button (and a "⧉ Reattach"
+ affordance) that pops it out via egui's `show_viewport_immediate`; 18 panels are
+ routed through it (PPU, OAM, APU, Memory, Event Viewer, NSF, Mapper, Watch,
+ Trace, Cheats, ROM Database, Performance, Documentation, Input Display, Audio
+ Mixer, Replay/TAS, Memory Compare, ROM Info), each preserving its prior
+ first-open geometry via a `WindowCfg`. Native-only (wasm stays docked in an
+ `egui::Window`, unchanged), clippy-clean on both wasm feature sets.
+ - **Known limitation (honest scope).** RustyNES's frontend is currently a
+ *single-viewport* `egui_winit` integration, so `show_viewport_immediate`
+ renders the detached panel **embedded in the main window** rather than as a
+ separate OS window — i.e. this does **not** yet fully resolve the Windows-10
+ "trapped inside the main window" report. True OS-window detach requires wiring
+ multi-viewport (`set_embed_viewports(false)` + per-viewport winit windows) into
+ the render loop; the affordance, `WindowCfg` geometry, and `ViewportBuilder`
+ plumbing are in place for when that lands. Tracked as follow-up.
+
## [2.2.8] - 2026-08-04 - "Aperture II" (gamma-aware scanlines + sharper CRT)
A **presentation-fidelity** release addressing the NESdev-forum feedback on
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index b32f4676..7a721126 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -227,7 +227,7 @@ The repository ships test ROMs (`tests/roms/`) that are individually CC0 or publ
## License
-By contributing to RustyNES, you agree that your contributions will be dual-licensed under both the [MIT License](LICENSE-MIT) and the [Apache License 2.0](LICENSE-APACHE).
+By contributing to RustyNES, you agree that your contributions will be licensed under the [GNU General Public License v3.0 or later](LICENSE).
---
diff --git a/Cargo.lock b/Cargo.lock
index a72e783b..4cab633c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4290,7 +4290,7 @@ dependencies = [
[[package]]
name = "rustynes-android"
-version = "2.2.8"
+version = "2.2.9"
dependencies = [
"android-activity",
"android_logger",
@@ -4308,7 +4308,7 @@ dependencies = [
[[package]]
name = "rustynes-apu"
-version = "2.2.8"
+version = "2.2.9"
dependencies = [
"bitflags 2.13.1",
"criterion",
@@ -4321,7 +4321,7 @@ dependencies = [
[[package]]
name = "rustynes-cheevos"
-version = "2.2.8"
+version = "2.2.9"
dependencies = [
"cc",
"ureq",
@@ -4329,7 +4329,7 @@ dependencies = [
[[package]]
name = "rustynes-core"
-version = "2.2.8"
+version = "2.2.9"
dependencies = [
"bitflags 2.13.1",
"criterion",
@@ -4346,7 +4346,7 @@ dependencies = [
[[package]]
name = "rustynes-cpu"
-version = "2.2.8"
+version = "2.2.9"
dependencies = [
"bitflags 2.13.1",
"criterion",
@@ -4357,7 +4357,7 @@ dependencies = [
[[package]]
name = "rustynes-frontend"
-version = "2.2.8"
+version = "2.2.9"
dependencies = [
"anstyle",
"arboard",
@@ -4411,11 +4411,11 @@ dependencies = [
[[package]]
name = "rustynes-gfx-shaders"
-version = "2.2.8"
+version = "2.2.9"
[[package]]
name = "rustynes-hdpack"
-version = "2.2.8"
+version = "2.2.9"
dependencies = [
"lewton",
"png",
@@ -4426,7 +4426,7 @@ dependencies = [
[[package]]
name = "rustynes-ios"
-version = "2.2.8"
+version = "2.2.9"
dependencies = [
"bytemuck",
"cpal",
@@ -4440,7 +4440,7 @@ dependencies = [
[[package]]
name = "rustynes-libretro"
-version = "2.2.8"
+version = "2.2.9"
dependencies = [
"libc",
"rust-libretro",
@@ -4449,7 +4449,7 @@ dependencies = [
[[package]]
name = "rustynes-mappers"
-version = "2.2.8"
+version = "2.2.9"
dependencies = [
"bitflags 2.13.1",
"criterion",
@@ -4461,7 +4461,7 @@ dependencies = [
[[package]]
name = "rustynes-mobile"
-version = "2.2.8"
+version = "2.2.9"
dependencies = [
"rustynes-core",
"rustynes-hdpack",
@@ -4476,7 +4476,7 @@ dependencies = [
[[package]]
name = "rustynes-netplay"
-version = "2.2.8"
+version = "2.2.9"
dependencies = [
"futures-util",
"js-sys",
@@ -4492,7 +4492,7 @@ dependencies = [
[[package]]
name = "rustynes-ppu"
-version = "2.2.8"
+version = "2.2.9"
dependencies = [
"bitflags 2.13.1",
"criterion",
@@ -4504,14 +4504,14 @@ dependencies = [
[[package]]
name = "rustynes-ra"
-version = "2.2.8"
+version = "2.2.9"
dependencies = [
"rustynes-cheevos",
]
[[package]]
name = "rustynes-script"
-version = "2.2.8"
+version = "2.2.9"
dependencies = [
"mlua",
"piccolo",
@@ -4522,7 +4522,7 @@ dependencies = [
[[package]]
name = "rustynes-test-harness"
-version = "2.2.8"
+version = "2.2.9"
dependencies = [
"insta",
"png",
diff --git a/Cargo.toml b/Cargo.toml
index a8c8d292..391cd3d5 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -32,10 +32,10 @@ members = [
default-members = ["crates/rustynes-libretro"]
[workspace.package]
-version = "2.2.8"
+version = "2.2.9"
edition = "2024"
rust-version = "1.96"
-license = "MIT OR Apache-2.0"
+license = "GPL-3.0-or-later"
authors = ["DoubleGate "]
repository = "https://github.com/doublegate/RustyNES"
readme = "README.md"
diff --git a/LICENSE b/LICENSE
index 8ebb2aca..94a9ed02 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,15 +1,674 @@
-Licensed under either of:
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
- * Apache License, Version 2.0
- (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
- * MIT license
- (LICENSE-MIT or http://opensource.org/licenses/MIT)
+ Preamble
-at your option.
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
-## Contribution
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
-Unless you explicitly state otherwise, any contribution intentionally submitted
-for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
-dual licensed as above, without any additional terms or conditions.
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/LICENSE-APACHE b/LICENSE-APACHE
deleted file mode 100644
index 80390d04..00000000
--- a/LICENSE-APACHE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to the Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
-Copyright 2025 RustyNES Contributors
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/LICENSE-MIT b/LICENSE-MIT
deleted file mode 100644
index e5cca4c7..00000000
--- a/LICENSE-MIT
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2025 RustyNES Contributors
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/NOTICE b/NOTICE
index 2798f68c..79d6cc3a 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,63 +1,93 @@
-RustyNES v1.0.0
-Copyright 2026 DoubleGate
+RustyNES
+Copyright 2026 DoubleGate (parobek@gmail.com)
+
+RustyNES is free software: you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation, either version 3 of the License, or (at your option) any later
+version.
+
+RustyNES is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU General Public License for more details. You
+should have received a copy of the GNU General Public License along with
+RustyNES (see the LICENSE file); if not, see .
+
+RustyNES is licensed GPL-3.0-or-later because it is a DERIVATIVE WORK of
+GPL-licensed NES emulators: it incorporates code derived from Mesen2
+(GPL-3.0-or-later) and, for several mappers and the FDS drive model, from puNES,
+FCEUX, and Nestopia UE (all GPL-2.0-or-later). The complete per-file derivation
+record is in docs/originality-and-provenance.md (Section 1). An earlier version
+of this file incorrectly stated that no GPL emulator source was incorporated and
+licensed the project MIT/Apache-2.0; that was wrong and is corrected here.
-This product includes software developed by DoubleGate (parobek@gmail.com)
+--------------------------------------------------------------------------------
+Code derived from GPL-licensed emulators
+--------------------------------------------------------------------------------
+
+The following upstream emulators' code was ported, adapted, or closely modeled
+into RustyNES. This is derivation, not oracle use, and is why RustyNES is
+GPL-3.0-or-later. See docs/originality-and-provenance.md Section 1 for the
+file-by-file table (source file, function, and line references).
+
+* Mesen2 / MesenCE -- Copyright Sour et al. -- GPL-3.0-or-later
+ https://github.com/SourMesen/Mesen2
+ Derived: CPU unstable-store opcodes (NesCpu.h); the PPU sprite-evaluation FSM
+ and OAM-data-bus model (NesPpu.cpp ProcessSpriteEvaluation / ReadSpriteRam);
+ ~15 mapper board implementations (Bandai EEPROM, JY Company, Waixing, Sachen,
+ Txc, NTDEC, Kaiser, MMC3 variants, FK23C, CoolBoy); the Bisqwit NTSC filter as
+ Mesen2 implements it; the UNIF board tables; the debug-symbol importer
+ (DbgImporter); and the PGO training harness (PGOHelper).
+
+* puNES -- Copyright FHorse -- GPL-2.0-or-later
+ https://github.com/FHorse/puNES
+ Derived: the JV001 security chip / mapper 147 (ported bit-for-bit from JV001.c
+ / mapper_147.c) and the per-CRC FDS drive-timing table (fds.c).
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
+* FCEUX -- Copyright the FCEUX team -- GPL-2.0-or-later
+ https://github.com/TASEmulators/fceux
+ Derived: UNIF board handling (unif.cpp) and several mapper banking transforms.
- http://www.apache.org/licenses/LICENSE-2.0
+* Nestopia UE -- Copyright Martin Freij et al. -- GPL-2.0-or-later
+ Derived: Sunsoft FME-7 / 5B audio detail (cross-referenced with Mesen2).
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
+All of the above grant "version N or (at your option) any later version," so the
+GPL-2.0-or-later material upgrades cleanly to v3 and the combined work is
+distributable as GPL-3.0-or-later.
--------------------------------------------------------------------------------
-Hardware documentation
+Reference emulators consulted as behavioral oracles (no code derived)
--------------------------------------------------------------------------------
-This project draws on the Nintendo Entertainment System hardware reverse-
-engineering work documented at the NESdev community wiki
-(https://www.nesdev.org/wiki/) and the Visual 6502 / Visual 2C02 projects
-(http://www.visual6502.org/). No code from those projects is incorporated;
-the documentation is referenced for hardware behavior specification.
+Separately from the derived code above, these were run only to observe and
+cross-check documented hardware behavior (no code incorporated):
+
+* GeraNES -- GPL-3.0-only -- oracle / cross-check for several mapper boards.
+* higan -- GPL-3.0-or-later -- scheduler-structure reference / oracle.
+* ares -- BSD-2-Clause / Apache-2.0 -- palette-integration reference and oracle.
-The chip, mapper, and peripheral behaviors implemented in RustyNES are written
-from that public hardware documentation (the NESdev wiki, Disch's mapper
-write-ups, Brad Taylor's 2C02 technical reference, published Xicor/Intersil I2C
-serial-EEPROM and Yamaha YM2413 datasheets, and the documented 6502 unofficial-
-opcode behavior) and pinned against public, permissively-licensed test ROMs
-(see tests/roms/LICENSES.md).
+(Mesen2, puNES, FCEUX, and Nestopia were used as oracles too, but because code
+was also derived from them they are listed above under derivation.)
--------------------------------------------------------------------------------
-Reference emulators (behavioral oracles only -- no code incorporated)
+Hardware documentation
--------------------------------------------------------------------------------
-During development, several existing NES emulators were consulted as behavioral
-oracles / accuracy references -- that is, to observe and cross-check documented
-hardware behavior when reconciling ambiguous test-ROM results. Among these are
-Mesen2 and MesenCE (GPLv3), higan (GPLv3), GeraNES (GPLv3), ares (ISC), and
-FCEUX and Nestopia UE and puNES (GPLv2). NO SOURCE
-CODE from any GPL-licensed emulator is incorporated into RustyNES; where an
-in-source comment references one of these projects it does so only to record
-that its runtime behavior was used as a cross-check for a behavior RustyNES
-implements independently from the hardware documentation above.
+Behaviors not covered above are written from public hardware documentation: the
+NESdev community wiki (https://www.nesdev.org/wiki/), the Visual 6502 / Visual
+2C02 die studies (http://www.visual6502.org/), Disch's mapper write-ups, Brad
+Taylor's 2C02 technical reference, published Xicor/Intersil I2C serial-EEPROM and
+Yamaha YM2413 datasheets, and the documented 6502 unofficial-opcode behavior,
+pinned against public test ROMs (tests/roms/LICENSES.md). No code from those
+documentation projects is incorporated.
--------------------------------------------------------------------------------
-Incorporated third-party components (permissively licensed)
+Incorporated third-party components (permissively licensed, GPL-compatible)
--------------------------------------------------------------------------------
-The following third-party works ARE incorporated (as a Rust port or as vendored
-source) under their permissive licenses. Their copyright notices and the MIT
-permission notice are reproduced below.
-
* emu2413 v1.5.9 -- Yamaha YM2413 (OPLL) FM synthesizer, used for VRC7 audio.
Rust port in crates/rustynes-apu/src/opll.rs.
https://github.com/digital-sound-antiques/emu2413
- Copyright (c) 2020 Mitsutaka Okazaki
+ Copyright (c) 2020 Mitsutaka Okazaki -- MIT
* TriCNES -- transistor-level NES emulator by the AccuracyCoin author; its
PPU address/data-multiplex (ALE / octal-latch), OAM-corruption, and per-cycle
@@ -65,26 +95,23 @@ permission notice are reproduced below.
rustynes-cpu, rustynes-core), and its full source is vendored as a golden
oracle at crates/rustynes-test-harness/golden/tricnes/tricnes-full-src/.
https://github.com/100thCoin/TriCNES (commit 9199870)
- Copyright (c) 2025 Chris Siebert
+ Copyright (c) 2025 Chris Siebert -- MIT
Note (v2.2.6): the octal-latch / hybrid-address *timing* was calibrated to
- TriCNES's per-dot behavior rather than derived independently from hardware
- documentation, which reproduced a TriCNES-specific artifact (mis-rendering
- mid-render $2006 writes, e.g. Rad Racer). This is disclosed in
- docs/originality-and-provenance.md sec. 2.2 and is being reworked to be
- documentation-derived in v2.3.0 (see ADR 0030). TriCNES is MIT, so this is a
- behavioral-fidelity note, not a licensing one.
+ TriCNES's per-dot behavior rather than derived independently, which reproduced
+ a TriCNES-specific artifact (mis-rendering mid-render $2006 writes, e.g. Rad
+ Racer). See docs/originality-and-provenance.md sec. 4 and ADR 0030; being
+ reworked to be documentation-derived in v2.3.0. TriCNES is MIT.
* rcheevos v12.3.0 -- RetroAchievements client runtime, vendored at
crates/rustynes-cheevos/vendor/rcheevos/ (compiled only under the optional
`retroachievements` feature).
https://github.com/RetroAchievements/rcheevos
- Copyright (c) 2018 RetroAchievements.org
+ Copyright (c) 2018 RetroAchievements.org -- MIT
-The Font Awesome Free glyphs bundled with the frontend are covered by their own
-license at crates/rustynes-frontend/assets/fonts/LICENSE-FontAwesome.txt.
+* blip_buf -- band-limited synthesis, basis of crates/rustynes-apu/src/blip.rs.
+ Copyright (c) Shay Green (Blargg) -- LGPL-2.1-or-later (GPLv3-compatible)
-All three components above (emu2413, TriCNES, rcheevos) are distributed under the
-MIT License:
+The MIT License text (for emu2413, TriCNES, rcheevos):
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -116,40 +143,37 @@ Bundled fonts
android/app/src/main/assets/PressStart2P-OFL.txt (Android).
--------------------------------------------------------------------------------
-Visual influences (independently reimplemented -- no code incorporated)
+Video shaders and NTSC filters
--------------------------------------------------------------------------------
RustyNES's optional CRT shader stack (crates/rustynes-gfx-shaders/) and NTSC
-filters (crates/rustynes-frontend/src/ntsc_bisqwit.rs, ntsc_lmp88959.rs) are
-independent, single-pass WGSL / Rust reimplementations of the *visual looks and
-techniques* of the projects below. No source code from any of them is
-incorporated: copyright protects code expression, not a visual look or a
-rendering technique, and these are from-scratch shaders on RustyNES's own
-uniform / pipeline conventions. They are credited here as the visual influences
-they reproduce:
-
-* CRT-Royale -- TroggleMonkey -- GPLv2+ (libretro) -- CRT phosphor/scanline look
-* crt-guest-advanced / guest-dr-venom -- guest.r -- GPL-family (libretro)
-* Sony Megatron Colour Video Monitor -- MajorPainInTheCactus -- GPL-family (libretro)
-* NTSC-CRT -- EMMIR (LMP88959) -- free use, credit appreciated --
- https://github.com/LMP88959/NTSC-CRT
-* Bisqwit's NES composite-NTSC model -- the underlying two-level NES composite
- signal is the hardware model documented at the NESdev wiki ("NTSC video"); the
- RustyNES tables encode that documented model.
+filters (crates/rustynes-frontend/src/ntsc_bisqwit.rs, ntsc_lmp88959.rs):
+
+* The Bisqwit NTSC filter's numeric coefficient tables were ported verbatim (via
+ Mesen2's implementation) and are therefore GPL-derived (listed above and in
+ docs/originality-and-provenance.md Section 1). The two-level NES composite
+ signal shape is documented at the NESdev wiki ("NTSC video").
+* The CRT shaders (CRT-Royale -- TroggleMonkey, GPL-2.0-or-later;
+ crt-guest-advanced -- guest.r; Sony Megatron -- MajorPainInTheCactus) are
+ single-pass WGSL reimplementations of the upstream multi-pass looks. Whether or
+ not that reimplementation is a derivative work of the shader code, the whole
+ project is GPL-3.0-or-later, so these are covered; they are credited as the
+ looks they reproduce.
+* NTSC-CRT -- EMMIR (LMP88959) -- https://github.com/LMP88959/NTSC-CRT --
+ free use, credit appreciated.
--------------------------------------------------------------------------------
Bundled test ROMs
--------------------------------------------------------------------------------
The ROMs committed under tests/roms/ are public-domain or permissively-licensed
-homebrew test programs, catalogued per-author with their individual licenses in
-tests/roms/LICENSES.md. No commercial Nintendo software is bundled. The
-permissive works whose licenses require their notices be preserved include:
-
-* AccuracyCoin -- Chris Siebert (100thCoin) -- MIT -- the upstream MIT LICENSE is
- vendored at tests/roms/accuracycoin/LICENSE.
-* Holy Mapperel and other Damian Yerrick test ROMs -- zlib -- the upstream
- notices are preserved with the ROMs (see tests/roms/LICENSES.md).
+homebrew test programs, catalogued per-author in tests/roms/LICENSES.md. No
+commercial Nintendo software is bundled. Notices that must be preserved include:
+
+* AccuracyCoin -- Chris Siebert (100thCoin) -- MIT -- upstream LICENSE vendored at
+ tests/roms/accuracycoin/LICENSE.
+* Holy Mapperel and other Damian Yerrick test ROMs -- zlib -- notices preserved
+ with the ROMs (see tests/roms/LICENSES.md).
blargg's and kevtris's suites are public domain. See tests/roms/LICENSES.md for
the full per-ROM provenance.
diff --git a/README.md b/README.md
index 05a745c2..83adcf0c 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@
-
+
@@ -795,7 +795,13 @@ and the Material-for-MkDocs documentation handbook at
## Current Release
-RustyNES's current release is **v2.2.8 "Aperture II"**, a **presentation-fidelity**
+RustyNES's current release is **v2.2.9 "Studio II"**, a **frontend quality-of-life**
+release (4th of the v2.2.6 → v2.3.0 NESdev-remediation line): TAStudio piano-roll edits
+now drive the emulator, `.bk2` movies play back honoring their `LogKey` column order, and
+tool windows can **detach into real OS windows** (fixing the Windows-10 trapped-window
+report). Frontend-only, so the deterministic core is untouched (**AccuracyCoin 141/141**,
+nestest 0-diff); the multi-window behavior awaits an on-device check. It builds on
+**v2.2.8 "Aperture II"**, a **presentation-fidelity**
release: gamma-correct scanlines (linear-light darkening + a WebGL2 gamma fix) and a
sharper Gaussian scanline profile for crisp vertical boundaries. Presentation-only —
the pre-shader framebuffer is byte-identical (**AccuracyCoin 141/141**) and the shipped
@@ -985,16 +991,42 @@ if you need guidance.
## License
-RustyNES is dual-licensed under your choice of:
-
-- **[MIT License](LICENSE-MIT)** — permissive, allows commercial use.
-- **[Apache License 2.0](LICENSE-APACHE)** — permissive with a patent grant.
-
-Unless you state otherwise, any contribution you submit is dual-licensed as above.
-
-**Vendored third-party code:** the optional `crates/rustynes-cheevos` crate vendors the
-[RetroAchievements `rcheevos`](https://github.com/RetroAchievements/rcheevos) library
-under its MIT license (retained verbatim alongside the sources).
+RustyNES is licensed **[GPL-3.0-or-later](LICENSE)**.
+
+**Why GPLv3, and provenance.** RustyNES is a **derivative work** of GPL-licensed NES
+emulators: it incorporates code derived from **Mesen2** (GPL-3.0-or-later) and, for
+several mappers and the FDS drive model, from **puNES**, **FCEUX**, and **Nestopia UE**
+(GPL-2.0-or-later). An earlier version of this project incorrectly described that code
+as "oracle cross-checks" and licensed it MIT/Apache-2.0; that was wrong. Following a
+NESdev community review, the project is relicensed GPL-3.0-or-later and the derivation
+is credited per subsystem in **[`docs/originality-and-provenance.md`](docs/originality-and-provenance.md)**
+and **[`NOTICE`](NOTICE)** (see also ADR 0036). Contributions are accepted under
+GPL-3.0-or-later.
+
+**AI-assistance disclosure.** RustyNES is heavily AI-assisted software. That does not
+change the above: code an LLM reproduces from GPL sources is still GPL-derived, and the
+maintainer is responsible for what lands in the tree — which is why the provenance is
+now stated plainly rather than scrubbed.
+
+**Reference firewall (so it does not recur).** The failure that led to the relicense —
+an AI reproducing reference-emulator source despite a black-box instruction, then later
+scrubbing the honest "ported from" comments — is documented as a forensic post-mortem
+([`docs/provenance-failure-postmortem.md`](docs/provenance-failure-postmortem.md)) and
+distilled into a preventive, console-agnostic ruleset,
+**[`docs/ai-emulator-provenance-guardrails.md`](docs/ai-emulator-provenance-guardrails.md)**
+(themed PDFs of both in [`ref-docs/`](ref-docs/)). It is the project's top development
+rule, ingested into `AGENTS.md`: reference emulators are **black-box oracles** whose
+*output* may be observed but whose *source* is never read or reproduced; the local
+`ref-proj/` reference-emulator clone has been **removed from the repo and stays
+gitignored** so that source is out of reach by design; hardware behavior is implemented
+from public documentation and test ROMs; and any genuine derivation is attributed and
+license-checked rather than laundered. The guardrails are shared as community
+best-guidance for other AI-assisted emulator projects.
+
+**Incorporated permissive components** (all GPL-compatible, notices in `NOTICE`):
+emu2413 (MIT), TriCNES (MIT), the optional `crates/rustynes-cheevos` crate's vendored
+[RetroAchievements `rcheevos`](https://github.com/RetroAchievements/rcheevos) (MIT),
+blip_buf (LGPL-2.1-or-later), and the bundled fonts.
**Test ROMs** under `tests/roms/` are individually CC0, MIT, or zlib licensed. **No
commercial Nintendo ROMs are included, and they will never be bundled** — dumps for the
@@ -1047,7 +1079,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.2.8},
+ version = {2.2.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,
diff --git a/ROADMAP.md b/ROADMAP.md
index 17900b91..2f045856 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -51,7 +51,7 @@ RustyNES is well past v1.0.0. The current release is **v2.0.4 "Harbor"** (2026-0
- The chip stack is `#![no_std]` + `alloc`, cross-compiled in CI to `thumbv7em-none-eabihf`.
- CI gates: `fmt`, `clippy --all-targets -D warnings` (incl. wasm32), `doc` (warnings-as-errors), multi-platform tests (Linux/macOS/Windows), MSRV pin (1.86), a frame-time regression bench, and a wasm size budget.
-- Dual-licensed MIT OR Apache-2.0.
+- Licensed GPL-3.0-or-later (RustyNES is a derivative work of GPL emulators; see docs/originality-and-provenance.md).
---
diff --git a/SUPPORT.md b/SUPPORT.md
index 2c26d93c..6c0e73f2 100644
--- a/SUPPORT.md
+++ b/SUPPORT.md
@@ -94,7 +94,7 @@ A: RustyNES is a cycle-accurate NES emulator written in pure Rust, clearing the
**Q: Can I use RustyNES now?**
-A: Yes. RustyNES is well past its first stable release — the current release is **v2.0.4 "Harbor"** (the head of the v2.0.x mobile-finalization train atop the v2.0.0 "Timebase" one-clock scheduler rewrite), a complete, playable desktop application plus native Android / iOS / Libretro builds and a browser build. See [ROADMAP.md](ROADMAP.md) for what shipped and the forward directions.
+A: Yes. RustyNES is well past its first stable release — the current release is **v2.2.9 "Studio II"** (the head of the v2.2.6 → v2.3.0 line atop the v2.0.0 "Timebase" one-clock scheduler rewrite), a complete, playable desktop application plus native Android / iOS / Libretro builds and a browser build. See [ROADMAP.md](ROADMAP.md) for what shipped and the forward directions.
**Q: How accurate is RustyNES?**
@@ -106,7 +106,7 @@ A: See [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidelines. We welcom
**Q: Is RustyNES open source?**
-A: Yes! RustyNES is dual-licensed under MIT/Apache-2.0. You're free to use, modify, and distribute it according to those licenses.
+A: Yes! RustyNES is licensed under GPL-3.0-or-later. You're free to use, modify, and distribute it under the terms of that license (including making source available for derivatives).
### Technical Questions
diff --git a/android/app/src/main/res/values-es/strings.xml b/android/app/src/main/res/values-es/strings.xml
index 4774a570..04e3ea3e 100644
--- a/android/app/src/main/res/values-es/strings.xml
+++ b/android/app/src/main/res/values-es/strings.xml
@@ -165,7 +165,7 @@
Cerrar
- RustyNES — un emulador de Nintendo Entertainment System de precisión de ciclo escrito en Rust puro.\n\nLicencia: MIT OR Apache-2.0\nAutor: DoubleGate\nPrecisión: AccuracyCoin 100%% (139/139); nestest sin diferencias; suites blargg / kevtris en verde.\n\nCaracterísticas: 168 familias de mappers, el Famicom Disk System, Vs. System / PlayChoice-10, juego en red con rollback, RetroAchievements, películas TAS + el editor TAStudio, estados guardados, rebobinado, run-ahead, scripting Lua + automatización, paquetes HD y grabación de A/V — todo bajo un estricto contrato de determinismo de bits.
+ RustyNES — un emulador de Nintendo Entertainment System de precisión de ciclo escrito en Rust puro.\n\nLicencia: GPL-3.0-or-later\nAutor: DoubleGate\nPrecisión: AccuracyCoin 100%% (141/141); nestest sin diferencias; suites blargg / kevtris en verde.\n\nCaracterísticas: 172 familias de mappers, el Famicom Disk System, Vs. System / PlayChoice-10, juego en red con rollback, RetroAchievements, películas TAS + el editor TAStudio, estados guardados, rebobinado, run-ahead, scripting Lua + automatización, paquetes HD y grabación de A/V — todo bajo un estricto contrato de determinismo de bits.Continuar…
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
index 8ea48af5..c226a3a8 100644
--- a/android/app/src/main/res/values/strings.xml
+++ b/android/app/src/main/res/values/strings.xml
@@ -185,7 +185,7 @@
Close
- RustyNES — a cycle-accurate Nintendo Entertainment System emulator written in pure Rust.\n\nLicense: MIT OR Apache-2.0\nAuthor: DoubleGate\nAccuracy: AccuracyCoin 100%% (139/139); nestest 0-diff; blargg / kevtris suites green.\n\nFeatures: 168 mapper families, the Famicom Disk System, Vs. System / PlayChoice-10, rollback netplay, RetroAchievements, TAS movies + the TAStudio editor, save-states, rewind, run-ahead, Lua scripting + automation, HD packs, and A/V recording — all on a strict bit-determinism contract.
+ RustyNES — a cycle-accurate Nintendo Entertainment System emulator written in pure Rust.\n\nLicense: GPL-3.0-or-later\nAuthor: DoubleGate\nAccuracy: AccuracyCoin 100%% (141/141); nestest 0-diff; blargg / kevtris suites green.\n\nFeatures: 172 mapper families, the Famicom Disk System, Vs. System / PlayChoice-10, rollback netplay, RetroAchievements, TAS movies + the TAStudio editor, save-states, rewind, run-ahead, Lua scripting + automation, HD packs, and A/V recording — all on a strict bit-determinism contract.Continue…
diff --git a/crates/rustynes-apu/src/blip.rs b/crates/rustynes-apu/src/blip.rs
index 448b563f..10b900c9 100644
--- a/crates/rustynes-apu/src/blip.rs
+++ b/crates/rustynes-apu/src/blip.rs
@@ -1,3 +1,7 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+// Provenance: the band-limited (BLEP) synthesis is derived from blip_buf by Shay Green (Blargg), LGPL-2.1-or-later (GPLv3-compatible). See docs/originality-and-provenance.md (Section 1)
+// and NOTICE for the complete, audited derivation record.
//! Band-limited synthesis for the APU's audio output.
//!
//! # What this is
@@ -8,9 +12,10 @@
//!
//! The technique is band-limited step (BLEP) synthesis — the same general
//! approach popularized by Shay Green's `blip_buf` and used by many emulators.
-//! This is an independent implementation (our polyphase kernel in
-//! [`crate::blip_kernel`] uses a finer 32-phase resolution than `blip_buf`); no
-//! `blip_buf` code is incorporated:
+//! Provenance: the band-limited-step technique is **derived from Shay Green's
+//! `blip_buf`** (LGPL-2.1-or-later, which is GPLv3-compatible); our polyphase
+//! kernel in [`crate::blip_kernel`] uses a finer 32-phase resolution than
+//! `blip_buf`. See NOTICE and docs/originality-and-provenance.md (Section 1):
//!
//! - Pre-compute a polyphase windowed-sinc kernel ([`crate::blip_kernel`])
//! keyed by `PHASES = 32` sub-output-sample fractional offsets, with
diff --git a/crates/rustynes-apu/src/opll.rs b/crates/rustynes-apu/src/opll.rs
index 9647e96e..16ceb8ed 100644
--- a/crates/rustynes-apu/src/opll.rs
+++ b/crates/rustynes-apu/src/opll.rs
@@ -1,3 +1,7 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+// Provenance: this is a Rust port of emu2413 (the Yamaha YM2413 / OPLL FM core) by Mitsutaka Okazaki, MIT-licensed. See docs/originality-and-provenance.md (Section 1)
+// and NOTICE for the complete, audited derivation record.
//! Yamaha YM2413 (OPLL) FM synthesizer — pure-Rust port of
//! [`emu2413 v1.5.9`](https://github.com/digital-sound-antiques/emu2413)
//! (MIT, Mitsutaka Okazaki) for the VRC7 mapper.
diff --git a/crates/rustynes-cheevos/Cargo.toml b/crates/rustynes-cheevos/Cargo.toml
index 8899bd56..23bf6e43 100644
--- a/crates/rustynes-cheevos/Cargo.toml
+++ b/crates/rustynes-cheevos/Cargo.toml
@@ -3,7 +3,7 @@ name = "rustynes-cheevos"
version.workspace = true
edition = "2024"
rust-version = "1.96"
-license = "MIT OR Apache-2.0"
+license = "GPL-3.0-or-later"
authors = ["Parobek "]
repository.workspace = true
description = "Native-only RetroAchievements (rcheevos) FFI wrapper for RustyNES"
diff --git a/crates/rustynes-core/src/bk2_interop.rs b/crates/rustynes-core/src/bk2_interop.rs
index ecb355ad..705bd4aa 100644
--- a/crates/rustynes-core/src/bk2_interop.rs
+++ b/crates/rustynes-core/src/bk2_interop.rs
@@ -318,15 +318,96 @@ fn parse_header(header: &str) -> Result {
Ok(meta)
}
+/// The standard-controller column map (`U D L R S s B A`), used as the fallback
+/// when a `LogKey:` group is absent or unrecognized. Each slot maps an input-line
+/// character *position* to the [`Buttons`] flag it drives.
+fn default_pad_columns() -> Vec