Skip to content

Commit 36c15ea

Browse files
doublegateclaude
andcommitted
docs: review round 3 (CodeRabbit on slice C, #593) -- 14 findings, 14 fixed
All 14 inline findings held. The review body had no outside-diff, nitpick or duplicate section. Toolchain: - docs/build-and-tooling.md's Channel bullet still told readers the libretro buildbot runs 1.96.0, the floor is checked on every PR, and a pin bump is a one-line edit. Round 1 (eecf8ea) fixed the MSRV bullet one line above and missed this one. It now says the buildbot uses the same toolchain and that both files move together (CI fails otherwise), and gives the 1.96 exception as history. - docs/agents/libretro.md: the `-C ar` bullet is marked HISTORICAL, pointing to the "UNDID THE SPLIT" bullet for the current state. Measurements: - docs/scheduler.md and docs/performance.md called both frame costs "on the shipped fast dot path". Only nestest (~3.95 ms) is. flowing_palette (~2.65 ms) is rendering-disabled, so its `_fast` variant's guard bails and never enters that path; the bench source says so (full_frame.rs:125-126). It is now labelled as the control it is. Records: - CHANGELOG [3.0.1] Verification links docs/STATUS.md. - OVERVIEW: v2.0.0 is "the first designated breaking release", not "the one" (v3.0.0 is MAJOR too). - VERSION-PLAN's MAJOR rule: the new-deliverable trigger applies when that release is DESIGNATED MAJOR (ADR 0043 allows a minor; D1/D29 place it at the end of v3.9.x). - The v3.0.1 plan separates its reply count from its resolve count: 279 replies = 153 thread replies + 126 PR comments; 77 resolves. External facts, checked before editing: - ADR 0035 and the v3.9.0 plan, Android developer verification. It started 2026-09-30 in four countries for apps distributed through the participating stores, and goes to certified devices worldwide in 2027. ADB and the "advanced flow" still install an unregistered app. The account paths: an individual gives photo ID and proof of address; an organisation gives organisation documents; limited distribution covers up to 20 devices without a government ID. Which path to take stays an open maintainer decision. (developer.android.com developer-verification guide; Help Net Security.) - v3.9.0, iOS signing: iPhone and iPad uploads require the iOS/iPadOS 27 SDK from April 2027, as Apple announced on 2026-09-09; Xcode 27 is the tool that provides it. The plan previously called the date an inference. - v3.4.0, hosting: "well inside the free 1,000 GB" had no forecast behind it. It is replaced by the capacity it implies: about 45,000 relayed player-hours a month at the inferred 22 MB per player-hour, with the allowance shared with Realtime SFU. The gate now measures the first month's traffic. - v3.4.0, privacy: RetroAchievements' privacy-policy requirement and F-Droid's NonFreeNet anti-feature are now separate items. The anti-feature does not itself require a policy. Also: - v4.0.0, T-API-ENUMS now covers rustynes-netplay (NetMessage among its enums), which rustynes-core does not re-export. - The v2.0.x plan: the blank line splitting two blockquotes (MD028) is now `>`. Checks: markdownlint (pre-commit) on the linted files; the pinned 0.49.1 on copies of the new plans, which reports only two MD049 errors older than this change, in the ignored v2.0.x plan's lines 95-96; release_anchor 14/0, release_state_prose 16/0, contribution_checklist 9/0, each run on its own. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014qfTKi2M3swo7qnwvYCkDj
1 parent f1c3c47 commit 36c15ea

13 files changed

Lines changed: 22 additions & 18 deletions

‎CHANGELOG.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ hardware-verified**. The maintainer's decisions are in
141141
- `cargo test --release --workspace --features test-roms --no-fail-fast`:
142142
3,234 passed, 0 failed, 11 ignored on the release tree (v3.0.0: 3,223 / 0 /
143143
11). `cargo test --workspace`: 2,886 / 0 / 7; the cosim crate 54 / 0.
144-
AccuracyCoin 144/144, nestest 0-diff.
144+
AccuracyCoin 144/144, nestest 0-diff. The per-suite counts and the mapper
145+
matrix are in [`docs/STATUS.md`](docs/STATUS.md).
145146
- The local commercial suites (`--features test-roms,commercial-roms`):
146147
`external_real_games` 60/0, `external_extended` 137/0, `external_coverage`
147148
6/0. The one moved baseline is *Famicom Yarou Vol.1* (T-GA23C-CHRRAM), which

‎OVERVIEW.md‎

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

‎VERSION-PLAN.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ v1.0.0 is the **production cut that integrates the cycle-accurate emulation engi
1919
MAJOR.MINOR.PATCH[-PRERELEASE]
2020
```
2121

22-
- **MAJOR** — an incompatible break of the public Rust API (`rustynes-core` and the chip-crate types it re-exports), or the first release of a new deliverable class ([ADR 0041](docs/adr/0041-hardware-release-is-v3.0.0.md): the first hardware-verified FPGA core). Now at `3`: **v3.0.0 "Cornerstone"** was MAJOR by the first trigger and shipped an unverified release-candidate core; the hardware-verified core is a later v3.x release, numbered after the board session and no later than v4.0.0 ([ADR 0043](docs/adr/0043-v3-is-the-api-major-and-a-release-candidate-core.md) and its 2026-10-07 amendment). **A format break alone is not a MAJOR trigger since 2026-10-07** (maintainer decision; see "Breaking-change policy" below).
22+
- **MAJOR** — an incompatible break of the public Rust API (`rustynes-core` and the chip-crate types it re-exports), or the first release of a new deliverable class when that release is designated MAJOR ([ADR 0041](docs/adr/0041-hardware-release-is-v3.0.0.md) named the first hardware-verified FPGA core; [ADR 0043](docs/adr/0043-v3-is-the-api-major-and-a-release-candidate-core.md) lets it be a minor instead, and its 2026-10-07 amendments place it at the end of v3.9.x). Now at `3`: **v3.0.0 "Cornerstone"** was MAJOR by the first trigger and shipped an unverified release-candidate core; the hardware-verified core is a later v3.x release, numbered after the board session and no later than v4.0.0 ([ADR 0043](docs/adr/0043-v3-is-the-api-major-and-a-release-candidate-core.md) and its 2026-10-07 amendment). **A format break alone is not a MAJOR trigger since 2026-10-07** (maintainer decision; see "Breaking-change policy" below).
2323
- **MINOR** — features (new mappers, new frontend features, new platforms). May carry a documented format break.
2424
- **PATCH** — bug fixes and accuracy refinements. May carry a documented format break when the fix needs one (v3.0.1 raised `EMULATION_EPOCH`).
2525
- **PRERELEASE** — `-alpha.N` / `-beta.N` / `-rc.N` when stabilizing a future minor/major.

‎docs/adr/0035-rustynes-is-permanently-non-commercial.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,9 @@ v4.0.0's final development, test and release activities.**
8080

8181
That covers:
8282

83-
- Android developer verification, which also applies to sideloaded apps and is
84-
global from 2027;
83+
- Android developer verification, which covers the ordinary installation path
84+
(from 2026-09-30 in four countries, worldwide on certified devices in 2027);
85+
ADB and Android's "advanced flow" can still install an unregistered app;
8586
- iOS signing, so that TestFlight uploads run;
8687
- the Google Play, F-Droid or IzzyOnDroid, and App Store listings.
8788

‎docs/agents/libretro.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
2020
- **Libretro buildbot CI (issue #311) shipped in PR #312 (2026-07-19/20, `b49dd1e0`) — and the upstream half is now DONE; the "stays OPEN by design" instruction this bullet used to lead with is RETIRED, see below.** `.gitlab-ci.yml` + a `[lib] name = "rustynes"` naming-collision fix + `[workspace] default-members` + RA memory-maps + an FDS load-path fix/disk-control + native Game Genie cheats all shipped. TAS and Netplay needed no new libretro-side wiring — RetroArch's own rollback/movie machinery already rides the existing `on_serialize`/`on_unserialize` hooks. **DONE as of 2026-07-21, re-measured 2026-09-20** — this bullet described the upstream half as pending for two months after it landed. Companion PRs `libretro/docs#1164` (merged 2026-07-21) and `libretro/libretro-super#2021` (merged 2026-07-24) are both in, the mirror + buildbot step the libretro team owned is complete, and `rustynes_libretro.so.zip` is on the nightly buildbot for **linux/x86_64, windows/x86_64 and apple/osx/arm64** (checked by fetching the three `latest/` listings, not by asking anyone). `dist/info/rustynes_libretro.info` upstream reads `license = "GPLv3+"`, `display_version = "v2.3.9"`. **Issue #311 is CLOSED and that is now CORRECT** — but read its timeline before citing it, because it closed twice for opposite reasons: `2026-07-19T22:28` by doublegate via a commit-body keyword (premature, reopened 27 minutes later at `22:55`), then `2026-07-21T13:07` **by `hizzlekizzle`, an upstream maintainer, by hand and with no commit id** — which is exactly the condition this bullet demanded. **The keyword rule still stands and the timeline is its evidence:** never put a closing keyword for an unfinished issue in a commit or PR body, because the first close proves GitHub acts on it instantly and the tracker then reports finished work that was not done. What retires an issue is a verified outcome — here, three buildbot listings and a maintainer's own click.
2121
- **The libretro buildbot is a THIRD CI system with its own rules — and the pinned toolchain fights it.** The first real run (pipeline #91899, 2026-07-20) passed 1 of 10 jobs. `rust-toolchain.toml`'s `channel = "1.96.0"` makes rustup install a *fresh* toolchain inside libretro's build image, bypassing the image's pre-provisioned cross targets, so 8 jobs died on `E0463: can't find crate for core`; each job in `.gitlab-ci.yml` now runs `rustup target add ${RUST_TARGET}` (NOT added to `rust-toolchain.toml`'s `targets` — that would cost every contributor and GH Actions job ~8 extra `rust-std` downloads). The Apple jobs must use `!reference` rather than `extends` for that, because GitLab's `extends` REPLACES array keys and would silently drop the templates' `SDKROOT`/`STRIP`/`CC`/`CXX` exports. **tvOS: the upstream template's `cargo +nightly build -Zbuild-std` override is OBSOLETE — don't reinstate it.** It dates from when `aarch64-apple-tvos` was tier 3 with no distributed `rust-std`; the target has since been promoted and rustup ships a complete prebuilt std **including `panic_abort`** (verified on the pinned 1.96.0: `rustup target add aarch64-apple-tvos` gives 26 rlibs and the crate `cargo check`s clean, bindgen included). Our job overrides `script` back to `!reference [.libretro-rust-apple-base, script]`, putting tvOS on the same pinned stable as every other job. That one change dissolved THREE stacked workarounds the `+nightly` path had forced: a nightly-channel reinstall (`+nightly` outranks both `rust-toolchain.toml` and `RUSTUP_TOOLCHAIN`, so the job rode the image's stale 1.94.0-nightly, below our MSRV); `CARGO_PROFILE_RELEASE_PANIC=unwind` (bare `-Zbuild-std` omits `panic_abort`, and `CARGO_UNSTABLE_BUILD_STD` does NOT override the hardcoded crate list — the CLI `-Z` flag wins); and clearing the image's `-C ar` (see the next bullet). (Since v2.8.0 that same variable is set to `unwind` again for EVERY buildbot job, tvOS included, by `.core-defs` — deliberately, for panic containment (L-1.1), not as the old tvOS workaround; `panic_abort` being available does not make the abort profile effective there.) Worth reporting upstream: every Rust core's tvOS job could drop `+nightly` the same way. **A green GitHub Actions run does not imply a green buildbot** — the `libretro-cross` CI job (the buildbot triples a Linux runner can model — at #554, 2026-09-24: 64- and 32-bit MinGW-Windows, Linux aarch64 / i686, armhf, the webOS `armv7-unknown-linux-gnueabi`, and Android/NDK; this parenthesis first said "MinGW-Windows and Android/NDK", which had been stale since the aarch64 and armhf legs landed; the Apple families are deliberately excluded, as bindgen needs a real per-target sysroot and there is no Apple SDK on a Linux runner) is the early-warning gate; before touching anything libretro-related, cross-check `cargo check --release -p rustynes-libretro --target <triple>` locally.
22-
- **The libretro build image injects `-C ar` into EVERY Apple job, and it is a hard error from Rust 1.97 — a bomb armed against the next MSRV bump.** The image (not the `rust-apple.yml` template, which sets no `RUSTFLAGS` at all, and not our `.cargo/config.toml`) adds `-Car=<path>,Clink-arg=-undefined,Clink-arg=dynamic_lookup,-rpath=<path>` to osx-x64 / osx-arm64 / ios-arm64 / tvos-arm64. `-C ar` was a deprecated no-op for years and became a **hard error in 1.97** (bisected locally: 1.93.0-nightly / 1.96.0 / 1.96.1 warn; 1.97.1 and 1.99.0-nightly error). No job trips it today — all four Apple jobs are on the pinned 1.96.0 and merely log the warning. **The day `rust-toolchain.toml` moves to 1.97+, all four fail together** — the warning lives in that file, at the line someone would edit. Discarding the flags is behaviour-preserving, not a gamble: rustc splits `-C` at the FIRST `=`, so the whole comma-joined string is swallowed as the `ar` value and those link args have never reached the linker for *any* core (cargo prints it as one argv token), and two upstream Rust cores have green tvOS jobs on the same image with the same dead token. The override works without knowing where the image sets it because cargo takes rustflags from exactly one source, first match wins: `CARGO_ENCODED_RUSTFLAGS` → `RUSTFLAGS` → `target.<triple>.rustflags` → `build.rustflags` (verified locally against a global `~/.cargo/config.toml` `build.rustflags`: `RUSTFLAGS=""` removes every injected `-C`, and empty means zero flags, not one empty argument).
22+
- **(HISTORICAL, until 2026-09-03; the current state is the "UNDID THE SPLIT" bullet below.) The libretro build image injected `-C ar` into EVERY Apple job, and it is a hard error from Rust 1.97 — a bomb armed against the next MSRV bump.** The image (not the `rust-apple.yml` template, which sets no `RUSTFLAGS` at all, and not our `.cargo/config.toml`) adds `-Car=<path>,Clink-arg=-undefined,Clink-arg=dynamic_lookup,-rpath=<path>` to osx-x64 / osx-arm64 / ios-arm64 / tvos-arm64. `-C ar` was a deprecated no-op for years and became a **hard error in 1.97** (bisected locally: 1.93.0-nightly / 1.96.0 / 1.96.1 warn; 1.97.1 and 1.99.0-nightly error). No job trips it today — all four Apple jobs are on the pinned 1.96.0 and merely log the warning. **The day `rust-toolchain.toml` moves to 1.97+, all four fail together** — the warning lives in that file, at the line someone would edit. Discarding the flags is behaviour-preserving, not a gamble: rustc splits `-C` at the FIRST `=`, so the whole comma-joined string is swallowed as the `ar` value and those link args have never reached the linker for *any* core (cargo prints it as one argv token), and two upstream Rust cores have green tvOS jobs on the same image with the same dead token. The override works without knowing where the image sets it because cargo takes rustflags from exactly one source, first match wins: `CARGO_ENCODED_RUSTFLAGS` → `RUSTFLAGS` → `target.<triple>.rustflags` → `build.rustflags` (verified locally against a global `~/.cargo/config.toml` `build.rustflags`: `RUSTFLAGS=""` removes every injected `-C`, and empty means zero flags, not one empty argument).
2323
- **v3.0.1 SPLIT THE TOOLCHAIN instead of disarming the `-C ar` bomb.** `rust-toolchain.toml` moved to 1.99.0; `.gitlab-ci.yml` `.core-defs` sets `RUSTUP_TOOLCHAIN: "1.96.0"` (it outranks `rust-toolchain.toml`), and every job's `rustup target add` became `rustup toolchain install ${RUSTUP_TOOLCHAIN} --profile minimal --target ${RUST_TARGET}`. The libretro templates set no `RUSTUP_TOOLCHAIN` or rustflags (checked in `rust-apple.yml`, `rust-linux-x64.yml`, `rust-windows-x64.yml`, `rust-android-jni.yml`, `rust-webos.yml`, 2026-10-06). The seven crates the core compiles declare `rust-version = "1.96"`, and GitHub CI's `libretro-cross` reads the version out of `.gitlab-ci.yml` (no literal in `.github/`) and builds on it. **That check has already paid for itself:** clippy 1.99 rewrote `for b in self.ram.iter_mut()` (a `Box<[u8; 2048]>`) to `for b in &mut self.ram`, which 1.96 rejects (`&mut Box<[T; N]>` is not `IntoIterator` there); clippy honoured nothing about the crate's `rust-version`, and only the 1.96 build caught it (`bus.rs`, fixed as `&mut *self.ram`). The documented two-line `RUSTFLAGS` fix in `rust-toolchain.toml` would let the buildbot follow; it was not taken in v3.0.1. **CORRECTED the same day: the buildbot CAN be tested before merge.** libretro's mirror of the GitHub repo runs a pipeline for every pushed BRANCH, not only `main` (`git.libretro.com/api/v4/projects/libretro%2FRustyNES/pipelines?ref=<branch>`; the v3.0.0 cycle shows pipelines for `release/v3.0.0` and the review slices). The pushed `release/v3.0.1` got pipeline 119606 within about 20 minutes, and all 15 jobs (Apple included) passed on the 1.96 pin. The job LIST is public; job LOGS need a login (401). A review-slice branch fails every job by construction (each holds only part of a release), so expect red there and do not read it as a defect.
2424
- **AND v3.0.1 UNDID THE SPLIT, the same day (2026-10-07).** The research for the v3.1 roadmap found that `libretro-infrastructure/libretro-build-rust` removed the `-C` usage from the build image on 2026-09-03 (`841f3619`, "Remove -C usage as no longer supported by rust"; the rebuilt image's own pipeline passed 2026-09-23). A throwaway branch, `test/libretro-rust-1.99`, set only `RUSTUP_TOOLCHAIN: "1.99.0"`; its pipeline 119614 passed all 15 jobs, `osx-x64`, `osx-arm64`, `ios-arm64` and `tvos-arm64` included. So the pin now equals `rust-toolchain.toml` again, the seven crates inherit the workspace `rust-version`, and `libretro-cross` FAILS if the two toolchains differ, so neither can drift alone. Two lessons: the hazard lived in someone else's image, so re-check it there before planning around it; and since the image now separates its `-C link-arg` flags properly, those link arguments reach the linker for the first time. That is harmless on 119614, but it is the first thing to suspect if an Apple link changes behaviour.
2525
- **`rust-libretro 0.3.2` is unmaintained (no commit since 2023-02) and has a MinGW bug we work around.** It casts a keycode with `cfg(target_family = "windows")`, but C enum signedness follows the *ABI*: only **MSVC** gives plain enums `int` — under **MinGW** (`x86_64-pc-windows-gnu`, what the buildbot builds) bindgen emits `c_uint` and the crate fails `E0308`. `.cargo/config.toml`'s `[env] BINDGEN_EXTRA_CLANG_ARGS_x86_64_pc_windows_gnu = "--target=x86_64-pc-windows-msvc"` fixes it; the generated-bindings diff is 28 lines, all enum signedness. Don't "clean up" that env var without rebuilding for `x86_64-pc-windows-gnu`.

‎docs/build-and-tooling.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
- **Rust edition**: 2024.
88
- **MSRV (minimum supported Rust version)**: 1.99, the pinned toolchain, for every crate. The libretro buildbot builds on the same toolchain (`RUSTUP_TOOLCHAIN` in `.gitlab-ci.yml`, which CI's `libretro-cross` checks against `rust-toolchain.toml`); v3.0.1 held its seven crates at 1.96 for one day, until a test pipeline showed the build image no longer passed `-C ar`. (History: 1.86 until v1.3.0 "Bedrock", which moved to 1.96 for the edition-2024 + egui 0.34.3 / wgpu 29 / rfd 0.17.2 dependency tier; 1.96 until v3.0.1.)
9-
- **Channel**: the pinned `1.99.0` stable release — *not* a floating `stable`. `rust-toolchain.toml` is the single source of truth: every GitHub Actions job resolves its toolchain from that file (`.github/actions/rust-setup` parses the `channel` and fails closed if it cannot), and local builds pick it up automatically as a directory override. **One exception:** the libretro buildbot runs 1.96.0, set by `RUSTUP_TOOLCHAIN` in `.gitlab-ci.yml` (which outranks the file), because its build image passes `-C ar`, a hard error from Rust 1.97. CI's `libretro-cross` job reads that value from `.gitlab-ci.yml` and builds on it, so the 1.96 floor is checked on every PR. There is no `toolchain:` version literal anywhere in `.github/`, so bumping the pin is a one-line edit here — but read the `-C ar` warning in `rust-toolchain.toml` before bumping to 1.97 or newer.
9+
- **Channel**: the pinned `1.99.0` stable release — *not* a floating `stable`. `rust-toolchain.toml` is the single source of truth: every GitHub Actions job resolves its toolchain from that file (`.github/actions/rust-setup` parses the `channel` and fails closed if it cannot), and local builds pick it up automatically as a directory override. **The libretro buildbot uses the same toolchain**: `RUSTUP_TOOLCHAIN` in `.gitlab-ci.yml` (which outranks the file) must equal the pin, and CI's `libretro-cross` job fails if the two differ, so a pin move edits both files in one change. There is no `toolchain:` version literal anywhere in `.github/`. (Until v3.0.1 the buildbot was a 1.96.0 exception, because its build image passed `-C ar`, a hard error from Rust 1.97; the image dropped the flag on 2026-09-03, and `rust-toolchain.toml` keeps the two-line fix should it return.)
1010
- **Nightly** is used for exactly one thing, outside CI and not a gate: `cargo fuzz`, which requires it for the sanitizer flags it threads through `rustc` (`cargo +nightly fuzz run <target>` — see `fuzz/README.md`). No build, test, lint, docs, release, or packaging path uses nightly.
1111
- **Targets supported**: `x86_64-unknown-linux-gnu`, `aarch64-apple-darwin`, `x86_64-pc-windows-msvc`. Tier 2: `aarch64-unknown-linux-gnu`. Cross-compile targets declared in `rust-toolchain.toml` (auto-installed): `thumbv7em-none-eabihf` (the `no_std` chip-stack gate) and `wasm32-unknown-unknown` (browser). Android arm64/arm/x86_64 via `cargo ndk` (see `docs/android.md`). The `x86_64-apple-darwin` release target was retired (ADR 0009).
1212

‎docs/performance.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ Set quantitative performance targets, identify expected hot paths, and lay out t
1616
> **These are DESIGN-PHASE targets, written before the cycle-accurate core
1717
> existed — they are aspirations, not gates.** The frame-cost row in particular
1818
> was never met and is knowingly accepted: the implemented core measures
19-
> **~3.95 ms** (`nes_run_frame_nestest_fast`) / **~2.65 ms**
20-
> (`nes_run_frame_flowing_palette_fast`) on the shipped fast dot path, and
19+
> **~3.95 ms** (`nes_run_frame_nestest_fast`) on the shipped fast dot path and
20+
> **~2.65 ms** (`nes_run_frame_flowing_palette_fast`, a rendering-disabled
21+
> control: the fast path's guard bails, so it never enters that path), and
2122
> ~4.46 / ~2.67 ms on the exact path, on a 2020 desktop (i9-10850K; see
2223
> "Current figures" below, measured 2026-09-23). The gate that
2324
> actually runs in CI is the **relative, same-runner regression check** (§CI

‎docs/scheduler.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,9 @@ This guarantees that save/load round-trips and a re-played input sequence produc
157157

158158
> These are the original **design-phase aspirations**, not gates. The frame-cost
159159
> figure was not met and is knowingly accepted — the implemented cycle-accurate
160-
> core measures **~3.95 ms** (nestest) / **~2.65 ms** (flowing palette) on the
161-
> shipped fast dot path, ~23% of the 16.639 ms NTSC budget (the v2.7.0 core,
160+
> core measures **~3.95 ms** (nestest) on the shipped fast dot path, ~23% of the
161+
> 16.639 ms NTSC budget, and **~2.65 ms** on flowing palette, a rendering-disabled
162+
> control whose fast-path variant never enters that path (its guard bails) (the v2.7.0 core,
162163
> 2026-09-23; v2.9.7's A12 change added about 1.9% on nestest). See
163164
> `docs/performance.md` §"Current figures" for the measured numbers, the
164165
> exact-path pair, and why the main optimization levers were measured and

‎to-dos/plans/v2.0.x-mobile-finalization-plan.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
> listing is an unversioned later step with no monetization attached. The plan is
99
> kept as written for the record; the section-level notes below mark the parts
1010
> ADR 0035 removed.
11-
11+
>
1212
> **Maintainer decision, 2026-06-23.** The Android (v1.8.x) and iOS (v1.9.0) apps
1313
> will **not** ship to their app stores on their original, independent timelines.
1414
> Both store launches are **held until after v2.0.0 "Timebase"** so the shipped

0 commit comments

Comments
 (0)