大家好!
我想分享一次 AI 游戏开发的经历,但这次更像是一个 AI 游戏 移植: Saint Dragon,我小时候很喜欢的那种半冷门的 Amiga 射击游戏,改编为原生 HTML/JS 浏览器游戏。
有趣的是,它没有源代码、原始资源和文档。我只有磁盘图像,属于 35 年历史的架构(至少在当时是著名的,而且有很多优秀的模拟器)。
我从原始磁盘的 ADF 和 IPF 开始。ADF 是逻辑复制:操作系统看到的字节。IPF 是更低层面的磁盘磁轨布局复制(我简化了),因此可以保留防复制磁盘。这很重要,因为磁盘空间很小,破解者常常从游戏中切除内容以适应磁盘。Saint Dragon 还使用了 Rob Northen 的 CopyLock 防复制保护,而 ADF 无法表示。
我使用 Claude 以及大量自己的旧 Amiga 知识完成了移植。首先我们构建了一个部分 Amiga 模拟器(68000 CPU、Copper、Blitter、Paula 音频、磁盘 DMA)。它不随游戏一起发布。我们把它当作显微镜,运行原始游戏,检查硬件状态,并将移植与其对比。要点如下:
-
磁盘解码:我们编写了 IPF → MFM → 自定义轨道解码器。所有 82/82 轨道通过游戏自己的校验,因此原始游戏本身接受了我们的重建。我们真实通过 CopyLock 的第一阶段,而模拟器必须支持
ILLEGAL指令作为控制流,因为 CopyLock 使用它们实现。 -
我们的第一次大失败:我们尝试在运行时从模拟器中抓取精灵。背景出现了大量敌人和 “DEMONSTRATION” 文字,帧缺失,一个 “player” 精灵竟然是敌人。我们丢弃了大约三分之一的工作,转而直接解码资源格式。规则变为:磁盘数据是真理的来源,截图仅用于验证。
-
资源:我们解码了全部 85/85 资源(自定义 RLE、平面图形),得到 685 个精灵对象、10 个调色板、背景和视差条。一个隐蔽的 bug:大型精灵是“链式”记录,索引错误会产生数十个无关的错误精灵。我们基本上通过匹配数据结构及其字段到实际数据字段实现。
-
完整反汇编:我们分类了 538/538 例程和全部 2,891 个调用站点,将一团乱码转化为可导航的调用图。
-
一个 1990 年的协程引擎:这很令人惊讶且意外,但每个敌人都有自己独立的栈并进行上下文切换,属于 80 年代末、90 年代初的小游戏。它几乎 1:1 对应 JavaScript 生成器,因此敌人脚本几乎逐行逐句翻译。
-
隐藏的波形语言:所有敌人出现都来自 602 条六字节记录,由滚动距离触发。很长时间我们以为没有 spawn 数据。其实有,只是我们还没找到读取它的光标。
-
碰撞:游戏使用双缓冲的 64×32 比特网格,子弹标记位,敌人消耗它们。基本上是 1990 年代手写的空间散列。
-
音频,最难的部分:乐器是真正的 68000 程序,而非采样,三次尝试重新合成都失败了。成功的办法是运行原始音频驱动在模拟器中,记录每次向 Paula 芯片写入的操作,然后在浏览器中重放该寄存器流。舞台主题在 98.3 秒时出现,正好符合解码后的分数数据预测。
-
结果:包括 intro、标题、全部 5 关及首领、配乐与音效、检查点、结局、最高分,以及键盘和触控控制,使其适配移动设备。
AI 表现出色与不足的地方:Claude 在搜索数千条汇编代码、翻译例程、编写探针和审计工具方面非常出色,而且永不疲劳。它在从外观猜测意义方面较弱:诸如 “这可能是龙精灵” 或 “这可能是调色板” 的合理标签常常是错误的。成功的循环是:
我发现了一个具体的不匹配(“这名敌人从错误侧进入”)→ 定位代码搜索 → 小幅修正 → 可执行检查 → 通过游玩确认。
我对原始游戏的记忆(以及与 WinUAE 并行运行的它)是最终的检验,而 Claude 提供了带宽。
如果你想了解所有血腥的细节(错误、死胡同、验证策略),完整的事后分析在这里: https://waldtier.com/games#saint-dragon
加分:与龙的链体代码亲密合作启发了我全新游戏 Vertebra,一款射击 Roguelike,你的尾巴即是你的构建。它可在这里玩: https://waldtier.itch.io/vertebra
很乐意回答问题!
评论 (0)