使用 LLM 讀取 68000 組語將 1993 年 Amiga 遊戲移植到 Godot

TL;DR

Claude Fable 5 成功將 1993 年的 Amiga 遊戲 Babylonian Twins 移植到 Godot 4,自動翻譯了原始的 68000 組語(72,758 行)以及後來 2010 年的 C++ 引擎(34,000 行)。AI 重建了無文件檔案格式,重現了與原始完全相同的二進位檔案,並暴露了數十年來從未被發現的錯誤。


為什麼這個實驗很重要

作者想測試現代的 LLM 是否能理解從未出現在訓練資料中的無文件 68k 組語。透過將完整的 Amiga 原始碼、素材和建置工具提供給 Claude,作者可以將 AI 生成的移植版與原始二進位檔案進行逐位元組的比較,為 LLM 在底層逆向工程任務上提供具體的基準。


步驟 1 – 在一小時內移植 2010 年的 C++ 引擎

  • 結果: 在 21 分鐘內建構了一個可遊玩的 Godot 專案,重現了整個 34k 行的 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 位元組。這個錯誤在重建的 demo 渲染出錯誤的圖形時被發現。
  • 變數區域差異: 大約有 108 位元組的差異,因為發布的二進位檔案是運行後 RAM 的快照,而全新的組譯則將這些變數留為零。AI 解釋說程式碼在讀取這些變數之前會先寫入它們,因此這種差異是無害的。

解碼無文件格式

關卡地圖

  • 關卡載入器包含 1,652 行無文件的 68000 程式碼。AI 透過追蹤繪圖常式並提取寬度/高度常數,推斷出了瓷磚網格格式(無標頭,壓縮區塊)。
  • 它重新生成了所有五個關卡,將它們渲染為 PNG,並與作者 2020 年的螢幕截圖進行了像素級的比較。兩個不匹配之處(天空漸層和水色循環)被追溯到遺失的 copper-list 資料,AI 隨後將其補上。

地圖格子屬性

  • 每個 16 位元的格子封裝了一個 6 位元的屬性、一個 bank-select 位元和一個 8 位元的瓷磚索引。AI 透過分析繪圖迴圈(遮罩低位元組)和碰撞常式(遮罩高位元)發現了屬性位元。它重建了完整的屬性表,包括實心地面、可攀爬的瓷磚、傷害代碼、門和致死區域。

物件表

  • 物件按畫面儲存在自訂表中。AI 識別了標記($1111 = 空畫面,$2222 = 死亡物件)並解碼了行為偏移量,例如 hiddenwallR-lrb。然後它將所有物件座標轉換為世界空間,並根據渲染的地圖進行了驗證。

Copper-list 天空漸層

  • 天空顏色由 copper list 生成,它寫入了一系列顏色字組(例如 dc.w $09FF,$09EF,…)。AI 提取了關卡 2 的 24 字漸層,將其渲染為垂直條紋,並在初始建構省略它後將其重新加入移植版。

Sprite-sheet 歧義

  • Amiga 的 sprite 以平面位元平面的方式儲存。AI 在工作表大小(frames * width * height * 2 * 5)中檢測到了歧義,並要求作者澄清。正確的解釋是兩個堆疊的行,每個方向一行,AI 隨後對其進行了解碼。

步驟 3 – 將原版作為來賓嵌入現代建構中

  • 在一個晚上,AI 加入了一個「來賓」模式,在 Godot 執行檔內以 50 Hz 啟動 1993 年的遊戲,當玩家返回現代版本時切換回 60 Hz。
  • 所有素材(PNG, WAV, JSON)由 Python 腳本一次性提取;行為在 GDScript 中重新實作。
  • 最終的 Steam 發布版提供了現代遊戲,加上 原始的 Amiga 版本作為第二個啟動選項。

AI 驅動的移植發現的錯誤

錯誤 原始症狀 AI 生成的修復
守衛推擊範圍 關卡 2 中高處平台上的守衛將玩家推過了堅固的岩石。 恢復了遺失的上限檢查(cmp.w #4,d4; bpl Sg.Far)。
隱藏門瓷磚 門顯示為空曠的天空,因為它們是由執行時程式碼繪製的,而不是儲存在地圖中。 將執行時門繪製常式加入移植版。
彈跳床物理 在現代建構中跳躍感覺太高。 發現 2010 年 iOS 建構中的按住跳躍旗標導致了按下時釋放的不匹配;修正了 Godot 中的輸入處理。
Sprite-sheet 方向 AI 最初鏡像了雙胞胎的面向方向。 澄清了原始工作表包含兩行(左/右)並保持了正確的方向。
遺失的天空漸層 第一次重建渲染了平坦的天空。 重新加入了 copper-list 顏色表,消除了像素差異警告。

由 LLM 自動化的發布工作流程

  • AI 生成了命令列旗標(--level, --pose, --drive, --probe, --screenshot)以實現無頭測試和腳本化遊戲過程。
  • 它產生了所有所需商店解析度的螢幕截圖,以每種語言啟動遊戲,並使用真實字體擷取了遊戲內字幕。
  • 商店元資料(標題、描述、圖示)被自動填寫;Steam 的 Web 儀表板只需要手動登入。 | 評論從 Google Play 被抓取、解析,任何回報錯誤的評論(例如一星的「cant get through door on level one」)都被提出以便立即修復。

社群反應(精選 HN 評論)

mattjoyce: 「我下載了一個 ZX81 記憶體傾印並要求 Claude 用 Go 重建它。它搞定了。」 – 突顯了 LLM 在復古運算考古學上的廣泛潛力。

hedgehog: 「讓 Claude 為類似的移植匯出工程指南會很有趣。」 – 建議工作流程本身可以成為可重複使用的藍圖。

robviren: 「過去那些非標準、取巧的程式碼數量,在今天感覺是不可能碰觸的複雜。」 – 強調了 AI 如何彌合 30 年的知識差距。

coder-pm: 「你有沒有在 UAE 中用相同的輸入對移植版和原版進行過測試?」 – 指出了一個有價值的未來驗證步驟;作者確認進行了逐像素的差異檢查。


這對未來的復古移植意味著什麼

  • 可行性: LLM 可以讀取無文件的 68k 組語,重建遺失的格式,並在最少的人工指導下產生忠實的現代移植版。
  • 速度: 整個流程——從原始碼匯入到可運行的 Godot 建構——耗時約 5 小時 的連續 AI 執行,遠快於手動重寫所需的時間。
  • 保存: 位元組相同的重建保證了原始遊戲可以被歸檔、研究,並在現代硬體上執行而不失真實性。
  • 錯誤發現: 自動化的逆向工程發現了潛伏三十年未被察覺的錯誤,展示了超越單純程式碼翻譯的實際好處。

去哪裡玩這些遊戲

  • 原始 1993 Amiga 版本:itch.io 上的免費磁片映像檔(使用 FS-UAE, WinUAE 或真實硬體執行)。
  • 決定版: 可在 iOS、Android 和(2026 年秋季)Steam 上取得,1993 年的版本作為次要啟動選項捆綁在一起。

該移植由在 Claude Code 中運行的 Claude Fable 5 驅動;作者提供了筆記、儲存庫和原始二進位檔案,AI 生成了這篇文章的初稿,隨後被逐行編輯。

Sources

相關