使用 LLM 读取 68000 汇编,将 1993 年的 Amiga 游戏移植到 Godot

摘要

Claude Fable 5 成功将 1993 年的 Amiga 游戏 Babylonian Twins 移植到 Godot 4,自动翻译了原始的 68000 汇编代码(72,758 行)和后来的 2010 年 C++ 引擎(34,000 行)。AI 重建了未公开的文件格式,复现了与原版完全一致的二进制文件,并暴露了数十年来从未被发现的 Bug。


为什么这项实验意义重大

作者想测试现代 LLM 能否理解从未出现在训练数据中的、未公开的 68k 汇编代码。通过向 Claude 提供完整的 Amiga 源代码、资源和构建工具,作者可以将 AI 生成的移植版与原始二进制文件进行逐字节比较,为 LLM 在底层逆向工程任务上提供了一个具体的基准。


步骤 1 – 不到一小时移植 2010 年的 C++ 引擎

  • 结果: 在 21 分钟内搭建了一个可玩的 Godot 项目,复现了整个 34,000 行的 C++ 代码库。
  • 关键洞察: AI 保留了原始的固定 tick 逻辑(60 Hz),并没有用 Godot 的 CharacterBody2D 替换自定义的移动代码。保留手写的碰撞例程避免了微妙的物理效果不匹配。
  • 技术说明: 原始游戏使用了乘法阻力系数(每个 tick velocity.x *= 0.85)。由于原版以 50 Hz 运行,相同的常数在 60 Hz 下会感觉不对。AI 将两种 tick 频率分开处理,保留了原始手感。

