Fallstudie * DX-Ball 1.07

Umbau DX-Ball
von seiner ausführbaren Datei.

Das Ziel ist eine wartbare C-Version des 1996er Windows-Spiels. REA hilft dem Agenten, das Original Funktion für Funktion zu inspizieren.

Modell: Windows i386 · C · REA

DXBALL.Die EXE-Funktion 0x00406400 wird mit REA überprüft. Ein Brick-Hit-Aufrufer liefert 20 plus 30 mal tile_x. Anweisungen laden x, multiplizieren mit 1,5625, subtrahieren 500,0, wenden pan_scale an und geben eine Ganzzahl zurück. Das gepflegte C wird in 3.205 Fällen unabhängig gegen das ursprüngliche x86 und durch VC4.0-Compiler-Wiedergabe mit 63 Bytes überprüft.
Eine Funktion, von ausführbar bis geprüft C. REA liefert die Anweisungen, Aufrufer und Datenlesungen; Das Rekonstruktionsprojekt implementiert und testet das Ergebnis. Offene Figur
55
beibehaltene C-Funktionen
45,380
vergleiche mit Originalcode
33
funktionen mit übereinstimmenden kompilierten Bytes

Projekt-Checkpoint: 7. Oktober 2026. Fortschrittsbuch · Testabdeckung

Das Projekt bisher

Der wiederhergestellte Code umfasst Brett- und Ressourcenhandhabung, Ziegelsteintreffer, Animationen, Partikel und Bonusproduktion. Aktuelle Builds bieten Inspektionsprogramme und eine Analysebibliothek. Die Arbeit am spielbaren Spiel wird mit Ball- und Paddelphysik, Power-Up-Handling und Windows-Integration fortgesetzt.

Ermittlung der Berechnung der linken / rechten Schallposition

Wenn ein Stein getroffen wird, wird seine horizontale Position an den Soundcode übergeben. Die Untersuchung musste wiederhergestellt werden, wie diese Bildschirmkoordinate zu einem Links / Rechts-Schwenkwert wird.

Ihr Codierungsagent

Verwenden Sie REA, um herauszufinden, wie DX-Ball die Stereoklangpositionierung berechnet. Erklären Sie die Berechnung und zeigen Sie den Code.

Eine Beispielaufforderung für Ihren Codierungsagenten, wobei die lokale ausführbare Datei verfügbar ist. Die folgende Untersuchung zeigt die REA-Abfragen und Beweise hinter der Antwort.

Der Agent hat REA verwendet, um die Funktion zu überprüfen, seinem Aufrufer mit Ziegelsteinen zu folgen und die Konstanten aus der ausführbaren Datei zu lesen. Diese Ergebnisse lieferten die Eingabe und Arithmetik, die zum Schreiben der folgenden C-Funktion erforderlich waren.

Das erste Funktionsergebnis für 0x406400 enthaltene Pseudocode-Deklaration FUN_00406400(void) und ruft __ftol(). Die Anweisungsansicht zeigte eine Stapeleingabe und Gleitkommaoperationen. Diese Diskrepanz gab dem Agenten einen konkreten Grund, weiter zu ermitteln.

Die erste Decompiler-Ansicht
REA Ergebnis * Pseudocode-Auszug
longlong FUN_00406400(void)
{
  longlong lVar1;

  lVar1 = __ftol();
  return lVar1;
}

Die Ausgabe zeigt einen Konvertierungsaufruf. Wenn Sie die folgenden Anweisungen lesen, werden die Eingabe und die Berechnung angezeigt, die diesen Aufruf einspeisen.

Drei Fragen beantwortet durch REA

  1. Stellen Sie die fehlende Eingabe wieder her

    Vertreter → REA · analyze_function
    {"procedure": "0x406400"}
    REA → Agent * Anweisungsauszug
    0x406409: MOV EAX, dword ptr [EBP + 0x8]
    0x40640c: MOV dword ptr [EBP + -0xc], EAX
    0x40640f: FILD dword ptr [EBP + -0xc]

    Das Funktionsergebnis enthält Anweisungen neben Pseudocode und Aufrufern. Hier, [EBP+8] macht die Integer-Eingabe verfügbar, die in der Dekompilierungsansicht fehlt.

  2. Die aufrufende Funktion erklärt die Eingabe

    Vertreter → REA · analyze_function
    {"procedure": "0x411f40"}
    REA → Agent · Auszug der aufrufenden Funktion
    0x411f5b: ADD EAX, 0x14
    0x411f5e: PUSH EAX
    0x411f5f: CALL 0x00406400

    REA nennt diese aufrufende Funktion bereits im ersten Ergebnis. Vor dem Aufruf multipliziert sie tile_x mit 30 und addiert 20. Das ergibt die Bildschirmkoordinate des Ziegels, 20 + 30 × tile_x.

  3. Lesen Sie die Werte hinter den Speicheradressen

    Vertreter → REA * zwei read_bytes Antr
    {"address": "0x420068", "length": 16}
    {"address": "0x4210a0", "length": 8}
    REA Byte-Ergebnisse * dekodiert als Doppel
    000000000000f93f → 1.5625
    0000000000407f40 → 500.0
    000000000000f03f → 1.0

    Die zurückgegebenen Bytes legen die beiden arithmetischen Konstanten und die anfängliche Schwenkskala fest. Der Agent hat jetzt die Werte, die für den C-Ausdruck benötigt werden.

Von den Erkenntnissen von REA zu C

Befolgen Sie die folgenden fünf Schritte. Jede Auswahl hebt die ursprünglichen Anweisungen und die von ihnen informierten C-Zeilen hervor.

