Как кольцо нацеливается на игрока
Для атаки Элли требуется прицельное кольцо с начальным счетом 16. Один из помощников рассчитывает направление полета каждой пули. Одно и то же кольцо может быть направлено в фиксированном направлении или повернуто в сторону игрока.
Используйте REA, чтобы узнать, как TH04 создает кольцо из пуль и направляет его на игрока. Объясните расчет и покажите код.
Пример запроса с исходным исполняемым файлом и восстановлением, доступным локально.
TH04 сохраняет полный оборот по часовой стрелке в 256 угловых единицах. Для 16 пуль каждый индекс добавляет по 16 единиц.: 0, 16, 32, …, 240. При добавлении направления движения игрока эти позиции меняются местами.
Шаблон запуска в восстановленном источнике
bullet_template.angle = 0;
bullet_template.group = BG_RING_AIMED;
bullet_template.count = 16;
bullet_template_tune();
В этих строках выбирается шаблон перед настройкой сложности и производительности. Прочитайте источник атаки.
Что возвращает REA
Мы проверяем bullet_velocity_and_angle_set(), которые задают скорость и угол наклона каждой пули. REA возвращает свои инструкции, псевдокод и ссылки. Три части этого результата объясняют закономерность.
-
Проверьте образ DOS, прежде чем читать его код
Агент → REAopen_binary {"path": "MAIN.EXE"} inspect_native_load_image {}REA → агент · выбранные поляstatus: "verified" format: "dos-mz" load_segment: 4096 header_bytes: 6144 module_bytes: 150114Проверка привязывает загруженный код и записи о перемещении к предоставленному исполняемому файлу. Путь, указанный выше, сокращен для отображения.
-
Прочитайте надпись на кольце "умножай и дели"
Агент → REA · функцияanalyze_function{"procedure": "0x2cfc8"}REA → агент · отрывок из инструкции0x2d0eb: MOV AX, SI 0x2d0ed: SHL AX, 0x8 0x2d0f0: MOV DL, byte ptr [0x53af] 0x2d0f9: IDIV BXSIзаписан общий индекс. При сдвиге значение умножается на 256, затем при делении используется значение, считанное изDS:53AF. Имена поддерживаемых источников, которые указаны в полеbullet_template.count. Полная последовательность приведена ниже. -
Найдите, где рисунок поворачивается в сторону игрока
Результат той же функции · выдержка из aim0x2d190: SUB AX, word ptr [0x53a6] 0x2d198: SUB AX, word ptr [0x53a4] 0x2d19d: CALLF 0x1000:1da8 0x2d1a2: ADD word ptr [BP + -0x2], AXСоответствующий поддерживаемый C++group_angle_offset += iatan2( player_pos.cur.y - bullet_template.origin.y, player_pos.cur.x - bullet_template.origin.x );Операнды команд предоставляют две разности координат и вспомогательное значение направления. Возвращаемое значение добавляется к относительному кольцевому углу. Имена источников делают эти адреса удобочитаемыми; REA позволяет агенту проверять исходные операции, стоящие за ними.
От ассемблера к удобочитаемому C++
Выберите шаг, который соответствует первоначальным инструкциям по расчету угла. В этом обзоре приведена схема прицельного кольца; полный исходный код также содержит данные о разбросах, стопках и случайных моделях.
0x2cfcf: MOV SI, word ptr [BP + 0x4]
0x2d0eb: MOV AX, SI
0x2d0ed: SHL AX, 0x8
0x2d0f0: MOV DL, byte ptr [0x53af]
0x2d0f4: MOV DH, 0x0
0x2d0f6: PUSH DX
0x2d0f7: CWD
0x2d0f8: POP BX
0x2d0f9: IDIV BX
0x2d0fb: MOV word ptr [BP + -0x2], AX
0x2d18d: MOV AX, [0x4650]
0x2d190: SUB AX, word ptr [0x53a6]
0x2d194: PUSH AX
0x2d195: MOV AX, [0x464e]
0x2d198: SUB AX, word ptr [0x53a4]
0x2d19c: PUSH AX
0x2d19d: CALLF 0x1000:1da8
0x2d1a2: ADD word ptr [BP + -0x2], AX
0x2d1b9: MOV AL, byte ptr [BP + -0x2]
0x2d1bc: ADD AL, byte ptr [0x53ad]
0x2d1c0: MOV [0xbcc8], AL
unsigned char aimed_ring_angle(
int index, int count,
int player_direction,
unsigned char rotation)
{
int angle = index;
angle = (angle * 256) / count;
angle += player_direction;
angle += rotation;
return (unsigned char)angle;
}
01 · Считываем маркерный индекс. Аргумент stack загружается в SI. В кольце из 16 маркеров этот индекс элемента находится в диапазоне от 0 до 15.
02 · Расставьте направления на полный оборот. SHL AX,8 8 умножается на 256. Число умножается на ноль и преобразуется в слово, затем IDIV делит результат на это число. Для числа 16 каждый индекс умножается на 16 угловых единиц.
03 · Добавьте направление движения игрока. Два вычитания образуют координаты игрока минус исходная точка. Вспомогательный инструмент direction возвращает угол в AX; при сложении все кольцо поворачивается к игроку.
04 · Добавьте поворот шаблона. ADD AL,[0x53ad] добавляет угол наклона шаблона. В исходном шаблоне Elly он равен нулю; другие шаблоны могут использовать тот же вспомогательный элемент с поворотом.
05 · Сохраняйте конечный угол в одном байте. Хранилище записывает AL в поле "Угол появления". Значения переносятся после 255, точно так же, как это происходит при преобразовании беззнаковых байт. Окружающий источник также преобразует этот угол и скорость в скорость вращения.
В сборке выбирается ветвь aimed-ring, вычисление aim и конечное хранилище. Приведенный выше текст на C++ представляет собой удобочитаемую сводку. Приведенные ниже проверки компилятора применяются к поддерживаемому исходному тексту в связанном проекте.
Ознакомьтесь с сохраняемым кольцом и прицелитесь в источник
angle_offset = (i * BULLET_ANGLE_FULL_TURN) / count;
if (i >= (count - 1)) {
group_complete = true;
}
goto aim_or_no_aim;
aim:
group_angle_offset += iatan2(
(player_pos.cur.y - bullet_template.origin.y),
(player_pos.cur.x - bullet_template.origin.x)
);
no_aim:
vector2_near(
bullet_template.velocity,
(group_angle_offset + bullet_template.angle),
speed
);
bullet_spawn_angle = (group_angle_offset + bullet_template.angle);
Кольцевой макрос · Цель и источник скорости · Представление угла
Проверка поддерживаемого источника
Записанные проверки проекта TH04 позволяют скомпилировать код для генерации маркеров, включая этот помощник, с помощью закрепленного набора инструментов Turbo C++ 4.0J.
2,139 совпадающих байта
Скомпилированный код генерации маркеров соответствует 2139-байтовому разделу исходного исполняемого файла.
Две чистые сборки
Две отдельные сборки генерируют одинаковые совпадающие байты. Записанные входные хэши соответствуют показанному здесь сохраненному источнику.
Записано 3 октября 2026 года. Ознакомьтесь с проверками компилятора.
Идентификация цели и объем анализа
| Первоначальная цель | MAIN.EXE , 156 258 байт, DOS MZ |
|---|---|
| Вспомогательная запись | 0x2cfc8 в загруженном изображении REA |
| Смещение исходного файла |
0x1e7c8, возвращаемый параметром address_to_file_offset
|
| Проверка записанного кода | REA 4.1.0 · 7 октября 2026 |
Проверки компилятора охватывают весь раздел кода для добавления маркеров, включая этот вспомогательный инструмент. Они также сравнивают его вклад в отображение и перекрывающееся перемещение.
REA проверил статический загрузочный образ DOS в сегменте загрузки 0x1000. Его адреса описывают этот аналитический образ. Результат функции сообщает о 503 байтах тела в двух диапазонах по 517 байт; выбранные инструкции, приведенные выше, находятся в этих сообщенных диапазонах.
Имена исходных текстов и проверки компилятором исходят из контрольной точки TH04 0d72e980. В предыдущих наблюдениях за реконструкцией использовались собственные аналитические скрипты проекта; на этой странице добавлена новая проверка REA для той же исходной цели. Предоставленная игра идентифицируется в манифесте репозитория, при этом независимое происхождение нетронутого дампа все еще открыто.
На рисунке показан расчет угла. Элементы управления в полной версии игры, хронометраж и поведение аппаратного обеспечения PC-98 проверяются во время выполнения в проекте реконструкции отдельно.
Полная реконструкция TH04
Проект создает четыре DOS-продукта для игры на поддерживаемом C++ и ассемблере. Помимо генерации маркеров, в исходном коде описаны этапы, боссы, рендеринг, ввод, меню, концовки и обработка результатов.
- Источник для генерации маркеров - это полный вспомогательный инструмент, другие типы шаблонов и настройка шаблона.
- Руководство по сборке и запуску DOS Создайте исходный код и протестируйте его в рабочем процессе эмулятора PC-98 проекта.
- Текущая проверка состояния проекта DOS и отдельный собственный порт x64.