Як кільце націлюється на гравця
Для атаки Еллі потрібно прицільне кільце з початковим рахунком 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.0 J.
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.