Armyja

如若不燃

主机游戏图形 API 移植中的契约重建问题——以《异度神剑3》的渲染适配为例

一、问题背景与工作定义

将一款为主机固定硬件深度特化的游戏迁移到另一套图形 API 上,通常被理解为“翻译图形调用”或“重写渲染后端”。但在实际工程中,真正困难的部分并不是 API 调用的逐条映射,而是恢复原系统在编译期已经确定、在新环境中却不再自动成立的隐含契约。

《异度神剑3》(Xenoblade Chronicles 3,社区常简称 XC3,亦有 XB3 的写法,指同一作品)是这类问题的典型样本。其渲染系统为 Switch 硬件做了深度特化,大量行为依赖离线编译的着色器产物、管线状态、整数渲染目标格式、Geometry Shader、Transform Feedback 以及绑定槽位等约定。翻译层需要把这些原本由固定硬件和离线工具链共同保证的约定,在运行时重新显式化。任何一条契约缺失,都可能导致管线状态对象无法创建、整个渲染通道输出异常,或特定特效完全失效。

因此,这项工作更准确的描述是:在另一套图形 API 上重建一组可验证的运行时契约,使可观察渲染行为与原系统保持一致。

二、翻译层的核心任务:从编译期特化到运行时契约

原游戏运行于 Switch 的 NVN 图形接口。NVN 属于低层显式 API,接近 Metal 或 Vulkan 的设计模型。为了在固定硬件上获得稳定的帧时间,游戏会将大量决策提前固化,包括离线预编译的着色器产物、渲染目标格式、深度与混合状态、采样器配置、顶点布局、绑定槽位、GS/TF 状态、内存布局与同步语义。

迁移到 Metal/MSL 环境后,翻译层需要回答的问题不再是“某个 API 是否被调用”,而是:该绘制调用在原始主机上使用何种附件格式,像素着色器应输出何种类型,绑定槽位如何映射,是否存在几何或变换反馈阶段,最终像素应满足何种约束。

从程序结构上看,原平台相当于编译期特化:类型与配置作为模板参数在构建时确定;移植层则相当于运行时解释:这些参数必须转化为显式事实并逐项校验。实践中反复出现的失败,多数发生在契约校验环节,而非渲染循环本身的控制逻辑。

三、离线着色器产物的构成与度量误区

工程记录中反复出现的“645”,需要先说明它当前实际指代什么。

XC3 的渲染系统在运行时按材质关键字、渲染目标格式、光照模式、阴影级别等条件,从预先生成的着色器产物中查表选择,而非现场编译。但“645”在当前审计口径下,指的是被审计的顶点与像素着色器 key 集合,不是原游戏的完整着色器库,也不覆盖计算着色器。每个 key 对应一条构建链下的产物,产物不是源代码,而是已经翻译到目标表示、可与宿主管线状态匹配的结果。

这里需要区分两个层面。着色器 key 来自控制流与代码路径,即 ctl/code。profile 值、事实条目的变化通常改变的是构建链、着色器反射结果以及这些 key 对应的产物,但不自动改变 key 集合本身。也就是说,key 集合是审计对象,产物是构建成本;两者不能混为一谈。把“重建产物”说成“重建整库”,会掩盖真正需要追踪的东西。

645 的构建属于验证手段,而非工作目标。目标是使 XC3 的渲染结果正确;着色器产物只是让宿主能够定位对应着色器。645 全部通过,只能说明当前 key 集合的产物被重新生成,不能说明运行时渲染问题得到解决。真正构成阻塞的是后续的运行时渲染子系统。

因此,645 应逐步改为增量构建:仅重建受影响的产物,已确认事实写入持久化表。该指标应被视为成本指标,而非进度指标。它解决的是“宿主能不能找到 shader 产物”,不解决“找到的产物与附件格式、绑定契约、管线状态是否匹配”。

四、运行时阻塞的分类:参数、契约与实现

