roomtest: обломки упавшего loose в комнате снизу (debris)

Loose-пол room1(2,6) при падении даёт кусок, который в оригинале улетает в
комнату снизу (links.down) и приземляется на первый floor, превращая его в
debris (порт move_loose/loose_land seg007).  Для room1(2,6): room2(0,6)=empty
пролёт → room2(1,6)=floor приземление → debris.

Минимальная реализация (без анимации полёта куска, только персистентный
результат — мини-версия P0 из docs/gates_spikes_plan.md):
- pop_map: сигнал pop_loose_fell (tilepos+1 упавшего loose).
- pop_level: pop_room_col_landing(room,col) — ряд первого floor сверху вниз
  (пустые ряды пролетаются), иначе -1.
- roomtest: при pop_loose_fell вычисляет debris-приземление в комнате снизу →
  персистентный override (dbr_room/dbr_pos, живёт между переходами) →
  enter_room применяет поверх загруженных тайлов (floor→debris 0x0E).

Проверено в MAME: провал loose room1(2,6) → debris в room2(1,6), сохраняется
при повторных входах.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-20 21:26:21 +03:00
parent bf7ddfd4da
commit d1bc97c589
5 changed files with 58 additions and 1 deletions
+30 -1
View File
@@ -27,13 +27,33 @@ static uint8_t room_fg[30], room_bg[30];
static uint8_t lcol_fg[3], lcol_bg[3], rcol_fg[3], rcol_bg[3], below_fg[10];
static uint8_t cur_room; /* номер текущей комнаты (для переходов) */
/* Персистентные debris-переопределения (упавший loose-кусок приземлился в
* комнате снизу → floor стал debris). Минимальный per-room override: живёт
* между переходами, применяется в enter_room поверх загруженных тайлов.
* (Полноценное per-room modifier-состояние — в docs/gates_spikes_plan.md, P0.) */
#define TILE_DEBRIS 0x0E
#define DEBRIS_OVR_MAX 4
static uint8_t dbr_room[DEBRIS_OVR_MAX], dbr_pos[DEBRIS_OVR_MAX], dbr_cnt;
static void add_debris_override(uint8_t room, uint8_t pos)
{
uint8_t i;
for (i = 0; i < dbr_cnt; i++)
if (dbr_room[i] == room && dbr_pos[i] == pos) return; /* уже есть */
if (dbr_cnt < DEBRIS_OVR_MAX) {
dbr_room[dbr_cnt] = room; dbr_pos[dbr_cnt] = pos; dbr_cnt++;
}
}
/* Загрузить комнату room в рабочие массивы и отрисовать её фон в ОБЕ
* страницы дабл-буфера (у каждой своя видео-ОЗУ/теневая копия). Оставляет
* активной страницу 1 — вызывающий восстанавливает нужную draw-страницу. */
static void enter_room(uint8_t room)
{
uint8_t pg;
uint8_t pg, i;
pop_room_load(room, room_fg, room_bg, lcol_fg, lcol_bg, rcol_fg, rcol_bg, below_fg);
for (i = 0; i < dbr_cnt; i++) /* применить debris-переопределения */
if (dbr_room[i] == room) room_fg[dbr_pos[i]] = TILE_DEBRIS;
pop_map_set(room_fg);
pop_map_set_edges(pop_room_link(room, 0), pop_room_link(room, 1),
pop_room_link(room, 2), pop_room_link(room, 3),
@@ -151,6 +171,15 @@ int main(void)
}
pop_loose_tick(); /* loose-полы: анимация + перерисовка (СЛОЙ ФОНА */
/* — ДО Kid, чтобы Kid всегда был поверх плиты) */
if (pop_loose_fell) { /* упавший кусок → debris в комнате снизу */
uint8_t fcol = (uint8_t)((pop_loose_fell - 1) % 10);
uint8_t down = pop_room_link(cur_room, LINK_DOWN);
pop_loose_fell = 0;
if (down) {
int8_t lrow = pop_room_col_landing(down, fcol);
if (lrow >= 0) add_debris_override(down, (uint8_t)(lrow * 10 + fcol));
}
}
kid_draw(); /* нарисовать новый кадр (детект выхода за поле) */
pop_fore_over_kid(kid_fp_obj_x(), kid_fp_obj_y(),
kid_fp_width(), kid_fp_height(),