ネイティブ / 体験型ケーススタディ / 読了目安:20分
DX-Ball:音だけでブロックの左右が分かる?
REA で DX-Ball のステレオパン関数を調査。命令と定数を追い、音のデモを試し、読み解いた計算を検証します。
このページの内容
01. 解析する前に試してみる
「左」を押して短い音を再生し、右でも繰り返します。次に倍率を−1にすると、位置はそのままで音の左右が入れ替わります。倍率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 / 1 | 0 | 中央 |
| 321 / 1 | 1 | 正数の切り捨て |
| 640 / −1 | −500 | 負の倍率で反転 |
| 640 / 20 | 10,000 | 数値結果が音声プレビューの範囲を超える |
両方を同じフォルダーに保存し、Node.js で検証を実行します。パッケージのインストールは不要です。
node check-case-labs.mjs07. 実際に検証したのはどこまで?
元 x86 関数との3,205件の比較と63バイトの一致は、一つの関数に関する元プロジェクトの結果です。当サイトは有理数の参照計算を使い、同じ位置・倍率の組み合わせで独立した計算実装を検証します。DXBALL.EXE の実行、ゲーム全体の再実装、音声エンジンの再現は行っていません。
出典: REA の DX-Ball 検証レポート · 固定コミットの保守対象パン関数。チュートリアル、図、ブラウザー実験は独自制作です。