67d62e3e8b
Уровень 12 (тень) — порт seg002/seg006: - check_shadow: подъём тени в комнате 15 по условию «меч подобран», init_shad_12, вход падением (seq 7); - autocontrol_shadow_level12: ждать Кида, бой, сближение, СЛИЯНИЕ; - общий урон (ранил тень — ранил себя) и check_killed_shadow (убил тень — убил себя); - таймер вспышки слияния 42 -> -1, sword_disappears при уходе из комнаты 18, появление плит в комнатах 2/13 после слияния. Переход 12 -> 13 бесшовный: двери у уровня нет, он кончается фактом попадания в комнату 23 (tbl_seamless_exit); флаг pop_seamless не даёт сбросить HP. Чит навигации по комнатам этот триггер придерживает — иначе комнату 23 двенадцатого уровня не посмотреть в принципе. Уровень 13 (Джафар): guard_notice_timer (фора после встречи), on_guard_killed + Jaffar_exit, check_fall_flo (гряда плит сверху) и три исключения loose-механики. Плюс спрайты визиря VIZIER.DAT — без них он рисовался обычным стражем; заодно цвет из данных комнаты применяется только к обычному стражу, как в оригинале. Падающие плиты — семь дефектов, найденных прогонами: - MOB_MAX 4 -> 14: check_fall_flo роняет шесть плит разом, лишние терялись без щебня; - одиночные сигналы посадки/провала больше не затираются в кадре; - честный loose_fall: сбитая плита рождается в том же кадре, от места удара, с половинной скоростью; - при снятии плиты метится и сосед справа (висел передний торец); - heal и отрисовка кусков разнесены на два прохода; - куски рисуются ПОСЛЕ фона, порядок между собой — по убыванию y (compare_curr_objs для пары 0x80 сортирует наоборот); - wall_pattern убран из ceil_over_kid_tile: у оригинала узор из draw_tile_bottom идёт в фон, а не в передний слой. Хост-тесты: два новых набора, t_shadow (45 проверок) и t_jaffar (44). TK_ROOMS 8 -> 24 — спецсобытия адресуют комнаты по реальным номерам. Осознанные расхождения (docs/impl_diff.md): нет мигания Кида спрайтами тени при слиянии, чит навигации не запускает бесшовный переход, чит K убивает через штатный путь смерти. Открытым остаётся разбор слоёв: MOB-CLIP-RIGHT, MID-OVERLAY-LAYER, GUARD-FALLOUT-VICTORY, BG-ONCE (BUGS_OPEN.md / TASKS_OPEN.md). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
77 lines
4.8 KiB
C
77 lines
4.8 KiB
C
/*
|
||
* pop_state.h — состояние, общее для банков и W1/W2. См. pop_state.c.
|
||
*
|
||
* Правило: если переменную читают/пишут по обе стороны банковой границы —
|
||
* её место здесь, а НЕ в банковом модуле (там она уедет в страницу банка).
|
||
*/
|
||
#ifndef POP_STATE_H
|
||
#define POP_STATE_H
|
||
|
||
#include <stdint.h>
|
||
|
||
/* Кусок loose приземлился (loose_land, seg007:11E8): 0 = нет, иначе
|
||
* tilepos+1 тайла, на который он лёг. Ставит отрисовка mob (банк),
|
||
* разбирает логика loose-полов (pop_map, W1/W2). */
|
||
extern uint8_t pop_loose_landed;
|
||
|
||
/* Кусок loose ушёл ниже поля своей комнаты: 0 = нет, иначе col+1; комната
|
||
* отправления — pop_loose_exit_room. Ставит отрисовка mob (банк 7),
|
||
* разбирает главный цикл (посадка в комнате снизу). */
|
||
extern uint8_t pop_loose_exit;
|
||
extern uint8_t pop_loose_exit_room;
|
||
|
||
/* Тайл СОСЕДНЕЙ (не отрисованной) комнаты изменился — перечитать кромки.
|
||
* Подробности — в pop_state.c. */
|
||
extern uint8_t pop_neigh_dirty;
|
||
|
||
/* Бесшовный переход между уровнями (seamless): подробности в pop_state.c.
|
||
* Ставится главным циклом при попадании в комнату-выход, гасится стартом
|
||
* уровня — он же единственный, кто на флаг смотрит. */
|
||
extern uint8_t pop_seamless;
|
||
|
||
/* Держатель бесшовного перехода после ЧИТ-телепорта (см. pop_state.c).
|
||
* Ставит pop_dbg_roomnav, снимает первая смена комнаты обычным ходом. */
|
||
extern uint8_t pop_nav_hold;
|
||
|
||
/* Чит «бессмертие» (I): Кида бьют, но HP не убавляется. Читают пути урона
|
||
* (боёвка в банке, пики в pop_map), переключает главный цикл. */
|
||
extern uint8_t pop_immortal;
|
||
|
||
/* Габариты ПОСЛЕДНЕЙ нарисованной двери уровня — порт глобалов
|
||
* leveldoor_right / leveldoor_ybottom (seg008 draw_leveldoor). Их ставит
|
||
* отрисовка (банк pop_bg), а читает clip_char (pop_map, W1/W2): кадры
|
||
* подъёма по лестнице (224..228) обрезаются по правому косяку проёма и по
|
||
* низу поднятой створки. Дверь рисуется ПОД персонажем, поэтому перекрыть
|
||
* его не может — оригинал именно режет спрайт.
|
||
* right — экранный X правой кромки; ybottom — room-space Y (без POP_YOFF).
|
||
* 0 = двери в отрисованной комнате нет. */
|
||
extern int pop_leveldoor_right;
|
||
extern int pop_leveldoor_ybottom;
|
||
|
||
/* droppedout (seg006:1140): Кида СПИХНУЛИ с уступа в бою — он падает из
|
||
* боевой стойки. Ставит start_fall (pop_map, банк 3), читает ИИ стража
|
||
* (guards.c, банк 1): по этому флагу страж решает, идти ли за упавшим вниз
|
||
* (guard_follows_kid_down, seg002:09F8). Отсюда и место в общем модуле —
|
||
* банки друг другу данные не отдают. */
|
||
extern uint8_t pop_droppedout;
|
||
|
||
/* leveldoor_open (seg007:456): 1 — дверь уровня открыта полностью. Пишет
|
||
* анимация двери (банк 6), читает подъём скелета (банк 1). Word, как в
|
||
* оригинале: на уровне 8 в него же СЧИТАЕТСЯ задержка до мыши (см.
|
||
* pop_state.c и pop_check_mouse в guards.c). */
|
||
extern uint16_t pop_leveldoor_open;
|
||
|
||
/* Отладочная «пустышка» для брейкпоинтов из банков — см. pop_state.c.
|
||
* Звать из отлаживаемого места под нужным `if`, брейкпоинт ставить на
|
||
* _pop_dbg_trap (резидент W1, адрес однозначен). */
|
||
extern uint8_t pop_dbg_hits;
|
||
void pop_dbg_trap(void);
|
||
|
||
#endif
|
||
|
||
/* Зеркало уровня 4 (jumped_through_mirror, seg003). −1 — Кид ТОЛЬКО ЧТО
|
||
* пролетел сквозь зеркало (ставит is_obstacle в pop_map, банк 3), и
|
||
* следующий pop_check_mirror родит тень; 0 — обычное состояние.
|
||
* Межбанковый: пишет pop_map, читает pop_map же, но через главный цикл. */
|
||
extern int8_t pop_jumped_mirror;
|