ネイティブ / 体験型ケーススタディ / 読了目安:22分
TH04:16発の弾はどうやって自機を狙う?
REA で TH04 の円形弾幕を調査。1バイトの角度、照準、回転を追い、操作できる図で小さな再実装を検証します。
このページの内容
01. 解析する前に試してみる
中央の周りでひし形を動かし、円形弾幕を発射してください。淡い線は最初の弾を示します。弾数を16から12にすると、整数の角度刻みでは円を等分できなくなります。キーボードを使う場合はスライダーで操作できます。
16方向を16角度単位ずつ離して配置します。
ゲーム映像ではなく角度の図解です。マウスの照準は atan2 を使った近似で、元の実装は iatan2 を使います。
操作できる角度図と、丸め・桁あふれの折り返しを明示的に検証する小さな円形配置の計算。
調査の前に図はすぐに使えます。バイナリ調査を再現するには、一致する手元の TH04 MAIN.EXE、設定済み Ghidra プロバイダー、以下にリンクした固定版の再実装ソースが必要です。 REA を設定する →
02. 実行ファイルのアドレス体系を確認する
TH04 は PC-98 の DOS プログラムです。関数のアドレスをたどる前に、ローダーがファイルをメモリーへどう配置するかを確認します。実行ファイルのハッシュ、ロードセグメント、コードモード、アドレスとファイル位置の対応を記録してください。読み込み条件のないアドレスは、誤ったバイト列を指す可能性があります。
公式報告には、調査の手がかりとなる既知のヘルパーと固定版の再実装があります。それを起点にするのはガイド付きの演習であり、エージェントが単独でプログラム全体を発見した証拠ではありません。
REA を使い、手元の TH04 MAIN.EXE を Ghidra で開いてください。DOS MZ のロード設定とファイルの同一性を、リンク先の TH04 検証レポートと照合します。一致したら、報告にある bullet_velocity_and_angle_set ヘルパーを調べ、アドレスをファイルのバイト位置へ対応付けてください。ファイルやロード設定が異なる場合は過去のアドレスを使わず、対応するヘルパーの探し方を説明してください。03. 円を描く前に一つの方向を読み解く
鍵は演算の順序です。インデックス、弾数、照準角、回転を別々に確認します。この円形配置の分岐は、floor(index × 256 / count) に照準角と回転を加え、1バイトに折り返すモデルで表せます。画面では時計回りに角度が増えます。
12発を試してください。先に掛けてから割るとオフセットは0、21、42、64…です。floor(256 / count) にインデックスを掛けると0、21、42、63…になります。最初は一致しても、途中からずれます。見た目がもっともらしい円でも、誤りは隠れています。
- 16発、照準角なし:0、16、32、…、240。
- 12発:インデックス3は63ではなく64。
- 照準角250にオフセット16を加えると、折り返して10。
- 右が0、下が64、左が128、上が192。
04. 円形配置と照準ヘルパーを分ける
自機と原点の座標が方向ヘルパーに入る箇所を追います。次にテンプレートの回転を加える場所と、最終的な1バイトを保存する場所を探します。各段階をテストできるよう、別々の調査結果として記録してください。
この図は、マウス方向に照準を合わせるため JavaScript の atan2 を使い、最も近い1バイト角度へ丸めています。元の実装は iatan2 です。すべての自機座標で完全な一致を示すには、そのヘルパーも読み解いて検証する必要があります。ここでは同等性を主張せず、円形配置の計算を示します。
自機狙いの円形弾幕の分岐だけを読み解いてください。乗算後に除算する命令列、照準角を求める呼び出し、テンプレートの回転の加算、最終バイトの保存を示します。円形配置の計算を独立して実装し、元の iatan2 の動作を別途確認するまでは、図の照準関数を近似と明記してください。12発と16発、負の回転、折り返しをテストします。05. 見た目を判断する前に角度をテストする
意図的に扱いづらい入力を選び、角度の数値を出力します。スクリーンショットでは1単位の誤差が正しく見えることがあります。均等割りできない弾数、255に近い照準角、ゼロをまたぐ回転をテストし、間隔だけでなく最終的なバイトの範囲も確認します。
最初の線がポインターから少しずれる場合は、円形配置の式を変える前に角度の量子化を調べます。上下が反転するなら座標系を確認してください。ネイティブの呼び出しグラフに矛盾が見えるなら、リアルモードのセグメント対応と実際の命令を確認します。
06. 既知の結果と比較する
以下を明確な確認点として使います。一致しても、この小さなルールを裏付けるだけで、アプリ全体の互換性を示すものではありません。
| 入力値 | 期待される角度 | 見つけられる問題 |
|---|---|---|
| 弾数16、照準角0、回転0 | 0, 16, 32, …, 240 | 等間隔 |
| 弾数12、照準角0、回転0 | 0, 21, 42, 64, …, 234 | 乗算してから除算 |
| 弾数16、照準角250、回転0 | 250, 10, 26, …, 234 | 1バイトの折り返し |
| 弾数4、照準角0、回転−1 | 255, 63, 127, 191 | 負の回転の正規化 |
両方を同じフォルダーに保存し、Node.js で検証を実行します。パッケージのインストールは不要です。
node check-case-labs.mjs07. 実際に検証したのはどこまで?
当サイトでは、抽出した円形配置の計算を検証し、新しい図を描画しています。元の DOS プログラムの実行、iatan2 ヘルパーの再現、過去のコンパイラーテストの再実行は行っていません。16発は学習用に選んだ数で、ゲームのすべての難易度や発射状態を示すものではありません。
出典: REA の TH04 検証レポート · 固定版の再実装にある円形配置マクロ。チュートリアル、図、ブラウザー実験は独自制作です。