README: English only; iPhone 15 Pro or newer; Hades being ported
- README.md: the Chinese half is removed, and so is its link at the top. - Requirement: an iPhone 15 Pro or newer (A17 Pro or later), or an M1 or later iPad, because the games' textures are BC-compressed. - Hades is listed as being ported, next to Super Mario Odyssey. - The third-party list names the Vulkan headers instead of bcdec. - The Super Mario 3D World magenta-squares known issue is gone: fixed and confirmed on an iPhone (feedback_snap). - AGENTS.md and docs/agents/README.md: everything, the README included, is in English. AGENTS.md also notes that Hades plays on the Mac through the Vulkan layer.
This commit is contained in:
1 parent
14fbcf9c37
commit
696d6a68dc
3 files changed
+6
-110
No files matched your search
@@ -1,12 +1,12 @@
|
||||
# Notes for agents
|
||||
|
||||
- This repository runs Nintendo Switch games natively on Apple platforms: the game's own code runs, rewritten only where Apple's kernel requires it. Seven games are playable on the iPhone: Super Mario Bros. Wonder (update 1.2.1, profile `010015100B514000`), Fire Emblem Engage (update 2.0.0, `0100A6301214E000`), Metroid Dread (update 2.1.0, `010093801237C000`), 13 Sentinels: Aegis Rim (update 1.10, `01003FC01670C000`), Super Mario 3D World + Bowser's Fury (update 1.2.2, `010028600EBDA000`), The Legend of Zelda: Breath of the Wild (update 1.9.0, SDK 20, `01007EF00011E000`) and The Legend of Zelda: Link's Awakening (update 1.1.0, SDK 8, `01006BB00C6F0000`). Super Mario Odyssey (update 1.4.1, SDK 7, `0100000000010000`) is being ported: it reaches its frame loop on the Mac. [README.md](README.md) is the player-facing page in English and Chinese (games, packing, playing); [docs/development.md](docs/development.md) has the internals, the script's options, building by hand, prewarm lists and per-game notes.
|
||||
- This repository runs Nintendo Switch games natively on Apple platforms: the game's own code runs, rewritten only where Apple's kernel requires it. Seven games are playable on the iPhone: Super Mario Bros. Wonder (update 1.2.1, profile `010015100B514000`), Fire Emblem Engage (update 2.0.0, `0100A6301214E000`), Metroid Dread (update 2.1.0, `010093801237C000`), 13 Sentinels: Aegis Rim (update 1.10, `01003FC01670C000`), Super Mario 3D World + Bowser's Fury (update 1.2.2, `010028600EBDA000`), The Legend of Zelda: Breath of the Wild (update 1.9.0, SDK 20, `01007EF00011E000`) and The Legend of Zelda: Link's Awakening (update 1.1.0, SDK 8, `01006BB00C6F0000`). Super Mario Odyssey (update 1.4.1, SDK 7, `0100000000010000`) is being ported: it reaches its frame loop on the Mac. Hades (update 1.0.38233, SDK 9, `0100535012974000`) is being ported too: it renders with Vulkan, which the host implements on Metal (`dm/gfx/vk/hle_vk.m`, profile key `graphics vulkan`), and plays on the Mac. [README.md](README.md) is the player-facing page (games, packing, playing); [docs/development.md](docs/development.md) has the internals, the script's options, building by hand, prewarm lists and per-game notes.
|
||||
- Each game's constants and shader tables form a game profile in `dm/games/<id>/`, where `<id>` is the base game's title ID: `game.tsv` plus the tables and `dmsh_chain.h`. Mario's profile is `010015100B514000`. Tools pick the profile with `DM_GAME`; `make -C dm/host` and `build_ipa.sh` pick it with `GAME`. There is no default game: set it every time (the tools stop and list the profiles otherwise). Put per-game values in the profile, not in code ([dm/games/README.md](dm/games/README.md)).
|
||||
- Per-build knowledge is keyed by the NSO build ID: rewriter cuts in `dm/tools/patch_nso.py`, the profile's `build` rows (the builds the NSP script accepts, and their display versions), and host behaviour that uses fixed module addresses checks `module_t.build_id` (from `fixups.tsv`; `dm_main_build()`, `DM_D2R_BUILD` for code inherited from D2R). When a new game build appears, carry addresses over with `dm/tools/nso_fnmap.py` and check them by disassembly; never let fixed addresses run on a build they were not found in.
|
||||
- To analyse or port **another** Switch title, first run `scripts/build_ipa_from_nsp.py` on its NSP folder. With no matching profile, it writes a survey to `<NSP folder>/<title ID>_survey/survey.md`, then a provisional profile guessed from it (`<NSP folder>/<title ID>_build/profile/<title ID>/`, found by the tools through `DM_GAMES_DIR`) and a best-effort IPA that may not boot. Then follow [docs/agents](docs/agents/README.md) (extraction, binary survey, host bring-up failure catalogue, graphics specifics, debugging recipes) and add a profile.
|
||||
- Scripts the user runs live in `scripts/` at the repository root (now `build_ipa_from_nsp.py`). Each one runs both in Spyder (F5, configured by the settings block at its top) and from a terminal (command-line options override those settings; non-zero exit on error). Tools that only agents or other scripts call stay under `dm/`.
|
||||
- Game files, keys and anything extracted from them live in the game's NSP folder, never in this repository and never in the home folder (it is nearly full): the work folder `<NSP folder>/<id>-work` for extraction, runs and analysis, beside the NSP script's `<id>_build/`. Tool venvs and other large scratch data go on that drive too. Do not print key values.
|
||||
- Language: `README.md` has the English text followed by the same text in Chinese (keep the two in step); everything else (docs, code comments, other files) is in English. Log messages stay as they are, and red log lines start with `【红】`. Exception until a shader-chain rebuild: the files the chain version hashes (`dm/gfx/tools/dmsh_chain.py`, `dmsh_build.py`, `dmsh_fetch.py`, `dmsh_facts.py`, `dmsh_xlate/Program.cs`, `dmsh_xlate.csproj`, `dm/ios/tools/ios_metal.py`) and the `dmsh_chain.h` headers they generate still have bilingual comments; editing them changes every game's chain version.
|
||||
- Language: everything is in English: `README.md`, docs, code comments and other files. Log messages stay as they are, and red log lines start with `【红】`. Exception until a shader-chain rebuild: the files the chain version hashes (`dm/gfx/tools/dmsh_chain.py`, `dmsh_build.py`, `dmsh_fetch.py`, `dmsh_facts.py`, `dmsh_xlate/Program.cs`, `dmsh_xlate.csproj`, `dm/ios/tools/ios_metal.py`) and the `dmsh_chain.h` headers they generate still have bilingual comments; editing them changes every game's chain version.
|
||||
- After changing anything on the shader translation chain, run the chain procedure for each affected profile. The chain covers `dm/gfx/tools/dmsh_*`, `Program.cs`, the profile's `shader_map.tsv` / `shader_facts.tsv` / `shader_pairs.tsv`, and its `nvn_*` / `shader_*` keys. The procedure:
|
||||
1. Run `dmsh_chain.py --header`, which writes the profile's `dmsh_chain.h`.
|
||||
2. Rebuild the shaders (Mac and, with `IOSOUT`, iOS).
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
# nxnative
|
||||
|
||||
[中文说明](#中文说明)
|
||||
|
||||
Play your own Nintendo Switch games natively on iPhone and iPad. Bring your game (its NSP files) and your `prod.keys`; one script turns them into an IPA that you sideload.
|
||||
|
||||
It is not an emulator: the game's own code runs directly on the Apple chip, with Switch graphics rebuilt on Metal. Nothing from any game is in this repository, and the project is not affiliated with Nintendo or any game publisher.
|
||||
@@ -17,7 +15,7 @@ This project is built on other people's work:
|
||||
- **[LibHac](https://github.com/Thealexbarney/LibHac)**: reads NSPs and layers updates over the base game in `dm/tools/nx_extract`. **hactool** did the first extractions.
|
||||
- **[SPIRV-Cross](https://github.com/KhronosGroup/SPIRV-Cross)**: SPIR-V to Metal Shading Language.
|
||||
- **deko3d** (zlib): its texture layout size algorithm is ported in `dm/gfx/nvn/nvn_tex.c`.
|
||||
- **libvpx** (VP9 movies), **stb_vorbis** (movie sound), **libdeflate**, **bcdec** and **NVIDIA FLIP** ship in `dm/third_party` with their licenses ([list](dm/third_party/README.md)).
|
||||
- **libvpx** (VP9 movies), **stb_vorbis** (movie sound), **libdeflate**, the **Vulkan headers** and **NVIDIA FLIP** ship in `dm/third_party` with their licenses ([list](dm/third_party/README.md)).
|
||||
- **Capstone**, **lz4**, **fontTools** and **XcodeGen** are used by the build.
|
||||
|
||||
## Games
|
||||
@@ -34,7 +32,7 @@ All of these are tested on an iPhone and playable:
|
||||
| The Legend of Zelda: Breath of the Wild | base game + update 1.9.0 (+ DLC) | ~16 GB | Upgraded to 60 fps (30 fps on Switch) |
|
||||
| The Legend of Zelda: Link's Awakening | base game + update 1.1.0 | ~6 GB | |
|
||||
|
||||
Being ported, not playable yet: Super Mario Odyssey (base game + update 1.4.1).
|
||||
Being ported, not playable yet: Super Mario Odyssey (base game + update 1.4.1) and Hades (base game + update 1.0.38233).
|
||||
|
||||
| | |
|
||||
|:---:|:---:|
|
||||
@@ -43,7 +41,7 @@ Being ported, not playable yet: Super Mario Odyssey (base game + update 1.4.1).
|
||||
| <br>Super Mario 3D World + Bowser's Fury | <br>The Legend of Zelda: Breath of the Wild |
|
||||
| <br>The Legend of Zelda: Link's Awakening | |
|
||||
|
||||
Needs iOS / iPadOS 26 or later. Other games aren't supported yet. For them the script writes a survey and still tries its best to pack an IPA, guessing the game's settings; such an IPA may not start.
|
||||
Needs iOS / iPadOS 26 or later on an iPhone 15 Pro or newer (A17 Pro chip or later) or an iPad with an M1 chip or later: the games' textures are BC-compressed, and older iPhones can't read that format. Other games aren't supported yet. For them the script writes a survey and still tries its best to pack an IPA, guessing the game's settings; such an IPA may not start.
|
||||
|
||||
## Pack an IPA
|
||||
|
||||
@@ -89,7 +87,6 @@ A connected game controller hides the touch controls and keeps every button.
|
||||
|
||||
- No amiibo and no online features.
|
||||
- Fire Emblem Engage: after switching away from the app and back, some sounds may stay silent until you restart it.
|
||||
- Super Mario 3D World: a few small magenta squares can appear near the birds in World 1-1.
|
||||
|
||||
## For developers
|
||||
|
||||
@@ -98,104 +95,3 @@ How it works, the script's options, running games on the Mac, adding a game, and
|
||||
## License
|
||||
|
||||
MIT (see [LICENSE](LICENSE)). Third-party code keeps its own license; see [dm/third_party](dm/third_party/README.md).
|
||||
|
||||
---
|
||||
|
||||
# 中文说明
|
||||
|
||||
在 iPhone 和 iPad 上原生运行你自己的 Nintendo Switch 游戏。准备好游戏(NSP 文件)和你的 `prod.keys`,一个脚本就能把它们打包成 IPA,再侧载安装。
|
||||
|
||||
这不是模拟器:游戏自己的代码直接跑在苹果芯片上,Switch 的图形在 Metal 上重建。本仓库不含任何游戏内容,项目与任天堂及各游戏发行商无关。
|
||||
|
||||
## 致谢
|
||||
|
||||
本项目建立在他人的工作之上:
|
||||
|
||||
- **[d2r-mobile](https://github.com/jhaizhou-ops/d2r-mobile)**(MIT)为《暗黑破坏神 II:狱火重生》开发了这套原生运行方法。nxnative(最初叫 smbw-mobile)从它的通用部分起步:NSO 改写器、代替 Horizon 的宿主、Metal 上的 NVN 层和 iOS 应用外壳。修正双向共享。
|
||||
- **Ryujinx**(MIT):它的着色器翻译器(`Ryujinx.Graphics.Shader`、`Ryujinx.Common` 和 `Spv.Generator` 1.3.2,原样放在 `dm/third_party/ryujinx`)把游戏的 Maxwell 着色器转成 SPIR-V。宿主行为拿不准时,它对内核和系统服务的模拟也是参考。
|
||||
- **[Atmosphère](https://github.com/Atmosphere-NX/Atmosphere)**:它的内核 mesosphère 是 Horizon 同步语义(地址仲裁器、条件变量)的参考。
|
||||
- **yuzu**:着色器参考工具用到的 Maxwell 指令编码,以及内核行为的交叉核对。
|
||||
- **[LibHac](https://github.com/Thealexbarney/LibHac)**:在 `dm/tools/nx_extract` 里读取 NSP、把更新叠到本体上。最早的解包用的是 **hactool**。
|
||||
- **[SPIRV-Cross](https://github.com/KhronosGroup/SPIRV-Cross)**:SPIR-V 转 Metal 着色语言。
|
||||
- **deko3d**(zlib):`dm/gfx/nvn/nvn_tex.c` 移植了它的贴图布局尺寸算法。
|
||||
- **libvpx**(VP9 影片)、**stb_vorbis**(影片声音)、**libdeflate**、**bcdec** 和 **NVIDIA FLIP** 连同许可证放在 `dm/third_party`([清单](dm/third_party/README.md))。
|
||||
- 构建时用到 **Capstone**、**lz4**、**fontTools** 和 **XcodeGen**。
|
||||
|
||||
## 游戏
|
||||
|
||||
以下游戏都已在 iPhone 上测试,可以正常游玩:
|
||||
|
||||
| 游戏 | 文件夹里放的 NSP | IPA 大小 | 备注 |
|
||||
|---|---|---|---|
|
||||
| 超级马力欧兄弟 惊奇 | 本体 + 1.2.1 更新 | 约 4 GB | |
|
||||
| 火焰纹章 Engage | 本体 + 2.0.0 更新(+ 扩展通行证 DLC) | 约 15 GB | 升级到 60 fps(Switch 上 30 fps) |
|
||||
| 密特罗德 生存恐惧 | 本体 + 2.1.0 更新 | 约 5 GB | |
|
||||
| 十三机兵防卫圈 | 本体 + 1.10 更新 | 约 5 GB | |
|
||||
| 超级马力欧 3D 世界 + 狂怒世界 | 本体 + 1.2.2 更新 | 约 3 GB | |
|
||||
| 塞尔达传说 旷野之息 | 本体 + 1.9.0 更新(+ DLC) | 约 16 GB | 升级到 60 fps(Switch 上 30 fps) |
|
||||
| 塞尔达传说 织梦岛 | 本体 + 1.1.0 更新 | 约 6 GB | |
|
||||
|
||||
正在移植、还不能玩:超级马力欧 奥德赛(本体 + 1.4.1 更新)。
|
||||
|
||||
| | |
|
||||
|:---:|:---:|
|
||||
| <br>超级马力欧兄弟 惊奇 | <br>火焰纹章 Engage |
|
||||
| <br>密特罗德 生存恐惧 | <br>十三机兵防卫圈 |
|
||||
| <br>超级马力欧 3D 世界 + 狂怒世界 | <br>塞尔达传说 旷野之息 |
|
||||
| <br>塞尔达传说 织梦岛 | |
|
||||
|
||||
需要 iOS / iPadOS 26 或更高版本。其他游戏暂不支持。脚本会为它们写一份分析报告,并猜测游戏的设置,尽力打出一个 IPA;这样的 IPA 可能启动不了。
|
||||
|
||||
## 打包 IPA
|
||||
|
||||
**1. 获取 nxnative 和所需工具**(只需一次,在装有 [Xcode](https://apps.apple.com/app/xcode/id497799835) 和 [Homebrew](https://brew.sh) 的 Mac 上):
|
||||
|
||||
```
|
||||
git clone https://github.com/seedds/nxnative.git && cd nxnative
|
||||
brew install xcodegen zstd spirv-cross
|
||||
brew install --cask dotnet-sdk
|
||||
python3 -m pip install lz4 capstone fonttools
|
||||
```
|
||||
|
||||
**2. 把一个游戏的 NSP 放进一个文件夹**,本体和更新(有 DLC 也放进去):
|
||||
|
||||
```
|
||||
~/Games/MarioWonder/
|
||||
Super Mario Bros. Wonder [010015100B514000][v0].nsp
|
||||
Super Mario Bros. Wonder [010015100B514800][v327680].nsp
|
||||
```
|
||||
|
||||
**3. 运行脚本:**
|
||||
|
||||
```
|
||||
python3 scripts/build_ipa_from_nsp.py ~/Games/MarioWonder -k ~/keys/prod.keys
|
||||
```
|
||||
|
||||
IPA 会出现在同一个文件夹里(这里是 `~/Games/MarioWonder/SMBWMobile.ipa`)。第一次打包要 30–60 分钟,之后约 10 分钟。需要的空闲磁盘空间约为 NSP 大小的两倍再加 10 GB。`-o`(输出路径)、`--app-name` 等选项用 `-h` 查看。
|
||||
|
||||
**4. 安装**:用你的侧载工具(AltStore、Sideloadly、LiveContainer 等)安装 IPA。App 会带上游戏的名字、图标和版本号(用更新的版本号,例如马力欧惊奇是 1.2.1;没有更新时用本体的)。
|
||||
|
||||
## 游玩
|
||||
|
||||
**触屏按键。** 点顶部的 **2D** / **3D** 切换布局,App 会记住你的选择。3D 世界和旷野之息默认 3D 布局,其他游戏默认 2D。
|
||||
连上游戏手柄后,触屏按键会隐藏,手柄上的所有按键都能用。
|
||||
|
||||
- **游戏语言**默认英文。想用中文,在 `Documents/env.txt` 里加一行 `DM_LANG=zh-Hans`。
|
||||
- **存档和日志**在「文件」App 里,App 名字对应的文件夹下:`save/` 和 `log.txt`。出问题时请发 `log.txt`(上一次运行的是 `log.prev.txt`)。
|
||||
- **第一次进新场景时短暂卡顿**是正常的:App 会为它编译一次图形,下次启动就记住了。
|
||||
- **重装:** 有些侧载工具重装后会给 App 一个新的数据文件夹。把旧文件夹里的 `save/` 和 `pso_user.tsv` 拷过去,进度就不会丢。
|
||||
- **不重新打包也能改设置:** 在 `Documents/env.txt` 里写一行一个设置,例如 `DM_OPMODE=0`(掌机模式:分辨率更低、帧率更高)。
|
||||
|
||||
## 已知问题
|
||||
|
||||
- 没有 amiibo,也没有联网功能。
|
||||
- 火焰纹章 Engage:切到别的 App 再回来后,部分声音可能一直没有,要重开游戏。
|
||||
- 超级马力欧 3D 世界:1-1 里可能出现几个小的品红色方块。
|
||||
|
||||
## 开发者
|
||||
|
||||
工作原理、脚本的全部选项、在 Mac 上运行游戏、添加新游戏、各游戏的技术笔记:[docs/development.md](docs/development.md)。更深入的移植和调试笔记:[docs/agents](docs/agents/README.md)。
|
||||
|
||||
## 许可证
|
||||
|
||||
MIT(见 [LICENSE](LICENSE))。第三方代码保留各自的许可证,见 [dm/third_party](dm/third_party/README.md)。
|
||||
@@ -17,7 +17,7 @@ Everything here was learned on Diablo II: Resurrected (SDK ~12, NVN 53, the orig
|
||||
- **Bring your own files.** Keys, NSPs and anything extracted from them stay in the game's work folder (`$W` = `<NSP folder>/<title>-work`, next to the NSPs on the user's external drive; the home folder is nearly full), never in the repository, never in a commit, never printed. Print key *names* and lengths only.
|
||||
- **Measure, then change.** Each fix in this repository started from a concrete observation (a crash address and its decompilation, a census over all shaders, a memory profile). Write the evidence into the code comment next to the fix, the way the existing code does; the next title will need it.
|
||||
- **One repository, one profile per title.** nxnative (first called smbw-mobile) started as a copy of d2r-mobile's generic parts. Title- or SDK-specific constants live in the game profile `dm/games/<id>/` ([dm/games/README.md](../../dm/games/README.md)). That covers program ID, known builds, modules, address-space partition, NVN driver tables, the shader tables and the app identity. The code reads the profile through `game_profile.h` (host) or `dm/games/game.py` (tools). Behaviour that fits only one title's code is gated by that title's build ID (`dm_main_build()`), never left on for every title. Some things are still built into the translator: the texture / sampler handle bases and the depth mode (see [04](04-graphics.md)). `dmsh_build.py` refuses a profile whose bases differ from the translator's.
|
||||
- **Write code comments in English**, and keep the `【红】` prefix for red log lines that mark something unimplemented or wrong. The README's Chinese half is the only Chinese text.
|
||||
- **Write code comments in English**, and keep the `【红】` prefix for red log lines that mark something unimplemented or wrong.
|
||||
- **Test where it runs.** The Mac host (`dm/host/dmhost`) is the development loop; the iOS app reuses the same host and graphics code. Never claim something works on iOS without running it there.
|
||||
|
||||
## Checklist for a new title
|
||||
|
||||
Reference in new issue
Block a user