当前阻塞项并非同一类问题,至少应分为三类,其确认方式各不相同。

第一类是参数值定义错误。 纹理槽数量从 16 调整为 27 目前仍是候选事实,尚未作为已修复结论确认。若该候选成立,其性质是函数逻辑未变、传入的配置值不正确,导致大量绑定返回空槽位。此类问题属于参数数值层面,通过配置核对即可确认。

第二类是类型签名或接口契约缺失。 整数渲染目标附件格式为 R8Uint、R32Uint 或 RG32Uint,而 MSL 默认生成 float4 输出。NVN 到 MTL 的映射关系本身没有错误,缺失的是一条事实,用于告知生成器该像素着色器的第二个颜色输出应返回 uint4。此类问题属于函数签名或接口契约层面。需要特别区分的是,管线状态能够创建,只证明该签名组合在宿主 API 下是合法的兼容性结果,不证明 bitcast 的数值语义正确。内容语义仍需像素级或数值级证据,不能由管线状态通过来替代。

第三类是函数实现缺失或仅有空壳。 几何着色器有若干个未进入映射表,宿主缺少 GS 编码路径,顶点到几何再到像素的链路只能退化为顶点到像素,接口自然不匹配。变换反馈的绑定、开始与结束接口当前是空实现,调用返回成功但没有副作用。此处需要严格限定证据边界:TF 接口为空实现是已确认的事实;但同一次绘制中缓冲区生产与消费链是否因此读到陈旧数据,尚未取得只读证据。因此,不能断言“下游 draw 读到旧 buffer”,也不能将特定特效异常直接归因于 TF 缺失。正确的下一步是先取得同 draw 的生产/消费链只读证据,再决定是否进入实现。

三类问题的区分很重要:参数值靠配置核对,契约靠格式约束与管线验证,实现靠补充引擎功能或选择性降级。混为一谈,容易把不同性质的困难叠加成“整体都难”的印象。

五、复杂度来源:耦合、掩盖与反馈稀缺

单项步骤往往并不复杂,整体推进缓慢来自四个因素的叠加。

其一是契约空间大。格式、输出类型、槽位、采样器、几何与变换反馈、同步、对齐,每个维度都有取值与约束。

其二是约束互相耦合。附件格式决定合法输出签名,签名决定管线状态能否创建,管线状态决定绘制能否执行。局部修改可能引发远端失败。

其三是错误掩盖严重。上游槽位错误可能在管线创建阶段才报错;变换反馈空实现不会主动报错,但它的实际后果取决于同 draw 的生产/消费链证据,目前尚未确认;几何着色器静默降级时,日志可能只显示链接失败。

其四是反馈带宽低。宿主运行通常一次性、不重试,按最小步骤推进并逐轮授权。同样的信息量,本地逆向工程可能数小时完成,此处需要数天。

若按组合空间估算,朴素上界是各维度取值数量的乘积。但工程上不能按乘积穷举,因为真正需要验证的是约束剪枝后的有效组合,且大量组合属于同一等价类。以整数渲染目标为例,若干绘制对可能只对应两三种签名模式,验证对象应是模式而非单个对。可行做法是离线批量生成候选,利用编译器与管线验证器进行兼容性剪枝,进行差分聚类,再为每个等价类选取代表执行一次宿主确认。需要明确:编译器与管线验证器只是兼容性 oracle,它们可以排除非法组合,但不自动回写事实表;VLM 等视觉工具只辅助筛查,不替代数值或像素 oracle 的确认职能。

六、为什么“看到了机器码”仍不能快速复现原逻辑

一个常见的疑问是:逆向工程针对机器码进行静态重编译,机器码里包含了程序执行的全部指令,按理说所有逻辑都清清楚楚,为什么不能快速复现原系统的渲染行为?

这个疑问触及了本项工作的核心难点。更准确的工程解释是:着色器指令流本身不足以恢复完整的执行环境。静态重编译能够把指令翻译成语义等价的宿主指令,但原系统运行所依赖的契约,分散在着色器指令流之外。

