31b82661eb
Порт PoP переехал в applications/SprPoP — приложение, которое собирается само: код, оригинальные данные, конверторы ресурсов и сборка внутри одной папки. Наружу знает единственный путь — корень тулчейна (SPRINTER_ROOT, по умолчанию ../..). applications/PoP/roomtest ЗАМОРОЖЕНА и остаётся архивом закрытых задач, багов и исполненных планов. Скопировано из applications/PoP/roomtest@4b74478. Перенос проверен побайтово: собранный sprpop.exe совпал с roomtest.exe того же коммита, все 39 дисковых ресурсов и все 16 генерируемых заголовков — тоже, host- тесты зелёные (15/15). Раскладка: src/ рукописный C (roomtest.c -> sprpop.c) gen/ генерируемые заголовки, в репозитории assets/orig/ оригинальные данные игры, вне репозитория (копирайт) assets/packed/ то, что ложится на диск, в раскладке диска tools/ конверторы; все пути — в одном tools/paths.py build/ выход: exe, каталоги ресурсов, hdd/, промежуточные atl/ Сборка ресурсов: assets/packed и gen — версионируемые ВХОДЫ, а не то, что пересчитывается каждым make. Автоматика построена на ОТСУТСТВИИ файла, а не на таймстемпах: git не хранит времена, и в свежем клоне сравнение по времени превращалось бы в лотерею. Недостающий ресурс или заголовок чинится сам, рекурсивным вызовом в ветку генерации. Музыка собирается из любого из четырёх наборов записей (make music-mp3, music-mt32, ...); набор входит в имя stamp'а, поэтому смена набора сама делает музыку устаревшей. Длины реплик больше не захардкожены: упаковщик печатает их в gen/pop_music_ticks.h, и шкала сцены выражена через них — иначе mt32 (реплики на 6% длиннее) молча ломал катсцену. Тулчейн: в app.mk два обратносовместимых крючка (SRC_DIR/BUILD_DIR), HDD_IMG стал ?=; команда сборки roomtest не изменилась. Корневой make host-tests переключён на SprPoP. Подгонка тайминга катсцены с принцессой (PV_MAGIC_LEAD): сцена render-bound и идёт ~49 тиков/с вместо 60, из-за чего кода реплики приходила раньше молнии. Это обход, а не лечение; разбор с замерами — docs/BUGS_OPEN.md, записи SND-PACE-DEAD, PV-RENDER-BOUND, MUS-LEFT-TEAR. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
64 lines
4.6 KiB
C
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);
|
|
|