ケーススタディ•DX-Ball1.07

DX-Ballの再構築
その実行可能ファイルから。

目標は、1996年のWindowsゲームの保守可能なCバージョンです。 REAは、エージェントが元の機能を一度に検査するのに役立ちます。

Windows i386*C·REA

DXBALL。EXE関数0x00406400はREAで検査されます。 命令はxをロードし、1.5625を乗算し、500.0を減算し、pan_scaleを適用して整数を返します。 維持されているCは、元のx86に対して3,205ケースで独立してチェックされ、VC4.0コンパイラによって63バイトに一致します。
実行可能ファイルからチェックされたC.REAまでの一つの関数は、命令、呼び出し元、およびデータ読み取りを提供します。 オープンフィギュア
55
維持されたC関数
45,380
元のコードとの比較
33
コンパイルされたバイトに一致する関数

プロジェクトチェックポイント:2026年10月7日。 進捗台帳 · テストカバレッジ

これまでのプロジェクト

回収されたコードは、ボードとリソースの処理、レンガのヒット、アニメーション、パーティクル、ボーナスの生産をカバーしています。 現在のビルドには、検査ユーティリティと分析ライブラリが用意されています。 プレイ可能なゲームの作業は、ボールとパドルの物理学、パワーアップハンドリングとWindowsの統合を続けています。

左/右の音の位置の計算を見つける

レンガがヒットすると、その水平位置がサウンドコードに渡されます。 調査は、その画面座標がどのように左/右パン値になるかを回復するために必要でした。

あなたのコーディングエージェント

REAを使用して、DX-Ballがステレオサウンドの位置を計算する方法を見つけます。 計算を説明し、コードを表示します。

ローカルの実行可能ファイルを使用して、コーディングエージェントのプロンプトの例を示します。 以下の調査は、REAクエリと答えの背後にある証拠を示しています。

エージェントはREAを使用して関数を検査し、ブリックヒット呼び出し元に従って実行可能ファイルから定数を読み取りました。 これらの結果は、以下のC関数を書くのに必要な入力と算術を提供しました。

の最初の関数の結果 0x406400 擬似コード宣言が含まれています FUN_00406400(void) と呼び出し __ftol(). その命令ビューは、スタック入力と浮動小数点演算を示しました。 その不一致は、エージェントに調査を続ける具体的な理由を与えました。

最初の逆コンパイラビュー
REA結果*擬似コードの抜粋
longlong FUN_00406400(void)
{
  longlong lVar1;

  lVar1 = __ftol();
  return lVar1;
}

出力に変換呼び出しが表示されます。 以下の手順を読むと、入力とその呼び出しを供給する計算が明らかになります。

REAを通じて答えた三つの質問

  1. 不足している入力を回復する

    エージェント→REA · analyze_function
    {"procedure": "0x406400"}
    REA→エージェント*命令抜粋
    0x406409: MOV EAX, dword ptr [EBP + 0x8]
    0x40640c: MOV dword ptr [EBP + -0xc], EAX
    0x40640f: FILD dword ptr [EBP + -0xc]

    関数の結果には、擬似コードと呼び出し元と一緒に命令が含まれます。 ここに, [EBP+8] 逆コンパイラビューから欠落している整数入力を公開します。

  2. 入力を理解するために発信者に従ってください

    エージェント→REA · analyze_function
    {"procedure": "0x411f40"}
    REA→エージェント*発信者の抜粋
    0x411f5b: ADD EAX, 0x14
    0x411f5e: PUSH EAX
    0x411f5f: CALL 0x00406400

    REAは、最初の結果でこの呼び出し元を識別しました。 その前の指示はスケールします tile_x 30で、20を追加すると、レンガの画面座標が得られます, 20 + 30 × tile_x.

  3. メモリアドレスの背後にある値を読み取る

    エージェント→REA·2 read_bytes ご要望-ご要望
    {"address": "0x420068", "length": 16}
    {"address": "0x4210a0", "length": 8}
    REAバイト結果*ダブルとしてデコード
    000000000000f93f → 1.5625
    0000000000407f40 → 500.0
    000000000000f03f → 1.0

    返されるバイトは、2つの算術定数と初期パンスケールを確立します。 エージェントは、C式に必要な値を持つようになりました。

REAの調査結果からCへ

以下の5つの手順に従ってください。 各選択は、元の指示と彼らが通知したC行を強調表示します。

