Тематическое исследование · 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 байтам.
Одна функция, от исполняемой до проверяемой C. REA предоставляет инструкции, вызывающие устройства и данные для чтения; проект реконструкции реализует и тестирует результат. Открыть рисунок
55
поддерживаемые функции C
45,380
сравнение с исходным кодом
33
функции с соответствующими скомпилированными байтами

Контрольная точка проекта: 7 октября 2026 года. Журнал выполнения работ · Тестовый охват

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

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

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

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

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

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

Пример запроса для вашего coding agent с доступным локальным исполняемым файлом. В приведенном ниже исследовании показаны запросы 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.

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

Полная сборка и подтверждающие доказательства
Результат 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 с привязкой к хэшу. В связанных материалах расследования сохраняются идентификаторы улик.

Поддерживаемый источник · Заметки о расследовании и ссылки на доказательства

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

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

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

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

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

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

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

Ознакомьтесь с подробностями воспроизведения компилятором

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

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

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

При оформлении заказа DX-Ball
scripts/rea function original/DXBALL.EXE 0x00406400 \
  --snapshot .analysis/rea/dxball.snapshot.json --json

Топ