跳转至

从源码构建

需要 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。存档在任一版本下均可加载。

  1. 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
  1. 将 config.example.toml 复制为 config.local.toml,并设置基础游戏、更新及你主机密钥文件的路径。config.local.toml 会被 git 忽略。工具会自行读取密钥文件。

  2. 解包并验证。这会在 updates 中为每个更新写入 build\extracted\v0(1.0.0)和 build\extracted\<ver>,以哈希标识;哈希不匹配会中止运行:

.venv-py314\Scripts\python tools\extract.py
  1. 着色器翻译器(只需一次;不涉及游戏文件)。这会发布 build\xlate\totk_xlate.exe:
.venv\Scripts\python tools\build_xlate.py
  1. 将模块提升(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 旁边。

  1. 准备着色器(每个构建文件夹和着色器翻译器只需一次)。它需要 refs\MacNativeGames(tools\fetch_refs.sh)来获取共享着色器列表:
.venv-py314\Scripts\python tools\prepare_shaders.py build\<ver> --version <ver>

若不执行此步骤,首次启动会在游戏过程中编译着色器和管线,并持续卡顿,直到缓存填满。AMD 驱动会按 exe 路径保存管线缓存,且容量有限:准备另一个构建文件夹可能会淘汰此构建文件夹的缓存。totk.exe --warm-shaders 会从着色器缓存重建它。

  1. 运行。保持窗口处于前台;窗口失去焦点会导致游戏卡住。
build\<ver>\totk.exe

设置位于 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