diff --git a/applications/PoP/roomtest/pop_bg.h b/applications/PoP/roomtest/pop_bg.h index c928a63..eb040b6 100644 --- a/applications/PoP/roomtest/pop_bg.h +++ b/applications/PoP/roomtest/pop_bg.h @@ -26,6 +26,14 @@ /* Экранный y нижней границы поля (ниже — статус-полоса + борт → клип). */ #define POP_CLIP_BOTTOM (POP_YOFF + POP_PLAYFIELD_H) +/* Экранный верх прямоугольника при ПЕРЕВОРОТЕ (зелье инверсии): поле + * отражается внутри себя, борта не трогаются. ОДНА формула на весь порт — + * блит тайла, heal точечных перерисовок и чёрные плиты обязаны считать + * одинаково, иначе стираем в одном месте, а рисуем в другом (именно так + * ломались чомперы и решётка). Зеркалит ВЫЗЫВАЮЩИЙ; у примитивов libbgi + * семантика координат не меняется. */ +#define POP_FLIP_TOP(top, h) (2 * POP_YOFF + POP_PLAYFIELD_H - (top) - (int)(h)) + /* Выбор ядра libbgi (pop_onscreen_cols / pop_heal_fast) переехал в * `_pop_draw.h` — его включают только три рисующих модуля. Из общего * заголовка SDCC размножал мёртвые копии этих inline'ов по всем TU: см. diff --git a/applications/PoP/roomtest/pop_room.c b/applications/PoP/roomtest/pop_room.c index 79bab84..ba979d6 100644 --- a/applications/PoP/roomtest/pop_room.c +++ b/applications/PoP/roomtest/pop_room.c @@ -576,8 +576,7 @@ void pop_ceil_bake_empty(int col) __banked int x = POP_COL_XH[col] * 8; pop_cd_touch(x, POP_YOFF, 64, CEIL_BAND_H + 1); /* bar мимо pop_blit_b */ gfx_set_bank(GFX_BANK_NORMAL); - setfillstyle(SOLID_FILL, BLACK); - bar(x, POP_YOFF, x + 63, POP_YOFF + CEIL_BAND_H); /* стереть плиту в ОЗУ-копии */ + pop_bar_black(x, POP_YOFF, 64, CEIL_BAND_H + 1); /* стереть плиту в ОЗУ-копии */ gfx_set_bank(GFX_BANK_TRANSPARENT); pop_t_clip_top = POP_YOFF; pop_t_bake_rest = 1; /* фон = покой (см. pop_t_bake_rest) */ @@ -681,8 +680,7 @@ void pop_floor_bake(int row, int col) __banked * НИЗ строго yb+64 (≈ низ передней грани пола): ниже — СТЕНА ряда ниже * (высокий спрайт), которую тут не перерисовываем → иначе чёрный бар. */ gfx_set_bank(GFX_BANK_NORMAL); - setfillstyle(SOLID_FILL, BLACK); - bar(x, yb + 26, x + 59, yb + 64); + pop_bar_black(x, yb + 26, 60, 39); gfx_set_bank(GFX_BANK_TRANSPARENT); pop_t_bake_rest = 1; /* фон = покой (см. pop_t_bake_rest) */ draw_tile(row, col); @@ -725,10 +723,7 @@ void pop_gate_redraw(int row, int col) __banked if (col + 1 > 9 || row < 0 || row > 2) return; x = POP_COL_XH[col + 1] * 8; yt = POP_YOFF + 63 * row; - pop_cd_touch(x, yt + 3, 32, 62); /* bar мимо pop_blit_b (DRAW-COST) */ - gfx_set_bank(GFX_BANK_NORMAL); - setfillstyle(SOLID_FILL, BLACK); - bar(x, yt + 3, x + 31, yt + 64); + pop_bar_black(x, yt + 3, 32, 62); /* зеркалится сама (переворот) */ gfx_set_bank(GFX_BANK_TRANSPARENT); draw_tile(row, col + 1); gfx_set_bank(GFX_BANK_NORMAL); @@ -761,7 +756,7 @@ void pop_loose_bake_empty(int row, int col) __banked pop_cd_touch(x, yb, 72, POP_YOFF + 63 * row + 66 - yb); gfx_set_bank(GFX_BANK_NORMAL); setfillstyle(SOLID_FILL, BLACK); - bar(x, yb, x + 39, POP_YOFF + 63 * row + 65); /* сам тайл: +40 (кусок пола заходит вправо; сосед перерисуется) */ + pop_bar_black(x, yb, 40, POP_YOFF + 63 * row + 65 - yb + 1); /* сам тайл: +40 (кусок пола заходит вправо; сосед перерисуется) */ if (col + 1 < 10) bar(xr, yb, xr + 31, POP_YOFF + 63 * row + 65); /* сосед: РОВНО 32 — не залезть в col+2 (его не перерисовываем) */ /* Новый статич. фон: сам тайл (empty → «стена вниз» topright комнаты diff --git a/applications/PoP/roomtest/pop_tile.c b/applications/PoP/roomtest/pop_tile.c index 1f8622f..be265d5 100644 --- a/applications/PoP/roomtest/pop_tile.c +++ b/applications/PoP/roomtest/pop_tile.c @@ -263,11 +263,7 @@ void pop_cd_clear(uint8_t p) * платили и блиты БЕЗ клипа (`ld -n(ix)` = 19 тактов номинала, у нас ~46). * А блитов без клипа большинство: весь фон вне fore-прохода — факелы, зелья, * перерисовка тайлов — идёт с pop_t_fclip_on == 0. */ -/* Экранный y при ПЕРЕВОРОТЕ (зелье инверсии): поле отражается внутри себя, - * борта не трогаются. Одна формула на весь слой фона — если её продублируют - * где-то ещё, получим двойной переворот (см. l9_invert_plan.md §II.2: - * зеркалит ТОЛЬКО вызывающий, у примитивов семантика не меняется). */ -#define FLIP_TOP(top, h) (2 * POP_YOFF + POP_PLAYFIELD_H - (top) - (int)(h)) +#define FLIP_TOP(top, h) POP_FLIP_TOP(top, h) /* формула — в pop_bg.h */ static void blit_b_clip(const uint8_t *img, int x, int top, int w, int h) { @@ -371,6 +367,15 @@ void pop_pot_b(uint8_t id, int x, int yb) { pop_blit_b(&pop_pot_at, id, x, yb) * обязан отразиться ровно так же, как сам тайл, — иначе heal чистит одно * место, а рисует в другое: именно так «ломалась анимация чомперов» * (найдено пользователем на первом же прогоне зеркального фона). */ +void pop_bar_black(int x, int top, int w, int h) +{ + if (pop_upside) top = FLIP_TOP(top, h); + gfx_set_bank(GFX_BANK_NORMAL); + setfillstyle(SOLID_FILL, BLACK); + bar(x, top, x + w - 1, top + h - 1); + pop_cd_touch(x, top, w, h); /* bar идёт мимо pop_blit_b (DRAW-COST) */ +} + void pop_heal_off(int x, int y, int w, int h) { int top = y + POP_YOFF; diff --git a/applications/PoP/roomtest/pop_tile.h b/applications/PoP/roomtest/pop_tile.h index 9fb0397..6fe509a 100644 --- a/applications/PoP/roomtest/pop_tile.h +++ b/applications/PoP/roomtest/pop_tile.h @@ -124,6 +124,13 @@ void pop_pot_b(uint8_t id, int x, int yb); /* heal в room-space (со сдвигом POP_YOFF) — все heal слоя фона/loose. */ void pop_heal_off(int x, int y, int w, int h); +/* Чёрная плита по ЭКРАННЫМ координатам, с учётом переворота (POP_FLIP_TOP). + * Пишет банком 0x50 — и в видео-ОЗУ, и в ОЗУ-копию, иначе heal вернёт + * стёртое. ВСЕ стирания слоя фона обязаны идти через неё, а не через голый + * bar: иначе при перевороте плита ложится в неотражённое место (так + * ломались решётка и плита-потолок). */ +void pop_bar_black(int x, int top, int w, int h); + /* ---- Чтение тайла отрисованной комнаты ------------------------------ */ uint8_t pop_tile_code(int row, int col); uint8_t pop_tile_mod(int row, int col);