具体而言,契约分布在四个位置。

第一,CPU 侧的命令流。 引擎在创建管线状态、绑定资源、设置渲染目标时,传递了大量元数据:附件格式、混合状态、深度测试模式、采样器描述、顶点布局。这些信息不在着色器指令里,而在 API 调用序列中。翻译层必须同时理解 CPU 侧命令的语义,才能知道某条着色器指令在何种上下文中执行。

第二,资源与元数据。 着色器变体的选择键、材质参数、纹理格式、缓冲区布局,由引擎的材质系统和离线工具链共同维护。运行时只看到“选中了某个变体”,看不到“为什么选它”。这些元数据是契约的一部分,但不随指令流自动转移。

第三,硬件与驱动的隐式保证。 格式转换、对齐规则、同步语义、管线状态合法性检查,在原平台上由固定硬件与驱动共同保证。静态重编译把指令搬到新环境后,这些保证不会自动跟随;翻译层必须用宿主 API 的显式规则重新表达它们。

第四,验证成本高于翻译成本。 即使指令可翻译,要确认“翻译后的行为与原行为等价”,仍需覆盖契约组合。等价性不是单条指令的属性,而是管线状态、格式、绑定、同步共同作用的结果。

需要澄清的是,实现一个兼容层并不要求知道原设计者的“设计意图”。行为等价也不是模拟器独有的策略:静态重编译与模拟器都需要重建环境语义,只是重建的位置和方式不同。模拟器在虚拟硬件层重建,静态重编译在宿主 API 层重建。两者的目标都是可观察行为一致,而不是还原设计文档。

因此,静态重编译解决的是“指令级等价”,而渲染适配需要的是“契约级等价”。前者可以从机器码中获得,后者必须从 CPU 命令、资源元数据、硬件语义和运行观察中逐项重建。看到机器码,不等于看到了契约;翻译了指令,不等于重建了执行环境。这正是“逻辑清清楚楚”却仍不能快速复现原行为的根本原因。

七、与一般逆向工程的差异

一般逆向工程的目标多样,成功标准也因任务而异。有些逆向任务同样要求严格的全有或全无验收,不能一概而论为“宽松析取式”。但在本次渲染适配的语境下,验收结构确实有一个值得指出的特征。

渲染适配的目标是两个系统在可观察行为上严格等价。它的验收逻辑是合取式的:即使九成绘制正确,剩余一成涉及几何着色器、变换反馈或整数渲染目标的问题仍可能导致黑屏或错色,必须全部满足。这与“找到一个关键算法或入口即可推进整体理解”的逆向任务在验收结构上不同,但这种差异应限定在本次任务的范围内,不应推广为“逆向都宽松、适配都严格”的二分。

另一项值得注意的差异在于,原游戏的许多行为是编译期特化结果,类似模板参数已定死;翻译层必须把这些参数转化为运行时显式事实。遗漏一条不是“理解少一点”,而是契约不成立。此外,主机着色器产物与管线描述往往经过离线预编译、符号剥离,采用私有二进制格式,硬件语义未公开,可依赖的白盒信息更少,只能依靠约束推导与少量运行确认。

因此,这项工作的难度不在于单个函数逻辑,而在于目标函数不同:它是约束满足与缺失功能实现的组合,且验收标准在本次任务中是全有或全无的。

八、契约敏感度的游戏间差异:2D、Unity 与深度特化引擎

同样涉及翻译或重编译,不同游戏的问题面差异显著。可以粗略认为,翻译层需要补充的契约数量,正比于引擎对硬件的特化深度、渲染管线复杂度与图形特性使用广度的乘积。任一因子增大,问题面都会放大。

