Étude de cas * DX-Ball 1.07

Reconstruction DX-Ball
de son exécutable.

L'objectif est une version C maintenable du jeu Windows de 1996. REA aide l'agent à inspecter l'original, une fonction à la fois.

Windows i386 · D · REA

DXBALL.La fonction EXE 0x00406400 est inspectée avec REA . Un appelant frappé par une brique fournit 20 plus 30 fois tile_x. Instructions chargez x, multipliez par 1,5625, soustrayez 500,0, appliquez pan_scale et renvoyez un entier. Le C maintenu est vérifié indépendamment par rapport au x86 d'origine dans 3 205 cas et par relecture du compilateur VC4.0 correspondant à 63 octets.
Une fonction, de l'exécutable au vérifié C. REA fournit les instructions, les appelants et les lectures de données; le projet de reconstruction implémente et teste le résultat. Figure ouverte
55
fonctions C maintenues
45,380
comparaisons avec le code d'origine
33
fonctions avec octets compilés correspondants

Point de contrôle du projet: 7 octobre 2026. Registre de progression · Couverture des tests

Le projet à ce jour

Le code récupéré couvre la gestion des cartes et des ressources, les coups de briques, les animations, les particules et la production de bonus. Les versions actuelles fournissent des utilitaires d'inspection et une bibliothèque d'analyse. Le travail sur le jeu jouable se poursuit avec la physique de la balle et de la pagaie, la manipulation de la mise sous tension et l'intégration de Windows.

Trouver le calcul de la position sonore gauche / droite

Lorsqu'une brique est touchée, sa position horizontale est transmise au code sonore. L'enquête nécessaire pour récupérer comment cette coordonnée d'écran devient une valeur de panoramique gauche / droite.

Votre agent de codage

Utilisez REA pour savoir comment DX-Ball calcule le positionnement du son stéréo. Expliquez le calcul et montrez le code.

Un exemple d'invite pour votre agent de codage, avec l'exécutable local disponible. L'enquête ci-dessous montre les requêtes REA et les preuves derrière la réponse.

L'agent a utilisé REA pour inspecter la fonction, suivre son appelant et lire les constantes de l'exécutable. Ces résultats ont fourni l'entrée et l'arithmétique nécessaires pour écrire la fonction C ci-dessous.

Le premier résultat de la fonction pour 0x406400 déclaration de pseudocode incluse FUN_00406400(void) et appeler __ftol(). Sa vue d'instruction montrait une entrée de pile et des opérations en virgule flottante. Cet écart a donné à l'agent une raison concrète de continuer à enquêter.

La première vue du décompilateur
REA résultat * extrait de pseudocode
longlong FUN_00406400(void)
{
  longlong lVar1;

  lVar1 = __ftol();
  return lVar1;
}

La sortie affiche un appel de conversion. La lecture des instructions ci-dessous révèle l'entrée et le calcul alimentant cet appel.

Réponses à trois questions via REA

  1. Récupérer l'entrée manquante

    Agent → REA · analyze_function
    {"procedure": "0x406400"}
    REA → extrait d'instructions de l'agent ·
    0x406409: MOV EAX, dword ptr [EBP + 0x8]
    0x40640c: MOV dword ptr [EBP + -0xc], EAX
    0x40640f: FILD dword ptr [EBP + -0xc]

    Le résultat de la fonction inclut des instructions à côté du pseudocode et des appelants. Ici, [EBP+8] expose l'entrée entière manquante dans la vue du décompilateur.

  2. Suivez l'appelant pour comprendre l'entrée

    Agent → REA · analyze_function
    {"procedure": "0x411f40"}
    REA → extrait de l'agent * appelant
    0x411f5b: ADD EAX, 0x14
    0x411f5e: PUSH EAX
    0x411f5f: CALL 0x00406400

    REA a identifié cet appelant dans le premier résultat. Son échelle d'instructions précédente tile_x par 30; l'ajout de 20 donne les coordonnées de l'écran de la brique, 20 + 30 × tile_x.

  3. Lire les valeurs derrière les adresses mémoire

    Agent → REA * deux read_bytes demandes
    {"address": "0x420068", "length": 16}
    {"address": "0x4210a0", "length": 8}
    Résultats des octets REA * décodés en doubles
    000000000000f93f → 1.5625
    0000000000407f40 → 500.0
    000000000000f03f → 1.0

    Les octets renvoyés établissent les deux constantes arithmétiques et l'échelle panoramique initiale. L'agent a maintenant les valeurs nécessaires pour l'expression C.

Des découvertes de REA à C

Suivez les cinq étapes ci-dessous. Chaque sélection met en évidence les instructions d'origine et les lignes C qu'elles ont renseignées.

Extrait original x86 ·
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
C Reconstruit
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 * Lire l'entrée. La vue d'instruction dans le résultat de la fonction de REA lit [EBP+8] et utilisations FILD pour charger l'entier. Suivre son appelant via REA établit la signification des coordonnées d'écran du paramètre C x.

L'extrait d'assemblage sélectionne les instructions d'entrée, d'arithmétique et de retour. La liste complète ci-dessous comprend également les magasins intermédiaires et la configuration et le nettoyage des fonctions.

Assemblage complet et preuves à l'appui
REA résultat · 0x406400–0x40643f
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

Ce que l'appelant fournit

La fonction de frappe de brique à 0x411f40 met à l'échelle sa coordonnée de tuile de 30, ajoute 20, puis la pousse avant l'appel:

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

Ce que les données lisent établissent

REA lectures d'octets, décodées en doubles little-endian
Adresse Valeur Utilisé pour
0x420068 1.5625 Première multiplication
0x420070 500.0 Soustraction
0x4210a0 1.0 initialement Échelle de casserole stockée

Enregistré avec REA 4.1.0 pour la cible DX-Ball 1.07 épinglée au hachage. Les notes d'enquête liées conservent les identifiants de preuve.

Source maintenue · Notes d'enquête et références des éléments de preuve

Vérification de la fonction récupérée

La fonction récupérée passe deux vérifications: ses valeurs de retour correspondent à l'original et ses octets compilés correspondent à l'exécutable.

3 205 cas de comportement

Les tests exécutent la fonction x86 d'origine et comparent sa valeur de retour avec le C maintenu. Ils couvrent chaque position entière de 0 à 640 à cinq échelles panoramiques: 0, 0,5, 1, 20 et -1.

63 octets correspondants

La fonction C est compilée avec la chaîne d'outils VC4.0 épinglée. La relecture du compilateur correspond à la fonction complète après avoir appliqué les relocalisations examinées et vérifié les constantes référencées.

Sur une échelle de 1, le calcul récupéré renvoie -500 sur le bord gauche, 0 au centre et 500 sur le bord droit. La prochaine partie du travail audio consiste à intégrer cette valeur au backend sonore du jeu.

Lire les détails de la relecture du compilateur

Poursuivre l'enquête

La même approche est utilisée pour les mises à jour de particules, les files d'attente d'explosion et la génération de bonus: inspectez les fonctions pertinentes, récupérez leur état et leurs dépendances, puis comparez l'implémentation avec l'original.

Pour inspecter vous-même la fonction sound-pan, suivez les instructions de configuration du projet DX-Ball et fournissez sa cible d'origine correspondante. Puis cours:

Dans la caisse de DX-Ball
scripts/rea function original/DXBALL.EXE 0x00406400 \
  --snapshot .analysis/rea/dxball.snapshot.json --json

Haut