ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

什么是静态重编译?MarathonRecomp从PowerPC到C++的移植原理全解析

什么是静态重编译?MarathonRecomp从PowerPC到C++的移植原理全解析

【免费下载链接】MarathonRecomp

An unofficial PC port of the Xbox 360 version of Sonic the Hedgehog (2006) created through the process of static recompilation

项目地址:https://gitcode.com/gh_mirrors/mar/MarathonRecomp
点击查看免费下载

MarathonRecomp(Marathon Recompiled)是一个通过静态重编译(Static Recompilation)技术,将 Xbox 360 版《Sonic the Hedgehog (2006)》移植到 PC 的非官方开源项目。它不做运行时模拟,而是把游戏原本的 PowerPC 代码直接转写成可读的 C++ 源码、把 GPU 着色器转成 HLSL,让游戏在 Windows、Linux 和 macOS 上以接近原生的方式运行。本文将用通俗的语言带你完整看懂它的工作原理。

一分钟看懂:静态重编译 vs 传统模拟器

对比项传统模拟器(Emulator)静态重编译(Recompilation)
运行方式运行时逐条解释/翻译指令提前把机器码翻译成宿主代码,直接编译
产物无(每次运行都要翻译)可阅读的 C++ 源码 + 着色器代码
性能受翻译开销影响接近原生
可修改性只能打内存补丁可直接在源码级别修改游戏逻辑
可维护性难以长期维护像普通 C++ 工程一样开发

打个比方:模拟器像是"同声传译",边说边翻;静态重编译则是先把整本书翻译出版,之后所有人读的都是译文。这也是为什么项目 README.md 强调它"NOT meant for public use"仍在积极开发中——因为整个游戏的代码都要被重写成一份可编译的工程。

项目是怎么组织这场"翻译"的?

整个仓库分成三大块,理解它们就理解了移植的骨架:

  • 重编译工具:tools/XenonRecomp 负责把 PowerPC 指令转成 C++;tools/XenosRecomp 负责把 Xenos GPU 着色器转成 HLSL。
  • 重编译产物库:MarathonRecompLib 存放工具链的配置与生成出的 C++ 代码。
  • 宿主运行时:MarathonRecomp 是你真正运行的程序,包含窗口、输入、音频、文件系统模拟和"补丁层"。

第一步:把游戏代码翻译成 146 个 C++ 文件

构建系统 MarathonRecompLib/CMakeLists.txt 中有一个关键循环:它会调用 XenonRecomp,为ppc_recomp.0.cpp到ppc_recomp.145.cpp共146 个源文件生成内容——这就是整个游戏default.xex可执行文件里 PowerPC 代码的翻译结果。

工具的配置写在 MarathonRecompLib/config/Marathon.toml.in,其中包含:

  • functions列表:告诉工具"这是一个函数入口,请从这里开始翻译";
  • invalid_instructions:标记哪些字节序列不是指令(比如 C++ 异常帧表),避免误翻译;
  • midasm_hook:汇编级钩子,在翻译出的代码中插入宿主 C++ 逻辑的"接线点",后文会重点讲。

而 MarathonRecompLib/config/switch_table.toml 则记录了 PowerPC 中switch语句的跳转表位置。PowerPC 的跳转表是数据不是代码,工具需要借助这份"地图"才能正确还原出switch-case结构,否则翻译结果会是一堆无法维护的跳转。

第二步:把着色器翻译成 HLSL

游戏的图形代码藏在shader.arc归档文件里。构建时先由 tools/u8extract 解包归档,再由 XenosRecomp 把 Xenos 着色器逐条转成 MarathonRecomp/gpu/shader/hlsl 风格的 HLSL 代码,最终打包成一个shader_cache.cpp(见 MarathonRecompLib/shader/shader_cache.h)。

运行时则通过第三方抽象层 plume 在 D3D12、Vulkan、Metal 等后端上执行这些着色器——也就是说,"Xbox 360 显卡指令"已经被彻底换成了现代 GPU 能直接编译的语言。

核心机制:让游戏代码"住进"一个模拟内存空间

翻译出来的代码不能直接跑,因为游戏代码满脑子都是"内存地址 0x82xxxxxx"。MarathonRecomp 的解法非常巧妙:

1. 一整块连续的模拟内存

MarathonRecomp/kernel/memory.h 中的Memory结构体在启动时申请一整块大内存(base),把游戏的default.xex映像原样拷贝进去。之后Translate(offset)负责"游戏地址 → 宿主地址"换算,MapVirtual负责反向换算。游戏代码看到的 32 位地址,在宿主上变成了真实指针,性能几乎零损耗。

2. 寄存器即结构体

PowerPC 的寄存器状态被建模成一个PPCContext结构体(r3~r31整数寄存器、f1~f13浮点寄存器……),每个翻译出来的函数都接收(ctx, base)两个参数。你可以在 MarathonRecomp/cpu/ppc_context.h 看到它被做成线程局部变量——因为游戏代码可以跑在任意线程上。

3. 游戏主线程就是一个"客人线程"

