L4-MIRROR шаги 1-2: зеркало в атласе + постановка тайла по открытию двери

Задача заведена активной на доске по решению пользователя (palace был
отложен 2026-08-04, но уровень 4 уже гоняется в MAME и зеркало —
единственное, что мешает пройти его сюжетно).  Механика целиком сверена по
SDLPoP, таблица соответствий в TASKS_OPEN.

Шаг 1 — АТЛАС.  tile_table[0x0D] = база 75, фронт 77 (наша таблица
совпадает с SDLPoP байт в байт).  Тайла 13 НЕТ НИ В ОДНОМ уровне
статически: перебор всех 15 res200N.bin даёт ноль попаданий (санити
разбора: ур.1 без чомпера, ур.3 с 18, ур.4 с паласными 25..29).  Значит
render_room эти id не увидит и на месте зеркала был бы чёрный провал —
грабли memory pop_atlas_dynamic_ids.  Добавлены MIRROR_ENV_IDS = {75,77} в
pop_pack_bg.py, 77 ещё и в FORE_ENV_IDS.  Оба набора переупакованы:
fore 17 -> 18 спрайтов, все страницы EMM в пределах 16 КБ.

Шаг 2 — ПОСТАНОВКА.  place_mirror() в pop_trob.c по переходу
pop_leveldoor_open 0/2 -> 1 (условие оригинала, seg007:0457 — иначе тайл
ставился бы заново каждый кадр открытой двери).  Пишет тайл 13 в комнату 4,
колонку 4, ряд 0; если комната уже на экране — POP_RD_FLOOR на обе
страницы.  Банк 6 3450 -> 3518.

НЕ ПРОВЕРЕНО В MAME: нужно нажать плиту выхода на уровне 4 и дойти до
комнаты 4.  Отдельный вопрос к проверке — не устареет ли g_fg коллизии,
если игрок окажется в комнате 4 в момент постановки.

Дальше по плану: 4 (прыжок сквозь + рождение тени), 5 (клип тени),
3 (отражение — косметика, самое дорогое).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-10 21:26:58 +03:00
parent 67a4c71138
commit 1b2111f2a0
7 changed files with 111 additions and 5 deletions
+43 -3
View File
@@ -409,7 +409,37 @@ static void animate_button(uint8_t idx, int8_t *type)
* type = -1. */
static const uint8_t leveldoor_close_speeds[5] = {0, 5, 17, 99, 0};
static void animate_leveldoor(uint8_t *m, int8_t *type)
/* ---- Спецсобытие уровня 4: ПОЯВЛЕНИЕ ЗЕРКАЛА ------------------------ *
*
* seg007:0457, хвост animate_leveldoor: когда дверь выхода ДОРИСОВАЛА
* открытие и leveldoor_open переходит 0/2 -> 1, оригинал ставит тайл
* зеркала прямо в данные комнаты:
*
* get_tile(mirror_room, mirror_column, mirror_row);
* curr_room_tiles[curr_tilepos] = tiles_13_mirror;
*
* Ставится он в ЧУЖУЮ комнату (4), а не в ту, где дверь. В статике уровня
* зеркала НЕТ НИ В ОДНОМ файле (проверено перебором всех 15 res200N.bin),
* поэтому его спрайты 75/77 пришлось добавить в атлас явным списком —
* MIRROR_ENV_IDS в pop_pack_bg.py (грабли memory pop_atlas_dynamic_ids). */
#define MIRROR_LEVEL 4
#define MIRROR_ROOM 4
#define MIRROR_TILEPOS 4 /* row 0, col 4 */
#define TILE_MIRROR 0x0D
static void place_mirror(uint8_t cur_room)
{
if (pop_current_level != MIRROR_LEVEL) return;
pop_level_set_tile(MIRROR_ROOM, MIRROR_TILEPOS, TILE_MIRROR);
/* Комната зеркала обычно НЕ та, где дверь выхода, — игрок войдёт в неё
* позже и она отрисуется целиком. Но если она уже на экране, тайл надо
* вернуть: зеркало ДОБАВЛЯЕТ графику поверх пустого места, поэтому
* хватает обычной пометки (wipe пола + полный draw_tile). */
if (cur_room == MIRROR_ROOM)
pop_set_redraw(MIRROR_TILEPOS, POP_RD_FLOOR, 2);
}
static void animate_leveldoor(uint8_t *m, int8_t *type, uint8_t cur_room)
{
if (*type < 0) return;
if (*type >= 3) {
@@ -420,7 +450,17 @@ static void animate_leveldoor(uint8_t *m, int8_t *type)
else *m = (uint8_t)(*m - sp);
} else {
if (*m < 43) (*m)++;
if (*m >= 43) { *m = 43; *type = -1; pop_leveldoor_open = 1; }
if (*m >= 43) {
*m = 43; *type = -1;
/* Условие оригинала — переход ИЗ 0 или 2, то есть ровно один раз
* за открытие; иначе зеркало ставилось бы заново каждый кадр,
* пока дверь стоит открытой. */
if (pop_leveldoor_open == 0 || pop_leveldoor_open == 2) {
pop_leveldoor_open = 1;
place_mirror(cur_room);
}
pop_leveldoor_open = 1;
}
}
}
@@ -538,7 +578,7 @@ void pop_process_trobs(uint8_t cur_room) __banked
animate_door(&mod[tp], &type);
break;
case TILE_LEVELDOOR:
animate_leveldoor(&mod[tp], &type);
animate_leveldoor(&mod[tp], &type, cur_room);
break;
case TILE_TORCH:
case TILE_TORCH_DEBRIS: