引言:街机黄金时代的硬件密码
1991 年,当《Street Fighter II: The World Warrior》席卷全球街机厅时,它不仅仅是一款格斗游戏,更是 Capcom CPS-1(Capcom Play System 1)硬件平台的巅峰之作。这款基于 M68000 处理器的街机系统,以其独特的图形架构和硬件设计,支撑了从《Final Fight》到《Street Fighter II》等一系列经典作品。三十多年后的今天,逆向工程研究者们正试图解开这个硬件系统的技术密码,从 ROM 数据中还原当年的设计智慧。
本文将从硬件架构、ROM 数据格式、图形系统解析三个维度,深入探讨 Street Fighter II CPS-1 逆向工程的技术实现路径。
一、CPS-1 硬件架构:三核协同的专用系统
1.1 处理器架构:M68000 + Z80 的黄金组合
CPS-1 系统采用了经典的三处理器架构:
- 主处理器:Motorola 68000 @ 10MHz(部分后期版本 12MHz)
- 声音处理器:Zilog Z80 @ 3.579545MHz
- 图形处理器:定制 ASIC CPS A-01(由 Ricoh 制造)
这种架构在当时代表了街机硬件的最高水平。M68000 作为 16/32 位处理器,提供了足够的计算能力处理游戏逻辑和物理模拟;Z80 专门负责 FM 合成音效和 PCM 采样播放;而定制 ASIC 则承担了所有图形渲染任务,实现了硬件加速的 tile-based 渲染。
1.2 主板结构:A-B-C 三板系统
CPS-1 采用模块化设计,由三块电路板组成:
- A 板(主板):包含所有处理器、内存和核心逻辑电路
- B 板(ROM 板):存储游戏程序、图形数据和声音数据
- C 板(安全板):包含游戏特定的安全芯片,防止盗版
这种设计使得游戏更换相对容易,只需更换 B 板和 C 板即可。对于逆向工程而言,这意味着 ROM 数据集中在 B 板上,便于提取和分析。
1.3 内存布局与总线结构
系统内存主要包括:
- 主程序 ROM:通常为 512KB-1MB,存储 68000 机器码
- 图形 ROM:2-4MB,存储 tile 数据和精灵表
- 声音 ROM:512KB-1MB,存储 Z80 程序和音频样本
- 工作 RAM:64KB 主 RAM + 16KB 视频 RAM + 2KB 声音 RAM
总线结构上,68000 通过地址总线和数据总线访问所有资源,而 Z80 通过专门的接口与主系统通信。图形 ASIC 直接访问视频 RAM 和图形 ROM,实现硬件加速的图形操作。
二、ROM 数据格式解析:二进制中的游戏世界
2.1 ROM 文件组织
典型的 Street Fighter II ROM 文件集包含多个文件,每个对应特定的数据区域:
sf2_01.rom // 主程序(68000代码)
sf2_02.rom // 主程序续
sf2_03.rom // 图形数据(tiles)
sf2_04.rom // 图形数据续
sf2_05.rom // 精灵数据
sf2_06.rom // 声音程序(Z80代码)
sf2_07.rom // PCM音频样本
sf2_08.rom // PCM音频样本续
sf2_09.rom // 调色板数据
2.2 程序代码结构
68000 程序代码采用大端序(big-endian)格式存储。逆向工程的第一步是反汇编这些代码,理解游戏逻辑:
; 典型的68000指令示例
move.w #$2700,sr ; 设置状态寄存器,禁用中断
lea $ff0000,a0 ; 加载视频RAM基地址到地址寄存器
move.l #$12345678,(a0) ; 向视频RAM写入数据
游戏逻辑通常包括:
- 角色状态机:站立、移动、攻击、防御等状态转换
- 碰撞检测:基于 bounding box 的简单碰撞系统
- AI 逻辑:对手行为的决策树
- 输入处理:摇杆和按钮输入的响应
2.3 图形数据格式
CPS-1 使用基于 tile 的图形系统,所有图形元素都由 8x8、16x16 或 32x32 像素的 tile 组成。图形数据在 ROM 中以平面格式存储:
Tile 数据结构:
- 每个 tile 占用 32 字节(8x8 像素,4 位 / 像素)
- 4 个位平面交错存储
- 需要配合调色板才能显示正确颜色
调色板组织:
- 每个调色板包含 16 个颜色条目
- 每个颜色为 12 位 RGB(4 位红,4 位绿,4 位蓝)
- 游戏通常使用多个调色板,支持 256 色同时显示
2.4 声音数据格式
声音系统包含两部分:
- FM 合成:通过 Yamaha YM2151 芯片生成
- PCM 采样:通过 OKI MSM6295 芯片播放压缩音频
PCM 样本通常采用 ADPCM 压缩,需要专门的解码算法才能还原为 WAV 格式。
三、图形系统深度解析:六层架构的艺术
3.1 六层渲染架构
CPS-1 的图形系统是其最精妙的设计,支持六个独立层的同时渲染:
- SCROLL1:8x8 像素 tile,最高优先级,常用于 GUI
- SCROLL2:16x16 像素 tile,主游戏层
- SCROLL3:32x32 像素 tile,背景层
- OBJ 层:精灵层,由多个 tile 组合成动画角色
- STAR1:星场效果层 1
- STAR2:星场效果层 2
正如 Fabien Sanglard 在CPS-1 图形系统研究中指出的,这种多层架构允许开发者创造复杂的视觉效果,如视差滚动、前景 / 背景分离等。
3.2 层优先级与混合
每个层都有可配置的优先级,开发者可以动态调整层的叠加顺序。更复杂的是 "优先级掩码" 功能:某些 tile 可以标记特定颜色,使其出现在 OBJ 层上方,即使 OBJ 层优先级更高。
这种机制在《Final Fight》中得到了巧妙应用:楼梯的某些部分出现在角色前方,而其他部分在角色后方,创造了真实的深度感。
3.3 精灵系统
OBJ 层支持最多 256 个 tile,这些 tile 可以组合成精灵。每个精灵由以下属性定义:
- 位置:屏幕坐标(X, Y)
- tile 索引:指向图形 ROM 中的 tile 数据
- 尺寸:1x1 到 4x4 个 tile 的组合
- 调色板:使用的颜色集
- 翻转:水平 / 垂直翻转标志
精灵系统的高效实现使得 Street Fighter II 能够流畅显示多个动画角色,每个角色包含数十个不同的动作帧。
3.4 视差滚动实现
Street Fighter II 大量使用视差滚动创造深度感。通过让不同层以不同速度移动,实现了伪 3D 效果:
// 伪代码:视差滚动计算
scroll1_x = camera_x * 1.0; // 前景层,完全跟随相机
scroll2_x = camera_x * 0.7; // 主层,部分跟随
scroll3_x = camera_x * 0.3; // 背景层,缓慢移动
E.Honda 关卡是视差滚动的典范:前景的浴缸边缘(SCROLL1)、地板和天花板(SCROLL2)、背景壁画(SCROLL3)以不同速度移动,创造了真实的浴室空间感。
四、逆向工程技术路径
4.1 ROM 数据提取工具链
现代逆向工程通常使用以下工具链:
- ROM 提取:使用专门的编程器从原始 ROM 芯片读取数据
- 反汇编:使用
das、IDA Pro或Ghidra分析 68000 代码 - 图形提取:自定义工具解析 tile 和调色板数据
- 声音提取:ADPCM 解码器还原音频样本
4.2 cpss:Capcom Sheets Explorer
Fabien Sanglard 开发的cpss 工具代表了逆向工程的高级阶段。这个工具能够从 ROM 数据中重建原始的设计图纸("sheets"),这些图纸是艺术家在网格纸上手绘的原始设计。
工具的工作原理:
- 解析图形 ROM 中的 tile 数据
- 根据 tile 使用模式重建精灵表
- 应用正确的调色板还原颜色
- 输出为 SVG 或 PNG 格式
通过 cpss,研究者发现了一些有趣的事实:
- Ryu 的图形数据占用 0x4500 区域
- Ken 大部分复用 Ryu 的资源,只添加少量差异
- E.Honda 和 Zangief 占用最多的图形资源(各 19 个 sheet)
4.3 游戏逻辑逆向
逆向工程不仅仅是提取资源,更重要的是理解游戏逻辑。以 Street Fighter II 为例,关键逻辑包括:
输入处理循环:
while (game_running) {
read_inputs(); // 读取摇杆和按钮
update_physics(); // 更新物理状态
check_collisions(); // 碰撞检测
update_animations(); // 动画更新
render_frame(); // 渲染帧
wait_vblank(); // 等待垂直消隐
}
AI 决策系统: AI 通常基于有限状态机,每个状态对应特定的行为模式。通过分析代码,可以发现 AI 如何根据距离、血量、对手状态做出决策。
4.4 现代重实现挑战
完全重写 Street Fighter II 面临多重挑战:
- 版权限制:不能分发包含原始 ROM 数据的代码
- 硬件模拟:需要精确模拟 CPS-1 的时序行为
- 资源重建:所有图形和声音需要重新创作或从 ROM 提取
- 逻辑还原:确保游戏手感与原版一致
成功的逆向工程项目通常采用 "clean room" 方法:一组工程师分析原始 ROM,生成技术文档;另一组工程师基于文档独立实现,避免版权问题。
五、技术细节与参数
5.1 关键内存地址
对于 Street Fighter II 逆向工程,以下内存地址至关重要:
- 视频 RAM 基地址:$FF0000
- 调色板 RAM:$FF8000-$FF87FF
- 精灵表 RAM:$FF9000-$FF97FF
- 输入端口:$FF8000(玩家 1),$FF8002(玩家 2)
- 垂直消隐标志:$FF8004
5.2 图形性能参数
- 屏幕分辨率:384x224 像素
- 刷新率:60Hz(NTSC)
- 颜色深度:12 位 RGB(4096 色)
- 同时显示颜色:256 色
- 最大精灵数:256 个 tile / 帧
- tile 缓存:1024 个 tile(视频 RAM)
5.3 逆向工程检查清单
进行 CPS-1 游戏逆向工程时,建议遵循以下步骤:
- 获取完整的 ROM 文件集
- 使用反汇编器分析 68000 代码入口点
- 识别关键数据表(角色数据、动画序列、攻击框)
- 提取图形数据并重建调色板
- 分析声音数据格式和解码算法
- 理解视频 RAM 布局和渲染流程
- 模拟输入处理和游戏逻辑
- 验证与原始 ROM 的行为一致性
六、结语:逆向工程的价值与未来
Street Fighter II CPS-1 的逆向工程不仅仅是一项技术挑战,更是对游戏开发历史的考古学研究。通过分析这些三十多年前的代码,我们能够:
- 理解硬件限制下的创意解决方案:在有限资源下实现复杂效果的设计智慧
- 保存数字文化遗产:防止经典游戏因硬件老化而永久消失
- 教育价值:为现代开发者提供历史视角和技术启发
- 推动仿真技术发展:精确的硬件模拟需要深入理解原始系统
随着工具链的完善和社区知识的积累,越来越多的经典街机游戏正在被逆向工程和保存。Street Fighter II 作为格斗游戏的里程碑,其技术实现将继续启发未来的游戏开发者和计算机历史研究者。
正如逆向工程师在sf2platinum 博客中所说:"我们不是在盗版游戏,而是在保存一段历史,理解那些让我们的童年充满欢乐的技术奇迹。"
资料来源:
- Fabien Sanglard, "Capcom CPS-1 Graphic system study" (2022)
- sf2platinum, "Reverse engineering Street Fighter 2 – The World Warrior" (2015)
- Fabien Sanglard, "CPSS: The Capcom Sheets Explorer" (2024)
- pcbjunkie.net, "Capcom CPS (CPS-1) Repair Guide"
延伸阅读:
- MAME 源代码:
src/mame/video/cps1.cpp - 68000 汇编语言教程
- 数字声音处理与 ADPCM 压缩算法