Зеркальные кадры персонажей — готовыми файлами, а не разворотом в рантайме
Замеры в 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:
@@ -47,6 +47,31 @@ def transpose_cols(w, h, rowmajor):
|
||||
return bytes(out)
|
||||
|
||||
|
||||
def vflip_cols(w, h, colmajor):
|
||||
"""COLUMN-MAJOR (out[col*h + row]) -> тот же формат, но кадр ЗЕРКАЛЕН ПО
|
||||
ВЕРТИКАЛИ: внутри каждой колонки байты идут снизу вверх.
|
||||
|
||||
Зачем отдельный набор. Спрайты персонажей лежат колонками ради
|
||||
БЕСПЛАТНОГО горизонтального флипа (accel копирует колонки, направление
|
||||
задаётся знаком страйда). Вертикальное зеркало у такой раскладки — это
|
||||
разворот байтов ВНУТРИ колонки, а accel копирует блок только вперёд:
|
||||
в рантайме это стоит ~0.6 с на страницу (замер MAME 2026-08-12), тогда
|
||||
как ГОТОВАЯ страница читается с диска за 0.045 с. Поэтому зелье
|
||||
инверсии (уровень 9) обслуживается вторым набором файлов *_v.atl.
|
||||
Раскладка каталога у него та же — движку достаточно подменить номер
|
||||
EMM-страницы (см. roomtest/pop_vflip.h)."""
|
||||
out = bytearray(len(colmajor))
|
||||
for col in range(w):
|
||||
b = col * h
|
||||
out[b:b + h] = colmajor[b:b + h][::-1]
|
||||
return bytes(out)
|
||||
|
||||
|
||||
def vflip_page(page):
|
||||
"""{idx: (w,h,pix)} -> то же с зеркальными по вертикали пикселями."""
|
||||
return {i: (w, h, vflip_cols(w, h, pix)) for i, (w, h, pix) in page.items()}
|
||||
|
||||
|
||||
def load_kid(aidx):
|
||||
"""Атлас-индекс aidx (== frame.image) -> res(401+aidx).png -> (w, h, 8bpp
|
||||
COLUMN-MAJOR). 0->0xFF, i->0x70+i. Пиксели транспонированы в колонки.
|
||||
@@ -149,6 +174,10 @@ def main():
|
||||
total += sz
|
||||
names.append(nm)
|
||||
print(f" {nm}: {len(pages[pg])} спрайтов, каталог {cnt}, {sz} Б")
|
||||
# Зеркальный по вертикали набор (зелье инверсии, уровень 9).
|
||||
nmv = f"kid{pg}_v.atl"
|
||||
_, szv = B.pack_atlas(os.path.join(OUT_DIR, nmv), vflip_page(pages[pg]))
|
||||
total += szv
|
||||
else:
|
||||
names.append(None)
|
||||
print(f" (kid стр {pg}: пусто)")
|
||||
@@ -160,6 +189,8 @@ def main():
|
||||
sw[i] = (w, h, pix)
|
||||
cnt, sz = B.pack_atlas(os.path.join(OUT_DIR, "sword.atl"), sw)
|
||||
total += sz
|
||||
_, szv = B.pack_atlas(os.path.join(OUT_DIR, "sword_v.atl"), vflip_page(sw))
|
||||
total += szv
|
||||
print(f" sword.atl (chtab_0, id {SWORD_IDS[0]}..{SWORD_IDS[-1]}): "
|
||||
f"{len(sw)} спрайтов, каталог {cnt}, {sz} Б")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user