以《茶杯头》为例,其为 Unity 制作的 2D 游戏,渲染需求较窄:主要是精灵、背景、界面与少量粒子;不涉及几何着色器、变换反馈或整数渲染目标;管线状态组合少,着色器变体少。翻译层面对的是 Unity 已归一化的着色器,许多平台差异在引擎层已被抽象。其失败模式也较局部:某个精灵的顶点或纹理映射错误,表现为三角形碎条或个别元素变黑。由于 2D 渲染是独立元素的叠加,单点错误通常只影响局部画面,不阻断整体游玩。2D 的“正确”标准天然比 3D 宽松。

Unity 3D 游戏则受益于引擎抽象层的兜底。ShaderLab 与多后端编译链本身面向跨平台设计,许多平台差异在引擎层已有标准化路径。翻译层面对的不是原生 NVN 特化着色器,而是 Unity 归一化后的产物,契约缺失较少。所谓“画面一下子就渲染出来”,并非翻译层做得完美,而是引擎层已经吸收了大量复杂度。

XC3 采用 Monolith Soft 自研引擎,为 Switch 深度优化,几乎同时踩中三个因子。特化深:大量着色器变体、私有格式、符号剥离、绑定槽与格式对齐深度依赖硬件。管线复杂:多通道混合管线,涉及几何缓冲、光照、阴影、大气、水、植被、粒子、后处理与界面。特性广:几何着色器用于粒子、阴影与植被,变换反馈的使用范围与依赖程度仍需同 draw 证据确认,整数渲染目标用于几何缓冲、标识与深度相关输出,采样器与绑定布局复杂。每一项已确认的特性都是翻译层的硬契约点,缺失时不是局部瑕疵,而是管线无法创建、通道黑屏、特效消失或光照全错。

失败模式的结构性差异正在于此:2D 是元素叠加,错一个只坏一个;3D 复杂管线是强耦合链,错一环可能整帧崩溃。

九、架构红利不等于管线简单:与《王国之泪》的对比

一个常见疑问是:《王国之泪》同样为 3D 游戏,为何其静态重编译进展看起来更快,是否说明其管线更容易逆向?

需要修正一个容易产生的误解。ARM64 同构与直连 Metal 是所有 Switch 游戏静态重编译的共同优势,并非《王国之泪》独有。因此,不能仅以“抄近道”解释差异。更准确的说法是:其管线同样复杂,但复杂度更多落在翻译层已有处理能力的维度上;XC3 的复杂度则集中在翻译层最脆弱、最缺乏现成语义的硬契约上。

《王国之泪》的几何缓冲格式相对常规,以标准 RGBA 与浮点格式为主,未像 XC3 那样为 NPR 数据设计大量非常规打包编码,翻译层对类型与格式的推断负担较小。公开报告显示相关静态重编译方案收集约 8,582 个着色器,而 XC3 在 yuzu 的进度报告中记录其管线缓存超过 15,000 条。这两个数字口径不同:一个是着色器数量,一个是管线缓存条目数,不能直接等同。即便按同口径比较,15,000 与 8,500 的比值约为 1.76 倍,不到一个数量级。更重要的是,着色器或管线数量本身不是契约搜索空间的直接度量;真正决定搜索空间的是格式组合、绑定模式、签名等价类的数量。数量更大只说明潜在组合更多,不自动等于“难一个量级”。

《王国之泪》对变换反馈的依赖也非核心路径,未出现“缺失导致粒子完全消失”的已证案例,复杂度更多体现在通道调度与带宽优化上,通常表现为性能开销或局部画质瑕疵,而非整条管线无法创建。

因此,《王国之泪》的管线并不简单,但其复杂度大部分落在翻译层已有处理能力内;XC3 的非标准几何缓冲、更大的管线集合与已确认的 GS/TF 接口缺口,则集中指向翻译层在类型系统、搜索空间与功能实现上的薄弱环节。

十、兼容层的环境语义重建策略

