Skip to content

release: cut v2.0.5 "Harbor" ("Landfall" — first iOS finalization; iOS re-port onto Timebase) - #244

Merged
doublegate merged 2 commits into
mainfrom
feat/v2.0.5-ios-landfall
Jul 9, 2026
Merged

doublegate merged 2 commits into
mainfrom
feat/v2.0.5-ios-landfall

Conversation

@doublegate

Copy link
Copy Markdown
Owner

Summary

Opens the iOS finalization window (v2.0.5 → v2.0.8) of the v2.0.x "Harbor" train — the iOS analogue of the Android v2.0.1 → v2.0.4 window — by re-porting the frozen v1.9.9 SwiftUI/Metal app onto the v2.0.0 "Timebase" core. Host / iOS-only: the emulation core is unchanged and byte-identical to v2.0.4 (AccuracyCoin 141/141, nestest 0-diff, #![no_std] chip stack untouched).

What landed

  • Pre-Timebase movie warning, surfaced + localized on iOS (EN + ES). Loading a pre-v2.0.0 .rnm still replays its input on the v2.0.0 core, but a non-blocking notice (distinct from the error alert) now tells the user byte-exact framebuffer/audio reproduction isn't guaranteed across the ADR-0028 epoch change. Drained via EmulatorCore.drainWarnings() → NesController.drainWarningCodes() (mapping HostWarning.preTimebaseMovie), routed through a new AppModel.warningMessage channel + a dedicated ContentView .alert, after both the saved-.rnm and foreign-movie load paths. Wording + ES copy byte-identical to the Android v2.0.4 host_warning_pre_timebase_movie string.
  • UniFFI-Swift binding surface re-confirmed against the v2.0.0 bridge (host emit contains drainWarningCodes, HostWarning.preTimebaseMovie, moviePlay(bytes:) — the exact symbols the host code references).
  • Version realignment: workspace 2.0.4 → 2.0.5 (18-crate lock cascade); iOS MARKETING_VERSION 1.9.1 → 2.0.5 (realigned from the frozen v1.9.x default).

Verification (host gates — all green)

cargo fmt --check · clippy --workspace --all-targets -D warnings (no issues) · RUSTDOCFLAGS=-D warnings cargo doc · thumbv7em no_std cross-compile · both wasm32 clippy gates · markdownlint (pinned v0.39.0) · UniFFI-Swift emit surface check · Localizable.xcstrings JSON validity. Core untouched → the determinism / AccuracyCoin 141/141 contract is unaffected.

Docs

CHANGELOG [2.0.5] · docs/STATUS.md (v2.0.4 demoted) · to-dos/ROADMAP.md · .github/release-notes/v2.0.5.md · docs/ios.md (v1.9.x → v2.0.x status) · new docs/ios-v2.0.5-readiness.md.

On-device / maintainer carryover (v2.0.9 / TestFlight upload)

xcframework build on macOS + archive with Xcode 26 / iOS 26 SDK (the App Store submission floor, a hard gate at v2.0.7); on-device save-state migration from a v1.9.x install; the AccuracyCoin / SMB / Zelda determinism smoke on Apple silicon; the TestFlight boot smoke confirming the notice renders under EN + ES and that a post-v2.0.0 .rnm produces no warning.

TestFlight-only; the App Store + AltStore PAL launch stays deferred to the v2.1.0 joint milestone.

🤖 Generated with Claude Code

…ease, iOS re-port onto Timebase)

