返回首页

Game Boy 上 Assembler 实现的 Rungler 合成器

这篇文章描述了受 Rungler Circuit 启发的 Game Boy 合成器的创建。使用了 APU 通道、用于调制的 LFSR、RGBDS assembler。讨论了实时限制、VBlank 时序以及针对中高级开发者的优化。

Game Boy 作为合成器:Assembler 中的 Rungler
Advertisement 728x90

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)调制振荡器的频率。混沌理论的完美体现——微小的参数调整就能产生截然不同的声音。

Google AdInline article slot

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 代码发现它们也大量内嵌汇编。

Google AdInline article slot

关键挑战:

  • 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。音效:从脉冲到噪声。

Google AdInline article slot

关键收获:

  • Game Boy APU 适合 LFSR 调制,但实时受重触发和 4 位分辨率限制。
  • VBlank 是 UI 成败关键(<1500 周期);汇编提供宝贵余量。
  • GBC 振荡器读取寄存器未文档化,依赖模拟器。
  • 位运算替代乘法:足以实现混沌效果。
  • 可扩展项目:Wave CH3、Karplus-Strong 下一步。

未来方向

下一步:4 位合成器(CH3 方波)、Karplus-Strong/Risset 鼓、视听表演(类似 Robert Henke)、profiler 调试、挑战 16 位运算极限。

— Editorial Team

Advertisement 728x90

继续阅读