Yuzu 与 Ryujinx 在适配时是否理解了所有契约?答案是否定的。但它们也并非“不理解契约也能跑”的黑盒。更准确的描述是:它们同样需要重建环境语义,只是重建的方式与静态重编译不同。

Ryujinx 将 Maxwell GPU 机器码解码为中间表示,再生成 GLSL 或 SPIR-V,本质是指令到指令的映射。它不需要知道指令组合的设计意图,但必须理解 NVN 与宿主 API 之间的语义对应关系,包括资源绑定模型、格式转换规则、管线状态映射。Yuzu 甚至不经过 GLSL,直接生成 SPIR-V 以提高速度,代价是更易出错。遇到不明确行为时,依赖启发式规则、转换优化与社区补丁。例如将几何着色器转换为计算着色器,只要最终效果一致即可。大量修复来自“运行游戏、触发缺陷、定位、打补丁”的循环。

因此,模拟器与静态重编译并非“不重建契约”与“重建契约”的对立。两者都需要重建环境语义,区别在于重建的层次:模拟器在虚拟硬件与 API 转换层重建,静态重编译在宿主 API 的显式契约层重建。模拟器可以用启发式和近似绕过某些细节,静态重编译则要求这些细节被精确表达。这也解释了为何模拟器当年看似“能跑”,而推进静态重编译时仍会被几何着色器、变换反馈与整数渲染目标卡住。

十一、先行者的工作方式

这项任务并非 XC3 独有。Switch 静态重编译、兼容层开发和图形管线逆向的先行者,以不同的工作方式处理过同类问题。他们的共同点不是“不累”,而是将认知负荷外部化为不同的形式,而非依赖持续的实时监督循环。

Belmante 与《超级马里奥兄弟:惊奇》原生移植。 项目基于静态预编译,将 Switch 的 ARM64 代码翻译为原生 C++,并自行实现 NVN 到 Vulkan 的转换层,直接对接驱动,不经过模拟器、JIT 或解释器。其工作方式是成果驱动的公开汇报:进展通过视频和社区公告同步,而不是逐轮提交给一个实时审批者。精力集中在攻克具体的转换层技术壁垒上。

gdkchan 与 Ryujinx。 Ryujinx 以 C# 从零构建,对 Maxwell GPU 进行了高保真的软件级复现,GPU 定时器频率、采样器描述符结构、同步点等均基于硬件测试与 nvservices 逆向。更重要的是,项目自带基于指令集模拟器(Unicorn)的差分测试工程,用自动化 oracle 验证 ARM 到 x86 的翻译正确性。这意味着指令翻译的一致性检查不依赖人工逐条审查,而是由机器完成海量重复验证。

realskyrin 与 Apple Silicon 移植 Skill。 其工作不是亲自移植某一款游戏,而是将完整工作流——版本识别、AArch64 离线改写、Horizon 服务重建、NVN 到 Metal 转换、证据阶梯与记录模板——固化为一份结构化的 Agent Skill,供任何 AI 编程助手调用。这是一种将方法论本身工具化的路径:精力花在设计高效工作流上,而不是在每个具体任务中手动执行流程。

ScanMountGoat 与《异度神剑》渲染研究。 通过 xc3_lib 工具库和专门的渲染研究网站,系统性地拆解了 XC1/2/3 的几何缓冲结构、材质类型、纹理布局等渲染主题。协作方式是异步的开源模式:贡献者提交 Pull Request 补充研究内容,维护者有时间和精力时审查。没有实时监督循环,产出是结构化的知识(文档、工具),而非逐轮工作报告。

peiikai 与 LASRecomp(《织梦岛》静态重编译)。 该项目将 Switch 版静态重编译到 Windows、macOS 和 Linux 原生平台。作者公开表示,几乎整个项目的代码、工具、逆向工程和文档都由 AI(Claude)完成,自身角色是指导、测试和审查,并承认该项目“超出了他个人的技术能力”。这最接近当前 AI 辅助移植的形态:AI 承担繁重的实现与探索,人类聚焦于方向设定和关键节点验收。