オリジナルx86*抜粋
0x406409: MOV EAX, dword ptr [EBP + 0x8]
0x40640c: MOV dword ptr [EBP + -0xc], EAX
0x40640f: FILD dword ptr [EBP + -0xc]
0x406415: FMUL double ptr [0x00420068]
0x40641e: FSUB double ptr [0x00420070]
0x406427: FMUL double ptr [0x004210a0]
0x406430: CALL 0x0041678c
0x40643e: RET
再構築されたC
DxBallInt dxball_screen_pan(DxBallInt x)
{
    double pan;
    pan = (double)x;
    pan = pan * 1.5625;
    pan = pan - 500.0;
    pan = pan * dxball_pan_scale;
    return (DxBallInt)pan;
}

01*入力を読みます。 REAの関数結果の命令ビューは次のようになります [EBP+8] と使用 FILD 整数をロードする。 REAを介して呼び出し元に続いて、Cパラメータの画面座標の意味を確立します x.

アセンブリの抜粋では、入力命令、算術命令、および戻り命令が選択されます。 以下の完全なリストには、介入する店舗と機能のセットアップとクリーンアップも含まれています。

完全なアセンブリおよび支持の証拠
REA結果·0x406400-0x40643e
0x406400: PUSH EBP
0x406401: MOV EBP, ESP
0x406403: SUB ESP, 0xc
0x406406: PUSH EBX
0x406407: PUSH ESI
0x406408: PUSH EDI
0x406409: MOV EAX, dword ptr [EBP + 0x8]
0x40640c: MOV dword ptr [EBP + -0xc], EAX
0x40640f: FILD dword ptr [EBP + -0xc]
0x406412: FST double ptr [EBP + -0x8]
0x406415: FMUL double ptr [0x00420068]
0x40641b: FST double ptr [EBP + -0x8]
0x40641e: FSUB double ptr [0x00420070]
0x406424: FST double ptr [EBP + -0x8]
0x406427: FMUL double ptr [0x004210a0]
0x40642d: FST double ptr [EBP + -0x8]
0x406430: CALL 0x0041678c
0x406435: JMP 0x0040643a
0x40643a: POP EDI
0x40643b: POP ESI
0x40643c: POP EBX
0x40643d: LEAVE
0x40643e: RET

発信者が供給するもの

でのブリックヒット機能 0x411f40 タイル座標を30でスケーリングし、20を加算してから、呼び出しの前にプッシュします:

0x411f50: MOV EAX, dword ptr [EBP + 0x8]
0x411f53: ADD EAX, EAX
0x411f55: LEA EAX, [EAX + EAX*0x2]
0x411f58: LEA EAX, [EAX + EAX*0x4]
0x411f5b: ADD EAX, 0x14
0x411f5e: PUSH EAX
0x411f5f: CALL 0x00406400
0x411f64: ADD ESP, 0x4

データが読み取るものが確立するもの

REAバイト読み取り、リトルエンディアン倍精度としてデコード
住所 値 のために使用される
0x420068 1.5625 最初の乗算
0x420070 500.0 引き算
0x4210a0 1.0 最初は 保存されたパンスケール

ハッシュピン付きDX-Ball1.07ターゲット用にREA4.1.0で記録されました。 リンクされた調査ノートには証拠Idが保持されます。

維持されたソース · 調査ノートおよび証拠の参照

復元された機能を確認する

復元された関数は、戻り値が元のものと一致し、コンパイルされたバイトが実行可能ファイルと一致するという2つのチェックを渡します。

3,205件

テストでは、元のx86関数を実行し、その戻り値を維持されたCと比較します。0、0.5、1、20、-1の5つのパンスケールで、0から640までのすべての整数位置をカバーします。

63一致するバイト

C関数は、ピン留めされたVC4.0ツールチェーンでコンパイルされます。 コンパイラの再生は、レビューされた再配置を適用し、参照された定数を確認した後、完全な関数と一致します。

スケールが1の場合、復元された計算では、左端に-500、中央に0、右端に500が返されます。 オーディオ作業の次の部分は、その値をゲームのサウンドバックエンドと統合することです。

コンパイラのリプレイの詳細を読む

調査を続ける

パーティクルの更新、爆発キュー、ボーナスの生成にも同じアプローチが使用されています。関連する関数を検査し、それらの状態と依存関係を回復し、実装を元のものと比較します。

サウンドパン機能を自分で検査するには、DX-Ballプロジェクトのセットアップ手順に従って、一致する元のターゲットを指定します。 次に実行します:

DX-Ballチェックアウトで
scripts/rea function original/DXBALL.EXE 0x00406400 \
  --snapshot .analysis/rea/dxball.snapshot.json --json

トップ