Замеры в MAME (такты Z80, кадр = 430 000) решили вопрос однозначно:
загрузка 28 атласов Кида с HDD — 27 160 092 такта (1.26 с), 970 003 на страницу;
разворот ОДНОЙ страницы на месте — 12 645 582 такта (0.59 с), т.е. 771 такт/байт.
Даже идеальный вариант (копия accel'ом ~0.25 кадра + asm-реверс ~2.2 кадра)
дал бы ~1.05 млн на страницу — то есть в лучшем случае сравнялся бы с чтением
готового файла. На 34 страницы: 1.5 с загрузки против 20 с разворота.
* Упаковщики пишут второй набор: vflip_cols/vflip_page в pop_pack_kid.py ->
kid0_v.atl…kid27_v.atl, sword_v.atl; pop_pack_guard.py -> g0_v.atl…g4_v.atl
ТОЛЬКО для обычного стража (на уровне 9 tbl_guard_type = 0; тень рисуется
атласами Кида, скелет/визирь с переворотом не встречаются).
* pop_vflip.c схлопнулся до таблицы «страница -> зеркальная пара»; весь
побайтовый разворот и аллокация EMM удалены.
* pop_vflip_load_all (банк 8) грузит набор ОДНИМ вызовом и откуда угодно —
задел под загрузку ресурсов во время интро. Зовётся при старте и при
смене уровня, если это POP_UPSIDE_LEVEL; чит U на других уровнях поднимает
набор лениво (страховка в главном цикле).
* Стартовый уровень стал параметром сборки: make LEVEL=N (-DFIRST_LEVEL).
Проверено в MAME на уровне 9: переворот мгновенный, pop_flip_screen = 897 263
такта (2.1 кадра) — это сама копия экрана, загрузки в кадре больше нет.
tests-host 6/6.
Спрайты персонажей хранятся column-major (ради бесплатного H-флипа), а
вертикальное зеркало у такой раскладки — разворот байтов ВНУТРИ колонки,
чего accel не умеет. Поэтому pop_vflip.c готовит зеркальные КОПИИ страниц
атласов: копия побайтово повторяет раскладку .atl (заголовок, каталог,
смещения лент), развёрнуты только пиксели — значит вызывающему достаточно
подменить номер страницы, которую он мапит в W0.
* Кэш ленивый (страница зеркалится при первом обращении в перевёрнутом
виде) и живёт до смены уровня — зелье переключает состояние туда-обратно,
перезеркаливать по 16 КБ на каждый переворот незачем. EMM хватает: 34
страницы из ~215 свободных.
* pop_cdraw/pop_kdraw: страница + позиция (top = 191 - obj_y для персонажа,
192 - top - h для клинка). «Пропустить skip строк сверху» у зеркальной
ленты = «срезать снизу» у оригинала, поэтому клипы считаются как обычно.
* Модуль резидентный: он маппит W3 (приёмник копии) — банку так нельзя.
* pop_vflip_reset на смене уровня: копии сделаны из старых страниц.
Проверено в MAME: чит U переворачивает всё разом, Кид и факелы вверх ногами,
полоса HP на месте, бег без следов на фоне (heal бьёт в те же координаты).
ОСТАЁТСЯ (L9-CLIPCHAR): clip_char в перевороте должен резать снизу, а не
сверху — пока при pop_upside не режем вовсе. Тени/брызг это не касается.