L4-MIRROR шаг 4: прыжок сквозь зеркало и рождение тени

Порт seg003:0798..08A9 + seg004:0239 + seg002:081D/1131 + seg006:1945.

- is_obstacle (pop_map.c): ветка зеркала — Кид, кадры бегового прыжка
  39..43, направление ВЛЕВО -> modif = 0x56, pop_jumped_mirror = -1,
  препятствия нет (пролетает насквозь).
- mirror_image / jump_through_mirror / pop_check_mirror (pop_map.c):
  отражённый Char уходит в слот Guard как CHARID_1_SHADOW, guardhp =
  hitp_max, у Кида hitp_curr = 1.  savekid НЕ делается — как в оригинале,
  отражается только копия.  Полосы HP перерисует pop_hp_draw сам.
- pop_check_mirror() зовётся из главного цикла ПЕРЕД отрисовкой персонажей
  (в оригинале — первая строка draw_people, seg008:228A).
- autocontrol_shadow + autocontrol_shadow_level4 + clear_char (guards.c):
  тень идёт СВОЕЙ веткой целиком, к стражьему ИИ не сводится — на уровне 4
  она не дерётся, а бежит влево и при x < 80 исчезает.

АТЛАС ТЕНИ — вскрылось при чтении seg006:0532.  Тень вне боевых кадров
150..189 ходит по таблице КИДА, и image оттуда индексирует спрайты Кида,
а не стража.  Выбор атласа в pop_cdraw шёл по СЛОТУ, то есть тень
рисовалась бы спрайтами стража.  Условие вынесено в
pop_frame_tbl_is_guard() (pop_kid.c) — его теперь читают и load_frame, и
отрисовка, разъехаться не могут.  Заодно из pop_load_fram_det_col выделен
pop_load_frame() без determine_col: jump_through_mirror берёт ось
отражения из curr_col, и пересчёт колонки по x там был бы вреден.

Константы MIRROR_* и DIR_56_NONE переехали в pop_guard.h — нужны и
постановке тайла (банк 6), и ИИ тени (банк 1).

Звука sound_45_jump_through_mirror в порте нет, пропущен.

Шаг 5 (клип тени слева от зеркала) НЕ сделан и оказался не однострочником:
в pop_cdraw есть клип сверху/снизу/справа, левого нет вовсе — нужен новый
примитив либо срез исходных колонок.  Расписано в TASKS_OPEN.

Цена: _CODE +18 Б, банк 1 2311 -> 2367, банк 3 10328 -> 10551,
банк 4 8243 -> 8267.  tests-host: все 5 наборов прошли.
НЕ ПРОВЕРЕНО В MAME — сценарий проверки записан в TASKS_OPEN.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-10 21:46:30 +03:00
parent 1b2111f2a0
commit 844fa6d767
12 changed files with 209 additions and 18 deletions
+18 -5
View File
@@ -328,6 +328,17 @@ void pop_kid_data_frame(uint16_t tbl_off, uint8_t idx, uint8_t *out5)
/* load_frame (seg006:0293): скопировать кадр Kid.frame из таблицы в
* cur_frame. Звать ТОЛЬКО когда страница данных замаплена в W0. */
/* Какая ТАБЛИЦА КАДРОВ у персонажа (seg006:0293). Вынесено из load_frame
* отдельной функцией, потому что тот же вопрос решает ОТРИСОВКА: набор
* атласов обязан совпадать с таблицей, иначе image из таблицы Кида ищется
* среди спрайтов стража. Для тени это не теория — она ходит кадрами Кида
* (и рисуется его спрайтами), а дерётся кадрами стража. */
uint8_t pop_frame_tbl_is_guard(int8_t charid, uint8_t frame)
{
return (uint8_t)(charid == CHARID_2_GUARD || charid == CHARID_4_SKELETON ||
(charid == CHARID_1_SHADOW && frame >= 150 && frame < 190));
}
static void load_frame(void)
{
/* Таблица кадров зависит от персонажа (seg006:0293): у Kid своя, у
@@ -341,10 +352,7 @@ static void load_frame(void)
* ТЕНЬ (charid_1_shadow) — по таблице стража ТОЛЬКО в кадрах 150..189,
* в остальных она ходит кадрами Кида (seg006:532). */
const uint8_t *f;
uint8_t use_guard_tbl =
(Char.charid == CHARID_2_GUARD || Char.charid == CHARID_4_SKELETON ||
(Char.charid == CHARID_1_SHADOW &&
Char.frame >= 150 && Char.frame < 190));
uint8_t use_guard_tbl = pop_frame_tbl_is_guard(Char.charid, Char.frame);
if (use_guard_tbl) {
int16_t idx = (int16_t)Char.frame;
if (idx >= 102 && idx < 107) idx += 70;
@@ -514,12 +522,17 @@ void play_seq(void)
* в оригинале. Раньше вторая половина связки работала только на ветке Кида
* (стражу колонку вёл pop_guard_enter/leave) — прямое следствие того, что
* физика знала один Kid. */
void pop_load_fram_det_col(void)
void pop_load_frame(void)
{
if (!kdat_ok) return;
gfx_w0_map(kdat_page);
load_frame();
gfx_w0_unmap();
}
void pop_load_fram_det_col(void)
{
pop_load_frame();
pop_determine_col();
}