Wine 与 DXVK 的通用工程策略。 Wine 不反汇编 Windows,而是通过黑箱测试法编写必须在真实 Windows 上运行的一致性测试套件,以可观察行为等价为唯一标准。DXVK 则用精细的脏标记系统跟踪最多 21 个纹理/采样器槽位和 4 个同时渲染目标的状态,以参数化的状态模型覆盖 D3D9 到 Vulkan 的管线组合,而非枚举所有状态。两者的“主管”都是 CI 系统和测试套件,人类开发者的精力集中在编写能通过自动化验证的代码上。

这些路径的共同逻辑是:将“该验证什么”“什么算通过”“哪些组合可以归并”这类元认知决策,尽可能固化为工具、清单、自动化测试或异步协作流程,而不是依赖监督者在每一轮中实时做出判断。

十二、AI 辅助的契约提取与验证流水线

传统流程是自动化粗筛加人工目视兜底,瓶颈在于人工反馈的带宽与主观性。AI 时代的方向不是让模型自由生成代码,而是分层自动化语义验证。

第一层是契约自动提取。 利用 AI 分析着色器字节码或中间表示,推断像素输出类型、绑定槽位、GS/TF 使用模式;以编译器与管线验证器作为兼容性 oracle,批量生成候选、自动剪枝、聚类;仅将等价类代表送入宿主确认。目标不是逐个对试错,而是批量生成加少量代表确认。再次强调:兼容性 oracle 的输出不自动写入事实表,确认仍然需要独立的证据。

第二层是视觉等价 oracle。 以 LPIPS 等高容差指标过滤黑屏、白屏等灾难性失败;以 OCR 与界面检测确认文字可读、布局正确;以轻量分类器识别深度冲突、纹理丢失、光照错误、粒子异常;以视觉语言模型按布尔清单裁决。AI 在此只做筛选与语义裁决,不替代数值或像素 oracle 的精确确认。

第三层是选择性降级或重写。 并非所有几何与变换反馈都必须原样实现。可分析每个阶段的实际用途:哪些可用计算着色器替代且视觉等价,哪些必须保留原实现。能替代的替代,不能替代的才补。此处的判断依据是证据,不是倾向。

第四层是跨游戏迁移与变异测试。 从已知适配中提取契约模式,作为先验候选缩小搜索空间;同时以语义保持的微小变异运行验证流水线,检测契约或 oracle 是否存在漏洞。

着色器翻译本身也应采用结构化约束加后置校验。不宜让大模型自由生成跨平台代码,因其容易忽略坐标系翻转、精度限定符、原子操作支持等硬件差异。更稳妥的方式是模型生成候选 MSL,再以跨平台语义映射规则表做后置校验与自动修正。

需要明确边界:以上方法是工程选项,不是下一阶段 scope 的扩张提案。AI 方法应服务于既定的验证目标——先取得真实资源快照,先完成 TF 同 draw 生产/消费链的只读证据,整数 RT 保留已有候选与运行时管线证据——而不是另起炉灶。

十三、运行现场快照的可行性与工程折中

验证工作流中还有一项实际需求:能否保存整个运行现场,下次直接从目标帧继续,而非每次从头重放输入。

首先需要区分三种保存。游戏内存档保存玩家进度、道具与位置,读档仍需重新加载场景,不能实现“打开即目标帧”。模拟器 save state 保存整个虚拟主机状态,包括 CPU、内存、GPU 与设备状态,可视为现场快照。静态重编译快照取决于实现,可能是引擎状态,也可能是进程内存加 GPU 资源,同样可以做到,但需要专门实现。

模拟器较易实现,因为它控制整台虚拟 Switch,CPU、内存、GPU、输入与音频均在其管理之下,状态边界清晰,直接打包即可。GPU 状态也是虚拟设备的一部分,恢复时重建虚拟设备即可。

