From 4cffbc9aa4cd7a111fa252511aefc390653e0160 Mon Sep 17 00:00:00 2001 From: Alexander Petrov Date: Wed, 29 Jul 2026 20:44:56 +0300 Subject: [PATCH] =?UTF-8?q?PoP=20roomtest=20(=D0=BF=D0=BB=D0=B0=D0=BD=20v2?= =?UTF-8?q?,=20=D1=84=D0=B0=D0=B7=D0=B0=201b):=20pop=5Fmap=20=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D0=B5=D0=B2=D0=B5=D0=B4=D1=91=D0=BD=20=D0=BD=D0=B0=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BC=D0=B5=D1=82=D0=BA=D0=B8=20=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D0=B5=D1=80=D0=B8=D1=81=D0=BE=D0=B2=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Loose-полы, плита-потолок и щебень от приземления больше не зовут pop_bg — ставят пометки (pop_set_redraw / pop_set_redraw_above), которые разбирает pop_redraw_needed из главного цикла. Удалены самодельные счётчики loose_bake/loose_rest/ceil_rest/ceil_bake/land_bake: их роль (вторая страница дабл-буфера) теперь у счётчика страниц в пометке. Осталось ОДНО исключение: падающий кусок (mob) — spawn/tick/pos. Это движущийся ОБЪЕКТ, а не перерисовка тайла, и в оригинале он живёт отдельно (mobs + draw_moving), поэтому разделение его на логику и отрисовку — следующая фаза. Из-за него pop_loose_tick остаётся единственной функцией pop_map, которую нельзя звать из __banked-кода; вся коллизия, физика, кромки и предметы — то, что понадобится стражам — чисты от графики. Замер: _CODE 24718 -> 24462, _DATA 4301 -> 4219 (ушли rest-массивы). Проверено в MAME: комната 12, осторожный шаг на плиту — тряска, падение плиты, Kid проваливается на ряд 1, дыра и щебень отрисованы; на замороженном кадре обе страницы дабл-буфера побайтово совпадают в области изменений (7 строк). Co-Authored-By: Claude Opus 5 --- applications/PoP/roomtest/pop_map.c | 89 ++++++++++------------------- 1 file changed, 31 insertions(+), 58 deletions(-) diff --git a/applications/PoP/roomtest/pop_map.c b/applications/PoP/roomtest/pop_map.c index a38d437..7b7a6ce 100644 --- a/applications/PoP/roomtest/pop_map.c +++ b/applications/PoP/roomtest/pop_map.c @@ -19,7 +19,14 @@ #include "pop_kid.h" #include "pop_map.h" #include "pop_ctrl.h" /* pop_ctrl_shift_held() — для check_grab */ -#include "pop_bg.h" /* pop_loose_shake_draw/bake_empty — перерисовка */ +#include "pop_redraw.h" /* пометки перерисовки (порт set_redraw_*) */ +/* pop_bg нужен ТОЛЬКО падающему куску (mob): spawn/tick/pos — это движущийся + * ОБЪЕКТ, а не перерисовка тайла (в оригинале он и живёт отдельно: mobs + + * draw_moving). Из-за него pop_loose_tick — единственная функция модуля, + * которую нельзя звать из __banked-кода; вся коллизия/физика/предметы, то + * есть то, что понадобится стражам, чиста от графики. Разделение mob на + * логику и отрисовку — задел следующей фазы. */ +#include "pop_bg.h" #include "pop_trob.h" /* room_modif + trob-список (пики/ворота) */ /* ---- Тайлы / действия / seq id (подмножество PoP) ------------------ */ @@ -142,11 +149,9 @@ static uint8_t g_lcol[6], g_rcol[6]; * отдельное — pop_ceil_modif[col] с той же семантикой (0 покой, 0x80.. — * тряска, 1..11 — отсчёт до падения). */ uint8_t pop_ceil_modif[10]; /* публично: читает pop_bg при отрисовке */ -static uint8_t ceil_rest[10]; /* «перерисовать ПОКОЙ» (2 = обе страницы) */ -static uint8_t ceil_bake[10]; /* «запечь колодец» на второй странице */ -static uint8_t land_bake, land_bake_pos; /* щебень от приземления — вторая страница */ static uint8_t *g_above; /* ряд 2 комнаты сверху (fg), мутабельный */ uint8_t pop_ceil_fell; /* 0 = нет; иначе col+1 провалившейся плиты-потолка */ + uint8_t pop_debris_at; /* 0 = нет; иначе tilepos+1 нового щебня в ЭТОЙ комнате */ void pop_map_set_above(uint8_t *above_row2_fg) { g_above = above_row2_fg; } @@ -1027,8 +1032,6 @@ static void check_bumped(void) * отсчёт до падения (на тайле стоят/пробили). Порт animate_loose/ * make_loose_fall/check_press. Перерисовка — в pop_bg (shake/bake). */ uint8_t pop_loose_modif[30]; /* публично: читает pop_bg при отрисовке */ -static uint8_t loose_bake[30]; /* счётчик «запечь пусто» (2 = обе страницы) */ -static uint8_t loose_rest[30]; /* счётчик «перерисовать ПОКОЙ» после тряски (2 = обе стр.) */ /* Плита-ПОТОЛОК: состояние/сигналы — см. объявления перед get_tile. */ @@ -1131,18 +1134,13 @@ void pop_loose_reset(void) int i; for (i = 0; i < 30; i++) { pop_loose_modif[i] = 0; - loose_bake[i] = 0; - loose_rest[i] = 0; } for (i = 0; i < 10; i++) { pop_ceil_modif[i] = 0; - ceil_rest[i] = 0; - ceil_bake[i] = 0; } pop_ceil_fell = 0; pop_debris_at = 0; pop_loose_landed = 0; - land_bake = 0; pop_loose_mob_reset(); } @@ -1201,24 +1199,17 @@ void pop_loose_tick(void) * Инкремент+сравнение считают row/col без деления. */ uint8_t row = 0, col = 0; for (pos = 0; pos < 30; pos++) { - if (loose_bake[pos]) { /* упал: запечь пусто (2 кадра=2 стр.) */ - pop_loose_bake_empty(row, col); - loose_bake[pos]--; - } else if (loose_rest[pos]) { /* тряска кончилась: перерисовать ПОКОЙ */ - /* modif уже 0 → shake_draw рисует базовый кадр (покой) обоих тайлов - * (col и col+1: правая грань loose живёт в 2,7). 2 кадра = обе - * страницы дабл-буфера — иначе на одной остаётся застывший - * дрожащий кадр правой грани → мерцание («бесконечная тряска»). */ - pop_loose_shake_draw(row, col); - loose_rest[pos]--; - } else if (pop_loose_modif[pos] != 0) { + if (pop_loose_modif[pos] != 0) { uint8_t m = ++pop_loose_modif[pos]; if (m & 0x80) { /* тряска (do_knock) */ - if (m >= 0x84) { /* конец тряски: сброс + перерисовать покой */ + if (m >= 0x84) { /* конец тряски: сброс + покой */ pop_loose_modif[pos] = 0; - loose_rest[pos] = 2; /* покой на ОБЕИХ страницах */ + /* modif уже 0 → кадр покоя обоих тайлов (col и col+1: + * правая грань loose живёт в соседе). ОБЕ страницы — + * иначе на одной застывает дрожащий кадр → мерцание. */ + pop_set_redraw(pos, POP_RD_LOOSE, 2); } else { - pop_loose_shake_draw(row, col); /* дрожащий кадр */ + pop_set_redraw(pos, POP_RD_LOOSE, 1); /* дрожащий кадр */ } } else if (m >= 11) { /* loose_floor_delay — падение */ /* remove_loose (seg007:0EB8): тайл → EMPTY (не debris!). @@ -1228,12 +1219,11 @@ void pop_loose_tick(void) * (стена-вниз от тайла снизу + чёрный фон). */ g_fg[pos] = TILE_EMPTY; pop_loose_modif[pos] = 0; - pop_loose_bake_empty(row, col); /* запечь пусто на ТЕКУЩЕЙ странице сразу */ - loose_bake[pos] = 1; /* + вторая страница следующим кадром */ - pop_loose_mob_spawn(row, col); /* отрыв падающего куска (L4) */ - pop_loose_fell = (uint8_t)(pos + 1); /* сигнал приложению: кусок улетел */ + pop_set_redraw(pos, POP_RD_LOOSE_GONE, 2); /* запечь пусто, обе стр. */ + pop_loose_mob_spawn(row, col); /* отрыв падающего куска */ + pop_loose_fell = (uint8_t)(pos + 1); /* сигнал приложению */ } else { /* отсчёт 1..10 — дрожащий кадр */ - pop_loose_shake_draw(row, col); + pop_set_redraw(pos, POP_RD_LOOSE, 1); } } if (++col == 10) { col = 0; row++; } /* row/col без деления */ @@ -1242,27 +1232,21 @@ void pop_loose_tick(void) * рисуются в полосе у потолка, а провалившаяся плита становится EMPTY в * НАШЕЙ копии ряда (g_above) — сверху открывается колодец. */ for (col = 0; col < 10; col++) { - if (ceil_rest[col]) { - pop_ceil_shake_draw(col); /* modif уже 0 → кадр покоя */ - ceil_rest[col]--; - } else if (pop_ceil_modif[col] != 0) { + if (pop_ceil_modif[col] != 0) { uint8_t m = ++pop_ceil_modif[col]; if (m & 0x80) { /* тряска от сотрясения (do_knock) */ - if (m >= 0x84) { pop_ceil_modif[col] = 0; ceil_rest[col] = 2; } - else pop_ceil_shake_draw(col); + if (m >= 0x84) { pop_ceil_modif[col] = 0; + pop_set_redraw_above(col, POP_RDA_CEIL, 2); } + else pop_set_redraw_above(col, POP_RDA_CEIL, 1); } else if (m >= 11) { /* loose_floor_delay — плита рушится */ pop_ceil_modif[col] = 0; if (g_above) g_above[col] = TILE_EMPTY; /* remove_loose */ - pop_ceil_bake_empty(col); /* колодец наверх на ТЕКУЩЕЙ странице */ - ceil_bake[col] = 1; /* + вторая страница следующим кадром */ - pop_loose_mob_spawn(-1, col); /* кусок отрывается от потолка */ + pop_set_redraw_above(col, POP_RDA_CEIL_GONE, 2); /* колодец, обе стр. */ + pop_loose_mob_spawn(-1, col); /* кусок отрывается от потолка */ pop_ceil_fell = (uint8_t)(col + 1); /* сигнал приложению */ } else { - pop_ceil_shake_draw(col); /* отсчёт 1..10 — дрожащий кадр */ + pop_set_redraw_above(col, POP_RDA_CEIL, 1); /* отсчёт 1..10 */ } - } else if (ceil_bake[col]) { - pop_ceil_bake_empty(col); - ceil_bake[col]--; } } pop_loose_mob_tick(); /* продвинуть+нарисовать падающий кусок (после тайлов) */ @@ -1270,29 +1254,18 @@ void pop_loose_tick(void) /* Отложенная допечка ПРОШЛОГО приземления на вторую страницу — ПЕРЕД * разбором нового: иначе при двух плитах, севших подряд, land_bake * затирался новым и на одной странице оставался старый пол. */ - if (land_bake && pop_loose_landed) { - uint8_t r = 0, c = land_bake_pos; - while (c >= 10) { c -= 10; r++; } - pop_floor_bake(r, c); - land_bake = 0; - } if (pop_loose_landed) { /* loose_land (seg007:11E8): на месте куска — щебень */ uint8_t pos = (uint8_t)(pop_loose_landed - 1); uint8_t r = 0, c = pos; pop_loose_landed = 0; while (c >= 10) { c -= 10; r++; } g_fg[pos] = TILE_DEBRIS; - /* Перерисовка ПО ПЛОЩАДИ ПОЛА (не bake_empty: та стирает и верх стены - * ряда ниже — оставался чёрный прямоугольник под тайлом). */ - pop_floor_bake(r, c); - land_bake_pos = pos; land_bake = 1; /* вторая страница дабл-буфера */ + /* Перерисовка ПО ПЛОЩАДИ ПОЛА (не LOOSE_GONE: та стирает и верх стены + * ряда ниже — оставался чёрный прямоугольник под тайлом). Обе + * страницы дабл-буфера. */ + pop_set_redraw(pos, POP_RD_FLOOR, 2); do_knock(r); /* удар плиты трясёт loose этого ряда */ pop_debris_at = (uint8_t)(pos + 1); /* сигнал приложению (персистентность) */ - } else if (land_bake) { - uint8_t r = 0, c = land_bake_pos; - while (c >= 10) { c -= 10; r++; } - pop_floor_bake(r, c); - land_bake = 0; } }