工程趣聞 2026 年 9 月 21 日

2026-09-21 — 《惡靈古堡4》GameCube 版逐位元反編譯完成

primary=https://github.com/adonis-singh/re4 primary=https://github.com/adonis-singh/re4/blob/master/docs/matching.md

《惡靈古堡4》GameCube 版逐位元反編譯完成

GitHub · adonis-singh/re4 · 更新於 2026-09-20

GitHub 上的 re4 專案把《惡靈古堡 4》GameCube 除錯版(G4BE08,內部代號「Nov 25 2004」試玩版)重建到與原始光碟逐位元相同:main.dol 與全部 114 個 REL 覆疊模組,用 config/G4BE08/build.sha1 逐一核對後全數通過。作者 adonis-singh 目前把倉庫的建置腳本與文件放在 CC0 授權下,原始程式碼版權仍屬 Capcom、Nintendo 與 CRI Middleware。

原本的問題

多數反編譯專案追求的是「功能等價」:重寫出的 C 程式碼行為一樣即可,編譯結果不必落在同一組指令上。但《惡靈古堡 4》GameCube 版的原始建置動用了三套不同編譯器:遊戲本體用 SN Systems ProDG 3.9.3(GCC 2.95.3,內部代號「SN BUILD v1.79」);CRI Middleware 的音訊與動畫函式庫(adx_*sfd_*mpv_*)用 Metrowerks CodeWarrior 2.4.7(GC/2.7);任天堂 SDK(OS*GX*)則是更舊的 CodeWarrior GC/1.2.5n。

每套編譯器對同一段 C 邏輯會挑出不同的暫存器配置與指令排程,單純重寫原始碼幾乎不可能剛好對上原始的每一個位元組,這也是絕大多數 GameCube/PowerPC 反編譯專案停在「能跑」而不是「位元組相同」的原因。判斷一個編譯單元是否過關,用的是 tools/bytecmp.py 逐字比對物件檔,回報 IDENTICAL 或列出還差哪些函式,再用 tools/fdiff.py 拉出單一函式的組合語言並排比較。

採用的方法

專案的規則是先找零程式碼的結構性差異:函式原型與標頭檔是否一致、資料大小與排列順序、rodata 與 vtable 之間的間隙、陳述式順序、inline 邊界,調整完這些之後才輪到會動到指令產生結果的技巧。真的比不過的地方,才用一行 // COMPILER-DIFF: 註解標記,例如刻意保留的死程式碼、asm("") 錨點,或是 register T x asm("rN") 這種暫存器釘選,目前倉庫裡共有 644 處。

關鍵限制是這些標記本身不能產生任何指令tools/asmcheck.py --all 會編譯每個 GCC 單元並列出所有源自組合語言範本的指令,篩到最後只剩八個原生即為純組合語言的單元(crt0eabi 等)與少數 PowerPC 硬體特有的成對浮點(paired-single)核心,合計 231 條指令;唯一還留著的例外是 lib/dct_ac.c,原廠編譯器對 .bss 與 8 位元組常數池的排放方式與現行工具鏈不同,屬於已記錄在案的 MWCC 差異,不算違規。2026 年 9 月 17 日的一次整理(docs/research/compiler.md 記為「Asm-removal pass」)把先前約 100 處手動塞入的組合語言指令(asm("li %0,0")asm("mr") 等)與約 100 處暫存器釘選的 asm { } 區塊,全部換成能重現相同位元組的一般 C 語法。

程式碼範圍原始編譯器
遊戲本體(src/gameSN Systems ProDG 3.9.3(GCC 2.95.3)
CRI Middleware 函式庫Metrowerks CodeWarrior 2.4.7(GC/2.7)
任天堂 SDKMetrowerks CodeWarrior GC/1.2.5n

實際效果

組建流程用 Python 3 的 configure.py 產生 ninja 規則,第一次執行會自動下載 decomp-toolkit、objdiff、wibo 與兩個版本的 CodeWarrior;唯一要手動處理的是原生 SN GCC,得拿 SN 的 GPL 原始碼跑 tools/sn-gcc/build.sh 自行編譯:

SN_GCC_SRC=/path/to/NGC_GNU_SRC/NGC tools/sn-gcc/build.sh
cp re4_debug_disc1.iso re4_debug_disc2.gcm orig/G4BE08/
python3 configure.py && ninja

使用者仍須自備除錯版光碟映像檔(disc 1 供 main.dol 與 110 個 REL、disc 2 供四個島嶼關卡 REL),組態階段直接從光碟讀取,倉庫本身不含任何遊戲資產。ninja 跑完後回報 DOL 與所有 REL 模組 100% 比對並連結成功build.sha1 核對出 115 行 OK。整個倉庫統計為 1083 個物件(675 個在 main.dol、408 個分散在 114 個 REL)、15641 個函式,約 55.5 萬行 C/C++ 原始碼與 3.3 萬行標頭檔。

函式名稱取自除錯版隨附的 Bio4.sym 符號表,檔名與編譯單元邊界則來自二進位檔裡殘留的 D:/Bio4/Prog/<file>.cpp assert 字串;結構欄位命名分三種——由 PS2 除錯版型別資訊比對得來的原廠命名(透過 tools/ps2sym.py)、依用途自訂並標記的命名,以及意義未知時用位移量表示的 xNN 佔位。這套逐位元重建的產出除了是改機、移植的共同基礎,倉庫裡的 motion_export.py 也已經能把動畫資料匯出成 glTF/BVH,並拿 Dolphin 模擬器實際跑遊戲畫面互相驗證。

原始來源:adonis-singh/re4docs/matching.md


End of article
0
Would love your thoughts, please comment.x
()
x