/*
 * pop_bg.h — отрисовка СТАТИЧЕСКОГО фона комнаты PoP композицией слоёв
 * (порт seg008.c draw_tile/wall_pattern, Шаг 3).  Рисует прямо в текущую
 * страницу (banked GFX_BANK_TRANSPARENT — в видео-ОЗУ + теневую копию,
 * 0xFF прозрачен), ОДИН раз при входе в комнату.
 *
 * Данные: getimage-спрайты в атласах pop_env0..4/pop_wall/pop_fore
 * (toolchain/pop_pack_bg.py), палитра pop_bg.pal.  Прямая адресация
 * id: env[id>>5] idx id&31, wall idx=id, fore idx=id — ноль remap-таблиц.
 */
#ifndef POP_BG_H
#define POP_BG_H

#include <stdint.h>

/* ---- Вертикальный layout (PoP-экран 320×200 в нашем 320×256) --------- *
 * Игровой экран 200px центрируем по высоте: сдвиг всего рисунка вниз на
 * POP_YOFF = (256-200)/2 = 28px (чёрные борта сверху/снизу).  Внутри 200px
 * верхние POP_PLAYFIELD_H = 192 — поле тайлов/спрайтов (комната = 3 ряда),
 * нижние 8 — статус-полоса (жизни/сообщения): тайлы/спрайты туда НЕ лезут.
 * Сдвиг применяется на границе примитивов (blit/heal) — логика рисования
 * остаётся в «room-space» y=0..191. */
#define POP_YOFF        28
#define POP_PLAYFIELD_H 192
/* Экранный y нижней границы поля (ниже — статус-полоса + борт → клип). */
#define POP_CLIP_BOTTOM (POP_YOFF + POP_PLAYFIELD_H)

/* Выбор ядра libbgi (pop_onscreen_cols / pop_heal_fast) переехал в
 * `_pop_draw.h` — его включают только три рисующих модуля.  Из общего
 * заголовка SDCC размножал мёртвые копии этих inline'ов по всем TU: см.
 * шапку `_pop_draw.h`. */

/* Загрузить 7 атласов фона.  Звать ДО initgraph (как poc.c — atlas_load
 * трогает W3; проверенный порядок).  Палитру pop_bg.pal грузит ПРИЛОЖЕНИЕ
 * после initgraph (gfx_pal_fload).  0 — OK, -1 — ошибка. */
int  pop_bg_load(void) __banked;

/* Освободить EMM-страницы атласов. */
void pop_bg_free(void) __banked;

/* Нарисовать комнату: fg[30]/bg[30] — foretable-коды/backtable-модификаторы
 * (по строкам, row*10+col).  lcol_fg/lcol_bg — 3 тайла правого столбца
 * ЛЕВОЙ соседней комнаты (для границы, напр. решётки ворот), или 0 —
 * тогда левая кромка = стена.  room_num — номер комнаты (зерно стен). */
void pop_room_draw(uint8_t room_num,
                   const uint8_t *fg, const uint8_t *bg,
                   const uint8_t *lcol_fg, const uint8_t *lcol_bg) __banked;

/* Задать ряд 0 комнаты СНИЗУ (fg-коды, 10 шт.) — для draw_tile_topright,
 * когда тайл нижнего ряда стал empty (после падения loose): «стена вниз»
 * рисуется по коду room_B(0, col-1).  0 — нет комнаты снизу. */
void pop_room_set_below(const uint8_t *below_row0_fg) __banked;

/* Задать ряд 2 (fg-коды + модификаторы, 10 шт.) комнаты СВЕРХУ — для полосы
 * кладки у потолка (seg008 draw_room доп. верхний ряд из room_A).  0 — нет
 * комнаты сверху (кромка уровня → пол). */
void pop_room_set_above(const uint8_t *above_row2_fg, const uint8_t *above_row2_mod) __banked;

/* Перерисовать передний слой (fore) тайлов футпринта Kid ПОВЕРХ него —
 * звать ПОСЛЕ kid_draw.  obj_x — ЛОГИЧЕСКАЯ X кадра (до ×8/7), obj_y — низ
 * спрайта, w/h — размер кадра, dir — направление Kid (<0 влево).  Метрики
 * берутся из pop_kid (kid_fp_*).  См. redraw_at_char/set_char_collision. */
void pop_fore_over_kid(int obj_x, int obj_y, uint16_t w, uint16_t h,
                       int8_t dir, uint8_t frame, uint8_t action) __banked;

/* Окно fore-слоя: прямоугольник СПРАЙТА (экранные координаты, y уже с
 * POP_YOFF), поверх которого fore-проход возвращает куски тайлов.  Ставит
 * тот, кто нарисовал спрайт (kid_draw / pop_guard_draw) — он один знает
 * итоговый габарит (у Kid — с учётом клинка и обрезки clip_char).  Вне
 * fore-проходов окно игнорируется: фон рисуется целиком.  Мотивация и
 * замер — в pop_bg.c у fclip_on. */
void pop_fore_set_clip(int x, int y, int w, int h) __banked;

/* То же для НЕ-Kid персонажа (страж): только слой fore + полоса потолка,
 * без оверлеев поз виса/полёта/подъёма.  obj_x — ЛОГИЧЕСКАЯ координата
 * (до ×8/7), как у kid_fp_obj_x(). */
/* __banked: отрисовка стража уехала в СВОЙ банк (pop_gdraw.c), поэтому
 * вызов стал кроссбанковым и обязан идти через трамплин.  Зовётся раз в
 * кадр, других вызывающих нет — цена одного трамплина здесь не видна. */
