Super Mario Odyssey running natively on Apple Silicon, with Metal graphics, touch controls, physical controller motion, and DualSense haptics and adaptive triggers. No JIT or jailbreak. Built on nxnative.
Provide your own base game, update 1.4.1, and console keys. The build tools prepare everything locally on your Mac. This repository contains the port's source and tools; it does not contain Nintendo assets.
I've been playing on an iPad Pro 13-inch (M5) and iPhone 17 Pro Max on iPadOS/iOS 27. Picture, sound, controls, motion and the main controller effects have been tested in gameplay. Installation
- A 4:3 iPad view with corrected camera projection, HUD, dialogue backgrounds and screen transitions. Mario and circular icons keep their proportions.
- A separate 239:110 iPhone view, matched to the tested iPhone 17 Pro Max.
- Live Duo layouts in the 4:3-prepared build: camera, HUD, safe areas and controls adapt together through landscape folding without restarting the game.
- Shake-to-throw Cappy, using a compatible physical controller's motion sensors.
- The game's original left/right vibration patterns, translated to controller haptics.
- PS5 DualSense support, with independent handle haptics and adaptive trigger feedback for supported game events.
- Optional up to 120 displayed FPS through frame interpolation on supported devices.
- Private iCloud save sync, under your own developer team's container.
Connect a controller in Settings → Bluetooth before opening the game.
Use the sticks to move and look, the face buttons to jump/throw Cappy, and L2/R2 to crouch or roll. Shake the controller for motion actions. Touch controls are available too; adaptive triggers require the appropriate controller.
Tap the top-center gear to open Settings. A drag, cancelled touch or second gear finger stays consumed without pressing a game control. VoiceOver also offers Open settings. The gear remains available with a controller. The full Odyssey touch layout always includes the D-pad and invisible floating right stick, alongside the fixed left stick and Nintendo face diamond.
The frame-rate counter sits in the safe-area top-left on iPhone and iPad. Tap it to hide its text; tap the same corner again to reveal it. Other gameplay touches stay active. The app remembers visibility, and generated presentation keeps the FG marker. The player confirmed hide/reveal working on the M5 iPad in the current build; the new phone package remains pending installation.
Settings has exactly three switches: Gyro, Device haptics, and Also with controller. Gyro On uses Auto, preferring fresh controller motion and falling back to iPhone/iPad sensors. Off disables motion. Existing calibration and controller feedback are preserved. The player reports iPhone device gyro working; other orientations, handoffs and iPad gyro need their own checks.
Device haptics On follows native rumble and guarded gameplay events through a separate finite phone sink. Also with controller controls only device vibration; it does not change controller vibration or adaptive triggers. Unsupported devices show Unavailable on this device and remain quiet. The tested iPad has no built-in actuator. Bullet Bill capture is a felt-positive native baseline. Build18's extra cues were physically rejected as too strong and buzzing. Build19 uses lower-strength, sharp one-shot haptic transients for confirmed in-game events; input edges never generate a cue. Strong native rumble takes priority, and held or duplicate events cannot renew a tap. Its physical feel is pending a new phone check. It covers guarded normal jumps/landings, long jumps/backflips, cap throws, standard coins and ground pounds. Special actor variants are not implied. Advanced stored preferences are retained without extra menu sections.
Existing stored frame-interpolation preferences are retained, and
DM_FRAMEGEN environment overrides keep precedence. The three-switch sheet
adds no display menu. No setting changes the game's 60 Hz simulation.
Choose --preset ipad or --preset duo for the 4:3 preparation with live
landscape adaptation from 1:1 through 16:9. Both produce a universal app with
the same guarded camera/HUD path; duo makes the intended target explicit.
Actual scene geometry and safe insets drive folding, rather than the phone/tablet
device name. The separate --preset iphone retains the 239:110 preparation
for the tested iPhone 17 Pro Max; use the Duo preset for a Duo.
The live path is enabled by default only after both exact-build camera and HUD
guards pass. Unsupported preparations or geometry keep proportional composition.
DM_ODYSSEY_DYNAMIC_DISPLAY=0 is a diagnostic opt-out. See
display transitions for source, frame ownership and
evidence limits. The observed Duo gameplay uses a labeled Mac-backed Simulator
preview; physical Duo execution and performance are untested.
The internal raster remains 1600 × 900. Full-screen aspect does not mean
native display-pixel rendering. On the tested ProMotion devices the FPS overlay
can show around 120 with FG; roughly half those frames are generated. This
doesn't double physics speed or mean the GPU renders 120 original game frames.
Interpolation can introduce visual artifacts and latency and falls back when
unsupported. Use --frame-generation off to turn it off, or --show-fps to see
the counter. See validation and limitations.
Progress lives in Documents/save, visible through the app's folder in Files
or Finder file sharing. Back it up before deleting or replacing the app.
Keep the same bundle ID and signing team when updating; deleting the app removes
its local container. The build/install tools don't delete an installed app or
launch it automatically. Save and fully close it before installing an update.
iCloud is off by default. Enable it only after following the iCloud setup guide, using the same container and environment on both devices. Saves upload in the background after completed game commits; there is no permanent sync button. Cloud imports happen before the game boots. Use one device at a time and close it before switching.
An iPad-to-iPhone handoff has been verified. Some later phone save captures failed intermittently; a tested interrupted-read fix and better diagnostics are included, but its live follow-up and reverse handoff remain unverified. Keep local backups and treat cloud sync as experimental.
The supported inputs are the base game (NSP or XCI) plus update 1.4.1 (v393216),
title ID 0100000000010000. The tools check exact module hashes/build IDs and
reject other versions. Input details and extracted-folder support
cover the same files used for the tested builds.
The player-facing entry point is tools/odyssey.py. It uses the shared runtime
in dm/, the exact-build profile in dm/games/0100000000010000/, and structural
HUD preparation in tools/prepare_odyssey_*.py. All extracted files, rewritten
game modules, shader caches, signing profiles and IPAs stay outside the checkout.
Run checks without any game files:
python3 tools/check.pyFor changes to binary observers, shaders or rendering, see AGENTS.md, CLAUDE.md and the runtime development guide. A source test passing is not proof of gameplay performance or how a physical controller feels.
Open an issue
with your device, OS version, port commit, game version, display preset and what
you were doing. The app's log.txt and diagnostics are in its Files folder.
Remove account/device details before posting; don't attach game files, keys,
saves or provisioning profiles.
- seedds/nxnative: native runtime, offline code rewriting, graphics translation, build tooling, and the original game profile.
- ly05010419/MacNativeGames: work used by nxnative; its license and notices are retained.
- fayaz12g/smo-aar: the aspect-ratio approach, reimplemented here with structural archive checks.
- Ryujinx and the other dependencies: shader translation, codecs, headers and utilities, under their respective licenses.
Port source is MIT; see LICENSE and source provenance. This is an unofficial fan project. Super Mario Odyssey and its game content belong to Nintendo. The game and its assets are not covered by this source license.
You don't need Codex, Claude, or another AI assistant. You need an Apple Silicon Mac, Xcode 27 or newer, an iPhone/iPad on iOS/iPadOS 26 or newer, your own game files and keys, and a developer account capable of signing with Increased Memory Limit. The tested signing path uses a paid Apple Developer team. Free-account sideloading and lower-memory devices haven't been validated. Allow about 40 GB free on the Mac for game files, caches and packaging and 12 GB on the device for installation headroom; actual requirements vary.
-
Prepare the Mac. Install and open Xcode, accept its license, and sign in under Xcode → Settings → Apple Accounts. Select that Xcode under Settings → Locations → Command Line Tools. Install Homebrew if you don't already have it, then run:
brew install python xcodegen spirv-cross zstd brew install --cask dotnet-sdk
The tools require .NET 10. If you install a newer SDK, also install the .NET 10 SDK so the pinned shader translator's .NET 10 runtime is available.
-
Download the source and prepare Python. Open Terminal and run:
git clone https://github.com/NicholasDominici/super-mario-odyssey-ios.git cd super-mario-odyssey-ios python3 -m venv .venv source .venv/bin/activate python -m pip install -r requirements.txt
-
Put your game files together. Create a folder outside the source repo, such as
~/Games/Odyssey. Put your base-game NSP or XCI and update 1.4.1 NSP there. Keep yourprod.keyselsewhere, such as~/Games/Keys/prod.keys. Only one game's files should be in the folder. Don't rename a different update to 1.4.1; its actual build will be checked. -
Build your private IPA. Replace the example paths below. Choose a bundle ID you control and keep it for future updates. For the tested 4:3 iPad:
python tools/odyssey.py \ --nsp-dir "$HOME/Games/Odyssey" \ --keys "$HOME/Games/Keys/prod.keys" \ --preset ipad \ --bundle-id com.yourname.odyssey \ --output "$HOME/Games/Odyssey-ipad-unsigned.ipa"
For the tested iPhone 17 Pro Max layout, change
--preset ipadto--preset iphone. For a Duo, use--preset duo. Use a different output filename for each preparation. The first build takes longer because it prepares shaders. The last line prints the IPA's path. That IPA contains your game files; keep it private. -
Connect and prepare the device. Connect it by USB, unlock it and tap Trust. Enable Settings → Privacy & Security → Developer Mode, then restart if prompted. Run
xcrun devicectl list devicesin Terminal and copy your device's identifier. Find your Team ID in your Apple Developer account's Membership details. Signing help covers common errors. -
Sign and install. Replace
YOUR_TEAM_ID,YOUR_DEVICE_IDand the IPA path:python tools/sign_install.py \ --ipa "$HOME/Games/Odyssey-ipad-unsigned.ipa" \ --team YOUR_TEAM_ID \ --device YOUR_DEVICE_ID \ --installXcode obtains a development profile for that device, the helper checks its memory entitlement, and then signs and installs the game. If Xcode reports a missing capability, follow the profile setup steps and rerun using
--profile. A signed IPA is also saved next to the unsigned one. Merely tapping an IPA in Files doesn't install it; development builds run only on devices allowed by their profile, and must be renewed when signing expires. -
Open Super Mario Odyssey and play. Pair your controller, choose Start or Continue, and test movement, sound and a few jumps. When updating later, make an in-game save, fully close the app, back up its
savefolder, and repeat steps 4–6 with the same bundle ID and signing team. Optional iCloud setup is in docs/ICLOUD.md.