Files
Sprinter-SDCC/applications/PoP/roomtest/_pop_bg.h
T
snark13 35b7cd5196 Фикс мерцания торцов: копия запечки требует ОКНА КЛИПА
Регресс от копии второй страницы (5ef721e), найден пользователем: уровень 1,
комната 6, Кид на кнопке (0,2) — дрожит нижняя грань переднего торца кнопки.
На уровнях 1-3 то же по торцам плит, полов и кнопок.

Причина системная.  Полная запечка зовёт draw_tile, а тот рисует тайлы
ЦЕЛИКОМ, то есть пишет ШИРЕ прямоугольника бара.  bake_copy переносит на
вторую страницу ровно бар — и всё, что легло вне него, на второй странице
остаётся прежним.  Страницы расходятся, это и есть мерцание через кадр.

У полосы потолка (pop_ceil_bake_empty) проблемы не было: там окно клипа
поставлено ещё в G1, и запечка ограничена ровно копируемым прямоугольником.
А у pop_floor_bake окна не было — до этого оно трижды отвергалось как
невыгодное по скорости.

Фикс: окно клипа в pop_floor_bake возвращено, но теперь это условие
КОРРЕКТНОСТИ, а не оптимизация — записано в коде, чтобы его не сняли снова
«как убыточное».  Само окно стоит ~8 500 такта (клипованный путь дороже
быстрого на ~1 500 на каждом из 7,6 блитов), но открывает копию второй
страницы, экономящую ~145 000: пара «запечка + копия» вдвое дешевле двух
запечек.

Второй гард того же захода: pop_set_redraw / pop_set_redraw_above гасят слот
копии при ПЕРЕпометке тайла — у кнопки с идущим таймером связи пометка
обновляется каждый кадр, и картинка каждый раз другая, копия старой не
годится.  Объявления pop_bake_slot_reset* без __banked: pop_redraw.c и
pop_room.c в одном банке, трамплин не нужен.

Заодно починен скрипт рестарта MAME: он оставлял недоеденный запрос `exit` в
очереди IPC моста, и НОВЫЙ экземпляр его подхватывал и сразу выходил.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 17:04:09 +03:00

64 lines
4.6 KiB
C

/*
* _pop_bg.h — ВНУТРЕННИЙ контракт между двумя половинами слоя фона.
* Публичный API слоя — pop_bg.h; общие листья (резидент) — pop_tile.h.
*
* Слой фона разрезан на два банка:
* pop_bg.c (банк 2) — ГОРЯЧАЯ половина: fore-проход поверх персонажей,
* оверлеи, клип. Работает каждый кадр.
* pop_room.c (банк 7) — ХОЛОДНАЯ: полная отрисовка комнаты (draw_tile),
* точечные перерисовки тайлов, падающие плиты,
* загрузка атласов. Раз на комнату/событие.
*
* Резать пришлось потому, что банк 2 упирался в 16 КБ страницы (90.4 % до
* разгрузки), а чомперам и остальным ловушкам уровня 3 место нужно. Граница
* проведена по частоте вызова: холодная половина платит трамплин (~654 такта)
* за каждый вызов сюда, и на входе в комнату таких вызовов ~40 — 26 000
* тактов, шестая часть кадрового бюджета РАЗОВО. Для горячего пути цена
* нулевая: он зовёт свои функции прямо, а общие листья — из резидента.
*
* Что осталось в банке 2 и вынесено сюда обёртками: кладка стены
* (wall_pattern — её зовёт и fore-проход каждый кадр) и решётка ворот
* соседней комнаты (draw_gate_back — её зовёт шовная окклюзия). Обратных
* зависимостей (горячая половина → холодная) нет вовсе.
*/
#ifndef _POP_BG_H
#define _POP_BG_H
#include <stdint.h>
/* Состояние дрожащих плит — живёт в pop_map, читают обе половины. */
extern uint8_t pop_loose_modif[30];
extern uint8_t pop_ceil_modif[10]; /* плита-потолок: loose ряда 2 комнаты сверху */
/* Видимая высота полосы кладки у потолка (room-space y 0..7): её печёт
* холодная половина, а поверх персонажа кладёт горячая. */
#define CEIL_BAND_H 8
/* Тайл ОБЪЕКТА активного персонажа (set_objtile_at_char, seg006:1833) — в
* момент обработки этого тайла спрайт попадает в midtable. Задаёт горячая
* половина (pop_fore_over_char), читают other_overlay_tile (там же) и
* порядок «плита vs Kid» в mob_tick_one (холодная). Писучие данные банка
* лежат в _DATA/W2 и видны из любого банка — см. sdcc_banked_call_rules. */
extern int8_t pop_bg_obj_col, pop_bg_obj_row;
/* ---- Точки входа ГОРЯЧЕЙ половины для холодной (через трамплин) ------- */
void pop_wall_pattern_b(int row, int col, int which_part) __banked;
void pop_wall_pattern_reset_b(void) __banked;
void pop_gate_back_b(uint8_t modl, int xh, int dby, int dmy) __banked;
#endif
/* ---- Слоты «первая запечка была на странице N» ----------------------- *
* bake_copy (pop_room.c) копирует готовый прямоугольник со второй страницы
* дабл-буфера вместо повторного пересчёта. Это верно ТОЛЬКО пока содержимое
* тайла между двумя кадрами не изменилось. У анимированных тайлов (кнопка с
* идущим таймером связи, ворота) пометка ОБНОВЛЯЕТСЯ каждый кадр, и картинка
* при этом другая — такой тайл обязан пересчитываться честно.
*
* Поэтому pop_set_redraw / pop_set_redraw_above гасят слот на ПЕРЕпометке
* (пометка пришла, когда счётчик ещё не отработал). Объявления БЕЗ __banked:
* pop_redraw.c и pop_room.c живут в одном банке, и трамплин тут не нужен. */
void pop_bake_slot_reset(uint8_t tilepos);
void pop_bake_slot_reset_above(uint8_t col);