1993年AmigaゲームをLLMを使って68000アセンブリを読み解き、Godotに移植する方法
TL;DR
Claude Fable 5は、1993年のAmigaタイトルBabylonian TwinsをGodot 4に成功裏に移植し、オリジナルの68000アセンブリ(72,758行)と2010年のC++エンジン(34,000行)の両方を自動翻訳しました。AIは文書化されていないファイルフォーマットを再構成し、元のバイナリと完全に一致するものを再現し、30年以上発見されていなかったバグを明らかにしました。
この実験が重要だった理由
著者は、現代のLLMが訓練データに存在しなかった未文書化の68 kアセンブリを理解できるかどうかを検証したかった。ClaudeにAmigaの完全なソースコード、アセット、ビルドツールを提供することで、AIが生成した移植版を元のバイナリとバイト単位で比較でき、低レベルのリバースエンジニアリングタスクにおけるLLMの実力を明確なベンチマークとして評価できるようになりました。
ステップ 1 – 1時間未満で2010年のC++エンジンを移植
- 結果: 21分でプレイ可能なGodotプロジェクトがスケルトン化され、34,000行のオリジナルC++コードベースが再現されました。
- 重要な洞察: AIは元の固定ティックロジック(60 Hz)を保持し、Godotの
CharacterBody2Dにカスタム移動コードを置き換えることはしませんでした。手書きの衝突ルーチンを維持することで、微妙な物理的な不一致を回避しました。 - 技術的ノート: オリジナルゲームは乗法的ドラッグ係数(各ティックで
velocity.x *= 0.85)を使用していました。元のゲームは50 Hzで動作していたため、同じ定数を60 Hzで使用すると違和感が出ます。AIは2つのティックレートを別々に扱い、元の感覚を維持しました。
ステップ 2 – 68000アセンブリを自動的に再構築
- 結果: Claudeは1993年のソースコードを再構成し、
vasmでアセンブルし、配布されたAmigaディスクとバイト単位で同一のバイナリを生成しました。 - 仕組み: モデルはASM‑Oneと
vasmのディアレクトの違い(例:cmp #4,d0のエンコーディング)を橋渡しする前処理を記述し、2008年の移行で生じた破損したファイル名マッピングを修正するスクリプトを生成しました。 orgの扱い: AIは元のコードがリンカを使わず手動でメモリレイアウト(org $6a000)を指定していることを学習しました。レイアウトを正しく再現しましたが、ASM‑Oneの「スキップ」セマンティクスの違いにより、1つのds.b 800ブロックで誤りが生じました。AIは初期に800バイトのゼロバイトを出力し、その後のデータを944バイト分ずらしてしまいました。再構築されたデモが間違ったグラフィックを描画したことでこの誤りが発見されました。- 変数領域の差分: 約108バイトの差異が生じました。これは配布されたバイナリが実行後のRAMスナップショットだったのに対し、新規アセンブリでは変数がゼロの状態だったためです。AIは、コードがそれらの変数を読む前に書き込んでいるため、差異は無害であると説明しました。
文書化されていないフォーマットの解読
レベルマップ
- レベルローダーは未文書化の68000コード1,652行から構成されています。AIは描画ルーチンをトレースし、幅/高さ定数を抽出することで、ヘッダーなし、圧縮されたチャンク形式のタイルグリッドフォーマットを推測しました。
- すべての5つのレベルを再生成し、PNGにレンダリングし、著者が2020年に撮影したスクリーンショットとピクセル単位で比較しました。2つの不一致(空のグラデーション、水の色のサイクル)は、欠落したコッパーリストデータに起因しており、AIはその後それらを追加しました。
マップセルのプロパティ
- 各16ビットセルは6ビットのプロパティ、バンク選択ビット、8ビットのタイルインデックスをパックしています。AIは描画ループ(低バイトのマスク)と衝突ルーチン(高バイトのマスク)の両方を分析することで、プロパティビットを発見しました。固体の地面、登れるタイル、ダメージコード、ドア、キルゾーンを含む完全なプロパティテーブルを再構成しました。
オブジェクトテーブル
- オブジェクトは各スクリーンごとにカスタムテーブルに格納されています。AIはマーカー(
$1111= 空のスクリーン、$2222= 動作停止オブジェクト)を識別し、hiddenwallR‑lrbのような動作オフセットをデコードしました。その後、すべてのオブジェクト座標をワールド座標に変換し、レンダリングされたマップと照合しました。
コッパーリストによる空のグラデーション
- 空の色は、一連の色ワード(例:
dc.w $09FF,$09EF,…)を書き込むコッパーリストによって生成されます。AIはレベル2の24ワードのグラデーションを抽出し、垂直帯としてレンダリングし、初期ビルドで省略されたため、その後再追加しました。
スプライトシートの曖昧さ
- Amigaのスプライトは平面ビットプレーンとして格納されます。AIはシートサイズ(
frames * width * height * 2 * 5)に曖昧さがあることに気付き、著者に確認を求めました。正しい解釈は、向きごとに1行ずつ重ねた2行の構造であり、AIはそれを正しくデコードしました。
ステップ 3 – オリジナルを現代ビルド内にゲストとして埋め込む
- 1晩のうちに、AIは「ゲスト」モードを追加し、Godot実行可能ファイル内で1993年のゲームを50 Hzで起動できるようにしました。プレイヤーが現代バージョンに戻ると、自動的に60 Hzに戻ります。
- すべてのアセット(PNG、WAV、JSON)はPythonスクリプトで一度だけ抽出され、振る舞いはGDScriptで再実装されました。
- 最終的なSteamリリースでは、現代ゲームに加えて、1993年のAmigaバージョンを2番目の起動オプションとしてバンドルしています。
AI駆動の移植によって明らかになったバグ
| バグ | 元の症状 | AI生成の修正 |
|---|---|---|
| ガードの押す範囲 | 高いプラットフォーム上のガードが、レベル2でプレイヤーを固体の岩を貫いて押し出していました。 | 未実装の上限チェック(cmp.w #4,d4; bpl Sg.Far)を復元。 |
| 隠しドアタイル | ドアが空の空に表示された。これはマップに保存されているのではなく、実行時コードで描画されるため。 | ポートに実行時ドア描画ルーチンを追加。 |
| タンポリンの物理 | 現代ビルドではジャンプが高すぎるように感じた。 | 2010年のiOSビルドの「ジャンプ保持フラグ」が、押下時のリリース不一致を引き起こしていたことを発見。Godotでの入力処理を修正。 |
| スプライトシートの向き | AIは初期に双子の向きを反転させてしまいました。 | 元のシートには左右の向きごとに2行あることを明確にし、正しい向きを維持。 |
| 空のグラデーションの欠落 | 最初の再構築では空が平らに描画されました。 | コッパーリスト色テーブルを再追加し、ピクセル差分警告を解消。 |
LLMによって自動化されたリリースワークフロー
- AIはヘッドレステストとスクリプト化されたゲームプレイを可能にするコマンドラインフラグ(
--level,--pose,--drive,--probe,--screenshot)を生成しました。 - すべての必要なストア解像度でスクリーンショットを生成し、各言語でゲームを起動し、実際のフォントを使用してゲーム内キャプションをキャプチャしました。
- ストアメタデータ(タイトル、説明、アイコン)は自動的に埋められ、SteamのWebダッシュボードへのログインは手動で1回のみ必要でした。
- Google Playからのレビューをスクレイピングし、解析し、バグ報告レビュー(例:1星「レベル1のドアを通り抜けられない」)を即座に修正対象として浮き彫りにしました。
コミュニティの反応(選択されたHNコメント)
mattjoyce: 「ZX81のメモリダンプをダウンロードして、ClaudeにGoで再構築させました。完璧に再現できました。」 – LLMのレトロコンピューティング考古学への広範な可能性を強調しています。
hedgehog: 「Claudeが類似した移植向けのエンジニアリングガイドをエクスポートできると面白いでしょう。」 – このワークフロー自体が再利用可能なブループリントになる可能性を示唆しています。
robviren: 「過去の非標準的でハッキング的なコードの量は、今日の私たちには触れるのが不可能に思えるほど複雑です。」 – AIが30年分の知識ギャップを埋めていることを強調しています。
coder‑pm: 「オリジナルのゲームと同一の入力を用いてUAEでポートを実行しましたか?」 – 価値ある将来の検証ステップを指摘。著者はピクセル単位の差分チェックを実施したと確認しています。
これからのレトロ移植に意味するところ
- 実現可能性: LLMは未文書化の68 kアセンブリを読み解き、欠落したフォーマットを再構成し、最小限の人的指導で忠実な現代移植を生成できます。
- スピード: ソースインポートから動作するGodotビルドまでの一連のパイプラインは、5時間の連続的なAI実行で完了し、手動での書き直しよりもはるかに高速です。
- 保存: バイト単位で同一の再構築により、オリジナルゲームが現代のハードウェア上で完全な本物性を保ったままアーカイブ・研究・実行が可能になります。
- バグ発見: 自動リバースエンジニアリングにより、30年間発見されなかったバグが明らかになり、単なるコード翻訳以上の実用的利点を示しています。
ゲームをプレイする方法
- オリジナル1993年Amigaバージョン: itch.ioで無料のディスクイメージ(FS‑UAE、WinUAE、または実機で実行)。
- Definitive Edition(Godot 4): iOS、Android、および(2026年秋)Steamで利用可能。1993年版を2番目の起動オプションとしてバンドルしています。
- この移植はClaude Code内で実行されたClaude Fable 5によって推進されました。著者はノート、リポジトリ、オリジナルバイナリを提供し、AIはこの記事の初稿を生成しました。その後、著者が1行ずつ編集しました。
Sources
関連
- プロジェクト
- Dispatch
- Dispatch
- Dispatch
- Dispatch