Hotdry.
systems-engineering

Street Fighter II CPS硬件逆向工程:从ROM数据到图形系统解析

深入分析Capcom CPS-1街机硬件架构,探讨Street Fighter II ROM数据格式解析、图形系统层叠机制与逆向工程技术实现路径。

引言:街机黄金时代的硬件密码

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 的图形系统是其最精妙的设计,支持六个独立层的同时渲染:

  1. SCROLL1:8x8 像素 tile,最高优先级,常用于 GUI
  2. SCROLL2:16x16 像素 tile,主游戏层
  3. SCROLL3:32x32 像素 tile,背景层
  4. OBJ 层:精灵层,由多个 tile 组合成动画角色
  5. STAR1:星场效果层 1
  6. 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 数据提取工具链

现代逆向工程通常使用以下工具链:

  1. ROM 提取:使用专门的编程器从原始 ROM 芯片读取数据
  2. 反汇编:使用dasIDA ProGhidra分析 68000 代码
  3. 图形提取:自定义工具解析 tile 和调色板数据
  4. 声音提取:ADPCM 解码器还原音频样本

4.2 cpss:Capcom Sheets Explorer

Fabien Sanglard 开发的cpss 工具代表了逆向工程的高级阶段。这个工具能够从 ROM 数据中重建原始的设计图纸("sheets"),这些图纸是艺术家在网格纸上手绘的原始设计。

工具的工作原理:

  1. 解析图形 ROM 中的 tile 数据
  2. 根据 tile 使用模式重建精灵表
  3. 应用正确的调色板还原颜色
  4. 输出为 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 面临多重挑战:

  1. 版权限制:不能分发包含原始 ROM 数据的代码
  2. 硬件模拟:需要精确模拟 CPS-1 的时序行为
  3. 资源重建:所有图形和声音需要重新创作或从 ROM 提取
  4. 逻辑还原:确保游戏手感与原版一致

成功的逆向工程项目通常采用 "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 游戏逆向工程时,建议遵循以下步骤:

  1. 获取完整的 ROM 文件集
  2. 使用反汇编器分析 68000 代码入口点
  3. 识别关键数据表(角色数据、动画序列、攻击框)
  4. 提取图形数据并重建调色板
  5. 分析声音数据格式和解码算法
  6. 理解视频 RAM 布局和渲染流程
  7. 模拟输入处理和游戏逻辑
  8. 验证与原始 ROM 的行为一致性

六、结语:逆向工程的价值与未来

Street Fighter II CPS-1 的逆向工程不仅仅是一项技术挑战,更是对游戏开发历史的考古学研究。通过分析这些三十多年前的代码,我们能够:

  1. 理解硬件限制下的创意解决方案:在有限资源下实现复杂效果的设计智慧
  2. 保存数字文化遗产:防止经典游戏因硬件老化而永久消失
  3. 教育价值:为现代开发者提供历史视角和技术启发
  4. 推动仿真技术发展:精确的硬件模拟需要深入理解原始系统

随着工具链的完善和社区知识的积累,越来越多的经典街机游戏正在被逆向工程和保存。Street Fighter II 作为格斗游戏的里程碑,其技术实现将继续启发未来的游戏开发者和计算机历史研究者。

正如逆向工程师在sf2platinum 博客中所说:"我们不是在盗版游戏,而是在保存一段历史,理解那些让我们的童年充满欢乐的技术奇迹。"


资料来源

  1. Fabien Sanglard, "Capcom CPS-1 Graphic system study" (2022)
  2. sf2platinum, "Reverse engineering Street Fighter 2 – The World Warrior" (2015)
  3. Fabien Sanglard, "CPSS: The Capcom Sheets Explorer" (2024)
  4. pcbjunkie.net, "Capcom CPS (CPS-1) Repair Guide"

延伸阅读

  • MAME 源代码:src/mame/video/cps1.cpp
  • 68000 汇编语言教程
  • 数字声音处理与 ADPCM 压缩算法
查看归档