
2026/09/03 23:28
1993 年の Amiga ゲームを Godot に移植し、LLM が 68000 アセンブリを読み取る
RSS: https://news.ycombinator.com/rss
要約▶
Japanese 翻訳:
歴史的な取り組みにより、1993 年の Amiga ゲーム「バビロニアの双子」が現代のデバイスへと持ち込まれ、その存続とアクセス可能性が確保されました。この作品は、当初イラクの工学部の学生であったムルタダ・サルマン氏が、Amiga 500(RAM は 512KB しか搭載しておらずハードディスクも未設置)上で純粋なアセンブリ言語を用いて開発されました。コモドールの経営破綻後、この稀少なタイトルは数十年間販売されずに放置されていましたが、2008 年に再び発見されました。以前に別のチームが 2010 年にモバイル向けへの移植を試みましたが、今般のプロジェクトでは専用の AI 駆動アプローチを用いて高忠実度での保存に注力しています。高度な人工知能とファイルシステムアクセス可能なワークフローを採用し、エンジニアたちは文書化されていないアセンブリコードをリバースエンジニアリングし、Godot 4 で元の C++ エンジンを再構築するとともに、平面ビットマップ解釈など複雑なグラフィックの曖昧さを解決しました。本プロジェクトは両方の体験を提供する点で特徴となっており、現代向けの移植版と、ディスクイメージに対してバイト単位同一の形で元の 1993 年版を実行する「ゲスト」モードを提供しています。リリースは秋に iOS、Android、Steam のプラットフォーム全体で行われ、「決定版」としては元の体験と現代のエングインを両方含みます。ローンチ後は継続的な AI 分析が行われ、ユーザーレビューで特定された出口プロンプトの問題など、自動パッチによって修正可能な隠れたバグに対処します。このイニシアチブは、失われた商業ゲーム史の一片を新しい観衆のために蘇らせるだけでなく、将来のレガシーソフトウェア保存活動において検証済みの基準としても確立されます。
本文
『バビロニア・ツインズ』を AI で現代へ:33 年の時を超えた移植プロジェクト
📜 プロジェクトの背景:1993 年の制約と挑戦
1993 年、イラク・バグダッド。経済制裁下でインターネットもなく、ハードディスクを持たない Amiga 500(RAM: 512KB)上で『バビロニア・ツインズ』が開発されました。
- 開発者: 当時のエンジニア学生(現在 33 歳)
- チーム:
- プログラミング:68000 アセンブラ純粋に手作業(全リソースはマニュアル一冊のみ)。
- 美術:ムルタダー・サルマン。
- 音楽:マヒール・アルサルマン。
- 環境の厳しさ:
- 電源は数時間しか入れず、メモリ不足でフロッピーディスクを頻繁に交換する必要があった。
- 50°C の猛暑によりハードウェアが故障したこともあった。
「手作業(by hand)」の意味: OS に頼らずゲームを実行する技術であり、起動時に割り込みベクタを保存してシステムを完全掌握しました。
move.l #$dff000,a0 ; ハードウェアレジスタの基準アドレス lea save(pc),a1 ; システムの状態を取得 move.w #$4000,intena(A0) ; AMIGAからの割り込み無効化
- Copper リスト: 画面をゲーム独自のプロセサブルビデオコプロセッサでリアルタイム制御。
- Blitter レジスタ: タイル移動の直接書き込みと完了待ち。
- CIA チップ: ジョイパッドからの直接読み取り。
このゲームはイラク初の商業ゲームでしたが、開発者の倒産や制裁により発売が頓挫し、ディスクは未公開のままとなっていました。2008 年、YouTube アップロード経由で再発見され、現在もスレッドが存在します。
注: 2010 年に同チームにより C++(約 3 万 4000 行)への移植と iPhone 向け展開が成功し、200 万人以上のダウンロードを記録しました。
🚀 なぜ今、再び挑戦するのか?
以前からの試みで AI モデルにレベルマップの意味を理解させることは難航していましたが、Claude Fable 5 の登場で状況が変わりました。
- 目標: Amiga アセンブラコードが含まれていない可能性が高いトレーニングデータの中で、論理推論能力をテストする。
- 3 つのステップ計画:
- 安全な依頼: 2010 年の C++ エンジンを Godot 4 に移植(コントロール基準)。
- 不公平な依頼: コメントのない 68000 アセンブラコード(7 万 2758 行)を Godot で再構築。
- 貪欲な依頼: 両者を統合し、1993 年版と現代版を同時に動作させる。
結果: レベルフォーマットは一度の試みで正常に読み込まれ、AI は私のヒントなしに完成しました。
⚙️ 移植の実行方法:Claude Code と自動化
ターミナルへのアクセスが可能だったため、ファイル編集からアセンブル、起動までを自動化して検証を行いました。
コマンドラインフラグによる精密制御
ゲームに以下のようなフラグを追加し、「感覚的な正しさ」を確認できるようにしました。
: レベルを直接読み込む--level=<名前>
: ツインズの位置と速度を正確に設定--pose=<仕様>
: スクリプトに従ってボタンを押す(フレーム単位)--drive=<仕様>
: スイッチ、ゲート、扉の状態をダンプ--probe
: フレームをレンダリングして終了--screenshot=<パス>
drive[btw_jump:2.2] pos=(25.44, 24.04) vel=(0.00, -14.51) ground=false apex_y=22.48
自動化されたチェック
- ヘッドレスチェック: コマンドラインフラグなしでスクリプトの全コンパイル確認とレベル構築失敗報告。
- ツールチェーン: vasm(アセンブル)と FS-UAE(起動)を活用。
- 人間による検証: 自動化された画像比較や「感覚的な正しさ」の確認は、私が視認して行いました。
🛠 ステップバイステップ:移植の詳細
ステップ 1:C++ 3 万 4000 行の一夜移植(Godot 4)
2026 年 7 月 1 日の深夜、21 分間で空の状態からプレイ可能なキャラクターまで作られました。
| タイムスタンプ | タスク内容 |
|---|---|
| 22:23 | Godot 4 プロジェクトの骨格作成、アセット同期 |
| 22:44 | 両方のツインズがプレイ可能に(衝突検出、物理演算など) |
| 23:19 | 全 38 種類のエンティティ移植完了 |
| 00:35 | 全画面フロー完了(メニュー、マップ、ストーリーなど) |
| 02:15 | macOS, iOS, Androidへのエクスポート完了 |
- 調整期間: 直後は「感覚的に正しい」と感じられず、約 3 日間かけてジャンプの軌道や物理演算の微調整を行いました。
- テスト協力: 13 歳の息子にビルドをプレイしてもらい、父子間のプロジェクトとなりました。
同じ単位、同じティック:60Hz vs 50Hz
元の Amiga 版は摩擦係数が各フレームごとに乗算的に適用されるため、ティックレート(更新周波数)が重要です。
- Amiga 版: 50Hz
- 移植版: 60Hz
static const float GROUND_DRAG_FACTOR = 0.85f; this->velocity.x *= GROUND_DRAG_FACTOR; // 各ティック!
- 1 秒間に
を 60 回掛ける摩擦力と、50 回掛けるものでは値が異なります。0.85 - 単一の定数で両方を統合するとゲームの挙動が変わるため、2 つの時計を維持しました。
CharacterBody2D の不使用
Godot の推奨物理システム
CharacterBody2D を使用せず、自作の移動コード(150 行)を移植しました。
- 理由: 他人の物理エンジンでは微妙な違和感が生まれ、独自の調整数やコメント(「将来の自分に向けたメモ」など)が含まれているため。
- 実装: 衝突処理ルーチンを一行ずつ移し、足元の位置補正などを独自に記述。
# キャラクターの足がタイルの中央にあるように0.5 を加える var bottom := pos.y + dim.y / 2 + 0.5 + i + fraction if int(bottom) == int(pos.y + dim.y / 2 + 0.49): continue var left := pos.x - dim.x / 4 # 非対称なプロブ!
ステップ 2:68000 アセンブラの完全再現(vasm)
7 万 2758 行に及ぶメモリのないアセンブラコードを、Apple Silicon Mac でバイト単位で再現しました。
- 課題:
命令によるリンカ・リロケーションの手動管理。レベルソースはアドレスごとに Amiga のメモリーレイアウトを行う必要があるため。org - 再構築までの時間: ファイルのフォルダから最初の一致に至るまでわずか15 分。
org $6a000 ; このセクションは $6a000 アドレスに配置 Mapadd: incbin "btwins:binary/L1/Map1.b" org mapadd+73*1024 ; マップ開始位置から 73KB 先へスキップ GLBtable: dc.w $3333,50,20,100 ; オブジェクトレコードの開始
重要発見: 1993 年当時のバイナリは、ゲーム実行後にメモリを保存してディスクに移行したスナップショットであり、単なるクリーンなアセンブラ出力ではありませんでした。変数の初期値ゼロと保存時の値の差異(約 108 バイト)がその証拠となりました。
ファイル形式の詳細な復元
レベルデータ
- ヘッダーも寸法情報もない数字のリストから、256 種類のタイルセットを読み取る。
- モデルは描画ルーチンを見つけ、グリッド幅と高さを計算し、すべてのレベルで最初の試行で正解しました。
マップセルのプロパティ(16 ビット)
各セルは以下のビット構成を持ちます。
| ビット | 内容 | 説明 |
|---|---|---|
| 15..10 | プロパティ (6 ビット) | 地面、登れる、痛い(反動)、致死、扉など |
| 8 | タイルバンク (1 ビット) | 使用する画像セットの選択 |
| 7..0 | タイル ID (8 ビット) | 256 種類の画像の中からどれを配置するか |
move.w (a1),d6 ; 同じセル and.w #$fc00,d6 ; 上位 6 ビットを保つ(プロパティ) bsr cbCheck ; 登れるか?痛い?
オブジェクトテーブル
敵やオブジェクトはマップではなく、ワールド座標上の小さなテーブルで管理されます。
Scr0: dc.w $3333,50,23,17 ; 生存オブジェクト:フレーム、次に x, y dc.w hiddenwallR-lrb,20 ; その振る舞い:崩壊壁(オフセット) ... dc.w $1111 ; このスクリーンの終わり
GAME.S のスクランブル
ほとんどのデータファイルはトリックで暗号化されていますが、
GAME.S は例外です。これはスクランブル解除ステップがない古いファイルであり、失われたディスクセットを回復する鍵となりました。
ドアはマップにない(真実)
- 勘違い: 「ドア」というタイルは存在せず、マップデータには穴のみが表示されていました。
- 実相: 18 バイトのオブジェクトレコードがランタイムでマップにスタンプされ、物理的な壁として機能します。
- 移植: この「空の穴」を正しく処理し、ドアの開閉状態を再現しました。
Copper スカイ(背景グラデーション)
Amiga 特有のカラーインデックス 31 を透明化し、Copper が選択されたスキャンライン上で背景色を塗り替えます。
col1: dc.w $09FF,$09FF,$09FF ; 空(青み) ... dc.w $0DCF,$0ECF,$0DCF ; 地平線近く(暖色系)
モデルはこのグラデーションを逃すことなく再現しました。
スプライトシーターの曖昧さ
平面形式のデータから描画順序を推論し、1993 年の選択(向かい合う方向ごとの 2 行スタック)を検出しました。
🔄 ステップ 3:古いゲームを新しいものに統合
「貪欲な依頼」により、1 つのプラットフォームで両版が動作します。
- 機能:
- ネームスペースとシーンホストを持ち、Godot エンジン内でシームレスに切り替え可能。
- 内部では 50Hz(Amiga 風)↔60Hz(現代風)を動的に変化させる。
- Steam 版への採用理由:
- データ、グラフィック、音楽は Python スクリプトで解読・変換済み(PNG, WAV, JSON)。
- ゲームの振る舞い(敵のパトロールなど)は独自言語で記述。
![画像イメージ:左右に 1993 年版と 2026 年版が表示された画面] (左: 1993 年 Amiga | 右: 2026 年 Godot)
🐛 発見・修正されたバグと欠陥
警備兵のバグ(レベル 2)
廊下を進むと、壁際に立っている槍を持つ兵士に攻撃されるケースが発生しました。
- 原因: 元のゲームでは「近づきすぎ」を両端で制限していましたが、移植版では上側の境界(近すぎる判定)が欠落しており、廊下全体から攻撃されてしまいました。
それより小さなもの
- 隠されたアートの問題: 扉の崩壊や偽の壁の破壊時に表れる第 2 のタイル層を「忠実に」再現すると、すべての秘密通路が最初から開きっぱなしになり、ゲームバランスが崩れました。
- ドアの問題: 「p1~p4」という鍵は単一のキーとして解釈され、チュートリアル出口が開かなくなりました。
- 音声: モノラル計算だったサウンドループがステレオ化し、音が半分になって停止・再開する現象が発生しました。
トリムボリンダ(ジャンプ)バグ
- 現象: ジャンプの高さが感じられず高く設定されていました。
- 原因: 入力処理の違い。2010 年版はイベント駆動(ボタンが物理的に解放されるまで待機)でしたが、Godot ではポーリング方式(保持を継続して報告)のため、ジャンプのタイミングがズレてしまいました。
📢 リリースと今後の予定
オープニング・レビュー
- スクリーンショット: 各ストアのピクセルサイズで起動し、真のフォントでキャプションバンドを描画。
- 言語対応: 11 カ国の言語に対応(当初ロシア語や韓語でエラーがありましたが修正済み)。
Steam とプラットフォーム上の課題
- Steam の負担: フォームが多く、メタデータ更新に API がなく、ブラウザからの手動操作が必須。
- レビュー対策: Google Play の公式 API は 7 日しか提供できず、15 年分のレビューをすべて収集するためにパブリックスクレイパーを使用。
重大な修正事例(1 スター評価)
Google Play で「出口を通れない」という 1 スターのレビューがありました。
「cant get through door on level one. opens but level dowsnt end」 (門を開いてもレベルが進まない)
- 原因: ゲームの出口は「開くアクション」と「進むアクション」が別々の操作です。欠落していたのは無料デモの最後と有料版の一部でした。
- 解決: このレビューをきっかけに修正し、2.0.3 として両プラットフォームで公開しました。
オリジナル版リリース(itch.io)
33 年後、1993 年の完全オリジナルは無料で提供されています。
- FS-UAE, WinUAE: エミュレーターでの起動可能。
- 真のハードウェア: Amiga 500 でプレイ可能。
🎉 まとめ:Babylonian Twins: Definitive Edition
このプロジェクトは、Claude CodeとClaude Fable 5 を利用した AI 支援による移植です。
- 私の役割: 問いかけ、プレイ、最終的な決定。
- AI の役割: コードの解釈、ファイル形式の推論、バイナリの再構築。
「108 バイトの部分」については、モデルが流通ファイルが保存後のメモリスナップショットであると指摘しましたが、私はその部分自体は確認していませんでした。しかし、プロジェクト全体で AI が人間を凌駕するスピードで進歩したことが実感できました。
Babylonian Twins: Definitive Edition は今秋 Steam へ —— こちらで wishlist してください。
- 📲 iOS / Android: 今日リリース済み(無料デモあり)。
- 💻 PC (Windows/Mac/Linux): 今秋のフルリリース予定。
- 🎮 1993 Original: itch.io で無料公開中。