# 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 БОЛЬШЕ НЕТ: отрисовка уехала в БАНК 2 (pop_bg + pop_cdraw # в одной странице — вызовы между ними прямые, если функция не помечена # __banked). Так снято главное ограничение резидента: из банка его было # не достать ни прямо, ни транзитивно, а банк→банк работает (трамплин # сохраняет страницу окна на СТЕКЕ, проверено вложенной цепочкой # банк1→банк2→банк1 в MAME 2026-07-30). Теперь в банки можно уводить и # логику, которая рисует. См. docs/layout_plan_v2.md §2, memory # sdcc_banked_call_rules. # Банк 5 = pop_ctrl.c (MEM-BANK5). CODE и DATA делят одно 32-КБ # пространство W1+W2, поэтому килобайт кода, уехавший в банк, — это # килобайт, доступный данным. Кандидат выбран не по размеру, а по частоте # вызова: диспетчер управления дёргается один раз за кадр на персонажа и # горячих банк→банк переходов не создаёт (в отличие от pop_level, чей # pop_level_tile зовётся из банка 2 на КАЖДЫЙ тайл). Шина control_* # переехала в pop_state.c — см. там. # --max-allocs-per-node: во сколько вариантов размещения регистров SDCC # упирается на узел. У sprinter-cc дефолт 100000 (агрессивно, как fast-сборки # библиотек) — на roomtest это МИНУТЫ на банк, потому что модули крупные. # Дефолт SDCC — 3000, и для разработки его достаточно: разница в размере # единицы процента, а сборка кратно быстрее. Замер (2026-08-05) — в шапке # TASKS_CLOSED.md, запись BUILD-FAST. # # make — быстрая сборка (ALLOCS=3000) # make ALLOCS=100000 — как раньше: минимальный код, для замеров размера # и для «релизного» образа # # ВАЖНО: любое сравнение занятости банков имеет смысл только при ОДНОМ и том # же ALLOCS — иначе сравниваются не правки, а уровни оптимизации. ALLOCS ?= 3000 # Build info не хранится вручную в C: ID и дата извлекаются Make из текущего # commit. Переопределения удобны для воспроизводимой release-сборки. BUILD_ID ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo dev) BUILD_DATE ?= $(shell git log -1 --format=%cs 2>/dev/null || echo unknown) BUILD_FLAGS := -DPOP_BUILD_ID=\"$(BUILD_ID)\" -DPOP_BUILD_DATE=\"$(BUILD_DATE)\" # Единственный список банковых исходников: из него строятся И ключи # sprinter-cc, И зависимости roomtest.exe. Раньше эти списки жили отдельно, # поэтому добавленные pop_shadow.c/pop_sfx_cold.c компилировались, но make не # замечал их последующие изменения и оставлял устаревший exe. BANK1_SRCS := guards.c BANK2_SRCS := pop_bg.c BANK3_SRCS := pop_map.c BANK4_SRCS := pop_cdraw.c pop_kdraw.c BANK5_SRCS := pop_ctrl.c pop_tile_cold.c BANK6_SRCS := pop_trob.c BANK7_SRCS := pop_room.c pop_redraw.c BANK8_SRCS := roomtest_cold.c pop_level_cold.c pop_kboot.c pop_guard_cold.c \ pop_shadow.c pop_sfx_cold.c pop_qsave.c pop_qsave_coldio.c \ pop_level_qsave.c # Банк 9 — оболочка: menu/settings/config/font, автомат, global timer, # title, attract-demo и таблица рекордов. Здесь остаются небольшие редкие # верхнеуровневые точки входа, но не рендеры крупных заставок. BANK9_SRCS := pop_menu.c pop_status.c pop_music.c pop_config.c pop_app.c pop_timer.c pop_ui.c pop_title.c pop_demo.c \ pop_flow.c pop_hof.c # Банк 10 — единый владелец экранных палитр/fade. Он намеренно отделён от UI: # его будут вызывать и игровой lifecycle, и все cutscene-ветки. BANK10_SRCS := pop_pal.c # Банк 11 — тяжёлая кинематика заставок: интерпретатор сценария и renderer # story/PV. Так анимации не вытесняют menu/config из банка оболочки. BANK11_SRCS := pop_cutscene.c pop_intro.c BANKED_SRCS := $(BANK1_SRCS) $(BANK2_SRCS) $(BANK3_SRCS) $(BANK4_SRCS) \ $(BANK5_SRCS) $(BANK6_SRCS) $(BANK7_SRCS) $(BANK8_SRCS) \ $(BANK9_SRCS) $(BANK10_SRCS) $(BANK11_SRCS) BANK_FLAGS := $(foreach f,$(BANK1_SRCS),--bank 1=$(f)) \ $(foreach f,$(BANK2_SRCS),--bank 2=$(f)) \ $(foreach f,$(BANK3_SRCS),--bank 3=$(f)) \ $(foreach f,$(BANK4_SRCS),--bank 4=$(f)) \ $(foreach f,$(BANK5_SRCS),--bank 5=$(f)) \ $(foreach f,$(BANK6_SRCS),--bank 6=$(f)) \ $(foreach f,$(BANK7_SRCS),--bank 7=$(f)) \ $(foreach f,$(BANK8_SRCS),--bank 8=$(f)) \ $(foreach f,$(BANK9_SRCS),--bank 9=$(f)) \ $(foreach f,$(BANK10_SRCS),--bank 10=$(f)) \ $(foreach f,$(BANK11_SRCS),--bank 11=$(f)) EXTRA_FLAGS ?= --gfx 256 -I $(CURDIR)/../poc/res/bg --max-allocs $(ALLOCS) \ $(BANK_FLAGS) $(PROF_FLAGS) $(BUILD_FLAGS) # Профилирование полосами бордюра (см. PROF() в roomtest.c) — ВКЛЮЧЕНО по # умолчанию, пока идёт работа с производительностью; make PROF=0 выключает. # Каждая фаза кадра красит бордюр в свой цвет, высота полосы на скриншоте # MAME = время фазы в растровых строках. PROF ?= 1 PROF_FLAGS := -DPROF_BORDER=$(PROF) # Стартовый уровень (отладка): make LEVEL=9 — начать сразу с девятого. # Дефолт держим на отлаживаемом сейчас уровне; для «настоящей» игры — LEVEL=1. # Константа объявлена в pop_tune.h (её видят обе половины главного цикла). LEVEL ?= 1 PROF_FLAGS += -DFIRST_LEVEL=$(LEVEL) # Стартовая КОМНАТА и позиция Кида в ней (отладка): make ROOM=15 POS=2 — # начать прямо в целевой комнате оптимизации, минуя проход уровня. POS — # тайл 0..29, то есть row*10+col. Дефолт — сцена 11/15 (Кид в 0,2), по # которой сняты замеры в docs/perf_l11_room15.md. make ROOM= (пусто) # возвращает штатный старт из данных уровня. ROOM ?= POS ?= 2 ifneq ($(strip $(ROOM)),) PROF_FLAGS += -DDBG_START_ROOM=$(ROOM) -DDBG_START_POS=$(POS) endif EXTRA_SRCS := pop_vflip.c pop_pace.c pop_sfx.c pop_state.c pop_draw.c pop_tile.c \ pop_kid.c pop_level.c pop_geom.c pop_guard.c pop_qsave_io.c BG_DIR := $(CURDIR)/../poc/res/bg KID_DIR := $(CURDIR)/../poc/res/kid LVL_DIR := $(CURDIR)/../SDLPoP/data/LEVELS # res2000 — attract-demo; res2001..res2014 — штатная игра. res2015/copy # protection намеренно не пакуется и не существует в маршруте загрузчика. LVL_NUMS := 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 LVL_DATA := $(foreach n,$(LVL_NUMS),$(LVL_DIR)/res20$(n).bin) # ДВА тайлсета: pop_* — подземелье (уровни 1-3, 7-9, 12, 13), # pal_* — дворец (4-6, 10, 11, 14). Раскладка id у них общая, различаются # файлы и палитра тайлсета (*tile.pal, 32 записи). chtab_1 (pop_pot.atl: # пламя, меч-предмет, зелья) от набора не зависит — один на оба. BG_SETS := pop pal BG_PAGES := 0 1 2 3 4 5 6 7 8 9 BG_DATA := $(foreach s,$(BG_SETS),\ $(foreach n,$(BG_PAGES),$(BG_DIR)/$(s)_env$(n).atl) \ $(BG_DIR)/$(s)_wall.atl $(BG_DIR)/$(s)_fore.atl \ $(BG_DIR)/$(s)_tile.pal) \ $(BG_DIR)/pop_pot.atl # ВСЕ 28 страниц Kid — иначе кадры торможения/разворота/приседа (image>23) # не рисуются (отрисовка пропускает незагруженную страницу). Палитра — # ЕДИНАЯ игровая (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) # Зеркальный ПО ВЕРТИКАЛИ набор (зелье инверсии, уровень 9): те же спрайты с # развёрнутыми колонками. Готовит упаковщик, а не рантайм — разворот # страницы стоит 0.59 с против 0.045 с на её чтение с диска (замер MAME # 2026-08-12, протокол в pop_vflip.c). KID_VPAGES := $(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)_v.atl) KID_DATA := $(KID_PAGES) $(KID_VPAGES) $(KID_DIR)/kid.pal \ $(KID_DIR)/sword.atl $(KID_DIR)/sword_v.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 \ $(GUARD_DIR)/g0_v.atl $(GUARD_DIR)/g1_v.atl $(GUARD_DIR)/g2_v.atl \ $(GUARD_DIR)/g3_v.atl $(GUARD_DIR)/g4_v.atl # Скелет — ОТДЕЛЬНЫЙ набор спрайтов (SKEL.DAT в оригинале): его грузит # уровень 3 (tbl_guard_type == 2), кадров меньше (28 против 34). SKEL_DIR := $(CURDIR)/../poc/res/skel # Зеркального набора у скелета НЕТ: зелье инверсии — уровень 9, там обычный # страж (tbl_guard_type[9] = 0). См. pop_pack_guard.py. SKEL_DATA := $(SKEL_DIR)/g0.atl $(SKEL_DIR)/g1.atl $(SKEL_DIR)/g2.atl \ $(SKEL_DIR)/g3.atl # Джафар — тоже отдельный набор (VIZIER.DAT): его грузит уровень 13 # (tbl_guard_type == 3). Кадров столько же, сколько у стража (34), но # палитра своя, из файла набора: curr_guard_color для не-стражей = 0. # Зеркального набора нет по той же причине, что у скелета. VIZIER_DIR := $(CURDIR)/../poc/res/vizier VIZIER_DATA := $(VIZIER_DIR)/g0.atl $(VIZIER_DIR)/g1.atl $(VIZIER_DIR)/g2.atl \ $(VIZIER_DIR)/g3.atl $(VIZIER_DIR)/g4.atl # ТЕНЬ — свой набор, запечённый упаковщиком (наложение спрайта на себя со # сдвигом; наш блит так не умеет, см. ../docs/shadow_atlas_plan.md). Две # половины в одном наборе: sk* — кадры вне боя (спрайты Кида), sf* — кадры # 150..189 (SHADOW.DAT, это тоже графика Кида, а не стража). SHADOW_DIR := $(CURDIR)/../poc/res/shadow SHADOW_DATA := $(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,$(SHADOW_DIR)/sk$(n).atl) \ $(foreach n,0 1 2 3,$(SHADOW_DIR)/sf$(n).atl) # ЗВУКОВЫЕ ЭФФЕКТЫ — оригинальная оцифровка, приведённая к частоте CBL # (10 937,5 Гц, 8 бит моно). 8 страниц по 16 КБ; см. ../docs/sound_plan.md. SND_DIR := $(CURDIR)/../poc/res/sound # Число файлов задаёт упаковщик (POP_SND_PAGES в pop_sound_tbl.h): с # 2026-08-25 звук не режется по границе страницы, поэтому страниц стало 10. # Список ОБЯЗАН совпадать: недостающий файл — это молча пропавшие эффекты. SND_DATA := $(foreach n,0 1 2 3 4 5 6 7 8 9,$(SND_DIR)/s$(n).bin) # МУЗЫКА: записи DOS-версии, приведённые к формату CBL и порезанные на # страницы EMM (toolchain/pop_pack_music.py). Пока в игре звучит один # трек — story_1_absence на первом экране intro; список расширяется # добавлением номеров в MUS_IDS, имена кусков задаёт упаковщик. MUS_DIR := $(CURDIR)/../poc/res/music MUS_IDS := 55 MUS_CHUNKS := 00 01 02 03 04 05 06 07 08 09 10 MUS_DATA := $(foreach i,$(MUS_IDS),$(foreach c,$(MUS_CHUNKS),$(MUS_DIR)/m$(i)_$(c).bin)) # UI: два исходных шрифта SDLPoP в одном EMM-атласе. Файл короче страницы: # хвост использует menu для временного snapshot палитры (без расхода W2). FONT_DIR := $(CURDIR)/../poc/res/font FONT_ATL := $(FONT_DIR)/font.atl FONT_DATA := $(FONT_ATL) # TITLE: четыре готовые композиции `show_title()` до story/intro. Каждая # режется на пять полос высотой <=49 px, так что runtime держит ровно одну # EMM-страницу во время рисования, а не отдельный framebuffer. TITLE_DIR := $(CURDIR)/../poc/res/title TITLE_SCENES := 0 1 2 3 TITLE_PARTS := 0 1 2 3 4 TITLE_DATA := $(TITLE_DIR)/title.pal \ $(foreach s,$(TITLE_SCENES),$(foreach p,$(TITLE_PARTS),$(TITLE_DIR)/t$(s)_$(p).atl)) # PV/INTRO: story и fallback-стадии режутся на полосы. Для настоящего PV # intro есть ещё чистый фон `b0_*` и шесть <=16K actor-атласов: они остаются # в EMM на время сцены, а не перечитывают полный 320x200 кадр с HDD. PV_DIR := $(CURDIR)/../poc/res/pv PV_STORY := 0 1 2 3 4 PV_SCENES := 0 1 2 3 4 5 6 7 PV_PARTS := 0 1 2 3 4 PV_ANIM := $(foreach p,$(PV_PARTS),$(PV_DIR)/b0_$(p).atl) \ $(PV_DIR)/a0.atl $(PV_DIR)/a1.atl $(PV_DIR)/a2.atl \ $(PV_DIR)/j0.atl $(PV_DIR)/j1.atl \ $(PV_DIR)/j2.atl $(PV_DIR)/h0.atl $(PV_DIR)/t0.atl PV_DATA := $(PV_DIR)/story.pal $(PV_DIR)/pv.pal \ $(foreach s,$(PV_STORY),$(foreach p,$(PV_PARTS),$(PV_DIR)/s$(s)_$(p).atl)) \ $(foreach s,$(PV_SCENES),$(foreach p,$(PV_PARTS),$(PV_DIR)/p$(s)_$(p).atl)) \ $(PV_ANIM) EXTRA_DATA := $(BG_DATA) $(KID_DATA) $(KID_BIN) $(GUARD_DATA) $(SKEL_DATA) \ $(VIZIER_DATA) $(SHADOW_DATA) $(SND_DATA) $(MUS_DATA) $(FONT_DATA) $(TITLE_DATA) $(PV_DATA) $(LVL_DATA) # Образ HDD для MAME: ресурсы раскладываются ПО КАТАЛОГАМ (8.3, как в DSS), # чтобы корень диска не зарастал десятками .atl. # BG\ — фон (env/wall/fore/pot) # KID\ — персонаж (kid0..27, палитра, меч, таблицы анимации) # GUARD\ — стражи (появятся здесь же) # FONT\ — текстовый атлас pause/settings UI # TITLE\ — нарезанные композиции оригинальной заставки # PV\ — story и Princess/Jaffar intro, нарезанные полосами # LEVELS\ — уровни HDD_PACK_ARGS := $(EXAMPLE).exe \ $(foreach f,$(BG_DATA),BG:$(f)) \ $(foreach f,$(KID_DATA) $(KID_BIN),KID:$(f)) \ $(foreach f,$(GUARD_DATA),GUARD:$(f)) \ $(foreach f,$(SKEL_DATA),SKEL:$(f)) \ $(foreach f,$(VIZIER_DATA),VIZIER:$(f)) \ $(foreach f,$(SHADOW_DATA),SHADOW:$(f)) \ $(foreach f,$(SND_DATA),SND:$(f)) \ $(foreach f,$(MUS_DATA),MUS:$(f)) \ $(foreach f,$(FONT_DATA),FONT:$(f)) \ $(foreach f,$(TITLE_DATA),TITLE:$(f)) \ $(foreach f,$(PV_DATA),PV:$(f)) \ $(foreach f,$(LVL_DATA),LEVELS:$(f)) include $(PROJ_ROOT)/app.mk TC := $(PROJ_ROOT)/applications/PoP/toolchain # Упаковщики создают сразу ГРУППУ файлов. Обычное multi-output правило # заставляло GNU make при `-B` запускать один и тот же упаковщик отдельно для # каждого .atl/.bin. Stamp-файл представляет один запуск генератора; все # созданные им файлы зависят от этого stamp без собственных рецептов. RESOURCE_STAMP_DIR := .resource-stamps BG_STAMP := $(RESOURCE_STAMP_DIR)/bg GUARD_STAMP := $(RESOURCE_STAMP_DIR)/guard SKEL_STAMP := $(RESOURCE_STAMP_DIR)/skel VIZIER_STAMP := $(RESOURCE_STAMP_DIR)/vizier SHADOW_STAMP := $(RESOURCE_STAMP_DIR)/shadow SOUND_STAMP := $(RESOURCE_STAMP_DIR)/sound MUSIC_STAMP := $(RESOURCE_STAMP_DIR)/music KID_STAMP := $(RESOURCE_STAMP_DIR)/kid KID_BIN_STAMP := $(RESOURCE_STAMP_DIR)/kid-bin FONT_STAMP := $(RESOURCE_STAMP_DIR)/font TITLE_STAMP := $(RESOURCE_STAMP_DIR)/title PV_STAMP := $(RESOURCE_STAMP_DIR)/pv $(RESOURCE_STAMP_DIR): mkdir -p $@ $(BG_STAMP): $(TC)/pop_pack_bg.py $(TC)/render_room.py | $(RESOURCE_STAMP_DIR) cd $(TC) && python3 pop_pack_bg.py dungeon && python3 pop_pack_bg.py palace touch $@ $(BG_DATA): $(BG_STAMP) @test -f $@ || { $(MAKE) -B $(BG_STAMP); test -f $@; } $(GUARD_STAMP): $(TC)/pop_pack_guard.py | $(RESOURCE_STAMP_DIR) cd $(TC) && python3 pop_pack_guard.py touch $@ $(GUARD_DATA): $(GUARD_STAMP) @test -f $@ || { $(MAKE) -B $(GUARD_STAMP); test -f $@; } $(SKEL_STAMP): $(TC)/pop_pack_guard.py | $(RESOURCE_STAMP_DIR) cd $(TC) && python3 pop_pack_guard.py SKEL touch $@ $(SKEL_DATA): $(SKEL_STAMP) @test -f $@ || { $(MAKE) -B $(SKEL_STAMP); test -f $@; } $(VIZIER_STAMP): $(TC)/pop_pack_guard.py | $(RESOURCE_STAMP_DIR) cd $(TC) && python3 pop_pack_guard.py VIZIER touch $@ $(VIZIER_DATA): $(VIZIER_STAMP) @test -f $@ || { $(MAKE) -B $(VIZIER_STAMP); test -f $@; } $(SHADOW_STAMP): $(TC)/pop_pack_shadow.py $(TC)/pop_pack_bg.py $(TC)/pop_pack_kid.py | $(RESOURCE_STAMP_DIR) cd $(TC) && python3 pop_pack_shadow.py touch $@ $(SHADOW_DATA) pop_shadow_atlas.h: $(SHADOW_STAMP) @test -f $@ || { $(MAKE) -B $(SHADOW_STAMP); test -f $@; } $(SOUND_STAMP): $(TC)/pop_pack_sound.py | $(RESOURCE_STAMP_DIR) cd $(TC) && python3 pop_pack_sound.py touch $@ $(SND_DATA) pop_sound_tbl.h: $(SOUND_STAMP) @test -f $@ || { $(MAKE) -B $(SOUND_STAMP); test -f $@; } $(MUSIC_STAMP): $(TC)/pop_pack_music.py | $(RESOURCE_STAMP_DIR) cd $(TC) && python3 pop_pack_music.py $(MUS_IDS) touch $@ $(MUS_DATA) pop_music_tbl.h: $(MUSIC_STAMP) @test -f $@ || { $(MAKE) -B $(MUSIC_STAMP); test -f $@; } $(KID_STAMP): $(TC)/pop_pack_kid.py $(TC)/pop_pack_bg.py | $(RESOURCE_STAMP_DIR) cd $(TC) && python3 pop_pack_kid.py touch $@ $(KID_DATA): $(KID_STAMP) @test -f $@ || { $(MAKE) -B $(KID_STAMP); test -f $@; } $(KID_BIN_STAMP): $(TC)/pop_extract_kid_data.py | $(RESOURCE_STAMP_DIR) cd $(TC) && python3 pop_extract_kid_data.py touch $@ kid_data.h $(KID_BIN): $(KID_BIN_STAMP) @test -f $@ || { $(MAKE) -B $(KID_BIN_STAMP); test -f $@; } $(FONT_STAMP): $(PROJ_ROOT)/toolchain/pop_extract_font.py \ $(CURDIR)/../SDLPoP/src/menu.c $(CURDIR)/../SDLPoP/src/seg009.c | $(RESOURCE_STAMP_DIR) cd $(PROJ_ROOT) && python3 toolchain/pop_extract_font.py touch $@ $(FONT_ATL) pop_font.h: $(FONT_STAMP) @test -f $@ || { $(MAKE) -B $(FONT_STAMP); test -f $@; } $(TITLE_STAMP): $(PROJ_ROOT)/toolchain/pop_pack_title.py \ $(CURDIR)/../SDLPoP/data/TITLE/res51.png \ $(CURDIR)/../SDLPoP/data/TITLE/res52.png \ $(CURDIR)/../SDLPoP/data/TITLE/res53.png \ $(CURDIR)/../SDLPoP/data/TITLE/res54.png \ $(CURDIR)/../SDLPoP/data/TITLE/res55.png | $(RESOURCE_STAMP_DIR) cd $(PROJ_ROOT) && python3 toolchain/pop_pack_title.py touch $@ $(TITLE_DATA): $(TITLE_STAMP) @test -f $@ || { $(MAKE) -B $(TITLE_STAMP); test -f $@; } $(PV_STAMP): $(PROJ_ROOT)/toolchain/pop_pack_intro.py \ $(CURDIR)/../SDLPoP/data/TITLE/res41.png \ $(CURDIR)/../SDLPoP/data/TITLE/res42.png \ $(CURDIR)/../SDLPoP/data/TITLE/res43.png \ $(CURDIR)/../SDLPoP/data/TITLE/res44.png \ $(CURDIR)/../SDLPoP/data/TITLE/res45.png \ $(CURDIR)/../SDLPoP/data/TITLE/res51.png \ $(CURDIR)/../SDLPoP/data/PV/res801.png \ $(CURDIR)/../SDLPoP/data/PV/res805.png \ $(CURDIR)/../SDLPoP/data/PV/res816.png \ $(CURDIR)/../SDLPoP/data/PV/res851.png \ $(CURDIR)/../SDLPoP/data/PV/res870.png \ $(CURDIR)/../SDLPoP/data/PV/res901.png \ $(CURDIR)/../SDLPoP/data/PV/res920.png \ $(CURDIR)/../SDLPoP/data/PV/res951.png \ $(CURDIR)/../SDLPoP/data/PV/res953.png \ $(CURDIR)/../SDLPoP/data/PV/res959.png \ $(CURDIR)/../SDLPoP/data/PV/res981.png \ $(foreach n,802 803 804 806 807 808 809 810 811 812 813 814 815 817,$(CURDIR)/../SDLPoP/data/PV/res$(n).png) \ $(foreach n,852 853 854 855 856 857 858 859 860 861 862 863 864,$(CURDIR)/../SDLPoP/data/PV/res$(n).png) \ $(CURDIR)/../SDLPoP/data/PV/res952.png \ $(foreach n,151 152 153 154 155 156 157 158 159,$(CURDIR)/../SDLPoP/data/PRINCE/res$(n).png) | $(RESOURCE_STAMP_DIR) cd $(PROJ_ROOT) && python3 toolchain/pop_pack_intro.py touch $@ $(PV_DATA): $(PV_STAMP) @test -f $@ || { $(MAKE) -B $(PV_STAMP); test -f $@; } # Явные цели позволяют собирать ресурсы без `make -B`, который по смыслу # принудительно пересобирает также libc, libbgi и само приложение. resources-bg: $(BG_DATA) resources-kid: $(KID_DATA) $(KID_BIN) resources-actors: $(GUARD_DATA) $(SKEL_DATA) $(VIZIER_DATA) $(SHADOW_DATA) resources-sound: $(SND_DATA) resources-music: $(MUS_DATA) resources-font: $(FONT_DATA) resources-title: $(TITLE_DATA) resources-pv: $(PV_DATA) resources-levels: $(LVL_DATA) resources: resources-bg resources-kid resources-actors resources-sound resources-music resources-font resources-title resources-pv resources-levels resources-rebuild: $(MAKE) -B resources # Принудительная перелинковка только roomtest, без глобального `-B` и без # принудительной пересборки библиотек/ресурсов. relink: resources $(MAKE) -W Makefile $(EXAMPLE).exe # HDD_PACK_ARGS содержит все эти файлы; make обязан подготовить их до запуска # упаковщика и при чистой сборке, а не полагаться на старое содержимое дерева. hdd: resources # sprinter-cc собирает все модули одним вызовом и depfile пока не выдаёт. # Банковые .c берём из того же списка, что формирует --bank; любой локальный # заголовок также обязан перелинковать приложение. wildcard намеренно # широкий: цена лишней полной сборки ниже риска получить stale-бинарник. LOCAL_HEADERS := $(wildcard *.h) $(EXAMPLE).exe: Makefile $(PROJ_ROOT)/app.mk $(BANKED_SRCS) $(LOCAL_HEADERS) \ $(BG_DATA) $(KID_DATA) $(KID_BIN) $(FONT_DATA) $(TITLE_DATA) $(PV_DATA) $(LVL_DATA) clean-resources: rm -rf $(RESOURCE_STAMP_DIR) .PHONY: resources resources-rebuild resources-bg resources-kid resources-actors relink \ resources-sound resources-music resources-font resources-title resources-pv resources-levels clean-resources