Resident Evil 4 (GameCube) – C/C++への完全なバイト同一デコンパイル
Resident Evil 4 (GameCube) – complete byte-identical decompilation to C/C++ (github.com)
要約
このプロジェクトは、ニンテンドーゲームキューブ版「バイオハザード4」のデバッグビルド(G4BE08)を、バイト単位で完全に一致するC/C++ソースコードにデコンパイルすることに成功しました。ビルドプロセスは、元のバイナリと完全に一致する実行ファイルを生成し、ゲームの構造とコンパイラの挙動に関する詳細なドキュメントも含まれています。
全文翻訳
Resident Evil 4 (GameCube) デコンパイル
これは、2枚組の "Nov 25 2004" プロトタイプである『バイオハザード4』のゲームキューブデバッグビルドの完全なデコンパイルです。デバッグビルドには Bio4.sym というシンボルファイルが付属しており、これにより全ての関数に名前が付けられ、完全なデコンパイルが可能になりました。
リポジトリをビルドすると、オリジナルのファイルである main.dol と全ての114個のRELオーバーレイが、ビルドごとに config/G4BE08/build.sha1 に対してチェックされ、完全に再現されます。ソースコードは src/ に約57万行のC/C++、include/ に4万4千行のヘッダーファイルがあり、アセンブリファイルは含まれていません。
コードは、オリジナルがビルドされたのと同じコンパイラでビルドされています。
| コード | コンパイラ |
|---|---|
| ゲーム | SN Systems ProDG 3.9.3, GCC 2.95.3 "SN BUILD v1.79", SNのGPLソースリリースからビルド |
CRIミドルウェア (adx_*, sfd_*, mpv_* および src/lib/ のその他) | Metrowerks CodeWarrior 2.4.7, CRIがライブラリと共に配布したもの |
Nintendo SDK (OS*, GX* および src/lib/ のその他) | Metrowerks CodeWarrior GC/1.2.5n, dolsdk2004 からのソース |
このリポジトリにはゲームアセットは含まれていません。ビルドするには、独自のデバッグディスクイメージが必要です。ディスク1には main.dol とほとんどのRELが含まれ、ディスク2にはアイランドステージ用の4つのRELが含まれています。
ビルド方法
Linux、Python 3、および ninja が必要です。最初の設定実行時に、decomp-toolkit、objdiff、wibo、およびCodeWarriorコンパイラがダウンロードされます。SN GCCはSNのソースから一度ビルドされます。
# 1. SNコンパイラを一度ビルドする (SNのGPLソースリリースが必要、tools/sn-gcc/build.sh参照)
SN_GCC_SRC=/path/to/NGC_GNU_SRC/NGC tools/sn-gcc/build.sh
# 2. ディスクイメージをコピーする
cp re4_debug_disc1.iso re4_debug_disc2.gcm orig/G4BE08/
# 3. ビルド
python3 configure.py && ninja
ninja は進捗レポートで終了し、100%一致してリンクされたと表示されるはずです。結果を確認するには、build/tools/dtk shasum -c config/G4BE08/build.sha1 を実行すると、ファイルごとに1つの OK が表示され、合計115個になります。
単一ユニットで作業する場合、python3 tools/bytecmp.py game/foo はオブジェクトファイルをオリジナルと比較し、python3 tools/fdiff.py game/foo <symbol> は関数をサイドバイサイドで表示します。
各部分の説明
src/game/はゲーム本体です。src/em*/は敵、src/wep*/は武器、src/pl*/はプレイヤーキャラクター、src/st*/は部屋(部屋ごとに1つのREL)です。src/t_*/、src/Tools/、src/tools/はゲーム内のデバッグエディタ、src/Sscrn/はメニュー画面、src/lib/はSDK、CRI、ランタイムライブラリです。include/にはヘッダーファイルが含まれており、再構築された構造体も含まれています。config/G4BE08/には、ユニットリスト、シンボル、分割、リンカースクリプト、およびRELごとのデータが含まれています。tools/には、ビルドスクリプト、比較ツール、SNコンパイラビルド、およびリサーチキットが含まれています。tools/motion_export.pyはゲームのアニメーションをglTFおよびBVHにエクスポートします。詳細はtools/motion/README.mdを参照してください。docs/overview.mdはエンジンの構造を解説したガイドです。docs/matching.mdはマッチングがどのように行われたかを説明し、docs/unit-notes.mdにはユニットごとのメモがあります。docs/research/は詳細なログです。
マッチングの精度
全てのユニットは、オリジナルのコンパイラでオリジナルのバイトにコンパイルされます。コードが特定の書き方でないと、コンパイラがオリジナルのレジスタや命令順序を選択しない場所がいくつかありますが、それらは自然な書き方が見つかっていません。これらの箇所は // COMPILER-DIFF: コメントでマークされており、現時点で526箇所あります。ほとんどはデッドテスト、空の asm("")、または register T x asm("rN") 宣言です。これらは出力に命令を挿入せず、python3 tools/asmcheck.py --all でチェックできます。docs/matching.md は各理由を説明しています。この数を減らす作業は継続中です。
残っているアセンブリのほとんどは、オリジナルの開発者がアセンブリで記述したコードです。なぜなら、当時のコンパイラではCで表現できなかったからです。これには、ペアードシングル演算や行列ルーチン、GQRセットアップ、例外ハンドラ、CRIビデオデコーダのキャッシュとSPRコード、そして元々アセンブリだった8つの起動、デバッガ、解凍ユニットが含まれます。ゲームコードでは asmcheck.py は231命令をカウントし、8つのアセンブリユニットは別途カウントされます。例外はCRIライブラリにあります。一つは、CodeWarriorのビルドとカプコンのビルドの違いを回避するための dct_ac の小さなブロックで、もう一つは何も出力しない28個のレジスタピンです。docs/naming.md に全てリストされています。
名前
関数名はカプコン自身のもの (Bio4.sym から) です。これらはC++のマンデッド名であるため、ゲームコードはC++で、SDK、CRI、CライブラリコードはCになっています。ファイル名とユニットへの分割は、アサートがバイナリに残した D:/Bio4/Prog/<file>.cpp パスから来ています。
構造体とフィールド名は3つのソースから来ています。ほとんどはカプコンのもので、PS2デバッグビルドのデバッグ情報から取得され、tools/ps2sym.py を使ってゲームキューブのレイアウトにマッチングされました。一部はコードの使用方法から命名された我々のものです。残りは、意味がまだ不明なためオフセットで命名された x1C のようなプレースホルダーです。カプコンの名前はカプコンのスペルを維持するため、命名スタイルは意図的に混在しています。定数はPS2ビルドの列挙型を使用します。詳細は docs/naming.md にあります。
貢献
ビルド方法、変更が通過する必要のある3つのチェック、およびルールについては CONTRIBUTING.md を参照してください。主なルールは、出力バイトが決して変更されないことです。
法的情報
再構築されたゲームおよびSDKのソースコードは、Capcom、Nintendo、およびCRI Middlewareの所有物であり、研究および保存目的のみで公開されています。このプロジェクトのために書かれたビルドスクリプト、ツール、設定、およびドキュメントはCC0ライセンスで公開されています。詳細は LICENSE を参照してください。