dwgx@blog:~$dwgx
> cd ../posts

ReC98: 東方 PC-98 五作品の bit-perfect 逆向

// created

ReC98 は東方 PC-98 復元計画で、nmlgc がクラウドファンディングで少しずつ解析してきたものだ。目標は ZUN 最初期の五作品、TH01 から TH05 までを、コンパイル可能なソースコードへ完全に復元すること。これらは 1997 年、1998 年の作品で、PC-9801 上でしか動かず、とっくに販売終了しており、ZUN 自身も原始データは失われたと言っている。ここにあるのは私が fork したもので、中身は変えず、ただビルドして一通り研究するだけだ。私が見た中で最もハードコアな逆向だからだ。

その基準は苛烈だ。リポジトリからビルドしたバイナリは原版とバイト単位で一致していなければならず、しかも全ての commit でそれを保たなければならない。手元にあるのはバイナリだけで、変数名もコメントも得られない。だから判断基準は「原始コードがこうではなかったと証明できない」ことになる。

PyTouhou のようなブラックボックス書き直しには進まず、完全なデコンパイルを貫いている。理由は実に現実的だ。TH04、TH05 の雑魚弾幕は .STD のバイトコードで、別途 VM を書いて解析できるが、中 boss と boss は全て exe にハードコードされていて、回避しようがない。

この作業を実際に可能にしているのは、五作品が共用する二つのライブラリ——master.lib(16 ビット x86 アセンブリで書かれた PC-98 DOS 抽象化レイヤー)と Borland C/C++ 4.0 ランタイム——を見抜いたこと、そして両方のソースが見つかったことだ。この二つだけで TH05 では OP.EXE の 74%、MAIN.EXE の 40% を占め、作業量を一気に大きく削れる。TH01 はさらに BERO の Pi loader を使っており、TH03 の ZUNSP.COM は実のところ Promisence Soft の SPRITE16.COM の皮替えだ。

使えるコンパイラは、当時 ZUN が使っていたあの Borland Turbo C++ 4.0J だけだ。他ではバイト単位の一致を揃えられない。しかも Borland は 32 ビット Windows 上で 16 ビット DOS をビルドするクロスコンパイラを一度も作らなかったので、C++ は DOS エミュレータの中でしかコンパイルできない。ビルドチェーンは MS-DOS Player で DOS ツールを走らせ、Tup で増分並列ビルドを行う。Tup はコンパイラのファイルオープンシステムコールを hook して #include 依存を追跡し、make よりずっとクリーンだ。Win11 では build.bat 一発で出荷まで済み、成果物は bin\th0? に落ちる。ただし実際に動かすには自分で原版素材を用意する必要があり、リポジトリにはゲームデータは一切含まれない。

TH01 のデコンパイルは 2022 年 8 月に一式完了しており、残りの作品は作者いわく時間の問題にすぎない。その後は重心が ZUN 原始コードのドキュメント化と考証へ移り、rec98.nmlgc.net 上のプロジェクトブログの方がかえってメインディッシュになった。