静态重编译更难,因为游戏是宿主系统上的原生程序,状态分散于游戏堆、栈、全局变量、宿主线程、图形 API 对象、音频输入设备与动态库内部状态。GPU 资源句柄与宿主 API 对象通常不能直接序列化:Metal 的管线状态对象无法原样写入文件再读回,恢复时通常需要重建资源或重放少量命令。

实现难度可分三档:模拟器快照相对简单,因其为虚拟整机管理者;有源码的静态重编译完整快照为中等,保存游戏世界状态,恢复时重建 GPU 资源;无源码的复杂 3D 游戏完整现场快照为困难,状态分散、GPU 资源不可直接序列化、流式加载与多线程同步均构成障碍。

多线程的难点不在于线程数量,而在于无法在所有线程的同一物理时刻拍照,容易捕获撕裂状态;线程私有状态不在共享内存中,栈、寄存器、线程局部存储与同步原语均需处理;互斥锁持有者、等待队列与原子变量不能简单序列化;CPU 与 GPU 异步,快照时需决定等待 GPU 空闲还是保存“已提交未完成”状态。

工程上通常不追求任意时刻完整快照,而采用帧边界快照:在一帧结束、下一帧开始前执行快照,此时工作线程已汇合、GPU 可等待空闲、逻辑状态完整。多线程难点被帧循环的同步点吸收。对验证工作流而言,更现实的是检查点加确定性重放:固定资源加载与输入序列,从检查点重放到目标帧。关注点是到达目标绘制,而非任意时刻恢复。

Mac 上已有实际项目实现类似能力。Ship of Harkinian 的快捷键定义为 F5 保存状态、F6 切换状态槽、F7 读取状态,且 Metal 是其 macOS 支持的渲染后端之一。其他重编译项目也报告了 save state 功能。这些多为引擎级状态序列化,而非模拟器式完整虚拟机快照,但对“跳到目标帧”的验证工作流效果一致。

十四、路线选择:复刻、重写与分层混合

路线选择取决于目标,而非技术优劣的单一判断。

路线 A 为原样复刻。 重建原始 API 语义、管线状态、几何缓冲格式、绑定槽位与几何变换反馈行为,目标是行为等价。优点是能够运行原始内容、复用资产、验收标准明确;缺点是契约空间巨大、长尾极长,且复刻对象是为弱硬件优化的低效管线,迁移到强硬件不会自动变快。

路线 B 为不理解契约、重写渲染。 不追求 API 级等价,只追求最终画面或美术效果等价,利用现代硬件特性重新设计管线。优点是性能上限高、无需逆向私有格式;缺点是“视觉等价”难以定义与验收,需要重建资产管线、材质系统与光照模型,工作量可能更大,且容易丢失原始管线中的细节。

路线 C 为混合。 保留原始游戏逻辑、资产、动画与物理,仅替换渲染后端。这是静态重编译加翻译层的路线。优点是复用原始内容、验收比路线 B 明确;缺点是仍需补渲染契约长尾,性能上限受限于原始管线加翻译开销。

更现实的做法是在路线 C 内部再分层:契约层保持等价,实现层选择性重写。契约层必须精确,包括像素输出类型、渲染目标格式、绑定槽位、几何与变换反馈接口、管线状态。实现层可以替换,例如以计算着色器替代部分几何或变换反馈、以 bindless 替代复杂绑定、以现代格式替代打包整数渲染目标。只要可观察行为等价即可。

这样既不需要“理解所有契约才能重写”,也不需要“重写所有东西才能运行”;只需精确确认契约,再按实际用途决定哪些实现可以替换。

十五、进度度量:能力成熟度与证据覆盖

进度不应以“645 是否通过”“实现了几个 API”或“运行了多少轮”衡量。建议从四个层面观察。

结果层:管线状态可创建率、关键通道像素正确率、端到端场景通过率。

