一个名为 bo2-mac 的新粉丝项目通过预先将游戏的原始 x86 机器代码转换为 ARM64 代码,实现了《使命召唤:黑色行动 II》在 Apple Silicon 上的原生运行。与在运行时翻译 Windows 调用的传统兼容层(如 Wine)不同,该项目确保游戏作为原生代码在单个进程中运行,并在 Apple M1 芯片上实现了 51–60 帧每秒的性能。

Project bo2-mac 标志和 Apple M1 性能统计
bo2-mac 项目在 Apple Silicon 上实现了原生性能,在各种游戏模式中达到高达 60 帧每秒。github.com

这张图片提供了项目目标以及在 Apple M1 硬件上实现的性能基准的高层概述。

Remill 和 LLVM 17 提升器图表
该项目利用 Remill 将 x86 函数提升到 LLVM IR 以进行重新编译。github.com

此视觉图说明了技术概述中提到的重新编译流水线的第一个步骤。

重新编译流水线

bo2-mac 项目将三个 x86 Windows 可执行文件——战役、僵尸模式和多人模式——转换为原生 ARM64 代码。该过程涉及五个步骤:通过 SHA-256 验证 Steam 版本,使用 Remill 对函数进行编目并提升到 LLVM IR,“折叠”这些 IR 以内联访客内存访问,实现 Win32 运行时,并将访客线程作为协程管理。

Apple M1 上的性能: 战役 51–60 fps; 僵尸 57–60 fps; 多人游戏 53–60 fps
Apple M1 上的性能github.com

HN Digest 根据 github.com 报告的数据绘制的图表;数值按原文显示。

为了保持性能,项目在将提升后的 IR 传递给 clang -O2 之前会对其进行重写。这确保了访客读写操作被内联,并且锁序列被转换为硬件原子操作。由于 ARM 不符合全内存顺序(TSO),该项目使用真实的内存屏障来管理这些操作。

“没有 Wine,也没有 JIT:游戏作为原生代码在单个进程中运行。”

— GitHub - adrbn/bo2-mac: Call of Duty: Black Ops II statically recompiled from 32-bit x86 Windows to native ARM64 macOS:

图形和运行时翻译

由于游戏依赖于 Direct3D 11,该项目实现了一个虚假的 COM 层,将这些调用转换为 Apple 的 Metal 框架。着色器转换由 HLSLcc 处理,这是一个将 DXBC 着色器转换为兼容 Metal 代码的 C++ 库。

D3D11 到 Metal 渲染器转换图表
该项目实现了一个自定义层,将 Direct3D 11 图形调用转换为 Apple 的 Metal 框架。github.com

此图表解释了“图形和运行时翻译”部分描述的图形转换机制。

其他系统组件也被移植到原生 macOS 框架。XAudio2 被映射到 CoreAudio,视频使用 libvpx 解码。该项目还包含一个本地响应器来模拟 Demonware 服务,允许游戏在没有互联网连接的情况下处理大厅和存储请求。

技术权衡与限制

虽然游戏可以原生运行,但目前仅限于本地游玩。由于项目依赖于本地响应器来模拟游戏的后端,因此不支持在线服务、局域网(LAN)或合作模式。此外,僵尸模式和多人模式的比赛规则是在“洁净室”环境中自定义编写的,这意味着其行为可能与原版游戏略有不同。

该项目还面临硬件限制;开发者报告称,Mac 在长时间运行过程中发热严重,在 M1 芯片上温度达到 111–116 °C。此外,虽然转换成功,但游戏仍是本地体验,用户仍需拥有原始 Steam 副本才能构建该应用程序。