统一内存是隐藏红利。Switch 和 Apple silicon 都是 UMA 架构,纹理和缓冲区理论上可以零拷贝共享,这比在 x86 独显机器上做模拟省掉一整条 PCIe 往返。
graph TD
A[自有游戏转储(NSP/NCA)] --> B[容器解析与解密]
B --> C[提取 ExeFS 可执行段]
B --> D[挂载 RomFS 资源]
C --> E[ARM64 映像重定位与加载]
E --> F{"SVC 调用分发"}
F -->|"图形 NVN"| G[命令缓冲重编码]
F -->|"音频 Audren"| H[音频服务桥接]
F -->|"输入 HID"| I[手柄与体感桥接]
F -->|"内核语义"| J[线程与同步原语]
G --> K[SPIR-V 转 MSL 与 Metal 管线]
H --> L[CoreAudio 输出]
I --> M[GameController 输入]
K --> N[帧同步与图层呈现]
L --> N
M --> N
J --> N
D --> J
Play your own Tears of the Kingdom and Breath of the Wild natively on Apple silicon Mac, iPhone and iPad. Not an emulator: the game's ARM64 code runs directly, NVN rebuilt on Metal. Bring your own game.
A technical exploration: can a Nintendo Switch game's NVN graphics be ported to Metal?
Tested with your own copies of Tears of the Kingdom and Breath of the Wild on Mac, iPhone and iPad, and of Ocarina of Time (Switch 2) on the Mac. Not an emulator: the game's own ARM64 code runs directly on Apple chips.
You must own the game. Use this project only with games that you bought, and with keys and system files dumped from your own Nintendo Switch. This is an independent, non-commercial project. It is not affiliated with, endorsed by, or sponsored by Nintendo. The Legend of Zelda and Nintendo Switch are trademarks of Nintendo.
The repository contains no game content and distributes none: no game program, art, text, audio, shaders or keys. Everything the game needs is made on your own computer from your own files when you build the app. The app you build contains the game, so it is for your own use only; do not share it. What the repository does hold is the information needed to make the port work: the patch code, the addresses and hashes used to check your files, and the shared shader list, which names shaders and bind states but contains no shader code.
Apple, Mac, iPhone, iPad, Apple Vision Pro and Metal are trademarks of Apple Inc.; this project is not affiliated with Apple. Other game titles and trademarks named here belong to their respective owners.
Whether dumping games, keys and system files is legal depends on where you live; check and follow your local laws.
Issues and pull requests that contain or ask for game files, keys or firmware will be deleted.
About
This project is a technical exploration, mainly feasibility experiments and analysis. The Nintendo Switch is an ARM system (an ARM64 CPU in NVIDIA’s Tegra X1), and Apple chips are ARM64 as well, so we want to test whether its games can, technically, be ported to Apple chips. It started from one question: can the NVN graphics a Switch game was written for be rebuilt faithfully on Apple’s Metal, and can the game’s own ARM64 code run directly on Apple chips without an emulator? Tears of the Kingdom and Breath of the Wild are the test cases, because they push the graphics API hard. The repository records the experiments, measurements and findings along the way; it is a study of the technique, not a game distribution. It does not encourage piracy: use only your own game data, dumped from a game you bought and from your own Switch, never game files, keys or firmware downloaded from the internet or obtained from anyone else.
How it works: bring your game file (XCI or NSP) and your prod.keys; one script builds a Mac app or an unsigned iPhone/iPad IPA. The game’s own ARM64 code runs directly on Apple chips (rewritten where the operating system requires it), the Switch system services are answered by a small host, and the game’s NVN graphics are rebuilt on Metal. The iOS build requires iOS/iPadOS 26 and iPhone 14 or newer; Tears of the Kingdom 1.4.3 has been played on an iPhone 14 and an iPad, Breath of the Wild 1.6.0 on an iPhone 14 (on the iPad it reaches the title), see iPhone and iPad. Details are in How it works.
Switch 2 games (experimental)
Switch 2 games run on the same Tears of the Kingdom runtime: their Ampere (NVN2) shaders go through the same translator,
and their SDK 20 services through the same host (docs/ns2-port.md). Ocarina of Time carries its own copy of
that runtime in games/oot.
Game
Version
Platform
Status
The Legend of Zelda: Ocarina of Time
update 131072
Mac
Playable from the title into Kokiri Forest and the village on an M4, not played through; resolution, MetalFX upscaling, frame lock and frame interpolation in the settings panel; games/oot, install
Donkey Kong Bananza
update 458752
Mac
Playable, early; not fully tested
Pokémon Pokopia
2.0.1
Mac
Early: plays its opening into the first area (scripted test, not fully played).
Community ports keep their own runtime, graphics layer and scripts in their folder and are built with the steps there.
VR: Tears of the Kingdom and Breath of the Wild on a Meta Quest 3 (6DoF)
Play Tears of the Kingdom 1.4.3 in a Meta Quest 3, with full 6DoF. The game runs on your Mac and draws the view
for every head pose, streamed to the headset over the USB-C cable: turn your head and the camera turns; lean and crouch
and it moves (Head position, 6DoF). First or third person, the game’s sound in the headset. Quest 3 controllers and
motion gestures are built in but not yet tested on a headset.
Tears of the Kingdom 1.4.3: the game renders one picture per frame, wide enough for both eyes, and each eye looks
it up along its own rays; turning the head reprojects it to the newest pose. The picture is what the game draws
without VR (grass, lighting, shadows). The stream to the headset is HEVC at the render size per eye chosen in the VR page
(at most 2048×2208); on an M4 at 1536×1656 a Quest 3 showed about 70 fps and about 70 ms from input to display
(measured 2026-11-10; 2048×2208 H.264, the setting before, gave 53 fps and 132 ms). Both eyes see the same picture, so there is
no stereo depth by default.
Stereo depth for Tears of the Kingdom (experimental, off by default): the game still runs each frame once; the
graphics layer replays the frame once per eye with the eye moved sideways by half the eye distance, so both eyes are
real renderings of the same moment. It costs about half the frame rate (about 30 fps against 53 with one picture, at
2048×2208 on an M4) and has no switch in the VR page yet. The game has no stereo renderer of its own, and an earlier attempt
that ran the game’s render jobs twice was removed because it damaged the picture (no grass, wrong lighting).
Breath of the Wild 1.6.0 / 1.9.0: the game’s own same-frame stereo renderer (the one of its Labo VR mode) draws
both eyes with the headset’s projection and eye distance; see the install page for its settings and limits.
One script builds and installs it, the headset side included: zeldaVR/install.md (code in
zeldaVR). VR stays off in the normal app.
Windows games
windows_games holds Windows PC games, one folder each. They are statically recompiled into arm64,
and their runtime draws with Metal. As with the Switch games, you bring your own copy and nothing from the game is in the
repository.
Game
Version
Platform
Status
Folder
Command & Conquer: Red Alert 2 and Yuri’s Revenge
1.006 and 1.001 (Steam release)
Mac, iPhone, iPad
Community port; a skirmish match plays on the Mac and iPhone 14, saves work on the Mac; English, 繁體中文, 简体中文
Hand it to an AI assistant. Open this repository in Claude Code, Codex, or any other AI assistant you like, tell it where your own game file and prod.keys are, and ask it to build and install the app and to sort out whatever comes up on your Mac. It follows the install skill, runs every step and checks the result; you just wait with a coffee. Installing and testing by hand is not recommended: there are many steps, and every Mac, game version and dump is a little different. That’s why I haven’t provided a one-click build option: an AI assistant is my one-click build option. For Red Alert 2 it needs only your own Steam install (no prod.keys) and follows its own skill.
Install skill
The install skill (.claude/skills/install-zelda/SKILL.md) is a short guide written for the assistant: which of your files goes where, the command for your case, how long each step takes (a build is 20–40 minutes; it must not be stopped), and the fix for each common error. Claude Code finds it by itself (or type /install-zelda). With any other assistant, start with: “Read .claude/skills/install-zelda/SKILL.md and follow it to install Tears of the Kingdom for me.”
Red Alert 2 has its own: .claude/skills/install-ra2/SKILL.md (/install-ra2), for the Mac and iPhone / iPad builds, the movies made smaller for the phone and the Chinese languages. “Read .claude/skills/install-ra2/SKILL.md and follow it to install Red Alert 2 for me.”
Let’s maintain the shader list together: no more stutter
Tip 提示
Every shader in the shared list is ready before you play. On a Mac the game does not stop to compile it, and on an iPhone or iPad nothing is missing from the picture. The more places players cover, the smoother the game gets for everyone.
The shared shader list now holds 17,335 shader variants (14,220 shaders) from the Mac, iPhone and iPad: only states a build does not make by itself, since every build makes each shader’s default variant. Every build makes them from the player’s own game files, so the list holds identifiers only, never game data. Helping takes no setup:
Play. Every build carries each shader of the game for its default bind state. When your game meets a shader in a state that variant does not serve, or builds a render pipeline the app’s list lacks, it notes it in shader-list-contribution.txt; default variants are never noted.
On a Mac, every 100 new rows (shaders and pipelines together) it asks you once, before the game starts. Click “Send”: the GitHub form opens and the file is shown, ready to drag in. If the GitHub CLI (gh) is installed and signed in, the dialog offers “Submit automatically” instead, which sends this batch for you (a private gist and an issue) without opening the browser. An iPhone or iPad never asks during play: while it is connected to the Mac that built its app (cable or the same Wi-Fi), the Mac asks instead. “Don’t remind me again” stops the reminders.
Everyone’s next build carries them. Nobody stutters there again.
Stuttering when you first start playing or enter a new scene is expected while new shaders compile—don’t be surprised. Performance typically improves as the cache warms up, and every shader the shared list gains is one nobody stutters on again.
What’s new
2026-11-11: Rankings, an anonymous frame-rate board (Tears of the Kingdom, Breath of the Wild, Ocarina of Time, Mac).
A settings tab of its own (key 1) shows the latest board, one group per frame lock and interpolation setting. Join the
board is off by default and never asked; once on, the session is kept on your Mac every 5 minutes and sent at start and
every 30 minutes; your own row is green and everyone shows as an anonymous name (controls).
Shader contributions are now sent at start and every 30 minutes as well.
2026-11-10: The Legend of Zelda: Ocarina of Time (Switch 2) on the Mac. Build it from your own dump (a .nup file or a
dump folder with update 131072) with build_app.py; no keys needed. On an M4 it plays from the title into Kokiri Forest and the
village, about 81–83 fps standing in the village at 720p or 1080p (from 720p); 720p is the default. The settings panel (key 1) has the resolution,
the upscaler (MetalFX or the game’s own), a frame lock and MetalFX frame interpolation (games/oot,
install).
2026-11-09: experimental Xenoblade Chronicles X 2.0.0 Mac diagnostic. Separate integrity pins, cumulative update merge and version-aware packaging; original 30 FPS by default, opt-in checked 60/120 timing experiment awaiting broader acceptance (details).
2026-11-08: The Legend of Zelda: Link’s Awakening 1.1.0 on Mac, experimental. Built from your own files; played by hand around Mabe Village (games/la).
2026-11-07: Hyrule Warriors: Age of Calamity builds from update 1.4.1 as well as 1.3.0 on Mac, experimental. The builder takes the version from the extracted game folder (games/aoc).
2026-11-03: optional SMAA and FXAA Quality for Tears of the Kingdom 1.4.3 on Mac. Choose the method and its quality separately on the Effects page; the game’s original FXAA remains the default (controls).
2026-11-03: the first Switch 2 games, experimental. Donkey Kong Bananza plays on the Mac from a development build;
Pokémon Pokopia plays its opening into the first area (scripted test). Pokopia 2.0.1 packages as a Mac app from your
own dump folder: python3 build_app.py <dump folder> --shared-fonts <the six .bfttf files a TOTK / BotW build extracted> (no keys; Switch 2 games, docs/ns2-port.md).
2026-11-02: Tears of the Kingdom 1.1.2 is no longer supported. The supported versions are 1.0.0, 1.2.1 and 1.4.3
(1.4.3 is the most tested). The builder now refuses a 1.1.2 update: build again with the 1.2.1 or 1.4.3 update and
the same -o (another game version). Your saves stay where they are (TOTK/profile); before the
first start on the new version the app backs them up next to them, 1.2.1 reads 1.1.2 saves as they are and 1.4.3
migrates them. Mods in mods/v112 are not loaded any more: put the mods for the version you build in its own
folder (mods.md).
Install and play
Everything from building the app to playing is in docs/install.md. The recommended way is to hand it to an AI assistant with the install skill (see the top of this page) rather than run the steps yourself:
Measuring by game state with the Metal performance tools of macOS 27 (TOTK_STATE_REPORTING=1, metal_perf_report.py): Metal performance diagnostics.
Acknowledgements
d2r-mobile (MIT) developed this way of running Switch games natively (for Diablo II: Resurrected): the NSO rewriter, the Horizon host and the NVN-on-Metal layer here started as its generic parts.
nxnative (MIT): the NSP common-ticket import follows its approach; the Switch 2 support also follows it and carries code of it (Ampere shaders, geometry shaders, SDK 20 services, one texture / sampler ID space per descriptor pool, the non-indexed indirect draw and the copy image stride).
ouncenative (MIT): Pokémon Pokopia’s shader layout — its GLSLC reader showed where the control section and the code area of each shader sit, which took our shader extraction from 2,385 to all 131,090 of Pokopia’s shaders.
pokopia-native (MIT): reference for Pokémon Pokopia (its run-time shaders, the dump layout, the driver-rewritten control bytes).
Ryujinx (MIT): the shader translator (vendor/ryujinx, built ahead into games/totk/prebuilt/macos-arm64/totk_xlate) and a reference for the system services; the sound effects and the mixer in games/totk/runtime are ported from Ryujinx.Audio.
SPIRV-Cross (Apache-2.0) turns SPIR-V into Metal Shading Language; it is fetched at a pinned commit and compiled with clang during the build.
hactool (ISC, with its bundled mbedTLS, Apache-2.0): merges the base game and its update at build time; fetched at a pinned commit.
deko3d (zlib): texture layout sizes. bcdec (MIT or public domain): BC texture decoding. libopus and libvpx (BSD) from Homebrew: audio and the pre-rendered movies.
x86recomp (MIT) is the recompiler and Win32 runtime of the Windows games (windows_games/ra2/third_party/x86recomp, with our changes); it builds on Berkeley SoftFloat 3 (BSD-3-Clause) and CORE-MATH (MIT), and on iOS on SDL3 (zlib), glslang, SPIRV-Cross and a decoders-only ffmpeg (LGPL). Its Simplified Chinese is converted with OpenCC (Apache-2.0), the added glyphs drawn from Noto Sans CJK (Source Han Sans, SIL OFL 1.1).
BasaltVR (MIT) streams the VR picture: zeldaVR/install_vr.sh fetches it at a pinned commit and applies our changes (zeldaVR/streamer/basaltvr.patch). On the headset, the ALVR client (MIT) shows it; it is downloaded from ALVR’s releases and checked by its SHA-256. BotW-BetterVR (MIT), UEVR and R.E.A.L. were references for the camera, first person and motion controls; no code is copied.
Ocarina of Time (games/oot; every source is listed in its COPIES.md): the NUP reader is nup (MIT); the AV1 movie decoder is adapted from nxnative, and the mesh and task shader stages, the HMMA matrix lowering and the typed pool arrays from ChiefSZ13/nxnative (MIT); dav1d (BSD-2-Clause) is bundled as the AV1 fallback; zbic (GPLv2) is run as a separate build tool, never copied or shipped. NVIDIA’s CUDA Binary Utilities and PTX documents and Mesa’s NAK were references for Ampere instruction semantics, and Lichii (GPL-3.0) for field meanings only; no code from it is copied.
Community ports that carry code from elsewhere list it in their own folder (third_party/COPIES.md). The main project’s and the Windows games’ copied code, with each license, is in THIRD_PARTY_NOTICES.md.
评论