Skip to content

Mobile and Cross Platform

DoubleGate edited this page Jun 29, 2026 · 1 revision

Mobile and Cross-Platform

RustyNES ports to mobile (Android and iOS) the same way it ports to the browser: the pure-Rust, byte-identical core is unchanged, and only a new host is written. Nothing touches the chip stack or the emitted-frame/sample contract, so AccuracyCoin 100% (139/139) holds on host CI.

Shared Mobile Architecture

  Android App (Kotlin)                   iOS App (SwiftUI)
           │                                      │
           │ drives the core via UniFFI           │ drives the core via UniFFI
           ▼                                      ▼
  rustynes-android (JNI)                  rustynes-ios (Metal/CoreAudio)
           │                                      │
           └──────────────────┬───────────────────┘
                              │
                    rustynes-mobile (shared)
                              │
                    rustynes-core (no_std)
  • crates/rustynes-mobile: The platform-agnostic bridge. Owns the typed control surface over rustynes_core::Nes and lets UniFFI generate the Kotlin (Android) and Swift (iOS) bindings from the #[uniffi::export] surface.
  • Determinism & data:
    • Input converges on the single late-latched Buttons mask per port, exactly as the desktop and wasm hosts do. Touch and hardware gamepad are indistinguishable to the core.
    • Save-states use the platform-independent .rns format, so a state saved on desktop loads on Android and iOS, preserving cross-play.
    • No commercial ROMs are ever bundled.

Android Host

The Android host (rustynes-android) uses a Jetpack Compose shell that drives the core through the generated NesController.

  • Glue: Carries only the narrow JNI/surface/audio glue UniFFI can't express (e.g., ANativeWindow → wgpu, AAudio sink).
  • Prerequisites: rustup target add aarch64-linux-android x86_64-linux-android, cargo-ndk.
  • Distribution: Currently distributed via GitHub-Releases sideload. Google Play launch is deferred to v2.1.0. Emulators are allowed on Google Play given no bundled ROMs.

iOS / iPadOS Host

The iOS / iPadOS application is a thin native SwiftUI shell over the byte-identical Rust core.

  • Glue: rustynes-ios adds only the hot glue UniFFI cannot express over a C ABI (Metal surface lifecycle, CoreAudio sink).
  • Metal Surface: The shim builds a surface from the UIView pointer (the SwiftUI MTKView) via a raw-window-handle 0.6 UiKit handle. wgpu-hal reads view.layer and drives Metal without needing an objc2 dependency.
  • Audio: AudioSink opens a cpal CoreAudio output stream fed by a lock-free SPSC ring. AVAudioSession is configured Swift-side.
  • Tools: Includes creator/power tools like Cheats, a read-only debugger inspector, a TAStudio piano-roll, foreign movie import, and a host audio-depth DSP.

WebAssembly Frontend

The web frontend builds via Trunk (trunk build --release).

The WASM frontend (crates/rustynes-frontend/web) runs the same core inside a browser canvas, providing a playable demo and lightweight embed capabilities.

Clone this wiki locally