从源码构建¶
需要 Windows 10 或更高版本、支持 AVX2 的 x86-64 CPU,以及支持 Vulkan 1.3 和 VK_EXT_external_memory_host 的 GPU。请为工作文件夹预留约 60 GB 空间。解包运行时需要约 55 GB 可用空间,完成后占用约 35 GB。
只想游玩的玩家可以直接使用安装程序代替:它会在玩家自己的机器上构建游戏,而无需这套工具链。
工具链¶
版本为构建验证所用版本;较新的补丁版本也可以。
| 工具 | 版本 | 安装方式 | 用途 |
|---|---|---|---|
| MSYS2 UCRT64 | clang/lld 23.1.3 | msys2.org 安装程序,安装到 C:\msys64,使用下方软件包 |
编译生成的 C 代码及运行时 |
| Visual Studio Build Tools | 2026、C++ 工作负载、Windows SDK 10.0.26100 | 使用 winget Microsoft.VisualStudio.BuildTools,并传入 --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended |
.NET NativeAOT 调用的链接器 |
| .NET SDK | 10.0 | winget Microsoft.DotNet.SDK.10 |
着色器翻译器(totk_xlate.exe) |
| Vulkan SDK | 1.4.363 | winget KhronosGroup.VulkanSDK |
验证层、vulkaninfo |
| uv | 0.13 | 来自 astral.sh 的独立安装程序 | 两个 Python 环境 |
| hactool | 1.4.0 @ 1d64a83 |
.venv\Scripts\python tools\build_hactool.py,见下文 |
NCA 与更新解包 |
MSYS2 软件包:先运行 pacman -Syuu(需运行两次;第一遍更新核心并退出):
pacman -S --needed --noconfirm mingw-w64-ucrt-x86_64-{clang,lld,ninja,gcc,make,pkgconf,sdl3,opus,libvpx,zstd,vulkan-devel,\
vulkan-memory-allocator,vulkan-validation-layers,shaderc,spirv-tools} base-devel git unzip
MSYS2 提供的 ffmpeg 是 GPLv3 构建,且从不参与链接;过场视频通过 libvpx 处理。
PATH:
- 将
C:\Program Files (x86)\Microsoft Visual Studio\Installer添加到用户 PATH:NativeAOT 需要vswhere.exe,否则发布会在链接步骤失败(MSB3073)。 - PATH 中靠前的另一个
cmake或ninja(例如 32 位 winlibs MinGW)会被意外选中。构建脚本自行从C:\msys64\ucrt64\bin调用 Ninja;在 shell 中,请把C:\msys64\ucrt64\bin放在最前面。
hactool¶
tools/build_hactool.py 会将 1d64a83 版本的 SciresM/hactool 拉取到 toolchain\src\hactool,应用 tools/hactool/ 中的两个补丁,并使用 MSYS2 UCRT64 gcc 构建静态的 toolchain\hactool\hactool.exe(只需几秒):
portable.patch:包含 MacNativeGames 的build_hactool()中可在 Windows 上运行的部分、MNG_TITLE_KEYS变量,以及nca.c中针对子节表填充和较新累积更新的子节布局的两处 BKTR 修复;unicode.patch:添加包含<activeCodePage>UTF-8</activeCodePage>的清单,使非 ASCII 用户配置文件下的路径能够原样传递到程序。
hactool 通过 -k <prod.keys> 读取密钥;MSYS2 shell 会设置 HOME,从而隐藏其默认密钥位置,因此在这些 shell 中需要传入 -k。
构建¶
在 PowerShell 中,从仓库根目录执行。每个依赖游戏版本的步骤都以 <ver> 作为版本参数:v143 对应 1.4.3,v121 对应 1.2.1。若省略 --version,工具默认使用 v121。存档在任一版本下均可加载。
- Python 环境(只需一次)。
.venv用于运行提升器(lifter)和构建;.venv-py314用于运行解包脚本,这些脚本需要 Python 3.14 标准库中的compression.zstd:
uv venv --python 3.12 .venv
uv pip install --python .venv/Scripts/python.exe -r tools/requirements.txt
uv venv --python 3.14 .venv-py314
uv pip install --python .venv-py314/Scripts/python.exe -r tools/requirements-py314.txt
-
将
config.example.toml复制为config.local.toml,并设置基础游戏、更新及你主机密钥文件的路径。config.local.toml会被 git 忽略。工具会自行读取密钥文件。 -
解包并验证。这会在
updates中为每个更新写入build\extracted\v0(1.0.0)和build\extracted\<ver>,以哈希标识;哈希不匹配会中止运行:
- 着色器翻译器(只需一次;不涉及游戏文件)。这会发布
build\xlate\totk_xlate.exe:
- 将模块提升(lift)为 C 代码,写入帧率补丁的 RomFS 部分,然后编译并链接
build\<ver>\totk.exe:
.venv\Scripts\python recomp\gen.py --exefs build\extracted\<ver>\exefs --out generated\<ver> --patches recomp\patches-<ver>.txt
.venv-py314\Scripts\python tools\make_romfs_patches.py --version <ver>
.venv\Scripts\python tools\build_game.py --version <ver>
提升大约需要 15 秒;24 线程下全新编译约需 200 秒。后续构建只会重新编译改动过的部分。--patches 会编入帧率、分辨率及其他补丁集,可在运行时切换。链接过程会将 SDL3.dll、libiconv-2.dll 和 libopus-0.dll 复制到 exe 旁边。
- 准备着色器(每个构建文件夹和着色器翻译器只需一次)。它需要
refs\MacNativeGames(tools\fetch_refs.sh)来获取共享着色器列表:
若不执行此步骤,首次启动会在游戏过程中编译着色器和管线,并持续卡顿,直到缓存填满。AMD 驱动会按 exe 路径保存管线缓存,且容量有限:准备另一个构建文件夹可能会淘汰此构建文件夹的缓存。totk.exe --warm-shaders 会从着色器缓存重建它。
- 运行。保持窗口处于前台;窗口失去焦点会导致游戏卡住。
设置位于 totk.exe 旁边的 totk.ini 中(totk.ini.example 列出了全部设置)。v121 的存档保存在 build\profile,其他版本保存在 build\profile-<ver>(build_game.py --profile 可更改)。
便携文件夹¶
.venv\Scripts\python tools\package_build.py --version <ver> 会生成 build\<ver>-portable,它可以在你没有安装 MSYS2、Python 或 .NET 的另一台机器上运行。romfs.bin 默认不会包含在内,除非传入 --with-romfs;否则请将它放到 exe 旁边的 romfs\ 中,或将 TOTK_ROMFS 指向其所在文件夹。在复制后的文件夹中运行一次 totk.exe --prepare-shaders。该文件夹包含从你的游戏派生的代码和数据:仅供你自己的机器使用。
检查¶
提交之前:
python tools/check_content.py --staged:确保没有游戏衍生内容被暂存。CI 也会运行同样的检查;git config core.hooksPath .githooks会在每次本地提交前运行它。build\<ver>\totk.exe --selftest:检查布局、分派表和宿主函数注册表,无需游戏文件。
lifter(recomp/)和 CPU 头文件(runtime/cpu.h、runtime/simd.h)会与 Unicorn 对照检查。每次 lifter 改动都必须通过这些检查,所有这些检查均使用 .venv 运行:
| 测试 | 检查内容 | 游戏文件 |
|---|---|---|
tests\diff\lift.py |
从提取的模块中采样指令;--coverage 列出 lifter 拒绝或 trap 的每个字(word) |
是 |
tests\diff\simd.py |
整个 FP/SIMD 编码空间 | 否 |
tests\diff\atomic.py |
独占加载/存储序列以及 ARMv8.1 原子操作 | 否 |
tests\diff\func.py |
生成器发出的完整函数,包括循环、跳转表和调用(调用会进入一个桩,在调用处检查寄存器) | 是 |
tests\flags_check.py |
将 runtime\cpu.h 的函数局部标志辅助函数与其打包版本进行对照 |
否 |
tests\excl_mt.py |
在竞争和 ABA 情况下、多个线程上的独占监视器辅助函数 | 否 |
tests\jumptables_check.py |
将 recomp/jumptables.py 与 Unicorn 参考实现(oracle)对照;必须报告 0 个不一致,在 1.4.3 上也要如此 |
是 |
运行时探针均为 totk.exe 的一种模式(列表位于 runtime/main.c 顶部):--probe-kernel、
--probe-vkexec、--probe-nvn-tex 和 --probe-shader 涵盖了大多数运行时改动。
着色器:.venv-py314\Scripts\python tools\shader_census.py --version <ver> --translate 会将每个 Maxwell 着色器提取到
build\<ver>\shaders\,并通过翻译器和 spirv-val 运行它;失败的组会进入 failures.txt。
tools\xlate_smoke.py 单独检查翻译器,无需游戏文件。
逆向工程(可选)¶
toolchain\ghidra\中的 Ghidra 12.1.2 配合 Adubbz 的 Ghidra-Switch-Loader(JDK 21)可以打开游戏模块(NSO)。tools\fetch_refs.sh会把本移植所依赖的上游项目克隆到refs\,只读。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 to/totk-pc-recomp