ant0-blase/MOHFrontline-PS2Recomp
GitHub: ant0-blase/MOHFrontline-PS2Recomp
通过静态重编译技术将PS2游戏《荣誉勋章:前线》移植为PC原生可执行文件的逆向工程项目。
Stars: 0 | Forks: 0
MOH Frontline — PS2 静态重编译
Medal of Honor: Frontline(PlayStation 2,SLUS_203.68)的原生 PC 移植版
通过静态重编译而非模拟方式构建。
游戏的 MIPS R5900 代码被提前翻译为 C++,编译为普通的原生可执行文件,并与手写的 PlayStation 2 硬件接口实现一起运行——包括 VU0/VU1、Graphics Synthesizer、VIF1、DMA 控制器和 I/O 处理器。
基于 [ran-j/PS2Recomp](https://github.com/ran-j/PS2Recomp) 构建。本仓库是针对 Frontline 的专属分支:包含运行时的工作及相关开发笔记。
## 进度
以下所有内容均由该移植版渲染:没有模拟器,也没有原始可执行文件——完全由重编译后的游戏代码驱动软件 Graphics Synthesizer。
 |
 |
| Cold boot. The publisher logo plays from the game's own video stream, with audio. |
Title screen. Textured plaque, alpha blending and the front-end font pipeline. |
 |
 |
| Level opening. "Your Finest Hour" opens on its date card and text, over the soundtrack. |
 |
 |
| Main menu. The campaign desk, with its map, compass and layered paper sprites. |
Mission Log. Mission detail, medal criteria and save/load entries. |
 |
 |
Code entry. The Enigma machine screen, here with the retail DAWOIKS cheat. |
…and it takes. All six campaigns unlocked, so the whole mission tree is reachable. |
 |
 |
| Level load. "Rough Landing" — mission title, artwork and a live progress bar. |
Loading banner. The between-screens transition. |
 |
| In engine. The invasion fleet off Omaha Beach — recompiled game code driving a
software Graphics Synthesizer. The banding across the water is the open defect below. |
**已实现功能**
- 冷启动并通过发行商 Logo 和开场动画——包含视频和音频。
- 前端界面:标题画面、主菜单、任务日志、简报画面、字体、HUD 精灵图。
- 通过 Enigma 界面输入代码,包括正式版的关卡解锁作弊码。
- 任务加载、加载画面,以及带有纹理、雾效和 Z 缓冲的第一个 3D 场景。
- 通过 IOP HLE 层流式传输音乐和音效。
- VU0 宏模式、VU1 微程序解释、VIF1 解包、GIF PATH1/2/3。
**已知缺陷 — 屏幕外几何体**
在 3D 场景中,巨大的剪切三角形会遮挡视野。原因已定位:Frontline 在 VU1 中不执行任何几何裁剪。其微程序改为测试裁剪标志寄存器,并且对于任何接触视锥体的图元,都会设置 **ADC 位**(打包顶点四字的第 111 位),以便 GS 剔除该顶点而不进行绘制。常驻的三个 VU1 微程序中,有一个在此处能正确驱动该路径;另一个则在 ADC 位清零的情况下发射了数百万个视锥体外顶点,而正是这些顶点被绘制了出来。详情请参阅[技术说明](docs/TECHNICAL-NOTES.md)。
## 构成方式
```
ps2xAnalyzer scans the ELF, exports a function map (Ghidra-assisted)
ps2xRecomp decodes R5900 and emits one C++ function per game function
ps2xRuntime the PS2 that generated code runs against
ps2xIOP HLE for the I/O processor: CD/DVD, memory card, SPU2, RPC
```
`ps2xRuntime` 是移植工作的核心所在——包含约 120 个文件中的 9.5 万行代码。对 Frontline 而言最重要的部分:
| 领域 | 文件 |
|---|---|
| VU1 微程序解释器(上/下层流水线、裁剪标志、DIV 延迟) | `src/lib/vu/ps2_vu1_*.cpp` |
| Graphics Synthesizer 寄存器文件与 GIF 数据包解码 | `src/lib/ps2_gs_gpu.cpp` |
| 软件光栅化器(三角形、精灵图、纹理、Z 缓冲、alpha) | `src/lib/ps2_gs_rasterizer.cpp` |
| VIF1 命令流、UNPACK、MPG 微代码上传 | `src/lib/ps2_vif1_interpreter.cpp` |
| 客户机内存、DMA 标签遍历、暂存器 | `src/lib/ps2_memory.cpp` |
| 基于 ELF 元数据的针对单个游戏的运行时补丁 | `src/lib/game_overrides.cpp` |
## 编译说明
需要 CMake 3.20+、支持 C++20 的编译器,以及支持 SSE4 的主机。
```
git clone --recurse-submodules https://github.com/ant0-blase/MOHFrontline-PS2Recomp.git
cd MOHFrontline-PS2Recomp
cmake -S . -B build-runtime-launcher -DCMAKE_BUILD_TYPE=RelWithDebInfo
```
接着,使用你自己的光盘镜像:
1. 从光盘中提取 `SLUS_203.68`。
2. 使用 `ps2xAnalyzer/tools/ghidra/ExportPS2Functions.java` 从 Ghidra 导出函数映射表。
3. 使用 `toml/` 中的配置将其重编译到 `recomp/` 目录中:
./ps2_recomp toml/launcher_recomp.toml
4. 编译并运行:
cmake --build build-runtime-launcher --target ps2MOHFrontlineRunner -j$(nproc)
./build-runtime-launcher/ps2xRuntime/ps2MOHFrontlineRunner extracted/SLUS_203.68
`tools-moh-run-capture.sh` 会运行游戏,并按固定间隔对窗口进行截图。`tools-moh-verified-run.sh` 对其进行了封装,并断言链接的二进制文件中确实包含正在测量的诊断探针,从而确保测试结果始终能追溯到生成它的构建版本。
## 诊断
运行时内置了检测探针,默认全部关闭,且均通过环境变量进行选择,因此无需修改代码即可测试假设:
| 变量 | 效果 |
|---|---|
| `PS2_MOH_DIAG_SPAN_LIMIT=
` | 丢弃宽度超过 N 个像素的图元。在裁剪缺陷未解决时可使 3D 场景变得可辨认——但它也会丢弃合法的全屏菜单四边形,因此切勿在前端界面使用。 |
| `PS2_MOH_DIAG_CLAMP_XY=1` | 在 `FTOI4` 之前对屏幕的 X/Y 坐标进行截断,而不是让 GS 字段发生回绕。 |
| `PS2_MOH_DIAG_NO_TEXTURE=1` | 平面渲染,用于将几何体故障与纹理故障区分开来。 |
| `PS2_MOH_VU_DIV_LATENCY=1` | 模拟 VU `DIV`/`WAITQ` 延迟,而不是立即清空 `Q`。 |
| `PS2_MOH_DIAG_NO_CF_MASK=1` | 禁用 24 位裁剪标志掩码,用于 A/B 测试。 |
这些是诊断工具,而非修复方案:在正常运行中均未启用,也不会根据关卡、帧或颜色进行条件触发。
## 技术说明
[`docs/TECHNICAL-NOTES.md`](docs/TECHNICAL-NOTES.md) 涵盖了耗费大量时间的发现及其背后的测量数据。以下是一些不仅局限于本游戏的通用经验:
- **`FTOI` 必须执行饱和截断。** 普通的 C++ `float`→`int32_t` 转换在溢出时属于未定义行为,并在 x86 上会导致符号翻转。这*正是*导致 3D 渲染损坏的*核心*缺陷;而 PS2 硬件会进行饱和截断。
- **VU1 微代码库并不稳定。** Frontline 每次运行都会将每个 0x800 字节的 bank 重写约 86 次,循环使用三个不同的程序。任何基于 VU1 地址的统计数据如果未按 `(bank, variant)` 标记,都将毫无意义。
- **GS 的 `Q` 寄存器会在 `RGBAQ` 上锁存**,而不是逐顶点锁存(在 PACKED 模式下)。
- **三角带顶点窗口必须在非绘制剔除时也进行推移** —— `XYZ3` 和 ADC 被抑制的顶点仍会移动窗口。
[`docs/SUBSYSTEM-MAP.md`](docs/SUBSYSTEM-MAP.md) 将游戏的子系统映射到了 ELF 地址,并为每个标签提供了证据。
## 致谢
- [PS2Recomp](https://github.com/ran-j/PS2Recomp) 作者 ran-j —— 本分支所基于的重编译器和运行时基础。
- 灵感来自 [N64Recomp](https://github.com/N64Recomp/N64Recomp)。
- 感谢 ELFIO、toml11 和 fmt 提供解析与格式化支持。
## 法律声明
*Medal of Honor: Frontline* 版权所有 © 2002 Electronic Arts Inc. 本项目不包含任何游戏代码和游戏资产:它仅为工具链以及对 PS2 硬件行为的原创重新实现,并且需要您合法拥有的游戏光盘才能运行。重编译器输出是在您的机器上生成的,并已通过 `.gitignore` 从本仓库中排除。上方的截图是该移植版运行时的画面捕获,包含于此仅用于记录其开发状态。标签:Bash脚本, C++, PlayStation 2, 云资产清单, 数据擦除, 游戏引擎, 游戏移植, 逆向工程, 静态重编译