L6-SHADOW: тень роняет решётку + кромка ряда ниже

1. L6-SHADOW (seg002:0090 + seg002:1064).  Тень встаёт при каждом входе в
   комнату 1 уровня 6 и делает ОДИН осторожный шаг (Shift+вперёд) в тот
   кадр, когда Кид прыгает к решётке (Kid.frame == 43, Kid.x < 128): встаёт
   на closer (1,1) и роняет решётку (1,2), за порожек которой Кид цепляется.
   do_init_shad переписан под таблицы init_shad_5/6 — первые 7 полей Char,
   как memcpy(&Char, source, 7) у оригинала.

   Проверено в MAME: «Кид прыгнул, зацепился, Тень сделал шаг, решётка
   упала».  Тем самым закрыт остаток GUARD-PHYS — нажатие плиты НЕ-Кидом
   работает.

2. BUG-BELOWROW-WALL.  При отсутствующей комнате снизу load_rowbelow
   (seg008:368) подставляет tiles_0_empty колонкам 1..9 и tiles_20_wall
   только левому краю; у нас стеной забивались все 11 позиций, и её
   topright лез жёлтыми треугольниками под пустые тайлы нижнего ряда
   (видно в шахте падения, комната 3).

Комнаты 1 и 3 уровня 6 сверены с картой SDLPoP: расхождения только силуэты
персонажей.  tests-host 5/5, size-check чист.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-11 22:20:12 +03:00
parent 740cc6d652
commit e4ef489872
6 changed files with 268 additions and 178 deletions
+48 -13
View File
@@ -224,18 +224,25 @@ static uint8_t demo_index; /* текущая запись
#define SEQ_2_STAND 2
#define TILE_POTION 10
/* init_shad_5 (data:0EF2): frame 15, x 55, y 55, direction 0 (вправо),
* curr_col −1 (ещё за левым краем), curr_row 0, action 0 (стоит). */
static void do_init_shad_5(uint8_t room)
/* Таблицы init_shad_N (data:0EEA/0EF2) — ПЕРВЫЕ СЕМЬ полей Char в том же
* порядке, в каком их копирует оригинал (`memcpy(&Char, source, 7)`):
* frame, x, y, direction, curr_col, curr_row, action.
* 5: x 55, y 55, вправо, колонка −1 (ещё за левым краем экрана), ряд 0;
* 6: x 81, y 118, вправо, колонка 0, ряд 1 — тень стоит на границе
* (1,0)-(1,1), одного осторожного шага хватает, чтобы встать на плиту. */
static const uint8_t init_shad_5[7] = { 0x0F, 0x37, 0x37, 0, 0xFF, 0, 0 };
static const uint8_t init_shad_6[7] = { 0x0F, 0x51, 0x76, 0, 0x00, 1, 0 };
static void do_init_shad(const uint8_t *tbl, uint8_t room)
{
pop_loadshad();
Char.frame = 0x0F;
Char.x = 0x37;
Char.y = 0x37;
Char.direction = 0;
Char.curr_col = -1;
Char.curr_row = 0;
Char.action = 0;
Char.frame = tbl[0];
Char.x = tbl[1];
Char.y = tbl[2];
Char.direction = (int8_t)tbl[3];
Char.curr_col = (int8_t)tbl[4];
Char.curr_row = (int8_t)tbl[5];
Char.action = tbl[6];
Char.room = room;
Char.charid = CHARID_1_SHADOW;
Char.alive = Kid.alive; /* наследование от Кида, см. шапку */
@@ -254,12 +261,22 @@ static void do_init_shad_5(uint8_t room)
uint8_t pop_check_shadow(uint8_t room) __banked
{
/* Уровень 6 (seg002:0090): условий на содержимое комнаты нет вовсе —
* тень встаёт при КАЖДОМ входе в комнату 1. Оригинал здесь ещё играет
* sound_25_presentation один раз, отмечая это `leveldoor_open = 0x4D`
* (переменная двери используется как флаг); звука у нас нет, а чужую
* переменную портить незачем — TODO вместе со звуком. */
if (pop_current_level == SHADOW_STEP_LEVEL) {
if (room != SHADOW_STEP_ROOM) return 0;
do_init_shad(init_shad_6, room);
return 1;
}
if (pop_current_level != SHADOW_STEAL_LEVEL) return 0;
if (room != SHADOW_STEAL_ROOM) return 0;
/* Зелья уже нет — тень своё дело сделала. Возвращаем 1 и здесь: стража
* комнаты 24 оригинал не поднимает НИКОГДА (return до enter_guard). */
if (pop_level_tile(room, SHADOW_POTION_TILEPOS) != TILE_POTION) return 1;
do_init_shad_5(room);
do_init_shad(init_shad_5, room);
return 1;
}
@@ -604,12 +621,30 @@ static void autocontrol_shadow_level5(void)
if (Char.x < 15) clear_char();
}
/* autocontrol_shadow (seg002:081D) — по уровням. Ветки 6 (шагает по плите)
* и 12 появятся со своими уровнями. */
/* autocontrol_shadow_level6 (seg002:1064). Вся логика — один осторожный шаг
* (Shift + вперёд) в тот кадр, когда Кид прыгает к решётке: тень встаёт на
* closer (1,1) и роняет решётку (1,2), за порожек которой Кид в этот момент
* цепляется. Условие смотрит на КИДА: кадр 43 — четвёртый кадр бег-прыжка,
* x < 128 отсекает прыжки в правой половине комнаты (там Кид ещё разбегается
* и до решётки ему далеко). */
#define FRAME_43_RUNJUMP 43
static void autocontrol_shadow_level6(void)
{
if (Char.room != SHADOW_STEP_ROOM) return;
if (Kid.frame != FRAME_43_RUNJUMP) return;
if (Kid.x >= 128) return;
move_6_shift();
move_1_forward();
}
/* autocontrol_shadow (seg002:081D) — по уровням. Ветка 12 появится со своим
* уровнем. */
static void autocontrol_shadow(void)
{
if (pop_current_level == MIRROR_LEVEL) autocontrol_shadow_level4();
if (pop_current_level == SHADOW_STEAL_LEVEL) autocontrol_shadow_level5();
if (pop_current_level == SHADOW_STEP_LEVEL) autocontrol_shadow_level6();
}
/* autocontrol_guard (seg002:701) + autocontrol_opponent (seg002:628). */