能力层:每个子系统按 L0 至 L5 衡量,分别为未识别、静态清单完成、离线候选完成、合成管线验证通过、真实绘制通过、像素与回归通过。

证据层:已确认事实数与已知未知项数之比,每条事实是否具备可复现证据,未解释差异数量。需要特别区分管线可建性与数值语义:管线状态通过只进入兼容性证据,不自动升级为内容正确性证据。

吞吐与风险层:每轮确认的独立事实数、每次宿主运行确认数、阻塞收敛速度、返工率,以及 645 重建次数。后者为成本指标,不是进度指标。

概括而言,进度等于关键路径上达到 L4/L5 的能力数、已验证像素覆盖与事实表覆盖之和,除以剩余阻塞。645 全部通过只是当前 key 集合的产物健康度,不是进度。

十六、结论

当前工作的实质,是将主机游戏的离线着色器产物、管线状态、绑定契约、几何与变换反馈语义,在 Metal 宿主上显式重建,使可观察渲染行为尽量严格等价。

难度在于:单个函数逻辑大多正确,难在补充参数值、补充类型签名契约、补充缺失函数实现;难在约束耦合、错误掩盖与反馈稀缺;难在验收是合取式,长尾是引擎级功能。

它比一般逆向工程更难,但这一判断应限定在本次任务的验收结构上,而不是将逆向整体简化为宽松任务。逆向工程同样有严格验收的场景。本次任务的特殊性在于:行为等价要求契约级重建,而机器码只提供指令级等价;契约分散在 CPU 命令、资源元数据、硬件语义与运行观察中,不会随指令翻译自动转移。宿主运行稀缺且逐轮授权,进一步压低了反馈带宽。

并非所有游戏更换 API 都如此困难。只有深度特化、复杂管线与广泛图形特性三者叠加的游戏才会如此。XC3 正属于这一类。《王国之泪》看起来更快,是因为其复杂度更多落在翻译层已有处理能力内;Yuzu 与 Ryujinx 能够运行,是因为它们同样在重建环境语义,只是选择在虚拟硬件与 API 转换层以启发式和近似方式完成,而非在显式契约层精确表达。

因此,问题不在于游戏渲染“设计得绕”,而在于主机游戏将大量复杂度压入离线工具链与固定硬件契约;翻译层当前所做的,是把这部分复杂度重新显式化。其难度来源,是一项在验收结构上比一般逆向工程更严格的工程任务。先行者的经验表明,将元认知决策工具化、流程化、异步化,而非依赖持续的实时监督循环,是让这类探索得以持续的关键路径。

参考链接

  1. realskyrin, ns-game-apple-arm-port: Agent skill for native Nintendo Switch game porting to Apple Silicon macOS, iPadOS and iOS with Rust and Metal. https://github.com/realskyrin/ns-game-apple-arm-port
  2. ScanMountGoat, xc3_lib: Rust libraries and tools for Xenoblade Chronicles rendering formats. https://github.com/ScanMountGoat/xc3_lib
  3. ScanMountGoat, Xenoblade Rendering Research. https://scanmountgoat.github.io/xenoblade-rendering-research/
  4. peiikai, LASRecomp: Static recompilation of Link’s Awakening (Switch) to native macOS, Windows and Linux. https://github.com/peiikai/LASRecomp
  5. gdkchan, Ryujinx: Experimental Nintendo Switch emulator written in C#. https://ryujinx.app/
  6. Belmante, Super Mario Bros. Wonder 原生移植相关报道. Notebookcheck / XDA Developers, 2026.
  7. WineHQ, Wine Conformance Test Suite 相关讨论. Wine mailing list / WineHQ.
  8. doitsujin, DXVK: Vulkan-based D3D9/D3D10/D3D11 implementation for Linux/Wine. https://github.com/doitsujin/dxvk
  9. yuzu, Progress Report 2022-08. yuzu 模拟器进度报告(XC3 管线数量与 shader 重编译器修复记录).