void pop_fore_over_char(int obj_x, int obj_y, uint16_t w, uint16_t h,
                        int8_t dir) __banked;

/* Восстановить фон там, где в прошлых кадрах рисовался ОВЕРЛЕЙ
 * (draw_other_overlay/floor_overlay/полоса потолка): он выходит за
 * прямоугольник Kid, поэтому kid_heal его не убирает — на второй странице
 * дабл-буфера остаётся след и мерцает.  Звать рядом с kid_heal. */
void pop_fore_heal(void) __banked;

/* Loose floors — динамическая отрисовка (состояние pop_loose_modif в
 * pop_map).  Звать на ТЕКУЩЕЙ (back) странице из pop_loose_tick.
 * shake_draw — дрожащий кадр (heal+SPRITE); bake_empty — запечь пустоту
 * после падения (NORMAL, в ОЗУ-копию). */
void pop_loose_shake_draw(int row, int col) __banked;
void pop_loose_bake_empty(int row, int col) __banked;

/* Плита-ПОТОЛОК (loose ряда 2 комнаты СВЕРХУ, наш ряд −1): дрожащий кадр в
 * полосе у потолка / «запечь» пустоту (колодец наверх) после провала.
 * Состояние — pop_ceil_modif[10] в pop_map. */
void pop_ceil_shake_draw(int col) __banked;
void pop_ceil_bake_empty(int col) __banked;

/* Кусок приземлился (loose_land) — переехал в pop_state.h: переменную
 * читают по обе стороны банковой границы. */
#include "pop_state.h"

/* Пики (spike) — перерисовка тайла (row,col) на back-странице по живому
 * modif (pop_trob).  Звать из pop_process_trobs.  См. pop_bg.c. */
void pop_spike_redraw(int row, int col) __banked;

/* Анимация факела/зелья (динамика каждый кадр; фон запечён без них):
 * modif — живой room_modif тайла.  Для факела col — колонка САМОГО факела
 * (пламя рисуется в ячейке правого соседа). */
void pop_torch_draw(int row, int col, uint8_t modif) __banked;
void pop_potion_draw(int row, int col, uint8_t modif) __banked;

/* Ворота на ЛЕВОМ шве (col0) — перерисовать по живому modif соседа слева.
 * g_lbg (lcol_bg) должен быть обновлён вызывающим.  Звать из основного цикла
 * на back-странице, когда сосед слева анимируется.  См. pop_bg.c. */
void pop_room_redraw_seam_left(void) __banked;

/* Перерисовать ПОЛ тайла (row,col) + правую грань в соседе на back-странице
 * (wipe по площади пола, БЕЗ стены ряда ниже).  Для смены тайла на месте:
 * кнопка нажата/отжата, floor → debris от упавшей плиты. */
void pop_floor_bake(int row, int col) __banked;
void pop_button_redraw(int row, int col) __banked;   /* = pop_floor_bake (кнопка) */

/* Дверь уровня: перерисовать её ПРАВУЮ половину (row, col = правая) с
 * запечкой — створка анимируется (pop_trob animate_leveldoor). */
void pop_leveldoor_redraw(int row, int col) __banked;

/* Ворота ВНУТРИ отрисованной комнаты: перерисовать по живому modif.
 * (row,col) — координаты САМИХ ворот; бары рисует ячейка правого соседа
 * (draw_tile, ветка lcode==4), туда и идёт wipe+redraw.  Порт draw_trob
 * (seg007:01E6), которым заканчивается animate_door. */
void pop_gate_redraw(int row, int col) __banked;

/* Падающий кусок loose (mob, seg007 move_loose): спавн при падении тайла
 * (row,col) и покадровое продвижение+отрисовка на back-странице.  tick
 * зовётся каждый кадр (внутри pop_loose_tick); клип низа делает clip. */
void pop_loose_mob_spawn(int row, int col) __banked;
void pop_loose_mob_tick(void) __banked;
void pop_loose_mob_reset(void) __banked;   /* убрать все куски (СТАРТ УРОВНЯ, mobs_count=0) */

/* Смена комнаты: куски продолжают падать в СВОИХ комнатах (do_mobs крутит
 * mobs[] независимо от drawn_room), сбрасывается только heal-история. */
void pop_loose_mob_room_changed(void) __banked;

/* Кусок НИЖЕ Kid по obj_y → рисуется ПОВЕРХ него (порт sort_curr_objs,
 * seg008:1561).  Звать после kid_draw, перед fore-слоем. */
void pop_loose_mob_draw_over(void) __banked;

/* Позиция куска (колонка, y низа) для check_loose_fall_on_kid.  0 — нет. */
uint8_t pop_loose_mob_pos(int *col, int *y) __banked;

/* Детектор выхода спрайта за поле: если спрайт [x,w] с ЭКРАННЫМ верхом
 * sy_top и высотой h заходит ниже поля (статус-полоса/борт) или выше
 * верхнего борта — взводит внутренний флаг «борта грязные» на 2 кадра.
 * Звать СРАЗУ после блита падающего объекта (Kid/кусок). */
void pop_clip_sprite(int x, int w, int sy_top, int h) __banked;

/* Почистить борта (верхний + статус-полоса/нижний) — но ТОЛЬКО в кадрах,
 * где кто-то реально вышел за поле (гейт по флагу от pop_clip_sprite):
 * даром в покое, O(1) при падении (не зависит от числа спрайтов).  Звать
 * КАЖДЫЙ кадр ПОСЛЕ kid_draw+fore на back-странице. */
void pop_room_clip_borders(void) __banked;

#endif
