---
title: 'DX-Ball inżynieria odwrotna: panoramowanie dźwięku-REA'
url: https://rea.tools/pl/showcase/dx-ball/
---

[Spis treści](https://rea.tools/pl/) / [Gabloty](https://rea.tools/pl/showcase/) / DX-Ball

Studium przypadku \* DX-Ball 1.07

# Przebudowa DX-Ball z jego pliku wykonywalnego.

Celem jest utrzymanie wersji C gry Windows z 1996 roku. REA pomaga agentowi sprawdzić oryginalną, jedną funkcję na raz.

Windows i386 \* C \* REA

![DXBALL.Funkcja EXE 0x00406400 jest sprawdzana za pomocą REA . Dzwoniący z cegły dostarcza 20 plus 30 razy tile_x. instrukcje załaduj x, pomnóż przez 1,5625, odejmij 500,0, zastosuj skalę pan_scale i zwróć liczbę całkowitą. Utrzymane C jest sprawdzane niezależnie od oryginalnego x86 w 3205 przypadkach i przez kompilator VC4.0 replay pasujący do 63 bajtów.](https://rea.tools/assets/localized/pl/figures/dx-ball-sound-pan-investigation.svg)

Jedna funkcja, od wykonywalnego do sprawdzonego C. REA dostarcza instrukcje, rozmówców i odczyty danych; projekt rekonstrukcji implementuje i testuje wynik. [Otwórz rysunek](https://rea.tools/assets/localized/pl/figures/dx-ball-sound-pan-investigation.svg)

55
:   utrzymywane funkcje C

45,380
:   porównania z oryginalnym kodem

33
:   funkcje z dopasowanymi skompilowanymi bajtami

Punkt kontrolny projektu: 7 października 2026 r. [Progress ledger](https://github.com/N0zoM1z0/dx-ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/PROGRESS.md) · [Pokrycie testu](https://github.com/N0zoM1z0/dx-ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ORACLES.md)

## Dotychczasowy projekt

Odzyskany kod obejmuje obsługę tablic i zasobów, trafienia cegieł, animacje, cząstki i produkcję bonusów. Obecne Kompilacje zapewniają narzędzia inspekcyjne i bibliotekę analiz. Prace nad grywalną grą kontynuowane są z fizyką piłki i wiosła, obsługą zasilania i integracją Windows.

## Znalezienie obliczenia lewej / prawej pozycji dźwięku

Po uderzeniu Cegły jej pozycja pozioma jest przekazywana do kodu dźwiękowego. Dochodzenie wymagało odzyskania, w jaki sposób ta współrzędna ekranu staje się wartością panoramowania w lewo/w prawo.

Twój agent kodowania

Użyj REA, aby dowiedzieć się, jak DX-Ball oblicza pozycjonowanie dźwięku stereo. Wyjaśnij obliczenia i pokaż kod.

Przykładowy monit dla agenta kodującego z dostępnym lokalnym plikiem wykonywalnym. Poniższe dochodzenie pokazuje zapytania REA i dowody stojące za odpowiedzią.

Agent użył REA do sprawdzenia funkcji, podążania za jej dzwoniącym z cegły i odczytywania stałych z pliku wykonywalnego. Wyniki te dostarczyły danych wejściowych i arytmetycznych potrzebnych do zapisania funkcji C poniżej.

Pierwszy wynik funkcji dla `0x406400` dołączono deklarowanie pseudokodu `FUN_00406400(void)` i dzwonienie `__ftol()`. Jego widok instrukcji pokazywał wejście stosu i operacje zmiennoprzecinkowe. Ta rozbieżność dała agentowi konkretny powód do dalszego dochodzenia.

Pierwszy widok dekompilatora

Wynik REA \* fragment pseudokodu

```
longlong FUN_00406400(void)
{
  longlong lVar1;

  lVar1 = __ftol();
  return lVar1;
}
```

Wyjście pokazuje wywołanie konwersji. Czytanie poniższych instrukcji ujawnia wejście i podawanie obliczeń, które wywołanie.

### Trzy pytania odpowiedział przez REA

1. #### Odzyskaj brakujące dane wejściowe

   Agent → REA · `analyze_function`

   ```
   {"procedure": "0x406400"}
   ```

   REA → agent \* fragment instrukcji

   ```
   0x406409: MOV EAX, dword ptr [EBP + 0x8]
   0x40640c: MOV dword ptr [EBP + -0xc], EAX
   0x40640f: FILD dword ptr [EBP + -0xc]
   ```

   Wynik funkcji zawiera instrukcje obok pseudokodu i rozmówców. Tutaj, `[EBP+8]` ujawnia dane wejściowe całkowite brakujące w widoku dekompilatora.
2. #### Postępuj zgodnie z rozmówcą, aby zrozumieć Dane wejściowe

   Agent → REA · `analyze_function`

   ```
   {"procedure": "0x411f40"}
   ```

   REA → agent \* fragment dzwoniącego

   ```
   0x411f5b: ADD EAX, 0x14
   0x411f5e: PUSH EAX
   0x411f5f: CALL 0x00406400
   ```

   REA zidentyfikował tego rozmówcę w pierwszym wyniku. Jego poprzednia skala instrukcji `tile_x` przez 30; dodanie 20 daje współrzędną ekranu Cegły, `20 + 30 × tile_x`.
3. #### Przeczytaj wartości za adresami pamięci

   Agent → REA \* dwa `read_bytes` wnioski

   ```
   {"address": "0x420068", "length": 16}
   {"address": "0x4210a0", "length": 8}
   ```

   Wyniki bajtów REA \* dekodowane jako podwójne

   ```
   000000000000f93f → 1.5625
   0000000000407f40 → 500.0
   000000000000f03f → 1.0
   ```

   Zwracane bajty ustanawiają dwie stałe arytmetyczne i początkową skalę przesuwania. Agent ma teraz wartości potrzebne do wyrażenia C.

### Od ustaleń REA do C

Wykonaj pięć poniższych kroków. Każdy wybór podkreśla oryginalne instrukcje i poinformowane przez nich linie C.

Oryginalny x86 \* fragment

```
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
```

Zrekonstruowany 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 \* odczytaj dane wejściowe.** Widok instrukcji w wyniku funkcji REA odczytuje `[EBP+8]` i używa `FILD` aby załadować liczbę całkowitą. Po wywołaniu przez REA ustanawia znaczenie współrzędnych ekranu parametru C `x`.

**02 \* pomnóż przez 1,5625.** `FMUL` czyta podwójne w `0x420068`. Bajty zwrócone przez REA `read_bytes` dekodowanie do `1.5625`; C używa tej samej stałej.

**03 \* Odejmij 500,0.** `FSUB` czyta podwójne w `0x420070`. Wynik bajtu REA dekoduje do `500.0`, przesunięcie środka obliczeń do współrzędnych ekranu `320`.

**04 \* Zastosuj zapisaną skalę.** Drugi `FMUL` czyta `0x4210a0`. Ten globalny nazywa się `dxball_pan_scale` w utrzymywanym źródle. Odczyt drugiego bajtu REA ustala jego początkową wartość `1.0`.

**05 \* Zwraca liczbę całkowitą.** Wezwanie na `0x406430` sięga `__ftol`, zidentyfikowane w wynikach callee REA. C rzuca wynik do `DxBallInt`; oryginał-porównania x86 sprawdzają zwróconą wartość.

Fragment zestawu wybiera instrukcje wejściowe, arytmetyczne i zwrotne. Pełna lista poniżej obejmuje również interwencyjne sklepy oraz konfigurację i czyszczenie funkcji.

Pełne zgromadzenie i dowody potwierdzające

Wynik REA \* 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
```

### Co dostarcza rozmówca

Funkcja brick-hit w `0x411f40` skaluje współrzędną płytki o 30, dodaje 20, a następnie popycha ją przed wywołaniem:

```
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
```

### Co odczytują dane

Bajt REA odczytuje, dekoduje jako mało - endian podwaja

| Adres | Wartość | Używany do |
| --- | --- | --- |
| `0x420068` | `1.5625` | Pierwsze mnożenie |
| `0x420070` | `500.0` | Odejmowanie |
| `0x4210a0` | `1.0` początkowo | Przechowywana skala patelni |

Nagrany z REA 4.1.0 Dla celu DX-Ball 1.07 przypiętego hash. Powiązane notatki z dochodzenia zachowują identyfikatory dowodów.

[Utrzymane źródło](https://github.com/N0zoM1z0/dx-ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/src/gameplay.c#L41) · [Notatki z dochodzenia i odniesienia do dowodów](https://github.com/N0zoM1z0/dx-ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/GAMEPLAY_OWNER.md)

## Sprawdzanie odzyskanej funkcji

Odzyskana Funkcja Przechodzi dwa kontrole: jej wartości zwracane są zgodne z oryginałem, a skompilowane bajty są zgodne z plikiem wykonywalnym.

### 3205 przypadków zachowania

Testy wykonują oryginalną funkcję x86 i porównują jej wartość zwracaną z utrzymanym C. obejmują każdą pozycję całkowitą od 0 do 640 w pięciu skalach pan: 0, 0,5, 1, 20 i -1.

### 63 pasujące bajty

Funkcja C jest kompilowana z przypiętym łańcuchem narzędzi VC4.0. Powtórka kompilatora pasuje do pełnej funkcji po zastosowaniu sprawdzonych relokacji i sprawdzeniu przywoływanych stałych.

W skali 1 odzyskane obliczenia zwracają -500 na lewej krawędzi, 0 Na środku i 500 na prawej krawędzi. Kolejną częścią pracy audio jest integracja tej wartości z zapleczem dźwiękowym gry.

[Przeczytaj szczegóły powtórki kompilatora](https://github.com/N0zoM1z0/dx-ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/BUILD_MATCHING.md)

## Kontynuuj dochodzenie

To samo podejście stosuje się w przypadku aktualizacji cząstek, kolejek wybuchowych i generowania premii: sprawdź odpowiednie funkcje, Odzyskaj ich stan i zależności, a następnie porównaj implementację z oryginałem.

Aby samodzielnie sprawdzić funkcję panoramowania dźwięku, postępuj zgodnie z instrukcjami konfiguracji projektu DX-Ball i podaj odpowiadający jej oryginalny cel. Następnie uruchom:

W kasie DX-Ball

```
scripts/rea function original/DXBALL.EXE 0x00406400 \
  --snapshot .analysis/rea/dxball.snapshot.json --json
```

- [Repozytorium DX-Ball](https://github.com/N0zoM1z0/dx-ball)Aktualne źródło, postęp i konfiguracja lokalna.
- [REA analiza przepływu pracy](https://rea.tools/guides/native/)Postępuj zgodnie z obliczeniami, a następnie użyj tego samego podejścia z własnym plikiem binarnym.
- [Cząstki i produkcja premii](https://github.com/N0zoM1z0/dx-ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ENTITIES_OWNER.md)Większe dochodzenie w sprawie stanu, kolejek i pikseli pisze.

[Zacznij od własnego celu](https://rea.tools/get-started/)
