1998年のUltima Onlineデモサーバーをリバースエンジニアリング
(draxinar.github.io)- OUO は、1998年の
Ultima Onlineデモサーバーを完全にリバースエンジニアリングしたプロジェクトで、MSVC x86バイナリの約 5,000個の関数を逆アセンブルし、移植可能な C99 に移し替えている UoDemo.exeはUltima Online: The Second Ageの初回リリースに含まれていたスタンドアロンのデモで、クライアントとWindowsに移植された完全なサーバーコード・データを一緒に収めていた- 各関数は元のバイナリと命令単位で比較され、クラス階層とvtableレイアウトを合わせたうえで、元と同じ制御フロー・構造体レイアウト・分岐を維持するよう手作業で変換された
- 復元版は1998年中頃の実際のライブ
Ultima Onlineサーバーコードに近いが、クラッシュ・オーバーフロー・未初期化変数といった 安定性の問題 や、スキル上昇・スポーン密度といった ゲームプレイ上の問題 がタグ付きで修正されている - 元のデモはクライアント1.25.33のみをサポートしていたが、復元版は1.25.30から 5.0.9.1 までの クライアント を暗号化の有無にかかわらずサポートし、1997〜2003年のサーバーデータファイルも募集中
デモファイルの出所と範囲
- 各関数は元のバイナリと命令単位で比較され、10年にわたる断続的な作業の末、最近のLLMの進歩によって仕上げることができた
UoDemo.exeの日付は 1998-09-02 で、サーバーデータは 1998年6月2日 の運用サーバーから抽出されたものだった- デモ用に一部の機能はスタブ化され、プレイ可能なマップは Ocllo 島に縮小されていたが、それ以外は1998年中頃に実際のライブ
Ultima Onlineで動いていた運用サーバーコードだった Ultima OnlineはOrigin Systems Inc.が開発した1997年のMMORPGで、商業的に成功した初期MMORPGの1つだった- Windowsでクライアントが動作し、サーバーである「shards」は複数のSolarisマシンで稼働しており、マップは地域ごとに分割されていた
- デモはOcllo島でドラゴンを倒すシンプルなクエストを提供し、会話、取引、戦闘など基本的なゲームメカニクスを見て回れるよう構成されていた
- 複数の
UOサーバーエミュレーターがこのデモの一部を再利用していたが、これまで完全にリバースエンジニアリングされた例はなかった UoDemo.exeはMicrosoft Visual C++ 5.0、すなわちVisual Studio 97でコンパイルされており、C++98以前の方言のC++を対象としていた
リバースエンジニアリング手法
-
逆アセンブルとシンボル推定
- 逆アセンブルには radare2 を使用
- シンボル名は、C++シンボルを含む実験的なLinux向けポートの
UOクライアント1.25.37から推定
-
C99への手動変換
- 各関数は、元のバイナリと同じ制御フロー、構造体レイアウト、分岐を維持するように手作業でC99へ翻訳された
- 差異がある箇所は、デモの実際のバグ修正またはプラットフォーム適応であり、ソース内に明示されている
-
検証方法
- Cビルドを再び
r2で逆アセンブルして元のものと比較 - 両者が一致した場合にのみ、その関数を完了と見なした
- ヘルパー関数は繰り返されるインラインパターンにのみ使われ、ヘルパーがインライン版と同じコードへ再展開される場合にだけ使用された
- Cビルドを再び
-
クラス階層の復元
- 初期段階で最も重要だった作業は、クラス階層を正確に合わせることだった
- 中核となる階層は
CEntity (0x10) -> CResourceEntity (0x1C) -> CItem (0x50) -> CContainer (0x5C) -> CMobile (0x37C) -> CPlayer (0x458)だった - 仮想ディスパッチはvtableスロットを通じて行われ、たとえば
vtable[0x18]はIsPlayer、[0xD0]はIsMobile、[0xE4]はIsNPCだった - このレイアウトが確定した後は、バイナリの大部分を比較的直接的に翻訳できた
復元結果と元コードとの差異
- 成果物は1998年の
Ultima Onlineサーバーのほぼ完全な複製に近いが、いくつか差異がある - 元コードに対して、クラッシュ、オーバーフロー、未初期化変数といった 安定性の問題 が修正されている
- スキル上昇、fame/notoriety の向き、スポーン密度といった ゲームプレイ上の問題 も修正された
- 各修正にはソース内でタグが付いており、
UoDemo.exeと比較する人が何がなぜ変わったのかを正確に確認できる - スポーンシステムやdecayシステムのような一部機能は壊れており、デモリリースのために部分的に無効化またはスタブ化されていた可能性がある
- それらの機能のコード自体は残っていたが、ライブの呼び出し箇所に到達せず、別途デコンパイルしてディスパッチを再接続するだけで動作させられた
- ゲームマップはOcllo島しか含まないなど、一部データが欠けていた
- サーバーデータ形式を操作する完全なツール群を作成し、残りの世界のドア、看板、装飾、テレポーター、罠、箱、スポーン位置を完全に再構築した
残っていたエコロジーシステム
- 引退した有名な ecology system は関数呼び出しが切れた状態だったが、コード内には今も残っていた
- 捕食者、獲物、スカベンジャーのシステムを再接続し、オオカミがウサギを追ったり、カラスがアイテムを食べたりする様子を見られるようになった
- ただし正確なデータが不足していたため、資源・生産システム全体までは実装していない
- 関連する背景資料として、Raph Kosterによる
UOの ecology system とUO資源システムの記事 1、2、3 がリンクされている
追加機能とクライアント互換性
- OSIが1999年2月に追加したMeditation、Stealth、Remove Trapスキルが新たに実装されている
- これらの機能の初期の痕跡の一部は、すでにコード内に残っていた
- ほとんどの新機能は、起動時に
-featuresパラメータで有効・無効を切り替えられる - デモサーバーにはアカウントシステムが完全になかったため、元の開発者たちが実装したであろう方式を推定し、やや現代化した形で再実装した
- 元のデモサーバーはクライアント1.25.33のみをサポートしていたが、1.25.30から5.0.9.1、すなわち 2007-03-27 までのすべての クライアント を暗号化の有無にかかわらずサポートするよう拡張された
- 数年間で完全に異なる暗号化方式が5種類存在したため、それぞれをクライアントバイナリからリバースエンジニアリングする必要があった
32ビットの原版と64ビットのデフォルトビルド
- 元のバイナリは32ビットだったが、現在のデフォルトビルドは64ビットを対象としている
- クラス階層はC構造体の埋め込みによって、元のC++継承を再現している
- この方式により、
CMobile*をCContainer*が必要な場所へ渡すことができる - 64ビットでポインタ幅が広がると継承されたフィールド位置がずれる可能性があるため、一部の構造体には32ビットと64ビットの両方で継承およびvtableレイアウトがバイナリと一致するよう、意図的にパディングが入れられている
公開リソース
- https://github.com/draxinar/ouo: コード
- https://github.com/draxinar/rundir:
UoDemo.datベースのデータ、修正、完成済みデータ、新機能を含む - https://uo.serpent-isle.com/: Test Center。実際のshardではないが、1998年の
Ultima Onlineサーバーを非常に忠実に再現した環境を試せる - UO:98: BatlinとDerrickのプロジェクトで、2016年にこの作業を始めるきっかけとなったインスピレーションの源
OUOはまだ初期段階であり、問題が残っている可能性がある- 見つけた問題は issue として報告でき、貢献も歓迎されている
Ultima Onlineコミュニティへのお願い
- 1997〜2003年頃の元の
Ultima Onlineサーバーのdynamic0.mul、dynamic0.bkp、regions.txt、resbank.mulファイルを持っている人がいれば提供を呼びかけている dynamic0.mulとdynamic0.bkpはサーバー保存ファイル、regions.txtはスポーン定義、resbank.mulは資源定義ファイル- 元の
dynamic0.mulやdynamic0.bkpが完全に失われている可能性は低そうだとしている dynamic0.mulファイルからプレイヤーデータを削除して個人情報を保護したうえで配布できるツールは、すでに用意されている- これらのファイルは
Ultima Online世界のコンテンツを非常に正確に再現するうえで大きな価値がある
1件のコメント
Hacker Newsのコメント
オリジナルのUltima Onlineサーバーの dynamic0.mul、dynamic0.bkp、regions.txt、resbank.mul ファイルを持っている人がいたら送ってもらえると本当にありがたい
これらは1997〜2003年ごろのサーバー保存ゲーム、スポーン定義、リソース定義ファイルで、特に dynamic0.mul や dynamic0.bkp は複数の安全な場所にバックアップされていたはずなので、完全に失われたと見るのは難しい
これらのファイルは Ultima Online の世界コンテンツを非常に正確に再現するうえできわめて価値が高い
本当にすごい。ちょうど昔のUltimaのゲームサウンドトラックを聴いていたところでこれを見かけたのが不思議だ
オリジナルで使われていたC++98以前のC++方言で逆アセンブル結果を書き、元のコンパイラをターゲットにすることを検討したのか気になる
昔のシステムで動いていたバイナリを逆アセンブルしたことがあるが、可能なら元のツールチェーンを目標にしたと思う。かなり興味深い哲学的な問いだ
eqclassic の最後の生存開発者として興味深く読んだが、ツールをどう使い、全体のプロセスがどうだったのかについてのもっと深い話を期待していた。それでも良い記事だ
当時は LLM はなかったが、3年後の PowerPC バイナリから得られた一部のデバッグシンボルが少し助けになった
packet_handler や entitylist といったファイル名が妙に見覚えある :D
最後の関門は、残りを磨き上げる前に事実上完璧なネットワークコードを備えることで、ここにすでに何百時間も費やしている
ソースを少し眺めただけだが、すべて TCP ベースなので、その上に別個の信頼性メカニズムを載せているようには見えない。だとすると、当時の MMO としてはかなり「遅い」選択に感じられて興味深い
UO を遊んでみたい人にとっては、今でもアクティブなプレイヤー基盤のあるゲームだ。UO Outlands のようなサードパーティサーバーは元のゲームプレイにより近いが、今どきの MMO に慣れた感覚だとかなり厳しい
他のプレイヤーにギャンクされて装備を失うこともある
今でもそのサーバーには2500人以上が接続していて、依然としてとても活発だ
私の最初の本当のプログラミングの成果はUltima Onlineのシャード用Webサイトを作ったことだった
ひどい PHP と HTML を使っていたが、その後20年以上動いていた。良い思い出だ
UO の周辺に今でも活発なコミュニティがあるのには驚いたし、とにかくこのプロジェクトは本当にすごい
当時は12〜13歳で、90年代末から2000年代初頭だった。エミュレータ名はもう覚えていないが、おそらく POL だった可能性が高い
そのシャードの目標は UO:Renaissance 以前の公式サーバーにできるだけ近づけることで、T2A のように見え、そう感じられるようかなり手を入れていた
多くを学んだし、その後 RunUO が出て2003年ごろにある程度安定してくると、POL で作ったものを RunUO 向けのC#コードへ移植する作業も手伝い、ついていくためにさらに学ぶ必要があった
そのシャードで一緒に作業していた人たちは皆、大学でコンピュータサイエンスを学んでいるか、すでにプログラマとして働いていて、私はスクリプトを少し書けるだけの子どもだった
この経験が後にプロになるうえで決定的だったと思う。実際の技術系企業での最初の仕事も、そのうちの一人がインターン枠が空いたときに推薦してくれて得られた
ある意味ではUOと私設シャードのおかげで今のキャリアがある
完全に必要に迫られてプログラミングを始めた
ゲーム名は忘れたがたぶん City of Heroes で、何年も終了していたのに、ある日誰かが私設サーバーを再び立ち上げた
昔の Shockwave オンラインゲームでも、ニッチなコミュニティがサーバーを再構築し、Shockwave ランタイムや逆コンパイラを作っている
似たような問題を解いているので、ゲームをまたいでコミュニティが重なることもある ;)
2つ目は地図を変えることで、静的アイテムの削除や新しい島と建物の追加などをしていた
3つ目は verdata.mul を変更して新しいアニメーションやアイテムグラフィックを追加することだった
非公式の POL サーバーで Ultima Online を遊んだおかげで、文字どおり IT の世界に入った。それ以前は会計士になろうとして勉強していた
これがきっかけで初めて IRC に入り、その後は freenode にまでつながった
UOエミュレータ界隈が私をネットワークプログラミングへ導いた
オンラインゲームの中で、これほど多くの副次的・創発的・偶発的なゲームプレイメカニクスをうまく取り込んだ例は見たことがない
その後の 3D MMO は、UO が提供していた興味深い経済、建築、探索の要素をかなり薄めてしまったように思う
PvP やクエスト系は他のゲームのほうが優れているかもしれないが、UO には今でも魅力があり、一人でもグループでも、見知らぬ人と軽く関わる形でも遊べて、気分に応じて自然に切り替えられた
ほとんどの人はこういうものを望まず、決められたレールの上にいることを好む
そしてこうしたゲームに最も惹かれる2つの集団は、一方がいるともう一方がゲームを去ってしまうという力学に陥る。しかも後者は前者がプレイしていることを必要としている
たとえば Asheron's Call はモッドコミュニティが非常に活発で、今ではエミュレータ界隈もある。ただ、サーバー人気は UO ほどではないようだ
Shadowbane はギルド中心が強かったが、少し無法者のように振る舞って、適当な相手やギルドと PvP する楽しさがあった
WoW、Old School RuneScape、Final Fantasy Online くらいを除けば、大きく遊べるものはあまりない
10年間断続的にこのプロジェクトを進めてきて、最近のLLMの進展のおかげで終わりが見えなかった作業をついに完了できた、というくだりが印象的だった
私も MFC C++ の逆コンパイルプロジェクトをやっているが、こういう作業では LLM が信じられないほど役に立つ
以前はUltima Onlineを楽しんでいた
最近は TazUO ゲームクライアントで Python スクリプティングを楽しんでいる。少し古い Python 3 バージョンではあるが、Razor や SteamUO でスクリプトを書くよりずっと良い
静かなシングルプレイヤーシャードであれこれ試したいなら、Memento は悪くなかった
Ultima 4 NES 版のスペイン語またはフランス語ローカライズのモバイル版を探していた。他の作品も同じだ
FF シリーズの Pixel Remaster のような形で処理されたものを望んでいる
今のところはエミュレータでしか遊べない
テキスト量の多いローカライズ RPG は、外国語を「遊びながら学ぶ」ためのとても簡単な方法で、読む練習にも良い
こういうものが作られるといいのだが
ああ、UO……本当に良い思い出だ。カードを持てる年齢ではなかったので、Palo Alto の Cybersmith まで自転車で行って前払い時間を買っていたのを覚えている
昔は Napa Valley シャードでかなり熱心に遊んでいた。Catskills に行くほどの勇気はなかった
今は UO のような体験が恋しいが、ああいうゲームに注ぎ込む時間がどうしてもない