PoP roomtest: pop_bg и pop_map в банки; --dataseg BANKn стал опцией
Резидента --w3 больше нет: отрисовка (pop_bg + pop_gdraw) уехала в БАНК 2, физика/коллизия (pop_map) — в БАНК 3. Куча W1/W2 1294 -> 6750 Б. Что это разблокировало. Резидент был тупиком: из банка он недостижим ни прямо, ни транзитивно, поэтому pop_map (самый крупный модуль, 5.8 КБ) в банк было не увести — он зовёт mob-отрисовку. Проверено, что банк->банк РАБОТАЕТ: ___sdcc_bcall_ehl читает страницу окна портом 0xE2 и кладёт её на СТЕК своего кадра (runtime/bank.s), поэтому вложенность корректна по построению. Подтверждено в MAME цепочкой W1 -> банк1 -> банк2 -> банк1: nested=124 after=8, ровно ожидаемое. Значит развязка mob'а (самое рисковое место, loose-полы) НЕ понадобилась — pop_map зовёт pop_bg трамплином. Правила вызовов проверены на сгенерированном asm и записаны в memory sdcc_banked_call_rules: трамплин выбирает ОБЪЯВЛЕНИЕ (__banked), а не раскладка — даже внутри одного .c между __banked функциями он есть. Внутрибанковые функции оставлены непомеченными и зовутся напрямую, в т.ч. через границу файла (pop_gdraw -> pop_fore_over_char). sprinter-cc: --dataseg BANKn БОЛЬШЕ НЕ ставится по умолчанию. Раньше вся писучая память банкового модуля уезжала в страницу банка и снаружи не читалась (проверено на .map: глобал лёг по 0x0001C000) — грабли на каждом переносе. Теперь данные банков по умолчанию в общем _DATA (W1/W2, замаплен всегда), а прежнее поведение — по явному --bank-data. Замеры (комната 3, Kid + страж; кадр Sprinter в турбо = 430 000 тактов): до переноса 338 508 (0.79 кадра) + pop_bg в банк 2 347 100 (+2.5 %) + pop_map в банк 3 371 100 (+9.6 % к исходному, 0.86 кадра) Плата — трамплины (~654 такта на вызов, ~30 вызовов за кадр). При пейсинге в 3 кадра это 29 % логического кадра, но запас до ОДНОГО кадра всего ~59 000 тактов — под звук его надо возвращать (следующий шаг: батчить кроссбанковые вызовы, начиная с pop_redraw_needed). Профилирование бордюром включено по умолчанию (make PROF=0 выключает) и переведено на реально работающие биты: бит 0 (красный) у бордюра Sprinter ИГНОРИРУЕТСЯ, поэтому различимых состояний четыре и значения обязаны быть чётными — 0 чёрный (ждём vsync), 2 синий (логика), 4 зелёный (фон), 6 циан (спрайты). Раньше нечётные номера сливались и полосы не читались. Проверено в MAME: комнаты 1/3 рисуются как прежде, бег и коллизия работают, в комнате 12 плиты проваливаются со щебнем — то есть цепочка loose банк3 -> банк2 живая. Полосы бордюра в комнате 3: логика 73 строки, фон 64, спрайты 128, свободно 23. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -21,28 +21,33 @@
|
||||
|
||||
__sfr __at (0xFE) io_border;
|
||||
|
||||
/* ПРОФИЛИРОВАНИЕ ПОЛОСАМИ БОРДЮРА (make PROF=1). Цвет бордюра держится,
|
||||
* пока фаза считает, поэтому высота полосы на скриншоте = время фазы в
|
||||
* растровых строках (1 строка ≈ 224 такта Z80 при 3.5 МГц). Это
|
||||
* единственный способ мерить здесь: мост MAME отвечает из фреймового
|
||||
* колбэка, поэтому выборка PC вырождается (100 % сэмплов в обработчике
|
||||
* прерывания). Фазы:
|
||||
/* ПРОФИЛИРОВАНИЕ ПОЛОСАМИ БОРДЮРА (включено по умолчанию; make PROF=0 —
|
||||
* выключить). Цвет бордюра держится, пока фаза считает, поэтому высота
|
||||
* полосы на скриншоте = время фазы в растровых строках. Это единственный
|
||||
* способ смотреть профиль без дебаггера: выборка PC вырождается (мост MAME
|
||||
* отвечает из фреймового колбэка, все сэмплы падают в обработчик
|
||||
* прерывания); точные такты — breakpoint'ы с {printf totalcycles; g}.
|
||||
*
|
||||
* ЦВЕТА: у бордюра Sprinter бит 0 (красный) ИГНОРИРУЕТСЯ, работают только
|
||||
* бит 1 (синий) и бит 2 (зелёный) — значит различимых состояний ровно
|
||||
* ЧЕТЫРЕ, и значения обязаны быть чётными. Отсюда фазы сгруппированы по
|
||||
* четыре, а не по семь (нечётные номера раньше сливались с соседями и
|
||||
* полосы не читались):
|
||||
* 0 чёрный — ожидание vsync (запас кадра)
|
||||
* 1 синий — ввод + heal (стереть прошлые спрайты)
|
||||
* 2 красный — логика (kid_tick/физика/страж в банке)
|
||||
* 3 лиловый — слой фона (loose/trobs/redraw_needed/шов)
|
||||
* 4 зелёный — kid_draw
|
||||
* 5 циан — guard_draw + fore поверх стража
|
||||
* 6 жёлтый — fore поверх Kid + чистка бортов
|
||||
* 7 белый — флип */
|
||||
#ifdef PROF_BORDER
|
||||
* 2 синий — ввод, heal и ЛОГИКА (kid_tick/физика/страж)
|
||||
* 4 зелёный — слой ФОНА (loose/trobs/redraw_needed/шов)
|
||||
* 6 циан — СПРАЙТЫ (страж, Kid, fore поверх них) */
|
||||
#ifndef PROF_BORDER
|
||||
#define PROF_BORDER 1
|
||||
#endif
|
||||
#if PROF_BORDER
|
||||
#define PROF(n) io_border = (n)
|
||||
#else
|
||||
#define PROF(n) ((void)0)
|
||||
#endif
|
||||
|
||||
/* Сколько банков грузит crt0_banked (читает его стартовый код). */
|
||||
const uint8_t n_banks = 1;
|
||||
const uint8_t n_banks = 3;
|
||||
|
||||
/* Режим читов (pop_cheat.h): на время разработки включаем в main. */
|
||||
uint8_t pop_cheats;
|
||||
@@ -287,7 +292,7 @@ int main(void)
|
||||
/* SPACE — тумблер дабл-буфера (edge, чтоб одно нажатие = один
|
||||
* переключ). Выключение возвращает показ на страницу 0. */
|
||||
|
||||
PROF(1); /* ввод + heal */
|
||||
PROF(2); /* ввод + heal */
|
||||
|
||||
uint8_t sp = kbd_raw_down(KBD_SPACE);
|
||||
if (sp && !sp_prev) {
|
||||
@@ -355,7 +360,7 @@ int main(void)
|
||||
kid_heal(); /* стереть прошлый кадр ЭТОЙ страницы */
|
||||
pop_guard_heal(); /* и прошлый кадр стража */
|
||||
pop_fore_heal(); /* + следы оверлея (шире прямоугольника Kid) */
|
||||
PROF(2); /* логика */
|
||||
PROF(2); /* логика (тот же синий) */
|
||||
kid_tick(); /* play_seq: следующий кадр */
|
||||
pop_phys_tick(); /* K3: падение/приземление/стена */
|
||||
pop_guard_tick(); /* логика стража — В БАНКЕ (guards.c) */
|
||||
@@ -381,7 +386,7 @@ int main(void)
|
||||
}
|
||||
}
|
||||
|
||||
PROF(3); /* слой фона */
|
||||
PROF(4); /* слой фона */
|
||||
|
||||
pop_loose_tick(); /* loose-полы: анимация + перерисовка (СЛОЙ ФОНА */
|
||||
/* — ДО Kid, чтобы Kid всегда был поверх плиты) */
|
||||
@@ -466,9 +471,9 @@ int main(void)
|
||||
flash_on = 1;
|
||||
}
|
||||
update_kid_render_dx(); /* straddle: смещение спрайта, если kid_room≠cur_room */
|
||||
PROF(5); /* страж: спрайт + fore поверх него */
|
||||
PROF(6); /* спрайты: страж, Kid, fore поверх */
|
||||
pop_guard_draw(); /* страж — ДО Kid (порядок как в оригинале) */
|
||||
PROF(4); /* kid_draw */
|
||||
PROF(6); /* kid_draw (тот же циан) */
|
||||
kid_draw(); /* нарисовать новый кадр (детект выхода за поле) */
|
||||
pop_loose_mob_draw_over(); /* падающая плита НИЖЕ Kid → поверх него (y-порядок) */
|
||||
if (pop_kid_hurt) { /* HP убавилось → «брызги» удара (draw_hurt_splash) */
|
||||
|
||||
Reference in New Issue
Block a user