Зеркальные кадры персонажей — готовыми файлами, а не разворотом в рантайме

Замеры в 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.
This commit is contained in:
2026-08-12 23:17:22 +03:00
parent c4dd2c7a87
commit 5b6664ffce
48 changed files with 219 additions and 107 deletions
+11 -1
View File
@@ -19,7 +19,7 @@ from PIL import Image
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
import pop_pack_bg as B
from pop_pack_kid import transpose_cols
from pop_pack_kid import transpose_cols, vflip_page
# Набор спрайтов соперника выбирается ТИПОМ УРОВНЯ (load_lev_spr, seg000:1092):
# tbl_guard_type = {0 guard, 1 fat, 2 skeleton, 3 vizier, 4 shadow, 1 нет}.
@@ -185,6 +185,16 @@ def main():
nm = f"g{pg}.atl"
cnt, sz = B.pack_atlas(os.path.join(OUT_DIR, nm), pages.get(pg, {}))
total += sz
# Зеркальный по вертикали набор — пара к kid*_v.atl (см. vflip_cols).
# ТОЛЬКО для обычного стража: зелье инверсии есть на уровне 9, а там
# tbl_guard_type = 0, то есть страж; скелет (уровень 3), визирь и
# жирный с переворотом не встречаются. Если чит U всё-таки включат
# на таком уровне, соперник нарисуется неперевёрнутым кадром —
# pop_vflip_page вернёт 0 (pop_vflip.h).
if SET_NAME == "GUARD":
_, szv = B.pack_atlas(os.path.join(OUT_DIR, f"g{pg}_v.atl"),
vflip_page(pages.get(pg, {})))
total += szv
print(f" {nm}: {len(pages.get(pg, {}))} спрайтов, каталог {cnt}, {sz} Б")
write_pal_header(os.path.join(HERE, "..", "roomtest", "pop_guard_pal.h"))
print(f"ИТОГО: {n} спрайтов стража, {max(pages)+1} EMM-страниц, {total} Б -> {OUT_DIR}")