街机麻将作为日本特有的游戏类型,其硬件设计体现了 90 年代街机产业的独特技术路径。与通用 JAMMA 标准不同,麻将街机采用了专用 56 针接口、按键矩阵扫描和非标准音频处理方案。这些技术特性为硬件保存带来了独特的挑战:如何在芯片标签被刮除、文档稀缺的情况下,实现精确的硬件仿真与状态保存?
街机麻将硬件的技术特殊性
非标准接口与按键矩阵
标准 JAMMA 接口提供 4 方向 + 3 按钮的配置,而麻将游戏需要至少 19 个专用按钮(A-N 字母键 + 5 个呼叫键)。为解决这一矛盾,厂商采用了 56 针专用接口,并引入了按键矩阵设计。
如 Nicole Express 在分析《Mirage Youjuu Mahjongden》时指出:"麻将游戏不使用 JAMMA 标准。有几种引脚排列变体,但到 80 年代末期基本稳定在 56 针连接器,类似于 JAMMA 但没有钥匙针。而且引脚布局完全不同!"
矩阵设计通常采用 6×4 或 3×7 布局,通过扫描线减少引脚需求。这种设计带来了两个技术挑战:
- 时序敏感性:矩阵扫描需要精确的时序控制,延迟或抖动会导致按键检测失败
- 多按键处理:传统设计假设不会同时按下多个按钮,因此缺少防鬼键二极管
音频处理的多样性
音频处理体现了各厂商的技术分歧。Nichibutsu 采用单端输出(一个引脚接扬声器正极,负极接地),而其他厂商使用差分输出(两个引脚分别接扬声器正负极)。这种不一致性要求适配器必须支持两种模式,通常通过跳线或开关实现。
芯片级逆向工程挑战
《Mirage Youjuu Mahjongden》的 PCB 分析揭示了典型的逆向障碍:
- CPU 识别:64 引脚表面贴装芯片标签被刮除,通过位置和引脚配置推断为 Motorola 68000
- 音频芯片:两个 OKI M6295 ADPCM 芯片提供 8 通道音频
- 定制 ASIC:Data East DECO 156 芯片组变体,功能需要逆向推导
FPGA 精确仿真的技术实现
Cycle-Accurate 架构设计
FPGA 仿真的核心优势在于时钟级精确性。对于 Motorola 68000 CPU,需要实现:
- 指令流水线:精确模拟预取、解码、执行、写回四个阶段
- 总线时序:模拟地址 / 数据总线复用、等待状态插入
- 中断处理:7 级中断优先级和自动向量机制
// 简化的68000总线周期状态机
module m68k_bus_fsm (
input clk,
input reset,
output reg [1:0] bus_state
);
localparam S0 = 2'b00; // 地址输出
localparam S1 = 2'b01; // 数据建立
localparam S2 = 2'b10; // 数据采样
localparam S3 = 2'b11; // 空闲
always @(posedge clk or posedge reset) begin
if (reset) bus_state <= S0;
else case (bus_state)
S0: bus_state <= S1;
S1: bus_state <= S2;
S2: bus_state <= S3;
S3: bus_state <= S0;
endcase
end
endmodule
按键矩阵的硬件仿真
矩阵扫描需要精确的时序控制。典型实现包括:
- 扫描计数器:6 位计数器循环激活扫描线
- 去抖动逻辑:10ms 机械去抖动延迟
- 优先级编码:处理同时按键的冲突
module key_matrix_scanner (
input clk,
input [5:0] row_select,
output reg [3:0] col_read,
input [23:0] key_state
);
// 6×4矩阵扫描
always @(posedge clk) begin
case (row_select)
6'b000001: col_read <= key_state[3:0];
6'b000010: col_read <= key_state[7:4];
6'b000100: col_read <= key_state[11:8];
6'b001000: col_read <= key_state[15:12];
6'b010000: col_read <= key_state[19:16];
6'b100000: col_read <= key_state[23:20];
default: col_read <= 4'b1111; // 默认高阻
endcase
end
endmodule
音频系统的精确仿真
OKI M6295 ADPCM 芯片需要:
- ADPCM 解码引擎:实现 4 位差分脉冲编码调制
- 采样率控制:支持 4kHz-8kHz 可调采样率
- 混合输出:4 通道音频混合与音量控制
软件模拟器(MAME)的技术权衡
架构优势与局限性
MAME 作为软件模拟器,其优势在于:
- 开发效率:C++ 实现,调试工具丰富
- 可扩展性:易于添加新游戏支持
- 状态保存:完整的快照功能
但存在时序精度问题:
- 指令级仿真:非 cycle-accurate,时序偏差可能累积
- 中断延迟:软件模拟难以精确重现硬件中断响应时间
- 音频同步:采样率转换可能引入相位失真
MAME 调试工具链
逆向工程中,MAME 调试器是关键工具:
# 内存搜索与断点设置
find 0,10000,"HIGH SCORE",0
bp 1234,a0 == 0 && a1 == 0
trace game.log,0,{tracelog "PC=%08X ",pc}
# 状态保存与恢复
save state.sav
load state.sav
状态保存机制
MAME 的状态保存包含:
- CPU 上下文:所有寄存器、标志位、程序计数器
- 内存状态:ROM 校验和验证,RAM 完整转储
- 设备状态:定时器、中断控制器、DMA 控制器
- 音频状态:当前采样位置、缓冲区内容
硬件状态保存策略
完整状态捕获框架
有效的硬件保存需要多层次状态捕获:
| 层级 | 内容 | 验证方法 |
|---|---|---|
| 静态 ROM | 程序代码、图形数据 | CRC32/MD5 校验 |
| 动态 RAM | 游戏状态、变量 | 差异比较 |
| 寄存器 | CPU / 外围寄存器 | 快照对比 |
| 时序状态 | 定时器、计数器 | 周期计数 |
| 音频状态 | 缓冲区、相位 | 波形分析 |
FPGA 保存实现
FPGA 状态保存需要特殊设计:
- 扫描链插入:通过 JTAG 接口读取内部寄存器
- 内存转储:通过 DMA 控制器批量读取内存
- 时序标记:插入时间戳记录状态变化序列
// 状态保存控制器
module state_save_controller (
input clk,
input save_trigger,
output reg [31:0] state_data,
output reg state_valid
);
reg [2:0] save_phase;
reg [15:0] addr_counter;
always @(posedge clk) begin
if (save_trigger) begin
case (save_phase)
0: begin // 保存CPU寄存器
state_data <= cpu_reg_file[addr_counter];
addr_counter <= addr_counter + 1;
if (addr_counter == 16) save_phase <= 1;
end
1: begin // 保存内存
state_data <= main_ram[addr_counter];
addr_counter <= addr_counter + 1;
if (addr_counter == 65535) save_phase <= 2;
end
// ... 其他状态保存
endcase
state_valid <= 1;
end else begin
state_valid <= 0;
save_phase <= 0;
addr_counter <= 0;
end
end
endmodule
验证与完整性检查
状态保存的验证需要:
- 黄金参考:原始硬件运行记录作为基准
- 差异分析:比较仿真与硬件的关键行为
- 边界测试:测试极端条件下的状态一致性
验证指标包括:
- 指令一致性:执行相同指令序列的寄存器状态
- 时序准确性:关键操作的时钟周期计数
- 输出一致性:视频输出像素级比较
- 音频保真度:采样点幅度与相位误差
技术权衡与选择指南
FPGA vs 软件模拟器决策矩阵
| 考量因素 | FPGA 优势 | 软件模拟器优势 |
|---|---|---|
| 时序精度 | Cycle-accurate | 指令级近似 |
| 开发成本 | 高(硬件设计) | 低(软件编程) |
| 运行性能 | 实时硬件速度 | 依赖主机性能 |
| 状态保存 | 需要专门设计 | 内置完善支持 |
| 可调试性 | 硬件调试复杂 | 软件调试方便 |
| 兼容性 | 特定硬件 | 跨平台支持 |
实际项目建议
基于项目需求的技术选择:
-
学术研究 / 博物馆保存:优先 FPGA 方案
- 需要最高精度的时间准确性
- 长期保存的硬件独立性
- 预算相对充足
-
游戏社区 / 爱好者:推荐 MAME 方案
- 开发资源丰富,社区支持强
- 易于分发和使用
- 兼容现有游戏库
-
商业再发行:混合方案
- FPGA 核心确保准确性
- 软件层提供用户界面和功能扩展
- 平衡成本与体验
具体实施参数
对于街机麻将硬件保存,建议以下技术参数:
FPGA 实现参数:
- 主时钟:12.288MHz(兼容多种 68000 变体)
- 内存接口:16 位数据总线,24 位地址总线
- 视频输出:240p@60Hz,RGB 24 位色
- 音频采样:44.1kHz,16 位立体声
- 状态保存:每帧自动快照,最大 256 个历史状态
软件模拟器优化:
- 时序补偿:动态调整指令周期计数
- 缓存优化:预解码常用指令序列
- 状态压缩:增量式快照存储
- 验证模式:与 FPGA 参考实现交叉验证
未来展望与挑战
技术发展趋势
- AI 辅助逆向工程:机器学习算法识别芯片功能和信号模式
- 云仿真平台:基于 Web 的硬件仿真,降低使用门槛
- 标准化保存格式:统一的硬件状态描述语言(HSDL)
- 3D 扫描与建模:物理 PCB 的数字化保存
持续挑战
- 文档稀缺:特别是专用 ASIC 的内部文档
- 硬件老化:原始设备损坏导致参考基准丢失
- 法律障碍:知识产权保护与保存需求的平衡
- 技术传承:老一辈工程师知识的数字化保存
结语
街机麻将硬件的保存不仅是技术挑战,更是文化遗产的保护。FPGA 与软件模拟器各有优势,实际项目中应根据具体需求选择合适的技术路径。无论选择哪种方案,完整的状态保存策略、严格的验证流程和开放的文档共享都是确保长期保存成功的关键。
通过精确的硬件仿真,我们不仅保存了游戏本身,更保存了特定历史时期的技术创新与设计思想。这种技术保存为未来的研究、教育和创新提供了宝贵的基础资源。
资料来源:
- Nicole Express - "Playing Arcade Mahjong at Home? Or is it just a Mirage?" (2026)
- MAME 官方调试器文档 - 内存指令与状态保存功能
- IGS 街机逆向工程系列 - ASIC27 协议分析与反盗版技术