リングがプレーヤーをどのように狙うか
エリーの攻撃は、最初のカウント16の目的としたリングを要求します。 一つのヘルパーは、各弾丸の方向を計算します。 同じリングは、固定方向に直面したり、プレイヤーに向かって回すことができます。
REAを使用して、TH04が弾丸のリングを作成し、プレイヤーにそれを向ける方法を見つけます。 計算を説明し、コードを表示します。
元の実行可能ファイルと再構築チェックアウトがローカルで利用可能なプロンプトの例。
TH04は256の角度の単位で完全な右回りの回転を貯える。 16箇条書きの場合、各インデックスには16単位が追加されます: 0, 16, 32, …, 240. プレイヤーの方向を追加すると、それらの位置が一緒に回転します。
回収されたソース内の発射テンプレート
bullet_template.angle = 0;
bullet_template.group = BG_RING_AIMED;
bullet_template.count = 16;
bullet_template_tune();
これらの行は、難易度とパフォーマンスチューニングの前にパターンを選択します。 攻撃のソースを読む.
REAが返すもの
私達は点検します bullet_velocity_and_angle_set()、各弾丸の速度と角度を設定する関数。 REAは、その命令、擬似コード、および参照を返します。 その結果の3つの部分がパターンを説明しています。
-
コードを読む前にDOSイメージを確認してください
エージェント→REAopen_binary {"path": "MAIN.EXE"} inspect_native_load_image {}REA→エージェント·選択されたフィールドstatus: "verified" format: "dos-mz" load_segment: 4096 header_bytes: 6144 module_bytes: 150114このチェックは、ロードされたコードと再配置レコードを提供された実行可能ファイルに関連付けます。 上記のパスは表示のために短縮されています。
-
リングの乗算と除算を読む
エージェント→REA ·analyze_function{"procedure": "0x2cfc8"}REA→エージェント*命令抜粋0x2d0eb: MOV AX, SI 0x2d0ed: SHL AX, 0x8 0x2d0f0: MOV DL, byte ptr [0x53af] 0x2d0f9: IDIV BXSI箇条書きのインデックスを保持します。 シフトはそれに256を乗算し、除算はから読み取られたカウントを使用しますDS:53AF. そのフィールドに保持されているソース名bullet_template.count. 完全なシーケンスが以下に表示されます。 -
パターンがプレイヤーに向かって回転する場所を見つける
同じ機能結果-目安抜粋0x2d190: SUB AX, word ptr [0x53a6] 0x2d198: SUB AX, word ptr [0x53a4] 0x2d19d: CALLF 0x1000:1da8 0x2d1a2: ADD word ptr [BP + -0x2], AX対応c++group_angle_offset += iatan2( player_pos.cur.y - bullet_template.origin.y, player_pos.cur.x - bullet_template.origin.x );命令オペランドは、2つの座標差と方向ヘルパーを公開します。 その戻り値は相対的なリング角度に追加されます。 REAは、エージェントがそれらの背後にある元の操作をチェックすることができます。
アセンブリから読み取り可能なC++へ
元の指示と角度の計算に一致するステップを選択します。 完全なソースは、スプレッド、スタック、ランダムパターンも処理します。
0x2cfcf: MOV SI, word ptr [BP + 0x4]
0x2d0eb: MOV AX, SI
0x2d0ed: SHL AX, 0x8
0x2d0f0: MOV DL, byte ptr [0x53af]
0x2d0f4: MOV DH, 0x0
0x2d0f6: PUSH DX
0x2d0f7: CWD
0x2d0f8: POP BX
0x2d0f9: IDIV BX
0x2d0fb: MOV word ptr [BP + -0x2], AX
0x2d18d: MOV AX, [0x4650]
0x2d190: SUB AX, word ptr [0x53a6]
0x2d194: PUSH AX
0x2d195: MOV AX, [0x464e]
0x2d198: SUB AX, word ptr [0x53a4]
0x2d19c: PUSH AX
0x2d19d: CALLF 0x1000:1da8
0x2d1a2: ADD word ptr [BP + -0x2], AX
0x2d1b9: MOV AL, byte ptr [BP + -0x2]
0x2d1bc: ADD AL, byte ptr [0x53ad]
0x2d1c0: MOV [0xbcc8], AL
unsigned char aimed_ring_angle(
int index, int count,
int player_direction,
unsigned char rotation)
{
int angle = index;
angle = (angle * 256) / count;
angle += player_direction;
angle += rotation;
return (unsigned char)angle;
}
01*箇条書きの索引を読みます。 Stack引数は次の場所にロードされます SI. 16箇条書きのリングでは、このメンバーインデックスは0から15まで実行されます。
02*フルターンの周りの方向をスペースします。 SHL AX,8 256で乗算します。 カウントはゼロです-単語に拡張され、その後 IDIV 積をその数で除算します。 カウント16の場合、各インデックスは16の角度単位を進めます。
03*プレイヤーの方向を追加します。 2つの減算は、プレーヤーマイナス原点座標を形成します。 方向ヘルパーは、角度を返します AX;それを追加すると、リング全体がプレイヤーに向かって変わります。
04*パターンの回転を追加します。 ADD AL,[0x53ad] テンプレートの角度を追加します。 Ellyの初期テンプレートはそれをゼロに設定します;他のパターンは回転で同じヘルパーを使うことができます。
05*最終的な角度を1バイトに保ちます。 店は書いています AL spawn-angleフィールドに移動します。 値は、符号なしバイトのキャストと同じように、255の後に折り返します。 周囲のソースもこの角度と速度を速度に変換します。
アセンブリは目的とされたリング枝、目的の計算および最終的な店を選ぶ。 上記のC++は読みやすい要約です。 以下のコンパイラチェックは、リンクされたプロジェクトの保守されたソースに適用されます。
リングを読み、ソースを目指してください。
angle_offset = (i * BULLET_ANGLE_FULL_TURN) / count;
if (i >= (count - 1)) {
group_complete = true;
}
goto aim_or_no_aim;
aim:
group_angle_offset += iatan2(
(player_pos.cur.y - bullet_template.origin.y),
(player_pos.cur.x - bullet_template.origin.x)
);
no_aim:
vector2_near(
bullet_template.velocity,
(group_angle_offset + bullet_template.angle),
speed
);
bullet_spawn_angle = (group_angle_offset + bullet_template.angle);
保守されたソースの確認
TH04プロジェクトの記録されたチェックは、このヘルパーを含む箇条書き生成コードを、固定されたTurbo C++4.0Jツールチェーンでコンパイルします。
一致するバイト数2,139件
コンパイルされた箇条書き生成コードは、元の実行可能ファイルの2,139バイトのセクションに一致します。
二つのクリーンビルド
2つの別々のビルドでは、同じ一致するバイトが生成されます。 記録された入力ハッシュは、ここに示されている維持されたソースと一致します。
2026年10月3日に録音されました。 コンパイラチェックを読む.
ターゲットidと分析範囲
| 元のターゲット | MAIN.EXE、156,258バイト、DOS MZ |
|---|---|
| ヘルパーエントリー | 0x2cfc8 REAのロードされたイメージで |
| 元のファイルオフセット |
0x1e7c8、によって返される address_to_file_offset
|
| 記録されたコード検査 | REA4.1.0•2026年10月7日 |
コンパイラチェックは、このヘルパーを含む完全なbullet-add codeセクションをカバーしています。 彼らはまた、そのマップの貢献と重複した再配置を比較します。
REAは負荷セグメントで静的DOS負荷イメージを検証しました 0x1000. そのアドレスは、その分析画像を記述します。 関数の結果は、517バイトのスパンにわたって2つの範囲で503のボディバイトを報告します。上記の選択された命令は、それらの報告された範囲にあります。
ソース名とコンパイラチェックはTH04チェックポイントから来ています 0d72e980. このページでは、同じ元のターゲットの新しいREA検査を追加します。 提供されたゲームのアイデンティティは、リポジトリマニフェストによって固定されており、独立した原始的なダンプの出所はまだ開いています。
図は角度の計算を示しています。 完全なゲームコントロール、タイミング、およびPC-98ハードウェアの動作には、再構築プロジェクトで別々のランタイムチェックがあります。
フルTH04の再構成
このプロジェクトは、維持されたC++とアセンブリからゲームの4つのDOS製品を構築します。 弾丸の生成を超えて、ソースはステージ、ボス、レンダリング、入力、メニュー、エンディングとスコアの処理をカバーしています。
- 箇条書き生成ソース完全なヘルパー、他のパターンタイプとテンプレートチューニング。
- DOSビルドと実行ガイドソースをビルドし、プロジェクトのPC-98エミュレーターのワークフローでテストします。
- 現在のプロジェクトの状態DOS検証と別のネイティブx64ポート。