f2093e0d89
Жалоба: стойка неподвижных Кида и стража занимала больше полутора
кадровых периодов. Гипотеза «виноват __banked» ЗАМЕРОМ НЕ
ПОДТВЕРДИЛАСЬ: весь банковый вызов (трамплин + смена страницы + тело
pop_guard_tick + возврат) стоит 654 такта при бюджете кадра 430 000.
Как мерил (выборка PC бесполезна — мост MAME отвечает из фреймового
колбэка, все сэмплы падают в обработчик прерывания): breakpoint'ы MAME с
действием {printf totalcycles; g} на входах фаз главного цикла, разности
соседних меток = стоимость фазы. Плюс профилирование полосами бордюра
(make PROF=1, макрос PROF() в roomtest.c) для быстрого взгляда.
Замер комнаты 3 (Kid + страж), такты, кадр = 430 000:
fore поверх стража 431 964
fore поверх Kid 402 816 -> 78 % всей работы кадра
остальное 241 956
ИТОГО 1 076 736 = 2.5 кадра
Две причины, обе устранены:
1. Fore-слой рисовал ЦЕЛЫЕ тайлы, хотя существует ровно для того, чтобы
вернуть куски поверх спрайта — за его прямоугольником в видеопамяти и
так правильный фон. Введено ОКНО клипа (pop_fore_set_clip): спрайт
сообщает свой итоговый габарит (у Kid — с клинком, брызгами и
обрезкой clip_char), fore-проход режет по нему. Отсев трёхступенчатый:
тайл целиком (tile_in_fclip, до обращения к атласу), кусок по грубому
габариту (до gfx_w0_map — w/h лежат в EMM-странице), и точный клип в
blit_b. Для последнего добавлен libbgi-примитив
gfx_blit_part_noclip — пара к gfx_blit_noclip, но под-прямоугольник.
2. Оставшиеся 341 К после клипа оказались НЕ пикселями: 18 вызовов
pop_prandom за проход, ~10 700 тактов каждый (32-битный LCG:
__mullong ~8 000 + __moduint). Раскладка кладки тайла — чистая
функция (комната, ряд, колонка), то есть константа комнаты, а
wall_pattern пересчитывал её каждый кадр. Теперь кэшируются готовые
РЕШЕНИЯ (что рисовать и с каким смещением), 3 байта на тайл, сброс в
pop_room_draw. Порядок вызовов prandom воспроизведён один в один,
включая то, что значение метки берётся только при сработавшем условии.
Итог того же замера: fore поверх стража 37 464, поверх Kid 46 464,
кадр целиком 334 716 = 0.78 периода (было 2.5). Ускорение 3.2x, сами
fore-проходы — 10x.
Проверка отсутствия регрессии: попиксельная разность скриншотов комнат
1/2/3 до и после — отличаются ТОЛЬКО языки пламени факелов (анимация),
кладка и метки совпадают байт в байт.
Побочно: sprinter-cc научился пробрасывать -DNAME в sdcc.
Память: куча W2 1245 -> 996 Б (кэш кладки 120 Б), резидент W3 12 819 ->
14 512 (свободно 1872 Б — становится тесно), банк 1 236/16384.
ВНИМАНИЕ: make size-check показывает рост 7 программ, но эталон
docs/size_baseline.tsv отстал (последний раз принят в 484b18d, libbgi
менялась в 95c22be/c127a4b/64ce633) — к этой правке рост отношения не
имеет: новый модуль библиотеки в чужие программы не линкуется.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
71 lines
4.5 KiB
Makefile
71 lines
4.5 KiB
Makefile
# roomtest — проверка порта статического фона PoP (Шаг 3): реальная
|
|
# композиция слоёв (pop_bg.c) для комнаты 1. --memory huge --gfx 256.
|
|
|
|
PROJ_ROOT := $(abspath $(CURDIR)/../../..)
|
|
EXAMPLE := roomtest
|
|
# small: W1+W2 как единое 32КБ-пространство, DATA сразу за CODE (иначе
|
|
# CODE ~23КБ переполняет W1 и лезет в фиксированный DATA@0x8000 в huge).
|
|
MEMORY ?= huge # small-раскладка + банки кода в W3 (стражи)
|
|
# --w3 берёт ОДИН файл на флаг (флагов можно несколько). В W3-резиденте
|
|
# держим ТОЛЬКО отрисовку, которую зовёт лишь главный цикл: pop_bg (тайлы)
|
|
# и pop_gdraw (спрайт стража). Всё остальное живёт в W1/W2, чтобы
|
|
# оставаться достижимым из __banked-модулей (guards.c): из банка
|
|
# резидентная страница W3 не видна — ни напрямую, ни транзитивно.
|
|
# См. docs/layout_plan_v2.md §2 (R2), §4.
|
|
EXTRA_FLAGS ?= --gfx 256 --w3 pop_bg.c --w3 pop_gdraw.c --bank 1=guards.c $(PROF_FLAGS)
|
|
# make PROF=1 — профилирование полосами бордюра (см. PROF() в roomtest.c):
|
|
# каждая фаза кадра красит бордюр в свой цвет, высота полосы на скриншоте
|
|
# MAME = время фазы в растровых строках.
|
|
PROF_FLAGS := $(if $(PROF),-DPROF_BORDER)
|
|
EXTRA_SRCS := pop_kid.c pop_ctrl.c pop_level.c pop_map.c pop_trob.c pop_redraw.c pop_geom.c pop_guard.c
|
|
|
|
BG_DIR := $(CURDIR)/../poc/res/bg
|
|
KID_DIR := $(CURDIR)/../poc/res/kid
|
|
LVL_DIR := $(CURDIR)/../SDLPoP/data/LEVELS
|
|
LVL_DATA := $(LVL_DIR)/res2001.bin
|
|
BG_DATA := $(BG_DIR)/pop_env0.atl $(BG_DIR)/pop_env1.atl $(BG_DIR)/pop_env2.atl \
|
|
$(BG_DIR)/pop_env3.atl $(BG_DIR)/pop_env4.atl \
|
|
$(BG_DIR)/pop_wall.atl $(BG_DIR)/pop_fore.atl \
|
|
$(BG_DIR)/pop_pot.atl
|
|
# ВСЕ 28 страниц Kid — иначе кадры торможения/разворота/приседа (image>23)
|
|
# не рисуются (kid_draw пропускает незагруженную страницу). Палитра —
|
|
# ЕДИНАЯ игровая (env+wall+kid).
|
|
KID_PAGES := $(foreach n,0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27,$(KID_DIR)/kid$(n).atl)
|
|
KID_DATA := $(KID_PAGES) $(KID_DIR)/kid.pal $(KID_DIR)/sword.atl
|
|
# Таблицы анимации (кадры+seqtbl) — отдельный бинарь в EMM-странице, его
|
|
# делает pop_extract_kid_data.py (не упаковщик спрайтов) — своё правило ниже.
|
|
KID_BIN := $(KID_DIR)/kid_data.bin
|
|
GUARD_DIR := $(CURDIR)/../poc/res/guard
|
|
GUARD_DATA := $(GUARD_DIR)/g0.atl $(GUARD_DIR)/g1.atl $(GUARD_DIR)/g2.atl \
|
|
$(GUARD_DIR)/g3.atl $(GUARD_DIR)/g4.atl
|
|
|
|
EXTRA_DATA := $(BG_DATA) $(KID_DATA) $(KID_BIN) $(GUARD_DATA) $(LVL_DATA)
|
|
include $(PROJ_ROOT)/app.mk
|
|
|
|
# Образ HDD для MAME: ресурсы раскладываются ПО КАТАЛОГАМ (8.3, как в DSS),
|
|
# чтобы корень диска не зарастал десятками .atl.
|
|
# BG\ — фон (env/wall/fore/pot)
|
|
# KID\ — персонаж (kid0..27, палитра, меч, таблицы анимации)
|
|
# GUARD\ — стражи (появятся здесь же)
|
|
# LEVELS\ — уровни
|
|
hdd: $(EXAMPLE).exe
|
|
$(PROJ_ROOT)/toolchain/make_hdd.sh $(PROJ_ROOT)/mame/v306/IMG/test_hdd.chd \
|
|
$(EXAMPLE).exe \
|
|
$(foreach f,$(BG_DATA),BG:$(f)) \
|
|
$(foreach f,$(KID_DATA) $(KID_BIN),KID:$(f)) \
|
|
$(foreach f,$(GUARD_DATA),GUARD:$(f)) \
|
|
LEVELS:$(LVL_DATA)
|
|
|
|
TC := $(PROJ_ROOT)/applications/PoP/toolchain
|
|
$(BG_DATA): $(TC)/pop_pack_bg.py $(TC)/render_room.py
|
|
cd $(TC) && python3 pop_pack_bg.py
|
|
$(GUARD_DATA): $(TC)/pop_pack_guard.py
|
|
cd $(TC) && python3 pop_pack_guard.py
|
|
|
|
$(KID_DATA): $(TC)/pop_pack_kid.py $(TC)/pop_pack_bg.py
|
|
cd $(TC) && python3 pop_pack_kid.py
|
|
kid_data.h $(KID_BIN): $(TC)/pop_extract_kid_data.py
|
|
cd $(TC) && python3 pop_extract_kid_data.py
|
|
|
|
$(EXAMPLE).exe: guards.c pop_guard.c pop_guard.h pop_gdraw.c pop_cheat.h pop_bg.c pop_bg.h pop_geom.c pop_geom.h pop_redraw.c pop_redraw.h pop_kid.c pop_kid.h pop_ctrl.c pop_ctrl.h pop_map.c pop_map.h pop_level.c pop_level.h pop_trob.c pop_trob.h kid_data.h $(BG_DATA) $(KID_DATA) $(KID_BIN) $(LVL_DATA)
|