th08:東方永夜抄 byte-perfect デコンパイル
th08 はコミュニティが進めている東方 decomp プロジェクトで、《東方永夜抄 ~ Imperishable Night》1.00d をバイナリから少しずつソースへ掘り起こしている。これは自分が書いたものではない。fork してきて自分でビルドし、対照しながら読んでいる。プロジェクト自身が highly WIP と掲げていてまだかなり初期段階なので、生きた教材として読んでいて、いま完成していることは期待していない。リポジトリは https://github.com/dwgx/th08。
matching decomp は「動く近似版をデコンパイルする」のとは別物だ。目標は、再ビルドしたバイナリが原版とバイト単位で一致すること。機能的に等価な C++ を書くだけでなく、コンパイラのローカル変数の配置や命令の生成の仕方まで原版と揃える必要がある。掘っているのはまさにこの層だ。
だからビルド環境に現代のツールチェインは使えない。当時のセットを復元する必要がある。Visual Studio 2002 に DirectX 8.0、すべて Web Archive から拾ってきた古い代物だ。byte-perfect には選択の余地がなく、原作者と同じコンパイラを使うしかない。build スクリプトは Python で書かれていて、走らせると build.ninja を生成し、あとは ninja に渡す。Linux/mac ではこの古いツールチェインを wine で動かす。macOS では CrossOver のほうが安定していて、CL.EXE のヒープ問題を回避できるらしい。
自分でビルドするには、まず原版の th08.exe 1.00d を用意する。プロジェクトはバージョンを SHA256 で照合していて、バージョンが違うと比較が全部崩れる。exe を resources/ に入れて python scripts/create_devenv.py を走らせ、コンパイラとライブラリを揃え、そのあと python3 ./scripts/build.py で再ビルドしたバイナリを出す。
核心は比較で、isledecomp の reccmp を使う。まず reccmp-project detect で原版と再ビルド版を認識させ、次に reccmp-reccmp --target th08 --html report.html で精度レポートを出す。どの関数が一致していて、どれがまだずれているかを直接教えてくれる。関数を一つ一致させるたびに、進捗が一目盛り進む。
もう一つ細かい話がある。古い MSVC7 上でローカル変数の配置を制御するために、@EstexNT が var_order pragma をわざわざ移植した。コンパイラの挙動を揃えるためだけに作られたこういう小道具こそ、matching decomp がどこまで掘り込むものかを一番よく物語っている。