Wie ein Ring auf den Spieler zielt
Ellys Angriff fordert einen gezielten Ring mit einer anfänglichen Anzahl von 16 an. Ein Helfer berechnet die Richtung jeder Kugel. Derselbe Ring kann in eine feste Richtung zeigen oder sich dem Spieler zuwenden.
Verwenden Sie REA, um herauszufinden, wie TH04 einen Kugelring erstellt und auf den Spieler richtet. Erklären Sie die Berechnung und zeigen Sie den Code.
Eine Beispiel-Eingabeaufforderung, bei der die ursprüngliche ausführbare Datei und der Rekonstruktions-Checkout lokal verfügbar sind.
TH04 speichert eine volle Drehung im Uhrzeigersinn in 256 Winkeleinheiten. Bei 16 Aufzählungszeichen addiert jeder Index 16 Einheiten: 0, 16, 32, …, 240. Das Hinzufügen der Richtung des Spielers dreht diese Positionen zusammen.
Die Zündvorlage in der wiederhergestellten Quelle
bullet_template.angle = 0;
bullet_template.group = BG_RING_AIMED;
bullet_template.count = 16;
bullet_template_tune();
Diese Linien wählen das Muster vor der Schwierigkeits- und Leistungsabstimmung aus. Lesen Sie die Quelle des Angriffs.
Was REA zurückgibt
Wir prüfen bullet_velocity_and_angle_set(), die Funktion, die die Geschwindigkeit und den Winkel jedes Geschosses festlegt. REA gibt seine Anweisungen, Pseudocode und Referenzen zurück. Drei Teile dieses Ergebnisses erklären das Muster.
-
Überprüfen Sie das DOS-Image, bevor Sie den Code lesen
Vertreter → REAopen_binary {"path": "MAIN.EXE"} inspect_native_load_image {}REA → Agent * ausgewählte Felderstatus: "verified" format: "dos-mz" load_segment: 4096 header_bytes: 6144 module_bytes: 150114Die Prüfung bindet den geladenen Code und die Umzugsdatensätze an die gelieferte ausführbare Datei. Der obige Pfad ist für die Anzeige verkürzt.
-
Lesen Sie die Multiplikation und Division des Rings
Vertreter → REA ·analyze_function{"procedure": "0x2cfc8"}REA → Agent * Anweisungsauszug0x2d0eb: MOV AX, SI 0x2d0ed: SHL AX, 0x8 0x2d0f0: MOV DL, byte ptr [0x53af] 0x2d0f9: IDIV BXSIenthält den Aufzählungszeichenindex. Die Verschiebung multipliziert es mit 256, dann verwendet die Division die gelesene ZählungDS:53AF. Die gepflegte Quelle benennt dieses Feldbullet_template.count. Die vollständige Sequenz erscheint unten. -
Finde heraus, wo sich das Muster dem Spieler zuwendet
Gleiches Funktionsergebnis * Zielauszug0x2d190: SUB AX, word ptr [0x53a6] 0x2d198: SUB AX, word ptr [0x53a4] 0x2d19d: CALLF 0x1000:1da8 0x2d1a2: ADD word ptr [BP + -0x2], AXEntsprechendes gepflegtes C ++group_angle_offset += iatan2( player_pos.cur.y - bullet_template.origin.y, player_pos.cur.x - bullet_template.origin.x );Die Anweisungsoperanden legen zwei Koordinatendifferenzen und einen Richtungshelfer offen. Sein Rückgabewert wird zum relativen Ringwinkel addiert. Quellennamen machen diese Adressen lesbar; Mit REA kann der Agent die ursprünglichen Vorgänge dahinter überprüfen.
Von Assembly zu lesbarem C ++
Wählen Sie einen Schritt aus, um die ursprünglichen Anweisungen mit der Winkelberechnung abzugleichen. Diese Zusammenfassung folgt dem Zielringpfad; Die vollständige Quelle behandelt auch Spreads, Stapel und Zufallsmuster.
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 * Lesen Sie den Aufzählungszeichenindex. Das Stapelargument wird geladen in SI. In einem 16-Punkte-Ring verläuft dieser Mitgliederindex von 0 bis 15.
02 * Platziere die Richtungen um eine volle Umdrehung. SHL AX,8 multipliziert mit 256. Die Zählung ist Null-erweitert zu einem Wort, dann IDIV dividiert das Produkt durch diese Anzahl. Für Zählung 16 rückt jeder Index 16 Winkeleinheiten vor.
03 * Fügen Sie die Spielerrichtung hinzu. Die beiden Subtraktionen bilden Spieler-minus-Ursprungskoordinaten. Der Richtungshelfer gibt einen Winkel in zurück AX; das Hinzufügen dreht den ganzen Ring in Richtung des Spielers.
04 * Fügen Sie die Drehung des Musters hinzu. ADD AL,[0x53ad] fügt den Schablonenwinkel hinzu. Ellys anfängliche Vorlage setzt es auf Null; Andere Muster können denselben Helfer mit einer Drehung verwenden.
05 * Halten Sie den endgültigen Winkel in einem Byte. Der Laden schreibt AL zum Spawnwinkelfeld. Werte werden nach 255 umgebrochen, genau wie bei der Umwandlung ohne Vorzeichen. Die umgebende Quelle wandelt diesen Winkel und diese Geschwindigkeit ebenfalls in Geschwindigkeit um.
Die Baugruppe wählt den Zielringzweig, die Zielberechnung und den Endspeicher aus. Das obige C ++ ist eine lesbare Zusammenfassung. Die folgenden Compiler-Prüfungen gelten für die gepflegte Quelle im verknüpften Projekt.
Lesen Sie die gepflegte Ring- und Zielquelle
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);
Ringmakro · Ziel- und Geschwindigkeitsquelle · Winkeldarstellung
Überprüfen der gepflegten Quelle
Die aufgezeichneten Überprüfungen des TH04-Projekts kompilieren den Code zur Bullet-Generierung, einschließlich dieses Helpers, mit seiner angehefteten Turbo C ++ 4.0J-Toolchain.
2.139 übereinstimmende Bytes
Der kompilierte Code zur Aufzählungszeichengenerierung entspricht einem 2.139 Byte großen Abschnitt der ursprünglichen ausführbaren Datei.
Zwei saubere Builds
Zwei separate Builds erzeugen dieselben übereinstimmenden Bytes. Die aufgezeichneten Eingabe-Hashes stimmen mit der hier gezeigten gepflegten Quelle überein.
Aufgenommen am 3. Oktober 2026. Lesen Sie die Compiler-Prüfungen.
Zielidentität und Analyseumfang
| Ursprüngliches Ziel | MAIN.EXE, 156.258 bytes, ZWEI MZ |
|---|---|
| Hilfseintrag | 0x2cfc8 im geladenen Bild von REA |
| Versatz der ursprünglichen Datei |
0x1e7c8, zurückgegeben von address_to_file_offset
|
| Inspektion aufgezeichneter Codes | REA 4.1.0 · 7. Oktober 2026 |
Compiler-Prüfungen decken den gesamten Abschnitt zum Hinzufügen von Code mit Aufzählungszeichen ab, einschließlich dieses Hilfsprogramms. Sie vergleichen auch den Kartenbeitrag und die überlappende Verlagerung.
REA hat das statische DOS-Ladebild am Ladesegment überprüft 0x1000. Seine Adressen beschreiben dieses Analysebild. Das Funktionsergebnis meldet 503 Körperbytes in zwei Bereichen über einen Zeitraum von 517 Byte; Die oben ausgewählten Anweisungen liegen in diesen gemeldeten Bereichen.
Die Quellnamen und Compilerprüfungen stammen vom Prüfpunkt TH04 0d72e980. Frühere Rekonstruktionsbeobachtungen verwendeten die projekteigenen Analyseskripte; Diese Seite fügt eine neue REA-Inspektion desselben ursprünglichen Ziels hinzu. Die Identität des gelieferten Spiels wird durch sein Repository-Manifest festgelegt, wobei die unabhängige Herkunft des unberührten Dumps noch offen ist.
Die Abbildung veranschaulicht die Winkelberechnung. Steuerung des vollständigen Spiels, Timing und Verhalten der PC-98-Hardware haben separate Laufzeitprüfungen im Rekonstruktionsprojekt.
Die vollständige TH04-Rekonstruktion
Das Projekt erstellt die vier DOS-Produkte des Spiels aus gepflegtem C ++ und Assembly. Über die Aufzählungszeichenerzeugung hinaus umfasst die Quelle Stufen, Bosse, Rendering, Eingabe, Menüs, Endungen und Partiturbehandlung.
Erkunden Sie das TH04-Repository
- Quelle zur Erzeugung von KugelnDer komplette Helfer, andere Mustertypen und Template-Tuning.
- DOS-Anleitung zum Erstellen und AusführenErstellen Sie die Quelle und testen Sie sie im PC-98-Emulator-Workflow des Projekts.
- Aktueller ProjektstandDOS-Verifizierung und den separaten nativen x64-Port.