步骤 2 – 自动重建 68000 汇编

  • 结果: Claude 重建了 1993 年的源代码,使用 vasm 进行汇编,并生成了与发布的 Amiga 磁盘逐字节完全一致的二进制文件。
  • 工作原理: 模型编写了一个预处理过程,以弥合 ASM-One 和 vasm 之间的方言差异(例如 cmp #4,d0 编码),并生成了一个脚本来修复由 2008 年的一次传输导致的损坏的文件名映射。
  • org 处理: AI 了解到原始代码在没有链接器的情况下使用了手动内存布局(org $6a000)。它正确地复现了该布局,除了一个 ds.b 800 块,因为 ASM-One 的“skip”语义有所不同;AI 最初输出了 800 个零字节,将后续数据偏移了 944 字节。当重建的演示渲染出错误的图形时,这个错误被发现了。
  • 变量区差异: 大约有 108 个字节存在差异,因为发布的二进制文件是运行后 RAM 的快照,而全新的汇编将这些变量留为零。AI 解释说,代码在读取这些变量之前会先写入它们,因此这种差异是无害的。

解码未公开的格式

关卡地图

  • 关卡加载器由 1,652 行未公开的 68000 代码组成。AI 通过追踪绘制例程并提取宽度/高度常量,推断出了瓦片网格格式(无标头,压缩块)。
  • 它重新生成了所有五个关卡,将其渲染为 PNG,并与作者 2020 年的截图进行了像素级完美比较。两处不匹配(天空渐变和水色循环)被追踪到缺失的 copper-list 数据,随后 AI 补上了这些数据。

地图单元格属性

  • 每个 16 位单元格打包了一个 6 位属性、一个 bank 选择位和一个 8 位瓦片索引。AI 通过分析绘制循环(屏蔽低位字节)和碰撞例程(屏蔽高位)发现了属性位。它重建了完整的属性表,包括实心地面、可攀爬瓦片、伤害代码、门和致命区域。

对象表

  • 对象按屏幕存储在自定义表中。AI 识别了标记($1111 = 空屏幕,$2222 = 死亡对象)并解码了行为偏移量,例如 hiddenwallR-lrb。然后,它将所有对象坐标转换为世界空间,并根据渲染的地图进行了验证。

Copper-list 天空渐变

  • 天空颜色由 copper list 生成,该列表写入一系列颜色字(例如 dc.w $09FF,$09EF,…)。AI 提取了关卡 2 的 24 字渐变,将其渲染为垂直条带,并在初始构建遗漏后将其重新添加到移植版中。

精灵表歧义

  • Amiga 精灵以平面位图形式存储。AI 检测到表大小存在歧义(frames * width * height * 2 * 5)并要求作者澄清。正确的解释是两个堆叠的行,每个朝向一行,随后 AI 对此进行了解码。

步骤 3 – 将原版作为客体嵌入现代构建中

  • 在一个晚上,AI 添加了一种“客体”模式,在 Godot 可执行文件中以 50 Hz 启动 1993 年的游戏,并在玩家返回现代版本时切换回 60 Hz。
  • 所有资源(PNG、WAV、JSON)均由 Python 脚本一次性提取;行为在 GDScript 中重新实现。
  • 最终的 Steam 版本发布时包含了现代游戏,外加原始的 Amiga 版本作为第二个启动选项。

AI 驱动的移植发现的 Bug

Bug 原始症状 AI 生成的修复
卫兵推击范围 关卡 2 中高台上的卫兵会将玩家推过坚硬的岩石。 恢复了缺失的上限检查(cmp.w #4,d4; bpl Sg.Far)。
隐藏门瓦片 门显示为空旷的天空,因为它们是由运行时代码绘制的,而不是存储在地图中。 在移植版中添加了运行时门绘制例程。
蹦床物理 在现代构建中跳跃感觉太高。 发现 2010 年 iOS 构建中保留的按住跳跃标志导致了按下时释放的不匹配;在 Godot 中更正了输入处理。
精灵表朝向 AI 最初镜像了双胞胎的朝向。 澄清了原始表包含两行(左/右)并保持了正确的朝向。
缺失的天空渐变 第一次重建渲染了平坦的天空。 重新添加了 copper-list 颜色表,消除了像素差异警告。

由 LLM 自动化的发布工作流

  • AI 生成了命令行标志(--level--pose--drive--probe--screenshot),以实现无头测试和脚本化游戏玩法。
  • 它生成了所有必需的商店分辨率的截图,以每种语言启动游戏,并使用真实字体捕获游戏内字幕。
  • 商店元数据(标题、描述、图标)被自动填充;Steam 的 Web 仪表板只需要手动登录。 | 从 Google Play 抓取评论、进行解析,并将任何报告 Bug 的评论(例如,一星评价“cant get through door on level one”)呈现出来以便立即修复。

社区反应(精选 HN 评论)

mattjoyce: “我下载了一个 ZX81 内存转储,并让 Claude 用 Go 重建它。它搞定了。” – 突显了 LLM 在复古计算考古学方面的更广泛潜力。

hedgehog: “让 Claude 为类似的移植导出一份工程指南将会很有趣。” – 表明该工作流本身可以成为一个可重用的蓝图。

robviren: “过去那些非标准的、充满 Hack 的代码量感觉今天根本无法触及。” – 强调了 AI 如何弥合了 30 年的知识鸿沟。

coder-pm: “你有没有在 UAE 中使用相同的输入将移植版与原版进行过对比运行?” – 指出了一个有价值的未来验证步骤;作者确认进行了逐像素的差异检查。


这对未来的复古移植意味着什么

  • 可行性: LLM 可以阅读未公开的 68k 汇编,重建缺失的格式,并在最少的人工指导下生成忠实的现代移植版。
  • 速度: 整个流程——从源代码导入到可运行的 Godot 构建——大约花费了 5 小时的连续 AI 执行时间,远快于手动重写所需的时间。
  • 保存: 逐字节相同的重建保证了原始游戏可以被归档、研究并在现代硬件上执行,而不会丧失真实性。
  • Bug 发现: 自动化逆向工程发现了潜伏了三十年未被察觉的 Bug,展示了超越单纯代码翻译的实际效益。

游玩渠道

  • 1993 年原始 Amiga 版本: itch.io 上的免费磁盘镜像(使用 FS-UAE、WinUAE 或真实硬件运行)。
  • 最终版: 可在 iOS、Android 和(2026 年秋季)Steam 上玩,1993 年版本作为辅助启动选项捆绑在内。

该移植由在 Claude Code 中运行的 Claude Fable 5 驱动;作者提供了笔记、仓库和原始二进制文件,AI 生成了本文的初稿,随后进行了逐行编辑。

Sources

相关