我前段时间开始用ChatGPT Pro反编译SFC版《三国志4》,最初动机是因为IDA Pro对SFC rom有现成的配置可用,以为是容易的入手点...结果光是训练(练兵)这一个功能就卡了几天,迭代了七八十个版本都几乎没有什么实质性进展。后来一请教Claude,发现还是GBA平台容易多了。事实证明果然如此——用GBA版《三国志》(也是4代移植),ChatGPT Pro几乎每一轮都能攻下一个子命令。
反编译难度也在一定程度上反映了汉化和修改难度(毕竟后者是前者的真子集;但这里没讨论素材压缩和汉化工具的问题,实际上汉化工程复杂度更多取决于素材处理,而不太依赖于游戏内部逻辑,所以实际情况会更复杂一些)
当然Claude的话靠不靠谱需要专家来评价,这里仅供参考...
太长不看版:
以完全反编译(matching decomp)为目标:
GBA < PS1 < GC ≈ Wii < NDS ≈ N64 < 3DS ≈ PSP < MD ≈ Wii U ≈ Vita ≈ DC < SFC ≈ FC ≈ GB ≈ GG/SMS ≈ NGPC ≈ WS/WSC ≈ Saturn ≈ PS2 ≈ Xbox ≈ PC-98 ≈ DOS < PC-88 < PS3 ≈ Xbox 360 < PS4 ≈ XB1 ≈ Switch ≈ Win x86/x64
以完全理解/还原游戏系统逻辑为目标(难度低于完全反编译):
GBA < PS1 < GC ≈ Wii < NDS ≈ PSP < N64 < 3DS ≈ MD ≈ Wii U ≈ Vita < FC ≈ GB < PS4 ≈ XB1 ≈ Switch ≈ Xbox ≈ Xbox 360 < SFC ≈ GG/SMS ≈ NGPC≈WS/WSC < DOS ≈ PC-98 < Saturn ≈ DC ≈ PS2 < PC-88 < PS3 < Win x86/x64
无论怎样,GBA都是最容易解析的平台,而PC端是最难的(当然很大程度上是加密/防破程序的问题)😂不得不说与我之前的直觉出入很大
以下给出Claude的解释(我上文还问过关于DOS/PS1的问题,所以回答会提及)。
问:SFC在IDA Pro里的支持比GBA/PS1好,反编译是不是会更容易?
答:这个前提其实值得商榷。我不确定 65816 在 IDA Pro 中的支持真的比 ARM 或 MIPS 更好——后两者是工业级主流架构,IDA Pro 和 Ghidra 对它们的分析能力都非常成熟(类型推断、调用约定识别、FLIRT 签名库等)。但即便假设 IDA 对 SFC 的支持确实不错,"静态分析工具好用"和"容易做反编译"之间的距离,在 SFC 上恰恰是最大的。原因出在更底层的地方。
65816 的状态依赖问题
65816 有一个让静态分析非常头疼的特性:寄存器宽度是运行时可变的。处理器状态寄存器中的 $m$ 标志和 $x$ 标志分别控制累加器 A 和索引寄存器 X/Y 是工作在 8 位还是 16 位模式。一条 LDA #$00 到底是加载一个字节还是两个字节,取决于执行到这条指令时 $m$ 标志的值。
这意味着反汇编器必须做 processor state tracking——追踪每条路径上的状态寄存器值。如果遇到间接跳转或者回调,状态就可能丢失,反汇编结果直接就会错。GBA 的 ARM/Thumb 虽然也有模式切换,但切换点是明确的(BX 指令),而且两种模式下指令的编码长度和行为都是完全确定的,不存在"同一条指令根据隐藏状态有不同语义"的问题。
真正的杀手问题:SFC 游戏大量是手写汇编
这才是最根本的差异。SFC 时代(大约 1990–1996),C 编译器对 65816 的支持并不好,生成的代码效率很低,在 SFC 有限的 3.58 MHz 主频下常常不可接受。所以大量 SFC 游戏——包括很多日系大作——是直接用 65816 汇编写的,或者至少核心逻辑和性能关键路径全是汇编。
这对 matching decompilation 是致命的:如果原始代码就不是 C 写的,那就根本不存在"还原出能编译成相同二进制的 C 代码"这回事。你最多只能做 reimplementation——理解逻辑后用现代语言重写,但不可能做到 byte-matching。
到了 GBA(2001–2006)和 PS1(1994–2003)时代,情况完全不同。GBA 几乎所有商业游戏都用 C 写,多数使用 GCC 的 ARM 交叉编译版本,少数使用 ARM 的商业编译器 ADS/RVCT。PS1 游戏绝大多数用 Sony 官方 PSYQ SDK 编译,底层也是 GCC。这意味着你有明确的编译器目标可以对齐。
一个具体的对比
假设你要反编译《火焰纹章:纹章之谜》(SFC)和《火焰纹章:烈火之剑》(GBA)。
SFC 版,你在 IDA 里看到的是直接操作 65816 寄存器的手写汇编,充满了 REP #$20 / SEP #$20(切换寄存器宽度)、直接页面寻址的技巧、以及为了节省 cycle 而做的各种非结构化跳转。要从中还原出"原始源码"——这个东西本来就不存在。
GBA 版,你看到的是 GCC 生成的标准 ARM 代码模式:函数序言/尾声规范、栈帧布局可预测、结构体访问有固定的 pattern。你可以在 decomp.me 上写 C 代码,用同版本 GCC 编译,然后逐字节比对。实际上 fireemblem8 的 matching decomp 项目已经推进得相当远了。
所以"工具支持好"到底意味着什么
IDA 的好支持帮助你读懂代码在干什么——这对 reimplementation 项目(比如理解游戏逻辑来做 fan translation 或 romhack)确实有价值。但 matching decompilation 的瓶颈从来不在"能不能读懂汇编",而在"能不能用同一个编译器复现出相同的二进制"。在这个维度上,SFC 因为手写汇编的普遍性,反而是最难的主机平台之一。
简单总结就是:GBA ≈ PS1 > SFC ≫ DOS,从 matching decomp 的可行性来看是这个排序。SFC 如果目标只是理解和重写,那工具支持确实有帮助;但如果目标是 byte-matching,它的先天条件其实比 GBA/PS1 差不少。
问:那么NDS跟GBA比反编译难度呢?
答:这是一个很自然的比较,因为两者都是 ARM 架构、都以 C 为主要开发语言。但实际做起来,NDS 的 matching decomp 难度明显高于 GBA,原因来自好几个层面。
编译器:从统一走向分裂
GBA 的生态非常干净——绝大多数游戏用的是 GCC 的 ARM 交叉编译版本(社区里常称为 agbcc),少数用 ARM ADS。基本上识别出编译器后就可以开工了。
NDS 这边就复杂了。任天堂官方 SDK 捆绑的是 Metrowerks CodeWarrior(mwcc),大量第一方和授权第三方游戏用的都是这个。但也有不少游戏用 GCC,还有一些用 ARM 的商业编译器。CodeWarrior 和 GCC 生成的代码模式差异很大——寄存器分配策略不同、函数序言/尾声风格不同、对结构体和数组的访问 pattern 不同。你必须先准确识别编译器和版本,才能开始 matching,而 CodeWarrior 的各版本之间行为差异也不小。
C++ 的引入
这可能是最大的实质性变化。GBA 时代,游戏几乎全是纯 C。到了 NDS,随着硬件能力提升和 SDK 的演进,C++ 使用变得普遍。这带来了一系列对 matching decomp 很不友好的东西:
虚函数表(vtable)的布局依赖编译器实现细节;模板实例化会生成大量你看不到对应源码的函数;构造函数和析构函数的隐式调用链很难从汇编中还原;name mangling 本身虽然可逆,但它意味着你的 C++ 代码必须在命名空间、类层次、参数类型上全部精确匹配。
一个 GBA 的函数可能就是一个平坦的 C 函数,局部变量和逻辑一目了然。同样功能的 NDS 代码可能是一个类的成员函数,通过 this 指针间接访问数据,中间穿插着编译器自动生成的析构逻辑。
Overlay 系统
GBA 的 ROM 直接映射到地址空间,整个程序就是一个 flat binary,分析起来很直观。
NDS 的游戏则普遍使用 overlay 机制——因为 NDS 的主 RAM 只有 4 MB,很多游戏会把代码分成多个 overlay,按需加载到同一段内存区域。这意味着同一个地址在不同时刻可能是完全不同的代码。函数之间的交叉引用变得不可靠,你需要先搞清楚 overlay 的加载表和生命周期,才能正确分析调用关系。
双处理器架构
GBA 只有一个 ARM7TDMI。NDS 有两个处理器:ARM9(主处理器,跑游戏逻辑)和 ARM7(副处理器,管音频、WiFi、触摸屏等)。ROM 里实际包含两个独立的二进制。虽然多数反编译工作集中在 ARM9 侧,但涉及音频或网络功能时就必须同时分析 ARM7 的代码以及两个处理器之间的通信协议(通过共享内存和 FIFO)。
代码规模
GBA ROM 上限 32 MB,实际多数游戏在 8–16 MB,其中很大比例是图形和音频资源,代码量通常不大。NDS ROM 上限 512 MB(虽然多数游戏在 32–128 MB),代码本身也更复杂——更多的系统功能调用、更深的抽象层次、更大的 SDK 库需要识别和剥离。
不过 NDS 也有做得不错的项目
Pokemon Diamond/Pearl/Platinum 和 HeartGold/SoulSilver 的 matching decomp 项目推进得相当好,这说明 NDS 的 matching decomp 是完全可行的。但这些项目投入的人力和时间都远超同系列 GBA 作品的反编译。而且 Pokemon 作为最受关注的系列,享有社区资源的极大倾斜——换一个关注度低的游戏,难度感受会更明显。
总结排序
如果把 matching decomp 的难度粗略排个序:
GBA < NDS < PS2/GC
GBA 和 NDS 之间的差距主要来自 C++ 和 CodeWarrior 带来的复杂性,而不是 ISA 本身。ARM 的底子让 NDS 仍然比 x86 平台或手写汇编平台好做很多,但它已经不再享有 GBA 那种"纯 C + 单一编译器 + flat binary"的理想条件了。
问:那么请你给所有主流掌机和家用主机(任天堂、世嘉、索尼、微软Xbox系列),还有PC平台(PC88/PC98/DOS/Windows X86/X64)从FC到几年前的Switch/PS4/Xbox One平台游戏反编译难度做一个排名。
答:这是一个涵盖面很大的问题,我尽量系统地整理。核心评估维度是:ISA 规律性、是否有 C/C++ 源码可还原、编译器生态的统一性、二进制结构复杂度、代码规模、以及操作系统/中间件层的厚度。
Tier S — 最容易
GBA:ARM7TDMI,纯 C,GCC 几乎一统天下,flat ROM 直接映射,代码量小。是 matching decomp 的理想平台,已有大量成功项目。
Tier A — 容易
PS1:MIPS R3000A,纯 C,PSYQ SDK(基于 GCC)覆盖率极高,硬件文档齐全。唯一增加难度的是 GTE(几何变换引擎)的协处理器指令需要特殊处理,但主体逻辑非常干净。
GC / Wii:PowerPC(Gekko / Broadway),C/C++,绝大多数游戏使用 Metrowerks CodeWarrior。Wii 和 GC 工具链高度一致,社区已经把 CodeWarrior 的代码生成模式摸得很透。Wind Waker、Twilight Princess、Melee 等大型项目推进顺利。C++ 的引入增加了一些复杂度,但 CodeWarrior 的行为比较稳定可预测。Wii 比 GC 略难一点,主要是代码规模更大。
Tier B — 中等
NDS:ARM9 + ARM7 双处理器,C/C++,CodeWarrior 或 GCC。Overlay 机制、C++ 使用、编译器多样性都增加了难度,但 ARM 的底子让它仍然可控。Pokemon 系列的 NDS decomp 项目证明了可行性。
N64:MIPS R4300i,主程序用 C(SGI 编译器工具链),这部分相对规律。真正的难点是 RSP 微码——N64 的图形和音频处理跑在 RSP 上,使用一套独立的自定义指令集,每个游戏的微码可能不同。主逻辑的 decomp 不算太难,但完整 decomp 必须处理微码。SM64 项目的成功证明了可行性,但它花了社区巨大的精力。
3DS:ARM11 + ARM9,C/C++,编译器主要是 GCC 或 ARM 的商业编译器。比 NDS 多了更厚的操作系统层(类 microkernel),系统调用和服务需要逆向。代码规模也上了一个台阶。
PSP:MIPS Allegrex(基于 MIPS R4000),C/C++,官方 SDK 编译器加上 GCC。VFPU(向量浮点单元)的指令需要额外处理,整体上和 PS1 同源但复杂度更高。
Tier C — 较难
Genesis / Mega Drive:Motorola 68000,这是一个有趣的过渡平台。68000 在当时有还算可用的 C 编译器,部分游戏确实用了 C,但大量游戏仍是手写 68K 汇编或 C 与汇编的深度混合。编译器种类也较杂。Sonic 系列的反汇编项目很成功,但那是 disassembly 而非 decompilation——因为原始代码就是汇编。
Wii U:PowerPC(Espresso),C/C++,工具链延续了 GC/Wii 的传统,理论上和 Wii 类似。但代码规模大幅增长,中间件层变厚,C++ 使用更重度,decomp 社区关注度也远不如 GC/Wii。
PS Vita:ARM Cortex-A9,C/C++,SN Systems 或 GCC 编译器。硬件本身不算复杂,但游戏普遍使用较重的 C++ 和各种中间件,社区资源也有限。
Dreamcast:SH-4,C/C++。开发环境分裂为 Katana SDK 和 Windows CE 两条路线,一部分游戏直接跑在实机上,另一部分跑在 WinCE 环境中,后者引入了 PE 格式和 Windows API 层,分析复杂度完全不同。SH-4 的工具支持也不如 ARM/MIPS/PowerPC 成熟。
Tier D — 困难
SFC / SNES:65816,如前面讨论的,大量手写汇编,寄存器宽度状态依赖,matching C decomp 基本不可行。但代码量相对有限,手动分析全部逻辑是可以做到的。
FC / NES:6502(Ricoh 2A03),几乎 100% 手写汇编。代码量很小(通常只有几十 KB),所以完全逆向是完全可行的,很多项目做到了完整的 matching disassembly。但因为没有 C 源码可还原,严格意义上不存在 decompilation,只有 disassembly。
GB / GBC:Sharp SM83(Z80 子集),情况和 FC 几乎一样——全手写汇编,代码量小。Pokemon Red/Blue 的完整 matching disassembly 是这个平台的标杆。
Game Gear / Master System:Z80,和 GB 类似,全手写汇编,代码量小。社区关注度远低于任天堂平台,工具和文档都少一些。
Saturn:双 SH-2 + 68000(音频)+ 两个 VDP,这是一个架构上极为复杂的平台。双 CPU 需要同步分析,两个独立的显示处理器各有自己的编程模型。开发难度在当年就臭名昭著,反编译难度同样很高。C 编译器是有的,但很多游戏为了榨取性能大量使用汇编。社区资源也非常有限。
PS2:MIPS R5900(Emotion Engine)+ 两个 VU(Vector Unit)+ IOP(I/O 处理器,本质是一个 PS1 CPU)。主逻辑用 C/C++ 写在 EE 上,这部分和 PS1 同源,理论上可以 decomp。但图形处理跑在 VU0/VU1 上,用的是专用微码,每个游戏不同。IOP 还有独立的驱动代码。多处理器 + 微码让完整 decomp 变得非常艰难。
Xbox:x86(Pentium III 定制版),C/C++,DirectX 8。从 ISA 角度这是最被工具支持的平台,IDA/Ghidra 完美支持。但问题在于:这本质上是一台 Windows PC,游戏用的是 MSVC 编译器,C++ 使用非常重度(vtable、RTTI、异常处理、STL),加上 DirectX 和各种中间件。代码规模比同代主机大不少。
PC-98:x86 16 位(8086 到 386 不等),早期全手写汇编,中后期有 C,但编译器种类繁多且多为日系工具(LSI C、Turbo C 日文版等)。segment:offset 寻址的所有 DOS 问题它都有,再加上日本独有的硬件外设(FM 音源、特殊显示模式)文档多为日文且不完整。
DOS:如之前讨论的——x86 16/32 位混合,编译器碎片化,大量手写汇编,segment 地址模型,DOS extender 的复杂性。
PC-88:Z80,几乎全部手写汇编。代码量不大但硬件文档稀缺,工具支持极有限,社区资源几乎为零。比 FC/GB 更难的原因不是技术本身,而是生态的荒芜。
Tier E — 极其困难到几乎不可行
PS3:Cell 架构——一个 PPE(PowerPC 核心)+ 六个可用的 SPE(Synergistic Processing Element)。PPE 上的主逻辑用 C/C++ 写,这部分用 PowerPC 工具可以分析。但性能关键代码跑在 SPE 上,每个 SPE 有自己独立的指令集、独立的 256 KB 本地存储、通过 DMA 和主内存交互。要完整 decomp 一个 PS3 游戏意味着要同时逆向 PPE 代码和多个 SPE 程序。再加上重度 C++、庞大的代码库、各种中间件,几乎没有 matching decomp 的可行性。
Xbox 360:PowerPC(Xenon,三核六线程),C/C++,MSVC 交叉编译。代码规模大、C++ 使用重、中间件多。虽然比 PS3 的 Cell 架构简单,但实际 decomp 难度仍然极高。
PS4 / Xbox One:x86-64,C/C++,代码规模达到数 GB,几乎所有 AAA 游戏都使用 Unreal Engine、Unity 等大型引擎或自研引擎,深度模板化的 C++,RTTI 和虚函数铺天盖地,大量着色器代码(GPU 侧),再加上商业中间件(Havok、FMOD、Wwise 等)层层叠加。理论上 x86-64 的工具支持是最好的,但代码量和抽象层次让 matching decomp 完全不现实。这些平台的逆向通常只针对特定模块或功能,不追求完整性。
Switch:ARM Cortex-A57,C/C++。和 PS4/Xbox One 属于同一代,很多游戏用同样的引擎。ARM ISA 本身很友好,但现代游戏的规模和复杂度使得完整 decomp 不现实。不过 Switch 的一些任天堂第一方游戏(如 BotW)因为社区热情极高,逆向工作推进得比同代索尼/微软平台的游戏要远。
Windows x86 / x64 游戏:排在最后不是因为 ISA 难,而是因为变量太多——MSVC/GCC/Clang/Intel 编译器都有人用,C++ 标准库实现不同,DRM/反篡改系统(Denuvo 等)主动对抗逆向,引擎和中间件碎片化,版本补丁频繁改变二进制。这是 matching decomp 条件最差的平台,几乎没有人尝试对 Windows 游戏做 matching decomp——逆向工作通常走 reimplementation 路线。
一个概览
如果用一个粗略的难度数轴来表示(左易右难):
GBA < PS1 < GC ≈ Wii < NDS ≈ N64 < 3DS ≈ PSP < MD ≈ Wii U ≈ Vita ≈ DC < SFC ≈ FC ≈ GB ≈ Saturn ≈ PS2 ≈ Xbox ≈ PC-98 ≈ DOS < PS3 ≈ Xbox 360 < PS4 ≈ XB1 ≈ Switch ≈ Win x86/x64
需要强调的是,FC/GB/SFC 这些"手写汇编平台"在这个排名里位置偏后,是因为严格意义上的 matching C decompilation 对它们不适用。如果把目标放宽为"完全理解并还原游戏的全部逻辑"(matching disassembly 或 reimplementation),它们因为代码量小反而很有优势,实际逆向工程的可行性相当高。
问:那么把目标改为"完全理解并还原游戏的全部逻辑",但是假设游戏核心系统是一样的(比如同一款游戏在各个平台上的移植版本),再给个排名。
答:好问题。当目标从"matching decomp"转变为"理解全部逻辑",排名会发生相当大的变化。核心评估维度变成了:反编译器/反汇编器输出的可读性、游戏逻辑在二进制中的信噪比、需要同时理解的代码流数量、以及平台抽象层的厚度。
同时因为假设游戏本身一样,代码规模的差异就主要来自平台胶水代码和中间件,而非游戏逻辑本身。
Tier S — 理解逻辑最容易
GBA:Hex-Rays 对 ARM7 的反编译输出质量很高,直接给你接近原始 C 的伪代码。flat ROM 意味着几乎没有平台噪音,游戏逻辑占二进制的绝大比例。你拿到的反编译结果基本就是"干货"。
PS1:Hex-Rays 对 MIPS 的支持同样成熟,输出可读性极高。几乎没有操作系统层,SDK 库函数容易识别和跳过。GTE 协处理器指令只涉及 3D 变换,不影响对游戏逻辑的理解。
Tier A — 容易
NDS:Hex-Rays ARM 输出依然很好。Overlay 和双 CPU 增加了一些结构上的分析工作,但一旦理清加载表、识别出 ARM7 侧只管外设,ARM9 上的游戏逻辑读起来和 GBA 差别不大。
GC / Wii:Hex-Rays 支持 PowerPC,输出可读性不错。SDK 库函数有签名可以批量识别跳过。硬件架构干净,图形 API(GX)是 CPU 侧的函数调用而不是独立微码,不存在需要单独理解的并行代码流。两者放一起是因为架构几乎一致,Wii 只是主频和内存略高。
PSP:Hex-Rays MIPS 输出和 PS1 一样可读。有一层轻量 OS,但系统调用容易识别。VFPU 指令在理解逻辑时可以当作"对向量做了某个数学运算"来处理,不构成实质障碍。
Tier B — 中等
N64:主 CPU 是 MIPS,Hex-Rays 给出的主逻辑伪代码可读性很好。问题在于图形和音频跑在 RSP 上,用的是独立指令集的微码。如果你只关心游戏逻辑(AI、状态机、数值系统),RSP 可以忽略;如果需要理解渲染管线或音频混合,就必须手动读微码,这部分没有好用的反编译器。
3DS:Hex-Rays ARM 输出良好。比 NDS 多了一层微内核操作系统,系统服务通过 SVC 调用,需要额外理解服务接口。但游戏逻辑本身一旦定位到,可读性不差。
Genesis / Mega Drive:Hex-Rays 对 68000 有反编译支持,输出质量尚可但不如 ARM/MIPS 那么干净。68000 的寻址模式比 RISC 复杂,伪代码中经常出现奇怪的指针运算需要人工解读。信噪比很好——几乎没有平台噪音。同时 Z80 子 CPU 只管音频驱动,游戏逻辑全在 68000 侧。
Wii U:PowerPC(Hex-Rays 支持),和 GC/Wii 同源。操作系统层比 GC/Wii 厚了不少,但核心问题是社区积累的平台知识远不如 GC/Wii 丰富——SDK 函数签名库不完善,很多系统调用需要自己逆向搞清楚含义。
Vita:ARM Cortex-A9,Hex-Rays 输出好。平台本身不构成太大障碍,排在这里主要是因为社区资源有限,SDK 和系统服务的逆向文档不如任天堂和 PS1/PS2 平台丰富。
Tier C — 较难
FC / NES:没有实用的反编译器,必须直接读 6502 汇编。但 6502 的指令集极小(大约 56 条指令),行为完全透明,没有任何平台抽象层。代码量通常只有 32–256 KB,其中还有大量是数据。一个有经验的人可以在几周内读完一个 FC 游戏的全部代码。难度不在于理解单条指令,而在于从平坦的汇编中重建高层逻辑结构——没有函数签名、没有类型信息、局部变量全是全局地址上的 ZP 操作。
GB / GBC:情况和 FC 几乎一样。SM83 指令集比 6502 还规整一些,代码量同样很小。Pokemon Red/Blue 被完整注释过,证明了完全理解的可行性。
PS4 / Xbox One:这是一个有趣的位置。Hex-Rays 对 x86-64 的反编译是所有架构中最好的——输出的伪代码几乎可以直接当 C 读,变量类型推断、结构体恢复、控制流重建都非常精准。如果你能定位到游戏逻辑函数,理解它的难度可能比 GBA 还低。但问题是定位本身。同一个游戏在 PS4 上的二进制可能是 GBA 版的 50–100 倍大小,绝大部分是引擎框架代码、平台适配层、中间件、以及 C++ 模板展开产生的大量胶水函数。从中找到真正的游戏逻辑就像在一座图书馆里找一本没有标签的书。一旦找到,读起来很轻松;但找的过程可能消耗大量时间。
Switch:ARM Cortex-A57,Hex-Rays ARM64 输出优秀。和 PS4/Xbox One 面临同样的信噪比问题,但任天堂第一方游戏通常中间件层比第三方游戏薄一些,逻辑定位会稍微容易。
Xbox(初代):x86,Hex-Rays 支持好。但这是第一个全面拥抱 DirectX + C++ 的主机平台,重度使用虚函数、COM 接口、异常处理。反编译输出虽然可读,但你需要在脑中重建整个 C++ 对象模型才能理解调用关系。
Xbox 360:PowerPC(Xenon),Hex-Rays 有支持。代码规模和 C++ 复杂度都上了一个台阶,三核架构意味着可能有多线程的游戏逻辑需要追踪。
Tier D — 困难
SFC / SNES:65816 没有好用的反编译器,必须读汇编。而 65816 的汇编比 6502 难读很多——寄存器宽度状态依赖意味着你读每条指令都要在脑中追踪 $m$ 和 $x$ 标志的当前值。寻址模式更多,bank 切换增加了地址空间的复杂性。代码量比 FC 大(通常 0.5–4 MB ROM,代码部分可能有几百 KB),纯手动理解工作量不小。
Game Gear / Master System:Z80,和 GB 类似都是读汇编,但社区积累的硬件文档和已逆向的参考项目远少于 GB。工具链也更原始。同样的工作在 GB 上可以借鉴大量前人成果,在 GG/SMS 上基本要从零开始。
DOS:Hex-Rays 对 16 位 x86 的反编译支持远不如 32/64 位。segment:offset 模型在伪代码中表现为大量 MK_FP 和 segment 运算,可读性很差。如果游戏用了 32 位 DOS extender(如 DOS/4GW),情况好一些——flat 内存模型,反编译输出接近正常的 32 位 C。但 16 位实模式的游戏读起来相当痛苦。再加上直接硬件操作(VGA 端口、DMA、中断向量)穿插在游戏逻辑中间,信噪分离也不容易。
PC-98:和 DOS 面临完全相同的 x86 16 位问题,再叠加一层:硬件外设(FM 音源芯片、GDC 显示控制器、bank memory)的寄存器操作文档大多只有日文资料,且不如 VGA/Sound Blaster 那样被广泛研究过。
Saturn:双 SH-2 + 68000 + 两个 VDP。Ghidra 对 SH-2 有基本支持但反编译输出质量不高。更根本的问题是,游戏逻辑可能分布在两个 SH-2 之间,你需要同时追踪两个 CPU 的执行流以及它们通过共享内存的同步。VDP 的显示列表编程又是一套独立的体系。架构本身的复杂性让"理解全部逻辑"的工作量翻倍。
Dreamcast:SH-4,Ghidra 有基本支持但反编译质量一般。最大的变数是 WinCE 路线——如果游戏跑在 WinCE 上,它本质上是一个 Windows CE 应用程序,带有 PE 格式、动态链接、Windows API 调用,分析模式完全不同于实机游戏。你甚至需要先搞清楚游戏走的是哪条路线。
PS2:主逻辑在 EE 上(MIPS),Hex-Rays 可以给出可读的伪代码,这部分其实不难。但 VU0/VU1 的微码是完全独立的代码流,IDA/Ghidra 对 VU 的支持非常有限。如果游戏逻辑中有任何部分被下放到 VU 上执行(有些游戏会把物理模拟或 AI 寻路放在 VU 上以利用其并行性),你就必须手动分析 VU 微码。IOP 侧还有音频和 I/O 驱动代码,又是一个 MIPS 子集的独立程序。
PC-88:Z80 汇编,代码量小,但硬件文档极度匮乏,现有逆向工具和社区资源几乎为零。同样是读汇编理解逻辑,在 FC/GB 上你有大量参考文档和前人项目可以借鉴,在 PC-88 上基本是独自面对黑箱。
Tier E — 极其困难
PS3:PPE 侧的 PowerPC 代码,Hex-Rays 可以处理。但性能敏感的游戏逻辑往往被分配到 SPE 上执行,而 SPE 使用的是独立的 Synergistic Processor Unit 指令集,Hex-Rays 不支持,Ghidra 的支持也很初级。每个 SPE 只有 256 KB 本地存储,代码通过 DMA 动态加载,你需要追踪 DMA 传输才能知道某个时刻 SPE 上跑的是什么代码。这不是简单的"多一个处理器"的问题——它根本改变了代码的组织方式和分析方法。
Windows x86/x64:看似矛盾——Hex-Rays x86-64 反编译是业界最强。但 Windows 游戏面临的是一组独特的非技术障碍。DRM 和反篡改(Denuvo、VMProtect、Themida)可能在你开始分析逻辑之前就挡住了你——这些系统会对代码进行虚拟化和混淆,你看到的不是原始指令流。即使绕过了保护,Windows 游戏的动态链接特性意味着大量逻辑散布在多个 DLL 中,运行时通过 COM/虚函数/回调串联,静态分析很难重建完整调用图。版本更新还会频繁改变二进制布局。相比之下,所有主机平台的 ROM/镜像都是静态的、完整的、没有保护的(或者保护已被社区攻破),这是一个巨大的起点优势。
总结:
GBA < PS1 < GC ≈ Wii < NDS ≈ PSP < N64 < 3DS ≈ MD ≈ Wii U ≈ Vita < FC ≈ GB < PS4 ≈ XB1 ≈ Switch ≈ Xbox ≈ Xbox 360 < SFC ≈ GG/SMS < DOS ≈ PC-98 < Saturn ≈ DC ≈ PS2 < PC-88 < PS3 < Win x86/x64
几个值得补充的微妙之处:FC/GB 跳到了 Xbox/PS4 前面——虽然后者有 Hex-Rays 的优秀输出,但从海量引擎代码中定位游戏逻辑的成本超过了直接读简单汇编的成本。PS4/XB1/Switch 和 Xbox/X360 放在一起是因为它们面临的本质问题相同(C++ 复杂度 + 信噪比),只是程度略有差异。PC-88 单独排在 Saturn/DC/PS2 之后,不是因为技术上更复杂,而是因为生态荒芜到几乎没有任何可借力的资源。Win x86/x64 垫底是因为 DRM/反篡改这个其他平台完全不存在的额外障碍。
和 matching decomp 排名的主要变化
几个值得注意的移动:
大幅上升的:FC 和 GB——从 Tier D 升到 Tier C。当目标只是"理解逻辑",它们代码量极小、零抽象层的优势就体现出来了,手写汇编不再是劣势而只是增加了一些阅读成本。
大幅上升的还有 PS4/Xbox One/Switch——从 Tier E 升到 Tier C。当你不需要 matching,只需要理解逻辑,Hex-Rays 的强大输出就变成了决定性优势。瓶颈从"不可能做 matching"变成了"需要从大量代码中定位逻辑"。
基本不变的:GBA 和 PS1 无论用什么标准都在最顶端。
相对下降的:没有平台真正下降,但 SFC 的相对位置没有改善——65816 的状态依赖问题不仅妨碍 matching decomp,同样妨碍人类阅读理解。它既没有反编译器的加持,又比 6502/Z80 难读,还比 FC/GB 代码量大,处在一个不太舒服的位置。