Game Boy 合成器:用汇编语言打造 Rungler
为 Game Boy (DMG/CGB) 开发一款受模块化合成与序列器启发的软件合成器。本项目从模拟 Rungler 电路 开始——这是 Rob Hordijk 的设计,包括两个振荡器和一个移位寄存器,用于产生混沌调制。全程使用 Sharp SM83 汇编实现,仅在 BGB 和 SameBoy 模拟器上测试。
背景与灵感
灵感来源于发现 Ess Mattisson 的作品:他在 Dirtywave M8 上做的单轨即兴演奏,以及 Junior 插件——一款类似 LSDJ 的 4 位合成器。RetroPlug 可以将 Game Boy 模拟器作为 VST 插件接入 DAW,并支持 MIDI 控制。目标?从 Game Boy 的 APU(4 个声道:2 个脉冲波、1 个方波、1 个噪声)中榨取出混沌音效——哔哔声、咚咚声和噪声。
Rungler 电路:两个振荡器,其中一个触发 3 位线性反馈移位寄存器 (LFSR)。其输出(0–7)调制振荡器的频率。混沌理论的完美体现——微小的参数调整就能产生截然不同的声音。
Game Boy 技术能力
拆解 APU 和 CPU,评估可行性:
- 移位寄存器:8 位字节,支持位运算(移位、OR)。实现简单。
- 振荡器:通道 1–2(带占空比的脉冲波)。最低频率 64 Hz,加上计数器用于下采样。通道 1 支持扫频。
- 调制:写入音频寄存器(如 $FF17 控制 CH1 音量)。无硬件乘法,使用位运算代替。音量:4 位(0–$F)。频率:NR13/NR14,在帧结束时应用,不重触发。
- 读取振荡器:仅 GBC 支持(未文档化寄存器),BGB/SameBoy 均兼容。
- UI:VRAM 中的精灵,VBlank 中断(约 60 Hz,4560 个周期)用于更新。基于图块的图形,分辨率 160x144。
实时陷阱:重触发声道会产生爆音;频率调制更平滑。
汇编开发
工具:RGBDS + VSCode 插件。为何选汇编而非 C?实时优化——剖析他人 C 代码发现它们也大量内嵌汇编。
关键挑战:
- VBlank 时机:逻辑置于中断中,控制在 1500 周期内(经 profiler 验证)。超限会导致撕裂(屏幕垃圾)。
- 16 位运算:手动操作 A 寄存器,追踪进位。
- 位运算:无乘除法——用查表或移位/OR/XOR 替代。
- 内存:VRAM 写入仅限 VBlank(扫描线 0–153)。
入门:教程、Pandocs、AI 辅助写“Hello World”。UI:光标、参数(频率、调制),响应式更新。
实现与限制
- LFSR 逻辑:由 osc1 触发,osc2 门控输入。3 位 → DAC(0–7)→ 缩放 + 偏置 → 寄存器。
- 序列:LFSR 生成触发,周期性重触发。
- 优化:清屏、光标绘制、LFSR 可视化。Profiler 确保安全区。
成果:并非完整的 Blippoo Box(受 4 位和时机限制),更像 Double Knot。音效:从脉冲到噪声。
关键收获:
- Game Boy APU 适合 LFSR 调制,但实时受重触发和 4 位分辨率限制。
- VBlank 是 UI 成败关键(<1500 周期);汇编提供宝贵余量。
- GBC 振荡器读取寄存器未文档化,依赖模拟器。
- 位运算替代乘法:足以实现混沌效果。
- 可扩展项目:Wave CH3、Karplus-Strong 下一步。
未来方向
下一步:4 位合成器(CH3 方波)、Karplus-Strong/Risset 鼓、视听表演(类似 Robert Henke)、profiler 调试、挑战 16 位运算极限。
— Editorial Team
暂无评论。