Open the iOS finalization window (v2.0.5 -> v2.0.8) of the v2.0.x "Harbor"
mobile-finalization train: the iOS/iPadOS analogue of the Android v2.0.1 -> v2.0.4
window, re-porting the frozen v1.9.9 SwiftUI/Metal app onto the v2.0.0 "Timebase"
core. This is a host / iOS-only cut: the cycle-accurate emulation core is
unchanged and byte-identical to v2.0.4 (AccuracyCoin 141/141, nestest 0-diff,
the deterministic #![no_std] chip stack untouched), so no accuracy / save-state /
determinism number moves.

Host-side re-port (what landed):

- Pre-Timebase movie warning, surfaced + localized on iOS. The v2.0.0 rewrite
  bumped the .rns/.rnm epoch (ADR 0028): a pre-v2.0.0 .rnm still replays its input
  on the new core, but byte-exact framebuffer/audio reproduction is no longer
  guaranteed. The v2.0.3 bridge queues a machine-readable HostWarning code for
  this; v2.0.5 surfaces it on iOS via EmulatorCore.drainWarnings() ->
  NesController.drainWarningCodes(), routed through a new non-blocking
  AppModel.warningMessage channel (distinct from the errorMessage alert so a
  warning never reads as a failure) and presented by a dedicated ContentView
  .alert. Drained after every successful moviePlay (both the saved-.rnm playMovie
  and the foreign-movie importForeignMovie paths). Localizable.xcstrings gains the
  EN source + ES translation, byte-identical to the Android v2.0.4
  host_warning_pre_timebase_movie resource (shared ES copy), so both platforms
  surface the same wording. Draining is idempotent (the queue empties on read), so
  each warning surfaces exactly once.

- UniFFI-Swift binding surface re-confirmed against the v2.0.0 bridge. A host
  build of rustynes-mobile + `uniffi-bindgen generate --language swift` emits
  exactly the surface the new host code references (drainWarningCodes() ->
  [HostWarning], HostWarning.preTimebaseMovie, moviePlay(bytes:)); the exhaustive
  switch over HostWarning is sound (the generated enum compiles into the app
  module). This is the iOS analogue of the wasm-bindgen-pin lib<->bindings
  lockstep discipline.

- Version realignment. Workspace 2.0.4 -> 2.0.5 (version-only Cargo.lock cascade,
  18 crates). iOS MARKETING_VERSION 1.9.1 -> 2.0.5 in ios/project.yml, realigned
  from the frozen v1.9.x checked-in default back to the workspace version; the
  build number stays CI-injected by the fastlane beta lane.

Verification (host gates all green): cargo fmt --check; clippy --workspace
--all-targets -D warnings (no issues); RUSTDOCFLAGS=-D warnings cargo doc; the
thumbv7em no_std cross-compile; both wasm32 clippy gates; markdownlint (pinned
v0.39.0) on the changed docs; the UniFFI-Swift emit surface check; Localizable
.xcstrings JSON validity.

Docs: CHANGELOG [2.0.5]; docs/STATUS.md current-release block (v2.0.4 demoted);
to-dos/ROADMAP.md; .github/release-notes/v2.0.5.md; docs/ios.md (v1.9.x -> v2.0.x
status + the Landfall re-port); new docs/ios-v2.0.5-readiness.md.

On-device / maintainer carryover (v2.0.9 / the TestFlight upload): the xcframework
build on macOS + archive with Xcode 26 / the iOS 26 SDK (the App Store submission
floor, a hard gate at v2.0.7); on-device save-state migration from a v1.9.x
install; the AccuracyCoin / SMB / Zelda determinism smoke on Apple silicon; the
TestFlight boot smoke confirming the pre-Timebase notice renders under EN + ES and
that a post-v2.0.0 .rnm produces no warning.

TestFlight-only; the App Store + AltStore PAL launch stays deferred to the v2.1.0
joint milestone.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 9, 2026 05:07
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

Gemini encountered an error creating the review. You can try again by commenting /gemini review.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR cuts v2.0.5 “Harbor” (“Landfall”) and begins the iOS finalization window by re-porting the iOS host app onto the v2.0.0 “Timebase” core, while keeping the emulation core byte-identical to v2.0.4. The main functional change is surfacing a non-blocking, localized (EN/ES) warning when playing a pre-v2.0.0 .rnm movie.

Changes:

  • Add an iOS host warning plumbing path: EmulatorCore.drainWarnings() → AppModel.warningMessage → ContentView alert.
  • Add the localized warning string to Localizable.xcstrings (ES translation included).
  • Bump versions/documentation for the v2.0.5 release (workspace version + iOS MARKETING_VERSION + release notes/status/roadmap).

Reviewed changes

Copilot reviewed 12 out of 13 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
to-dos/ROADMAP.md Updates “Current release” to v2.0.5 and describes iOS finalization scope.
ios/RustyNES/Localizable.xcstrings Adds EN source + ES translation for the pre-Timebase movie warning.
ios/RustyNES/EmulatorCore.swift Adds drainWarnings() and maps HostWarning → localized strings.
ios/RustyNES/ContentView.swift Adds UI presentation for warnings (new alert modifier).
ios/RustyNES/AppModel.swift Introduces warningMessage state and surfaces warnings after successful movie loads.
ios/project.yml Realigns iOS MARKETING_VERSION to 2.0.5.
docs/STATUS.md Updates current release header/details to v2.0.5.
docs/ios.md Updates iOS status narrative to reflect the v2.0.5 Timebase re-port.
docs/ios-v2.0.5-readiness.md Adds a new v2.0.5 readiness/verification record.
CHANGELOG.md Adds v2.0.5 changelog entry describing the iOS re-port and warning surfacing.
Cargo.toml Bumps workspace package version to 2.0.5.
Cargo.lock Version-only lockfile cascade to 2.0.5 across workspace crates.
.github/release-notes/v2.0.5.md Adds release notes for v2.0.5 “Landfall”.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ios/RustyNES/ContentView.swift Outdated
…Copilot review)

Adopt Copilot's review on PR #244: two chained `.alert` modifiers on one view
race in SwiftUI — only one presents and the loser is dropped — so a stale,
undismissed `errorMessage` from a prior operation could suppress the new v2.0.5
`warningMessage` (or vice versa), defeating the distinct-notice intent. (On the
movie-load success path the two are mutually exclusive, since `surfaceWarnings()`
runs only when `moviePlay` did not throw; the risk is a pre-existing error alert
still on screen when a later load queues a warning.)

Replace the two alerts with a single alert that multiplexes both channels:
present when either is non-nil, show the error text in preference to the warning,
and on dismissal clear ONLY the visible channel — so a still-queued warning
re-presents on the next render pass after the error is dismissed. Neither channel
is dropped, and a warning still never reads as a failure. `warningMessage` stays a
distinct `@Published` channel; only the presentation is unified.

Docs updated to match (STATUS current-release block, the v2.0.5 readiness record,
the release-notes override, and the ROADMAP bullet).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@doublegate
doublegate merged commit 2cd5312 into main Jul 9, 2026
23 checks passed
@doublegate
doublegate deleted the feat/v2.0.5-ios-landfall branch July 9, 2026 05:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants