ネイティブ / 体験型ケーススタディ / 読了目安:20分

DX-Ball:音だけでブロックの左右が分かる?

REA で DX-Ball のステレオパン関数を調査。命令と定数を追い、音のデモを試し、読み解いた計算を検証します。

このページの内容

01. 解析する前に試してみる

「左」を押して短い音を再生し、右でも繰り返します。次に倍率を−1にすると、位置はそのままで音の左右が入れ替わります。倍率0なら中央です。表示する数値は読み解いた計算、音声はその説明用の表現です。

ステレオの実験試す / 観察する / 説明する
画面上の X 座標 320整数のパン値 0
左
右

trunc((320 × 1.5625 − 500) × 1) = 0

位置を聞き分けるにはヘッドホンがおすすめです。音は再生ボタンを押したときだけ鳴ります。

数値のルールは報告に基づきます。音は正規化した Web Audio による説明用の表現で、元の音声エンジンではありません。

作るもの

位置からパン値を求める関数、音による説明、再実装と元の機械語を比較するための手順。

調査の前に

ラボではヘッドホンがあると分かりやすくなります。バイナリ調査には、お持ちの英語版 DX-Ball 1.07 実行ファイルとネイティブ解析プロバイダーが必要です。報告には対象のダイジェストと調査記録があります。 REA を設定する →

02. ブロックの衝突から音声呼び出しを追う

画面の片側でブロックが壊れる、という目に見える出来事から始めます。音声呼び出しをさかのぼり、呼び出し元が何を渡すか特定します。座標に見える数値でも、実際はタイル番号、オフセット、倍率をかけた位置かもしれません。

報告のアドレスを再利用する前に、リリースが完全に一致するか確認します。対象ヘルパーの開始位置は0x406400と報告されています。実行ファイルが異なるなら、同じアドレスと決め付けず、対応する動作を探してください。

この調査用プロンプトをコピー
報告と一致する手元の DX-Ball 1.07 実行ファイルを REA で調べてください。公式報告のパン処理ヘルパーから始め、ブロック衝突側の呼び出し元を確認します。引数の組み立て方を説明し、呼び出し箇所の命令とヘルパーの入力読み込みを両方示してください。逆コンパイラーのシグネチャが完全とは仮定しないでください。

03. 擬似コードで引数が欠けたら命令を読む

機械語命令が取得できても、逆コンパイラーが短く役に立たない本体を返すことがあります。スタックからの読み込み、浮動小数点演算、参照データ、整数変換を一緒に確認します。各定数の元バイト列を、型とバイト順も含めて求めてください。

記録された式は trunc((x × 1.5625 − 500) × scale) です。呼び出し元が水平位置を渡します。最後の変換に注目してください。ゼロ方向への切り捨ては負数で重要になり、負の無限大方向への切り下げとは異なります。

  • 入力は関数のどこに入るか?
  • 参照先のどのバイトが各浮動小数点定数になるか?
  • scale は引数か、保存された状態か、固定リテラルか?
  • テストする入力範囲で、変換は切り捨て、丸め、飽和、オーバーフローのどれになるか?

04. 数値を音で確かめるときの注意

まず数値関数を実装し、左・中央・右を確認します。次に小数になる周辺位置も試します。x = 319、scale = 1 では変換前が−1.5625、整数結果は−1です。floor を使うと誤って−2になります。

音声ボタンは pan / 500 を Web Audio のステレオパンに渡し、プレビューだけを−1…1に制限します。方向を聞き取りやすくするもので、DirectSound の音量カーブや元ゲームの音を再現しません。表示する整数値は制限しません。

この調査用プロンプトをコピー
記録された位置からパン値への計算を独立して実装してください。x = 0、1、319、320、321、640 と倍率0、0.5、1、20、−1をテストし、ゼロ方向への整数変換を保ちます。利用者の操作で音が鳴るプレビューを作り、正規化は別の処理と明記してください。プレビューのクリッピングを元の数値ルールと混同しないでください。

05. 3,205件の一致が示す範囲を知る

プロジェクトは、641個の整数位置と5種類の倍率を元の x86 関数と比較したと報告しています。指定の旧環境でコンパイルした63バイトの一致も別途報告しています。選択した入力での動作一致と、生成される機械語の一致は別の検証です。

自分の調査では、入力の組と両方の出力を保存します。不一致があれば最小の失敗例に絞ります。コンパイラーの版、オプション、再配置の扱いを明確にしてからバイト一致を試みてください。当サイトの JavaScript テストは記録された計算を検証しますが、元バイナリとの比較は再実行しません。

06. 既知の結果と比較する

以下を明確な確認点として使います。一致しても、この小さなルールを裏付けるだけで、アプリ全体の互換性を示すものではありません。

画面 X 座標 / 倍率整数のパン値確認する意味
0 / 1−500左端
319 / 1−1負数の切り捨て
320 / 10中央
321 / 11正数の切り捨て
640 / −1−500負の倍率で反転
640 / 2010,000数値結果が音声プレビューの範囲を超える

両方を同じフォルダーに保存し、Node.js で検証を実行します。パッケージのインストールは不要です。

ターミナル
node check-case-labs.mjs

07. 実際に検証したのはどこまで?

元 x86 関数との3,205件の比較と63バイトの一致は、一つの関数に関する元プロジェクトの結果です。当サイトは有理数の参照計算を使い、同じ位置・倍率の組み合わせで独立した計算実装を検証します。DXBALL.EXE の実行、ゲーム全体の再実装、音声エンジンの再現は行っていません。

当サイトの数値テスト結果を読む →

出典: REA の DX-Ball 検証レポート · 固定コミットの保守対象パン関数。チュートリアル、図、ブラウザー実験は独自制作です。

次の実験なぜ 200 + 10% は220になる? →

REA は初めてですか? REA とは? · ガイドの検証方針