---
title: 'DX-Ball Обратный инжиниринг: Панорамирование звука — REA'
url: https://rea.tools/ru/showcase/dx-ball/
---

[Главная](https://rea.tools/ru/) страница / [Витрины](https://rea.tools/ru/showcase/) / DX-Ball

Тематическое исследование · DX-Ball 1.07

# Восстанавливаем DX-Ball из его исполняемого файла.

Целью является создание поддерживаемой версии игры Windows на языке C, выпущенной в 1996 году. REA помогает агенту проверять оригинал, по одной функции за раз.

Windows для i386 · с · REA

![DXBALL.EXE функция 0x00406400 проверяется с помощью REA . Вызывающий абонент, попавший в тупик, выдает значение tile_x в 20 и 30 раз больше. Инструкции загружают x, умножают на 1,5625, вычитают 500,0, применяют pan_scale и возвращают целое число. Поддерживаемый C проверяется независимо от исходного x86 в 3205 случаях и с помощью компилятора VC4.0 воспроизводится на соответствие 63 байтам.](https://rea.tools/assets/localized/ru/figures/dx-ball-sound-pan-investigation.svg)

Одна функция, от исполняемой до проверяемой C. REA предоставляет инструкции, вызывающие устройства и данные для чтения; проект реконструкции реализует и тестирует результат. [Открыть рисунок](https://rea.tools/assets/localized/ru/figures/dx-ball-sound-pan-investigation.svg)

55
:   поддерживаемые функции C

45,380
:   сравнение с исходным кодом

33
:   функции с соответствующими скомпилированными байтами

Контрольная точка проекта: 7 октября 2026 года. [Журнал выполнения](https://github.com/N0zoM1z0/dx-ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/PROGRESS.md) работ · [Тестовый охват](https://github.com/N0zoM1z0/dx-ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ORACLES.md)

## Проект до сих пор

Восстановленный код охватывает управление доской и ресурсами, удары кирпичом, анимацию, частицы и получение бонусов. В текущих сборках доступны утилиты проверки и библиотека анализа. Продолжается работа над игрой, в которую можно играть, физикой мяча и весла, управлением усилениями и интеграцией Windows.

## Определение положения звука слева/справа при расчете

При ударе по кирпичу его горизонтальное положение передается в звуковой код. В ходе исследования было необходимо восстановить, как эта координата экрана преобразуется в значение поворота влево/вправо.

Ваш кодирующий агент

Используйте REA, чтобы узнать, как DX-Ball рассчитывает расположение стереозвука. Объясните расчет и покажите код.

Пример запроса для вашего ИИ-помощника для программирования с доступным локальным исполняемым файлом. В приведенном ниже исследовании показаны запросы REA и доказательства, лежащие в основе ответа.

Агент использовал REA для проверки функции, отслеживания ее вызывающего устройства и считывания констант из исполняемого файла. Эти результаты предоставили входные данные и арифметику, необходимые для написания функции на языке Си, приведенной ниже.

Первый результат функции для `0x406400` включал псевдокод, объявляющий `FUN_00406400(void)` и вызывающий `__ftol()`. В окне команд отображался ввод данных из стека и операции с плавающей запятой. Это несоответствие дало агенту конкретную причину продолжить расследование.

Первое представление декомпилятора

Результат REA · фрагмент псевдокода

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

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

На выходе отображается вызов преобразования. При чтении приведенных ниже инструкций можно увидеть входные данные и вычисления, которые используются для этого вызова.

### Ответы на три вопроса с помощью REA

1. #### Восстановите недостающие входные данные

   Агент → REA · функция `analyze_function`

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

   REA → агент · отрывок из инструкции

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

   Результат работы функции включает инструкции наряду с псевдокодом и вызывающими элементами. Здесь `[EBP+8]` предоставляет целочисленный ввод, отсутствующий в представлении декомпилятора.
2. #### Следуйте за вызывающим абонентом, чтобы понять вводимые данные

   Агент → REA · функция `analyze_function`

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

   REA → агент · отрывок из сообщения о звонящем

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

   REA идентифицировал этого вызывающего абонента в первом результате. В предыдущих инструкциях tile_x масштабируется `tile_x`на 30; добавление 20 дает экранную координату кирпича, `20 + 30 × tile_x`.
3. #### Считайте значения, стоящие за адресами памяти

   Агент → REA · два `read_bytes`запроса на чтение в байтах

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

   Результаты в байтах REA · декодируются как двойные

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

   Возвращаемые байты задают две арифметические константы и начальный масштаб панорамирования. Теперь у агента есть значения, необходимые для выражения на языке Си.

### От выводов REA до C

Выполните пять шагов, описанных ниже. В каждом выбранном элементе выделены исходные инструкции и основные строки, которые они содержали.

Оригинальная выдержка из 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

```
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 · Считайте входные данные.** В окне команд в результате работы функции REA отображается `[EBP+8]` и используется `FILD` для загрузки целого числа. Отслеживание вызывающего абонента через REA устанавливает значение экранной координаты параметра C `x`.

**02 · Умножить на 1,5625.** `FMUL` считывает удвоенное значение `0x420068`. Байты, возвращаемые функцией REA's `read_bytes`, декодируются как `1.5625`; C использует ту же константу.

**03 · Вычтите 500,0.** `FSUB` считывает двойное значение в `0x420070`. Результат в байтах REA расшифровывается как `500.0`, смещая центр вычисления на экранную координату `320`.

**04 · Примените сохраненную шкалу.** Второй `FMUL` показывает значение `0x4210a0`. В поддерживаемом источнике этот глобал называется `dxball_pan_scale`. При чтении второго байта REA его начальное значение равно `1.0`.

**05 · Возвращает целое число.** Вызов по `0x406430` 0x406430 достигает значения `__ftol`, указанного в результатах поиска вызываемого абонента REA. C преобразует результат в `DxBallInt`; исходные сравнения с x86 проверяют возвращаемое значение.

В приведенном ниже отрывке из сборки выбираются инструкции по вводу, арифметике и возврату. В приведенный ниже полный список также включены промежуточные хранилища, настройка и очистка функций.

Полная сборка и подтверждающие доказательства

Результат 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
```

### Что предоставляет вызывающий абонент

Функция brick-hit в `0x411f40` масштабирует свою координату плитки на 30, добавляет 20, а затем перемещает ее перед вызовом:

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

### То, что читают данные, устанавливает

Считывается байт REA, декодируемый как удвоение в порядке убывания

| Адрес | Ценность | Используется для |
| --- | --- | --- |
| `0x420068` | `1.5625` | Первое умножение |
| `0x420070` | `500.0` | Вычитание |
| `0x4210a0` | `1.0` изначально | Сохраненные весы для поддонов |

Записано с помощью REA 4.1.0 для цели DX-Ball 1.07 с привязкой к хэшу. В связанных материалах расследования сохраняются идентификаторы улик.

[Поддерживаемый источник](https://github.com/N0zoM1z0/dx-ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/src/gameplay.c#L41) · [Заметки о расследовании и ссылки на доказательства](https://github.com/N0zoM1z0/dx-ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/GAMEPLAY_OWNER.md)

## Проверка восстановленной функции

Восстановленная функция проходит две проверки: ее возвращаемые значения совпадают с исходными, а скомпилированные байты соответствуют исполняемому файлу.

### 3 205 случаев нарушения поведения

Тесты выполняют исходную функцию x86 и сравнивают возвращаемое ею значение с сохраненным значением C. Они охватывают все целочисленные позиции от 0 до 640 в пяти масштабах панорамирования: 0, 0,5, 1, 20 и -1.

### 63 совпадающих байта

Функция C компилируется с помощью закрепленной цепочки инструментов VC4.0. Повторное воспроизведение компилятором соответствует полной функции после применения рассмотренных изменений и проверки констант, на которые даны ссылки.

При шкале, равной 1, восстановленные вычисления возвращают значение -500 по левому краю, 0 по центру и 500 по правому краю. Следующая часть работы со звуком - это интеграция этого значения со звуковым сопровождением игры.

[Ознакомьтесь с подробностями воспроизведения компилятором](https://github.com/N0zoM1z0/dx-ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/BUILD_MATCHING.md)

## Продолжайте расследование

Тот же подход используется для обновления частиц, создания очередей с расширением и генерации бонусов: проверьте соответствующие функции, восстановите их состояние и зависимости, а затем сравните реализацию с исходной.

Чтобы самостоятельно проверить функцию панорамирования звука, следуйте инструкциям по настройке DX-Ball project и укажите соответствующую исходную цель. Затем запустите:

При оформлении заказа DX-Ball

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

- [Текущий источник репозитория](https://github.com/N0zoM1z0/dx-ball) DX-Ball, ход выполнения и локальная настройка.
- [Рабочий процесс анализа](https://rea.tools/guides/native/) REA Завершается вычислением, затем используйте тот же подход с вашим собственным двоичным файлом.
- [Создание частиц и бонусов](https://github.com/N0zoM1z0/dx-ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ENTITIES_OWNER.md) - более масштабное исследование состояния, очередей и записи пикселей.

[Начните со своей собственной цели](https://rea.tools/get-started/)
