L9-INVERT: чёрные плиты слоя фона тоже зеркалятся (баг решётки)
Найдено пользователем: поднимающаяся решётка анимировалась неправильно, а в углу (0,0) оставался чёрный прямоугольник — заливки шли голым bar по НЕПЕРЕВЁРНУТЫМ экранным координатам. Формула переворота вынесена в pop_bg.h (POP_FLIP_TOP) — одна на весь порт, и добавлен pop_bar_black: чёрная плита банком 0x50 с учётом переворота и с пометкой области (bar идёт мимо pop_blit_b). На неё переведены все четыре стирания слоя фона: решётка, полоса потолка, floor_bake, loose_bake_empty. Проверено в MAME: перевёрнутая комната чистая, артефакта в углу нет. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -26,6 +26,14 @@
|
|||||||
/* Экранный y нижней границы поля (ниже — статус-полоса + борт → клип). */
|
/* Экранный y нижней границы поля (ниже — статус-полоса + борт → клип). */
|
||||||
#define POP_CLIP_BOTTOM (POP_YOFF + POP_PLAYFIELD_H)
|
#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) переехал в
|
/* Выбор ядра libbgi (pop_onscreen_cols / pop_heal_fast) переехал в
|
||||||
* `_pop_draw.h` — его включают только три рисующих модуля. Из общего
|
* `_pop_draw.h` — его включают только три рисующих модуля. Из общего
|
||||||
* заголовка SDCC размножал мёртвые копии этих inline'ов по всем TU: см.
|
* заголовка SDCC размножал мёртвые копии этих inline'ов по всем TU: см.
|
||||||
|
|||||||
@@ -576,8 +576,7 @@ void pop_ceil_bake_empty(int col) __banked
|
|||||||
int x = POP_COL_XH[col] * 8;
|
int x = POP_COL_XH[col] * 8;
|
||||||
pop_cd_touch(x, POP_YOFF, 64, CEIL_BAND_H + 1); /* bar мимо pop_blit_b */
|
pop_cd_touch(x, POP_YOFF, 64, CEIL_BAND_H + 1); /* bar мимо pop_blit_b */
|
||||||
gfx_set_bank(GFX_BANK_NORMAL);
|
gfx_set_bank(GFX_BANK_NORMAL);
|
||||||
setfillstyle(SOLID_FILL, BLACK);
|
pop_bar_black(x, POP_YOFF, 64, CEIL_BAND_H + 1); /* стереть плиту в ОЗУ-копии */
|
||||||
bar(x, POP_YOFF, x + 63, POP_YOFF + CEIL_BAND_H); /* стереть плиту в ОЗУ-копии */
|
|
||||||
gfx_set_bank(GFX_BANK_TRANSPARENT);
|
gfx_set_bank(GFX_BANK_TRANSPARENT);
|
||||||
pop_t_clip_top = POP_YOFF;
|
pop_t_clip_top = POP_YOFF;
|
||||||
pop_t_bake_rest = 1; /* фон = покой (см. pop_t_bake_rest) */
|
pop_t_bake_rest = 1; /* фон = покой (см. pop_t_bake_rest) */
|
||||||
@@ -681,8 +680,7 @@ void pop_floor_bake(int row, int col) __banked
|
|||||||
* НИЗ строго yb+64 (≈ низ передней грани пола): ниже — СТЕНА ряда ниже
|
* НИЗ строго yb+64 (≈ низ передней грани пола): ниже — СТЕНА ряда ниже
|
||||||
* (высокий спрайт), которую тут не перерисовываем → иначе чёрный бар. */
|
* (высокий спрайт), которую тут не перерисовываем → иначе чёрный бар. */
|
||||||
gfx_set_bank(GFX_BANK_NORMAL);
|
gfx_set_bank(GFX_BANK_NORMAL);
|
||||||
setfillstyle(SOLID_FILL, BLACK);
|
pop_bar_black(x, yb + 26, 60, 39);
|
||||||
bar(x, yb + 26, x + 59, yb + 64);
|
|
||||||
gfx_set_bank(GFX_BANK_TRANSPARENT);
|
gfx_set_bank(GFX_BANK_TRANSPARENT);
|
||||||
pop_t_bake_rest = 1; /* фон = покой (см. pop_t_bake_rest) */
|
pop_t_bake_rest = 1; /* фон = покой (см. pop_t_bake_rest) */
|
||||||
draw_tile(row, col);
|
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;
|
if (col + 1 > 9 || row < 0 || row > 2) return;
|
||||||
x = POP_COL_XH[col + 1] * 8;
|
x = POP_COL_XH[col + 1] * 8;
|
||||||
yt = POP_YOFF + 63 * row;
|
yt = POP_YOFF + 63 * row;
|
||||||
pop_cd_touch(x, yt + 3, 32, 62); /* bar мимо pop_blit_b (DRAW-COST) */
|
pop_bar_black(x, yt + 3, 32, 62); /* зеркалится сама (переворот) */
|
||||||
gfx_set_bank(GFX_BANK_NORMAL);
|
|
||||||
setfillstyle(SOLID_FILL, BLACK);
|
|
||||||
bar(x, yt + 3, x + 31, yt + 64);
|
|
||||||
gfx_set_bank(GFX_BANK_TRANSPARENT);
|
gfx_set_bank(GFX_BANK_TRANSPARENT);
|
||||||
draw_tile(row, col + 1);
|
draw_tile(row, col + 1);
|
||||||
gfx_set_bank(GFX_BANK_NORMAL);
|
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);
|
pop_cd_touch(x, yb, 72, POP_YOFF + 63 * row + 66 - yb);
|
||||||
gfx_set_bank(GFX_BANK_NORMAL);
|
gfx_set_bank(GFX_BANK_NORMAL);
|
||||||
setfillstyle(SOLID_FILL, BLACK);
|
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)
|
if (col + 1 < 10)
|
||||||
bar(xr, yb, xr + 31, POP_YOFF + 63 * row + 65); /* сосед: РОВНО 32 — не залезть в col+2 (его не перерисовываем) */
|
bar(xr, yb, xr + 31, POP_YOFF + 63 * row + 65); /* сосед: РОВНО 32 — не залезть в col+2 (его не перерисовываем) */
|
||||||
/* Новый статич. фон: сам тайл (empty → «стена вниз» topright комнаты
|
/* Новый статич. фон: сам тайл (empty → «стена вниз» topright комнаты
|
||||||
|
|||||||
@@ -263,11 +263,7 @@ void pop_cd_clear(uint8_t p)
|
|||||||
* платили и блиты БЕЗ клипа (`ld -n(ix)` = 19 тактов номинала, у нас ~46).
|
* платили и блиты БЕЗ клипа (`ld -n(ix)` = 19 тактов номинала, у нас ~46).
|
||||||
* А блитов без клипа большинство: весь фон вне fore-прохода — факелы, зелья,
|
* А блитов без клипа большинство: весь фон вне fore-прохода — факелы, зелья,
|
||||||
* перерисовка тайлов — идёт с pop_t_fclip_on == 0. */
|
* перерисовка тайлов — идёт с pop_t_fclip_on == 0. */
|
||||||
/* Экранный y при ПЕРЕВОРОТЕ (зелье инверсии): поле отражается внутри себя,
|
#define FLIP_TOP(top, h) POP_FLIP_TOP(top, h) /* формула — в pop_bg.h */
|
||||||
* борта не трогаются. Одна формула на весь слой фона — если её продублируют
|
|
||||||
* где-то ещё, получим двойной переворот (см. l9_invert_plan.md §II.2:
|
|
||||||
* зеркалит ТОЛЬКО вызывающий, у примитивов семантика не меняется). */
|
|
||||||
#define FLIP_TOP(top, h) (2 * POP_YOFF + POP_PLAYFIELD_H - (top) - (int)(h))
|
|
||||||
|
|
||||||
static void blit_b_clip(const uint8_t *img, int x, int top, int w, int 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 чистит одно
|
* обязан отразиться ровно так же, как сам тайл, — иначе 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)
|
void pop_heal_off(int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
int top = y + POP_YOFF;
|
int top = y + POP_YOFF;
|
||||||
|
|||||||
@@ -124,6 +124,13 @@ void pop_pot_b(uint8_t id, int x, int yb);
|
|||||||
/* heal в room-space (со сдвигом POP_YOFF) — все heal слоя фона/loose. */
|
/* heal в room-space (со сдвигом POP_YOFF) — все heal слоя фона/loose. */
|
||||||
void pop_heal_off(int x, int y, int w, int h);
|
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_code(int row, int col);
|
||||||
uint8_t pop_tile_mod(int row, int col);
|
uint8_t pop_tile_mod(int row, int col);
|
||||||
|
|||||||
Reference in New Issue
Block a user