/* * pop_vflip.c — таблица «страница атласа -> её ВЕРТИКАЛЬНО ЗЕРКАЛЬНАЯ пара» * (зелье инверсии, уровень 9). См. pop_vflip.h. * * Сами зеркальные ленты делает упаковщик (`vflip_cols` в pop_pack_kid.py) и * кладёт рядом с обычными: kid0_v.atl, sword_v.atl, g0_v.atl… Здесь остаётся * только связать пары: зеркальный файл грузится обычным atlas_load, а его * раскладка байт-в-байт совпадает с оригиналом — значит движку достаточно * подменить НОМЕР СТРАНИЦЫ, которую он мапит в W0. * * Почему не считаем в рантайме (замеры MAME 2026-08-12, такты Z80): * загрузка одной 16-КБ страницы с HDD — 970 003 такта (0.045 с); * разворот той же страницы на месте — 12 645 582 такта (0.59 с). * Даже идеальная конвертация (accel-копия + asm-реверс) даёт ~1.05 млн — * то есть в лучшем случае сравнивается с чтением готового файла, а стоит * asm-модуля. На все 34 страницы: 1.5 с загрузки против 20 с разворота. * * РЕЗИДЕНТ: pop_vflip_page зовёт отрисовка персонажей (банк 4) на каждый * спрайт — трамплин тут ни к чему, а кода всего ничего. */ #include #include #include "pop_vflip.h" /* Персонажных страниц: 28 (Кид) + 5 (страж) + 1 (меч) = 34; с запасом. */ #define VF_MAX 40 static uint8_t vf_src[VF_MAX]; /* страница оригинала */ static atlas_t vf_atl[VF_MAX]; /* зеркальный атлас (его page) */ static uint8_t vf_n; /* Взять УЖЕ ЗАГРУЖЕННЫЙ зеркальный атлас под своё управление (дальше его * освобождает pop_vflip_reset). Нужен тем, кто читает зеркала не файлом, а * куском архива ресурсов: загрузку делает вызывающий, связывание — мы. */ int pop_vflip_take(const atlas_t *orig, const atlas_t *mirror) { if (!orig || !mirror || vf_n >= VF_MAX) return -1; vf_atl[vf_n] = *mirror; vf_src[vf_n] = orig->page; vf_n++; return 0; } int pop_vflip_add(const atlas_t *orig, const char *path) { atlas_t m; if (!orig || vf_n >= VF_MAX) return -1; if (atlas_load(&m, path) != 0) return -1; return pop_vflip_take(orig, &m); } uint8_t pop_vflip_page(uint8_t src) { uint8_t i; for (i = 0; i < vf_n; i++) if (vf_src[i] == src) return vf_atl[i].page; return 0; /* пары нет — рисуем обычным атласом */ } uint8_t pop_vflip_ready(void) { return vf_n != 0; } void pop_vflip_reset(void) { uint8_t i; for (i = 0; i < vf_n; i++) atlas_free(&vf_atl[i]); vf_n = 0; }