Архивы ресурсов 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
+24 -8
View File
@@ -8,6 +8,7 @@
#include <sprinter_mem.h>
#include <cbl.h>
#include "pop_sfx.h"
#include "pop_arc.h"
#define POP_SND_FILES /* имена файлов нужны ТОЛЬКО здесь, см. pop_sound_tbl.h */
#include "_pop_sfx.h"
@@ -20,16 +21,31 @@ int pop_sfx_init(void) __banked
if (pop_snd_ok) return 0;
/* Одним блоком: страницы блока идут подряд по логическому индексу, и
* таблица звуков адресует их именно так (page = смещение >> 14). */
blk = mem_alloc_pages(POP_SND_PAGES);
if (!blk) return -1;
for (i = 0; i < POP_SND_PAGES; i++) {
pop_snd_page[i] = mem_get_page(blk, i);
if (!pop_snd_page[i] ||
bank_load_file(pop_snd_page[i],0,pop_snd_files[i],16384) != 16384) {
mem_free_block(blk);
* таблица звуков адресует их именно так (page = смещение >> 14).
*
* Из АРХИВА, а не десятью файлами: `open` стоит 51,4 мс против 32,6 мс
* на чтение 16 КБ (замер 2026-08-25), то есть девять лишних открытий —
* это почти полсекунды на ровном месте. Таблица живёт на стеке, см.
* pop_arc.h. */
{
pop_arc_t arc;
uint8_t tbl[POP_SND_PAGES * POP_ARC_REC];
if (pop_arc_open(&arc, "SND\\snd.arc", tbl, POP_SND_PAGES) !=
POP_SND_PAGES)
return -1;
blk = mem_alloc_pages(POP_SND_PAGES);
if (!blk) { pop_arc_close(&arc); return -1; }
for (i = 0; i < POP_SND_PAGES; i++) {
pop_snd_page[i] = mem_get_page(blk, i);
if (!pop_snd_page[i] ||
pop_arc_read(&arc, tbl, i, 0, pop_snd_page[i], 0, 0) != 16384) {
pop_arc_close(&arc);
mem_free_block(blk);
return -1;
}
}
pop_arc_close(&arc);
}
snd_blk = blk;
pop_snd_want = 1; /* набор есть — звук по умолчанию включён */