diff --git a/CHANGELOG.md b/CHANGELOG.md index 6166c94..796e693 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,17 +9,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.14.0] "Foundry" - 2026-07-12 + +Tenth release of the RustyNES-parity roadmap: Mobile Phase 1, the UniFFI bridge foundations. + ### Added -- **New crate `rustysnes-mobile`** (`v1.14.0 "Foundry"`, Mobile Phase 1): a `UniFFI` bridge +- **New crate `rustysnes-mobile`** (Mobile Phase 1): a `UniFFI` bridge generating Kotlin (Android) and Swift (iOS) bindings over `rustysnes_core::facade::EmuCore` — the same facade the desktop frontend and `rustysnes-libretro` already drive the emulator through. MVP surface: ROM load/close, `run_frame`, the peripheral setters (Gamepad/Mouse/Super Scope/Multitap), framebuffer + per-frame audio access, save/load state, reset/power-cycle. - Verified for - real: a genuine `cargo ndk` cross-compile to `arm64-v8a` produced an actual ARM64 `.so` - (confirmed via `file`), and `uniffi-bindgen` generated real, correctly-shaped Kotlin and Swift - bindings from the compiled library. + Verified for real: a genuine `cargo ndk` cross-compile to `arm64-v8a` produced an actual ARM64 + `.so` (confirmed via `file`), and `uniffi-bindgen` generated real, correctly-shaped Kotlin and + Swift bindings from the compiled library. - **`no_std` CI gate expanded to a per-crate matrix**: `rustysnes-{cpu,ppu,apu,cart,core}` each now build standalone against `thumbv7em-none-eabihf --no-default-features`, replacing the prior single aggregate-only `rustysnes-core` build. diff --git a/Cargo.lock b/Cargo.lock index 19f60e1..9856893 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3654,7 +3654,7 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "rustysnes-apu" -version = "1.13.0" +version = "1.14.0" dependencies = [ "bitflags 2.13.0", "rustysnes-savestate", @@ -3662,7 +3662,7 @@ dependencies = [ [[package]] name = "rustysnes-cart" -version = "1.13.0" +version = "1.14.0" dependencies = [ "bitflags 2.13.0", "rustysnes-savestate", @@ -3671,7 +3671,7 @@ dependencies = [ [[package]] name = "rustysnes-cheevos" -version = "1.13.0" +version = "1.14.0" dependencies = [ "cc", "ureq", @@ -3679,7 +3679,7 @@ dependencies = [ [[package]] name = "rustysnes-core" -version = "1.13.0" +version = "1.14.0" dependencies = [ "criterion", "rustysnes-apu", @@ -3694,7 +3694,7 @@ dependencies = [ [[package]] name = "rustysnes-cpu" -version = "1.13.0" +version = "1.14.0" dependencies = [ "bitflags 2.13.0", "rustysnes-savestate", @@ -3702,7 +3702,7 @@ dependencies = [ [[package]] name = "rustysnes-frontend" -version = "1.13.0" +version = "1.14.0" dependencies = [ "anstyle", "bytemuck", @@ -3742,11 +3742,11 @@ dependencies = [ [[package]] name = "rustysnes-gfx-shaders" -version = "1.13.0" +version = "1.14.0" [[package]] name = "rustysnes-libretro" -version = "1.13.0" +version = "1.14.0" dependencies = [ "libc", "rust-libretro", @@ -3755,7 +3755,7 @@ dependencies = [ [[package]] name = "rustysnes-mobile" -version = "1.13.0" +version = "1.14.0" dependencies = [ "rustysnes-cart", "rustysnes-core", @@ -3765,7 +3765,7 @@ dependencies = [ [[package]] name = "rustysnes-netplay" -version = "1.13.0" +version = "1.14.0" dependencies = [ "js-sys", "rustysnes-core", @@ -3777,7 +3777,7 @@ dependencies = [ [[package]] name = "rustysnes-ppu" -version = "1.13.0" +version = "1.14.0" dependencies = [ "bitflags 2.13.0", "rustysnes-cart", @@ -3787,14 +3787,14 @@ dependencies = [ [[package]] name = "rustysnes-savestate" -version = "1.13.0" +version = "1.14.0" dependencies = [ "thiserror 2.0.18", ] [[package]] name = "rustysnes-script" -version = "1.13.0" +version = "1.14.0" dependencies = [ "mlua", "rustysnes-core", @@ -3803,7 +3803,7 @@ dependencies = [ [[package]] name = "rustysnes-test-harness" -version = "1.13.0" +version = "1.14.0" dependencies = [ "insta", "rustysnes-apu", diff --git a/Cargo.toml b/Cargo.toml index a413d33..65e7211 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ members = [ ] [workspace.package] -version = "1.13.0" +version = "1.14.0" edition = "2024" rust-version = "1.96" license = "MIT OR Apache-2.0" diff --git a/crates/rustysnes-apu/Cargo.toml b/crates/rustysnes-apu/Cargo.toml index ac9dcdd..92ff1b3 100644 --- a/crates/rustysnes-apu/Cargo.toml +++ b/crates/rustysnes-apu/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustysnes-apu" -version = "1.13.0" +version = "1.14.0" edition.workspace = true rust-version.workspace = true license.workspace = true diff --git a/crates/rustysnes-cart/Cargo.toml b/crates/rustysnes-cart/Cargo.toml index 1f05761..7d34515 100644 --- a/crates/rustysnes-cart/Cargo.toml +++ b/crates/rustysnes-cart/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustysnes-cart" -version = "1.13.0" +version = "1.14.0" edition.workspace = true rust-version.workspace = true license.workspace = true diff --git a/crates/rustysnes-cheevos/Cargo.toml b/crates/rustysnes-cheevos/Cargo.toml index 76126c5..8cfdeb0 100644 --- a/crates/rustysnes-cheevos/Cargo.toml +++ b/crates/rustysnes-cheevos/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustysnes-cheevos" description = "Native-only RetroAchievements (rcheevos) FFI wrapper for RustySNES" -version = "1.13.0" +version = "1.14.0" edition.workspace = true rust-version.workspace = true license.workspace = true diff --git a/crates/rustysnes-core/Cargo.toml b/crates/rustysnes-core/Cargo.toml index f0b6a7e..7097ffd 100644 --- a/crates/rustysnes-core/Cargo.toml +++ b/crates/rustysnes-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustysnes-core" -version = "1.13.0" +version = "1.14.0" edition.workspace = true rust-version.workspace = true license.workspace = true diff --git a/crates/rustysnes-cpu/Cargo.toml b/crates/rustysnes-cpu/Cargo.toml index 7fd780d..cc1acf7 100644 --- a/crates/rustysnes-cpu/Cargo.toml +++ b/crates/rustysnes-cpu/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustysnes-cpu" -version = "1.13.0" +version = "1.14.0" edition.workspace = true rust-version.workspace = true license.workspace = true diff --git a/crates/rustysnes-frontend/Cargo.toml b/crates/rustysnes-frontend/Cargo.toml index dbcaf5a..46e33e9 100644 --- a/crates/rustysnes-frontend/Cargo.toml +++ b/crates/rustysnes-frontend/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustysnes-frontend" description = "RustySNES: cross-platform SNES emulator binary (winit + wgpu + cpal + egui)" -version = "1.13.0" +version = "1.14.0" edition.workspace = true rust-version.workspace = true license.workspace = true diff --git a/crates/rustysnes-gfx-shaders/Cargo.toml b/crates/rustysnes-gfx-shaders/Cargo.toml index 086bd82..b0effb3 100644 --- a/crates/rustysnes-gfx-shaders/Cargo.toml +++ b/crates/rustysnes-gfx-shaders/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustysnes-gfx-shaders" description = "RustySNES: shared WGSL presentation-shader sources (blit + post-filters)" -version = "1.13.0" +version = "1.14.0" edition.workspace = true rust-version.workspace = true license.workspace = true diff --git a/crates/rustysnes-mobile/Cargo.toml b/crates/rustysnes-mobile/Cargo.toml index 13e2e9b..46e793d 100644 --- a/crates/rustysnes-mobile/Cargo.toml +++ b/crates/rustysnes-mobile/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustysnes-mobile" description = "RustySNES: UniFFI mobile bridge (Kotlin/Swift bindings over the emulation core)" -version = "1.13.0" +version = "1.14.0" edition.workspace = true rust-version.workspace = true license.workspace = true diff --git a/crates/rustysnes-netplay/Cargo.toml b/crates/rustysnes-netplay/Cargo.toml index 2736d78..5ba765d 100644 --- a/crates/rustysnes-netplay/Cargo.toml +++ b/crates/rustysnes-netplay/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustysnes-netplay" description = "RustySNES: GGPO-style rollback netplay (UDP native, WebRTC browser)" -version = "1.13.0" +version = "1.14.0" edition.workspace = true rust-version.workspace = true license.workspace = true diff --git a/crates/rustysnes-ppu/Cargo.toml b/crates/rustysnes-ppu/Cargo.toml index 0f944c2..9059be5 100644 --- a/crates/rustysnes-ppu/Cargo.toml +++ b/crates/rustysnes-ppu/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustysnes-ppu" -version = "1.13.0" +version = "1.14.0" edition.workspace = true rust-version.workspace = true license.workspace = true diff --git a/crates/rustysnes-savestate/Cargo.toml b/crates/rustysnes-savestate/Cargo.toml index 48e6c11..31eafe2 100644 --- a/crates/rustysnes-savestate/Cargo.toml +++ b/crates/rustysnes-savestate/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustysnes-savestate" -version = "1.13.0" +version = "1.14.0" edition.workspace = true rust-version.workspace = true license.workspace = true diff --git a/crates/rustysnes-script/Cargo.toml b/crates/rustysnes-script/Cargo.toml index 6375249..3eccb58 100644 --- a/crates/rustysnes-script/Cargo.toml +++ b/crates/rustysnes-script/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustysnes-script" description = "RustySNES: sandboxed Lua 5.4 scripting (memory read/write + a per-frame callback)" -version = "1.13.0" +version = "1.14.0" edition.workspace = true rust-version.workspace = true license.workspace = true diff --git a/crates/rustysnes-test-harness/Cargo.toml b/crates/rustysnes-test-harness/Cargo.toml index 83c8efb..b48e366 100644 --- a/crates/rustysnes-test-harness/Cargo.toml +++ b/crates/rustysnes-test-harness/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustysnes-test-harness" -version = "1.13.0" +version = "1.14.0" edition.workspace = true rust-version.workspace = true license.workspace = true diff --git a/docs/STATUS.md b/docs/STATUS.md index 3d58563..195d145 100644 --- a/docs/STATUS.md +++ b/docs/STATUS.md @@ -3,12 +3,12 @@ This file is authoritative for per-suite pass counts, the board / coprocessor matrix, and version policy. Everything else defers to it. -**Current release:** `v1.13.0 "Vantage"` (`v0.1.0 "Foundation"`, +**Current release:** `v1.14.0 "Foundry"` (`v0.1.0 "Foundation"`, `v0.2.0 "Persistence"`, `v0.3.0 "Continuum"`, `v0.4.0 "Completion"`, `v0.5.0 "Fidelity"`, `v0.6.0 "Shippable"`, `v0.7.0 "Resolution"`, `v0.8.0 "Community"`, `v0.9.0 "Threshold"`, `v1.0.0 "Zenith"`, `v1.0.1 "Aftertouch"`, `v1.1.0 "Latchkey"`, `v1.2.0 "Phosphor"`, `v1.3.0 "Palimpsest"`, and `v1.4.0 "Convergence"` precede it; see `to-dos/VERSION-PLAN.md` for the -full ladder). **`v1.5.0`-`v1.13.0`** are the opening rungs of the RustyNES-parity ladder — a CI +full ladder). **`v1.5.0`-`v1.14.0`** are the opening rungs of the RustyNES-parity ladder — a CI safety net (`v1.5.0 "Bedrock"`), a MkDocs documentation site + PWA + accuracy ledger (`v1.6.0 "Lighthouse"`), the debugger extracted into its own module plus a hex Memory panel (`v1.7.0 "Telemetry"`, `v1.7.1` patch), a Memory Compare panel + in-app Docs panel @@ -17,9 +17,12 @@ safety net (`v1.5.0 "Bedrock"`), a MkDocs documentation site + PWA + accuracy le time (`v1.10.0 "Atelier"`), fixing RetroAchievements to actually load a game for the first time (`v1.11.0 "Podium"`), adding a third presentation post-filter (`PostFilter::Xbrz`) plus extracting the WGSL shader sources into a new `rustysnes-gfx-shaders` crate for reuse by the -planned mobile bridge (`v1.12.0 "Refraction"`), and adding two accessibility theme variants +mobile bridge (`v1.12.0 "Refraction"`), adding two accessibility theme variants (`AppTheme::HighContrast`/`Colorblind`) while honestly re-scoping the other two originally-planned -items (`v1.13.0 "Vantage"`) — all frontend/tooling/CI work with **zero +items (`v1.13.0 "Vantage"`), and — reversing `v1.0.0`'s "no mobile appetite" default — a new +`rustysnes-mobile` `UniFFI` bridge crate over `EmuCore`, real-verified via a `cargo ndk` ARM64 +cross-compile and inspected Kotlin/Swift binding output, plus the `no_std` CI gate expanded to a +per-crate matrix (`v1.14.0 "Foundry"`) — all frontend/tooling/CI work with **zero change** to the accuracy dashboard, per-suite pass counts, or coprocessor tier matrix below, which stayed byte-identical throughout; see `CHANGELOG.md` for full per-release detail. `v1.0.0` closes the production-cut diff --git a/to-dos/ROADMAP.md b/to-dos/ROADMAP.md index d6ab539..a492285 100644 --- a/to-dos/ROADMAP.md +++ b/to-dos/ROADMAP.md @@ -344,10 +344,10 @@ under `v1.0.0`) and the netplay save-state-cost pre-work. a save-state migration fixture and a keyboard-nav audit, were investigated and found to already be a verified-non-issue and a manual-walkthrough task respectively, not code fixes — both honestly re-scoped rather than force-fit), then the mobile track's bridge foundations - (`v1.14.0 "Foundry"` — new `rustysnes-mobile` `UniFFI` crate over the same `EmuCore` facade the - desktop frontend uses; verified for real with a genuine `cargo ndk` ARM64 cross-compile and - inspected Kotlin/Swift binding output, not just claimed; the mobile/Android+iOS "no appetite" - default from `v1.0.0` is formally reversed, `docs/adr/0012`) — with + (`v1.14.0 "Foundry"`, **RELEASED 2026-07-12** — new `rustysnes-mobile` `UniFFI` crate over the + same `EmuCore` facade the desktop frontend uses; verified for real with a genuine `cargo ndk` + ARM64 cross-compile and inspected Kotlin/Swift binding output, not just claimed; the mobile/ + Android+iOS "no appetite" default from `v1.0.0` is formally reversed, `docs/adr/0012`) — with the rest of the mobile track — Android + iOS apps plus dormant monetization scaffolding (`v1.15.0`-`v1.18.0`) — and a PGO/BOLT pipeline last (`v1.19.0`). Tracked in lockstep against RustyNES's own continuing development via `to-dos/LOCKSTEP-CHECKLIST.md`, not a frozen diff --git a/to-dos/VERSION-PLAN.md b/to-dos/VERSION-PLAN.md index dc7afee..47ca9b3 100644 --- a/to-dos/VERSION-PLAN.md +++ b/to-dos/VERSION-PLAN.md @@ -1162,11 +1162,9 @@ into a hollow "audit passed" claim. See `docs/frontend.md` for the full explanat rationale; stands up `docs/mobile-readiness.md`; a new ADR records the mobile-platform-target decision, citing that `docs/adr/0002`'s gate is already closed favorably. -### `v1.14.0 "Foundry"` — Mobile Phase 1: bridge foundations +### `v1.14.0 "Foundry"` — Mobile Phase 1: bridge foundations — **RELEASED 2026-07-12** -Implemented (this PR; the version bump + "RELEASED" marker land in the separate -`chore(release)` closeout PR, matching every prior rung's two-PR pattern): new crate -`rustysnes-mobile`, a `UniFFI` bridge over `rustysnes_core::facade::EmuCore` +Delivered: new crate `rustysnes-mobile`, a `UniFFI` bridge over `rustysnes_core::facade::EmuCore` (the same `std`-only facade the desktop frontend and `rustysnes-libretro` already drive the emulator through — `Board: Send` since `v1.0.0` and the chip-stack crates' `#![no_std]`+`alloc` posture were both already proven, not new work here). MVP surface: ROM load/close, `run_frame`,