Архивы ресурсов PBA1: звук одним файлом, музыка потоком; ALLOCS 6000

ЗАМЕР, из которого всё выросло (MAME, 2026-08-25): `open` стоит 51,4 мс,
а чтение 16 КБ из уже открытого файла — 32,6 мс.  То есть 61 % времени
загрузки уходит на ОТКРЫТИЕ, а не на данные, и чистая скорость чтения —
491 КБ/с, а не 260.  На диске игры 343 файла; одна только стартовая пачка
(kid+shadow+bg+sound+guard, ~142 файла) — это 7,3 секунды чистого open.

* toolchain/pop_pack_arc.py + pop_arc.c/h (банк 8) — формат PBA1:
  заголовок 512 Б, магия, count, записи по 4 байта (offset в СЕКТОРАХ —
  архив бывает больше 64 КБ; size в байтах — ресурс всегда <= 16 КБ,
  он обязан лезть в EMM-страницу).  Таблицу держит вызывающий на своём
  стеке: в W2 её класть нельзя, а стека в точке загрузки израсходовано
  75 байт из 1279 (замер там же).
* libc: bank_read_page — чтение из УЖЕ ОТКРЫТОГО файла в EMM-страницу.
  bank_load_file переписана через неё, поэтому дублирования работы с W3
  не осталось и резидент почти не вырос.
* Набор эффектов: 10 файлов -> SND\snd.arc, один open вместо десяти.
* Музыка: трек лежит ОДНИМ файлом и читается порциями по странице —
  нарезка на куски больше не нужна.  Этот же путь понадобится финалу
  `won` (1,2 МБ), который в память целиком не влезает.
* Менеджер звука приведён к оригиналу: играющая музыка участвует в
  таблицах приоритета наравне с эффектами (seg000:1672 + data.h:433).
  Почти вся музыка НЕперебиваема, поэтому поверх неё эффект не стартует —
  ровно как в SDLPoP; раньше эффект её перебивал.
* ALLOCS 3000 -> 6000 (решение пользователя): сборка +20 с, резидент
  -161 байт.  Куча 87 -> 248 Б.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-25 17:13:25 +03:00
parent 34ba5f71d5
commit ba3aca07bf
25 changed files with 357 additions and 67 deletions
+14 -6
View File
@@ -34,7 +34,10 @@ MEMORY ?= huge # small-раскладка + банки кода в W
#
# ВАЖНО: любое сравнение занятости банков имеет смысл только при ОДНОМ и том
# же ALLOCS — иначе сравниваются не правки, а уровни оптимизации.
ALLOCS ?= 3000
# 6000, а не 3000 (решение пользователя 2026-08-25): сборка дольше секунд на
# двадцать, зато SDCC размещает регистры плотнее и резидент W1 худеет
# примерно на 150 байт — а это ровно те байты, которых не хватает куче.
ALLOCS ?= 6000
# Build info не хранится вручную в C: ID и дата извлекаются Make из текущего
# commit. Переопределения удобны для воспроизводимой release-сборки.
BUILD_ID ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo dev)
@@ -51,7 +54,7 @@ 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 \
BANK8_SRCS := roomtest_cold.c pop_arc.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,
@@ -171,7 +174,11 @@ 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)
SND_PARTS := $(foreach n,0 1 2 3 4 5 6 7 8 9,$(SND_DIR)/s$(n).bin)
# На диск уходит ОДИН архив вместо десяти файлов: `open` дороже чтения
# (51,4 мс против 32,6 мс на 16 КБ, замер 2026-08-25), см. pop_arc.h.
SND_ARC := $(SND_DIR)/snd.arc
SND_DATA := $(SND_ARC)
# МУЗЫКА: записи DOS-версии, приведённые к формату CBL и порезанные на
# страницы EMM (toolchain/pop_pack_music.py). Пока в игре звучит один
@@ -179,8 +186,7 @@ SND_DATA := $(foreach n,0 1 2 3 4 5 6 7 8 9,$(SND_DIR)/s$(n).bin)
# добавлением номеров в 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))
MUS_DATA := $(foreach i,$(MUS_IDS),$(MUS_DIR)/m$(i).bin)
# UI: два исходных шрифта SDLPoP в одном EMM-атласе. Файл короче страницы:
# хвост использует menu для временного snapshot палитры (без расхода W2).
@@ -294,8 +300,10 @@ $(SHADOW_DATA) pop_shadow_atlas.h: $(SHADOW_STAMP)
$(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)
$(SND_PARTS) pop_sound_tbl.h: $(SOUND_STAMP)
@test -f $@ || { $(MAKE) -B $(SOUND_STAMP); test -f $@; }
$(SND_ARC): $(SND_PARTS) $(TC)/pop_pack_arc.py
python3 $(TC)/pop_pack_arc.py $@ $(SND_PARTS)
$(MUSIC_STAMP): $(TC)/pop_pack_music.py | $(RESOURCE_STAMP_DIR)
cd $(TC) && python3 pop_pack_music.py $(MUS_IDS)