MarathonRecomp/cpu/guest_thread.h 定义了GuestThread:程序入口 MarathonRecomp/main.cpp 在加载完游戏映像后,执行GuestThread::Start({ entry, 0, 0 }),把游戏的入口点丢进一个真实线程里运行。游戏从此像"住进"宿主程序的租户,通过函数分发表(PPCFunc查找表)在成千上万个翻译函数之间跳转。

4. 跨层调用:C++ 与游戏代码互相调用

MarathonRecomp/kernel/function.h 提供了两套桥接工具:

  • HostToGuestFunction:宿主 C++ 函数包装成游戏函数(参数自动从寄存器/栈中按 PowerPC 调用约定取回,返回值写回r3/f1);
  • GuestToHostFunction:反过来,让宿主代码以游戏的方式调用翻译后的函数。

指针参数会经过g_memory.MapVirtual/Translate自动在两套地址空间之间转换——这正是"静态重编译"能保持高性能的关键:没有指令翻译层,只有普通的函数调用。

补丁层:在源码级别"修"游戏

这是静态重编译相对模拟器最迷人的能力:因为代码是 C++,所以可以直接写逻辑。

MarathonRecomp/patches/ 目录里躺着一整套质量改进补丁:宽屏与动态分辨率(aspect_ratio_patches)、帧率解锁(fps_patches)、相机控制、文字渲染、加载速度等。

而更底层的修改通过前文提到的midasm_hook实现。以 MarathonRecompLib/config/Marathon.toml.in 为例:

[[midasm_hook]] name = "SetMSAALevel" address = 0x82607CD4 registers = ["r4"]

含义是:在 PowerPC 地址0x82607CD4处"拦截",把r4寄存器的值交给宿主 C++ 函数SetMSAALevel处理。配置文件里还能看到InfiniteLives、RestoreChaosSpearFlips、DisableRadialBlur等钩子——它们分别对应"无限生命""还原混沌尖刺翻转动画""禁用径向模糊"等玩家选项。配置一个开关,翻译出的代码就会在正确的位置跳或不跳某段指令。

此外,宿主侧也能在游戏函数执行前后插入逻辑,例如 MarathonRecomp/app.cpp 中对DocMarathonState::Update的包装:先修正帧间隔误差、再执行原始翻译代码、最后读取暂停状态——一个函数调用同时完成了"原逻辑 + 三个增强"。

那些 api/ 头文件是什么?

打开 MarathonRecomp/api/ 会看到按游戏类名组织的头文件树:Sonicteam/Player/State/SonicContext.h、SoX/Graphics/Texture.h、Chao/CSD/...等。这是团队对游戏内部数据结构(类布局、成员偏移)的逆向映射结果,相当于给整个游戏写了一份"接口文档"。

MarathonRecomp/api/README.md 规定了严格的命名规范与映射规则:成员必须带offsetof/sizeof断言保证布局正确、不确定的字段命名为m_Field194(用十六进制偏移标注)……这套纪律确保了头文件与游戏真实内存布局始终一致。

如何参与构建:编译步骤速览

如果你想亲手体验一次完整的静态重编译流程,官方构建文档在 docs/BUILDING.md,核心步骤:

  1. 克隆仓库(需要子模块,即两个重编译器): git clone --recurse-submodules https://gitcode.com/gh_mirrors/mar/MarathonRecomp
  2. 放入游戏文件:将合法获取的default.xex、shader.arc、shader_lt.arc放入MarathonRecompLib/private/(仓库不包含任何游戏资产);
  3. 安装依赖:Windows 用 Visual Studio 2022(含 C++ Clang 组件);Linux 用 clang/cmake/ninja;macOS 用 Xcode;
  4. 构建:cmake . --preset linux-release然后cmake --build。

第一次编译会比较久——因为 XenonRecomp 要把整个游戏的代码翻译成 146 个 C++ 文件,再把它们全部编译进最终二进制。之后每次构建,就是再跑一次"翻译 + 编译"。

总结:静态重编译的完整链路

把全文串起来,MarathonRecomp 的移植原理可以概括为一条流水线:

阶段做什么关键文件
1. 代码翻译PowerPC → C++(146 个源文件)tools/XenonRecomp、switch_table.toml
2. 着色器翻译Xenos Shader → HLSL/Metaltools/XenosRecomp
3. 运行时模拟内存 + 客人线程 + 寄存器上下文kernel/memory.h、cpu/guest_thread.h
4. 补丁层汇编钩子 + 宿主代码包装,实现画质/玩法增强patches/、Marathon.toml.in
5. 现代化外壳SDL3 窗口/手柄/音频、安装向导、成就菜单hid/、apu/、ui/

一句话总结:静态重编译 = 逆向 + 代码生成 + 普通 C++ 工程开发。游戏从"只能在一台停产主机的芯片上跑的机器码",变成了"一份可以在任何现代电脑上编译、阅读和修改的源代码"——这正是 MarathonRecomp 最核心的移植原理。

【免费下载链接】MarathonRecomp

An unofficial PC port of the Xbox 360 version of Sonic the Hedgehog (2006) created through the process of static recompilation

项目地址:https://gitcode.com/gh_mirrors/mar/MarathonRecomp
点击查看免费下载
上一篇:arxiv-sanity-preserver批量处理技巧:高效管理大量PDF文件
下一篇:超全解析:Fashion-MNIST性能指标评测体系与实战指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

返回列表