Original x86 * Auszug
0x406409: MOV EAX, dword ptr [EBP + 0x8]
0x40640c: MOV dword ptr [EBP + -0xc], EAX
0x40640f: FILD dword ptr [EBP + -0xc]
0x406415: FMUL double ptr [0x00420068]
0x40641e: FSUB double ptr [0x00420070]
0x406427: FMUL double ptr [0x004210a0]
0x406430: CALL 0x0041678c
0x40643e: RET
Rekonstruiertes C
DxBallInt dxball_screen_pan(DxBallInt x)
{
    double pan;
    pan = (double)x;
    pan = pan * 1.5625;
    pan = pan - 500.0;
    pan = pan * dxball_pan_scale;
    return (DxBallInt)pan;
}

01 * Lesen Sie die Eingabe. Die Anweisungsansicht im Funktionsergebnis von REA lautet [EBP+8] und verwendet FILD um die Ganzzahl zu laden. Wenn Sie seinem Aufrufer durch REA folgen, wird die Bildschirmkoordinatenbedeutung des Parameters C festgelegt x.

Der Assemblyauszug wählt die Eingabe-, Arithmetik- und Rückgabeanweisungen aus. Die vollständige Liste unten enthält auch die dazwischenliegenden Speicher sowie die Einrichtung und Bereinigung von Funktionen.

Vollständige Versammlung und unterstützende Beweise
REA Ergebnis · 0x406400–0x40643e
0x406400: PUSH EBP
0x406401: MOV EBP, ESP
0x406403: SUB ESP, 0xc
0x406406: PUSH EBX
0x406407: PUSH ESI
0x406408: PUSH EDI
0x406409: MOV EAX, dword ptr [EBP + 0x8]
0x40640c: MOV dword ptr [EBP + -0xc], EAX
0x40640f: FILD dword ptr [EBP + -0xc]
0x406412: FST double ptr [EBP + -0x8]
0x406415: FMUL double ptr [0x00420068]
0x40641b: FST double ptr [EBP + -0x8]
0x40641e: FSUB double ptr [0x00420070]
0x406424: FST double ptr [EBP + -0x8]
0x406427: FMUL double ptr [0x004210a0]
0x40642d: FST double ptr [EBP + -0x8]
0x406430: CALL 0x0041678c
0x406435: JMP 0x0040643a
0x40643a: POP EDI
0x40643b: POP ESI
0x40643c: POP EBX
0x40643d: LEAVE
0x40643e: RET

Was die aufrufende Funktion übergibt

Die Brick-Hit-Funktion bei 0x411f40 skaliert die Kachelkoordinate um 30, addiert 20 und schiebt sie dann vor den Anruf:

0x411f50: MOV EAX, dword ptr [EBP + 0x8]
0x411f53: ADD EAX, EAX
0x411f55: LEA EAX, [EAX + EAX*0x2]
0x411f58: LEA EAX, [EAX + EAX*0x4]
0x411f5b: ADD EAX, 0x14
0x411f5e: PUSH EAX
0x411f5f: CALL 0x00406400
0x411f64: ADD ESP, 0x4

Was die Daten lesen, stellen Sie fest

REA Byte liest, dekodiert als Little-Endian-Doubles
Anschrift Wert Verwendet für
0x420068 1.5625 Erste Multiplikation
0x420070 500.0 Subtraktion
0x4210a0 1.0 zunächst Gespeicherte Pfannenwaage

Aufgezeichnet mit REA 4.1.0 für das Hash-angeheftete DX-Ball 1.07-Ziel. Die verknüpften Ermittlungsnotizen behalten die Beweismittel-IDs bei.

Gepflegte Quelle · Ermittlungsnotizen und Beweisreferenzen

Überprüfen der wiederhergestellten Funktion

Die wiederhergestellte Funktion besteht zwei Prüfungen: Ihre Rückgabewerte stimmen mit dem Original überein und ihre kompilierten Bytes stimmen mit der ausführbaren Datei überein.

3.205 Verhaltensfälle

Die Tests führen die ursprüngliche x86-Funktion aus und vergleichen ihren Rückgabewert mit dem gepflegten C. Sie decken jede ganzzahlige Position von 0 bis 640 auf fünf Pan-Skalen ab: 0, 0,5, 1, 20 und -1.

63 übereinstimmende Bytes

Die C-Funktion wird mit der angehefteten VC4.0-Toolchain kompiliert. Die Compiler-Wiedergabe stimmt mit der vollständigen Funktion überein, nachdem die überprüften Verschiebungen angewendet und die referenzierten Konstanten überprüft wurden.

Bei einer Skala von 1 gibt die wiederhergestellte Berechnung -500 am linken Rand, 0 in der Mitte und 500 am rechten Rand zurück. Der nächste Teil der Audioarbeit besteht darin, diesen Wert in das Sound-Backend des Spiels zu integrieren.

Lesen Sie die Compiler-Wiedergabedetails

Setzen Sie die Untersuchung fort

Der gleiche Ansatz wird für Partikelaktualisierungen, Explosionswarteschlangen und Bonusgenerierung verwendet: Überprüfen Sie die relevanten Funktionen, stellen Sie ihren Zustand und ihre Abhängigkeiten wieder her und vergleichen Sie dann die Implementierung mit dem Original.

Um die Sound-Pan-Funktion selbst zu überprüfen, befolgen Sie die Einrichtungsanweisungen des DX-Ball-Projekts und geben Sie das passende Originalziel an. Dann lauf:

In der Kasse des DX-Ball
scripts/rea function original/DXBALL.EXE 0x00406400 \
  --snapshot .analysis/rea/dxball.snapshot.json --json

Oberen