SprPoP: звуковые эффекты без перелинковки — раскладка уехала на диск
Часть II плана music_runtime_index_plan.md (SI0..SI4). gen/pop_sound_tbl.h БОЛЬШЕ НЕ ГЕНЕРИРУЕТСЯ: раскладка набора читается из SND/snd.idx (формат PSI1, писатель и разборщик — tools/pop_idx.py, 22 теста в make test-tools). Один и тот же sprpop.exe работает с набором SDLPoP (9 страниц) и MSDOS (10) — sha256 бинарника при смене набора не меняется. Заодно умолчание источника эффектов переведено на SDLPoP (SND_SRC=sdlpop): сборка обязана работать без оригинального дистрибутива DOS. У кого он есть, включает лучший набор явно — make SND_SRC=msdos (там полнее оцифровка: в SDLPoP звук 48 spiked пустой). Устройство: pop_snd_tbl/pop_snd_page/pop_snd_pages — резидентные данные (pop_snd_data.c), тип и инварианты — рукописный pop_snd_tbl.h. Записи читаются ОДНИМ read прямо в таблицу, поэтому sizeof(pop_snd_ent_t) == 5 стало частью дискового контракта: проверяется статически и полем размера записи в заголовке. POP_SND_PAGES как compile-time размер набора исчез — вместо него POP_SND_MAX_PAGES (вместимость, 16) и runtime pop_snd_pages. Цена: таблица переехала из _CODE в _DATA, суммарный резидент почти не изменился (куча 239 -> 229 Б); банк 8 +601 Б на чтение и валидацию. Валидация не доверяет файлу: заголовок целиком плюс каждая запись (страница, смещение, кратность блоку, непересечение с блоком тишины, выход за последнюю страницу). Последнее считается В БЛОКАХ — байтовый адрес конца не влезает в uint16, а 32-битная арифметика на Z80 дорога. НЕТ ИНДЕКСА — ЭФФЕКТОВ НЕТ, НО МУЗЫКА ИГРАЕТ. Первая версия просто возвращала ошибку, и игра становилась непроходимой: тишину льёт первый блок набора, без набора CBL не открывался, а с ним вставала музыка (её блоки считает тот же насос) — заставка ждала конца трека вечно. Теперь поднимается пустой набор с блоком тишины. Заливается ровно 128 байт и под DI: gfx_w0_page_prepare ставит в страницу IRQ-стабы, и заливка всей страницы затирала их — первое же прерывание давало чёрный экран. Грабли сборки: смена SND_SRC тихо давала неверный результат (sdlpop -> msdos -> sdlpop оставлял чужой набор в assets/packed). Причина не в логике, а в секундной гранулярности mtime. Лечение убирает время из решения: смена варианта сносит stamp'ы своего семейства, а упаковка, сборка архива и копия индекса делаются одним рецептом. То же получила и музыка (MUSIC_FMT). Проверено в MAME: таблица в памяти совпадает с файлом из образа побайтово; один EXE поднимает оба набора; отладочный --order reverse (30 из 31 записей отличаются от штатных) звучит правильно; битый индекс выключает эффекты, не роняя игру; без индекса PV-сцена проходит с музыкой; Ctrl+S работает в обоих режимах. Разбор — docs/sound_plan.md §10. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011MsUsEFAQfsjjQpJ7RtKVY
This commit is contained in:
@@ -1,6 +1,14 @@
|
||||
# Аудио без перелинковки: runtime-индексы музыки и эффектов
|
||||
|
||||
> Статус: план будущего улучшения, 2026-08-30. Код пока не менялся.
|
||||
> Статус: **часть II (эффекты, SI0..SI4) СДЕЛАНА 2026-08-31** — разбор и
|
||||
> результаты в `sound_plan.md` §10. Часть I (музыка, MI0..MI5) — план.
|
||||
>
|
||||
> Что в реализации разошлось с планом ниже: файл назван `SND/snd.idx`
|
||||
> (единый basename с `snd.arc`, оба в нижнем регистре), а при отсутствии
|
||||
> индекса поднимается ПУСТОЙ набор с блоком тишины — иначе встаёт музыка
|
||||
> и игра непроходима (§10.5 sound_plan). Про `ticks60` в `PMI1` решено:
|
||||
> поле в формате оставить даже если сценарии перейдут на ожидание звука —
|
||||
> загрузчик волен не тащить его в память.
|
||||
|
||||
## 1. Цель
|
||||
|
||||
@@ -330,13 +338,13 @@ Makefile должен:
|
||||
|
||||
Один и тот же `sprpop.exe` должен работать с разными наборами PCM-эффектов,
|
||||
если в них сохранена исходная нумерация sound id 0..56. Замена набора должна
|
||||
сводиться к замене согласованной пары `SND/SOUND.IDX` + `SND/SND.ARC`, без
|
||||
сводиться к замене согласованной пары `SND/snd.idx` + `SND/snd.arc`, без
|
||||
генерации C-заголовка и перелинковки EXE.
|
||||
|
||||
Набор состоит из двух согласованных файлов:
|
||||
|
||||
- `SND/SND.ARC` — обычный архив PBA1 с PCM-страницами;
|
||||
- `SND/SOUND.IDX` — описание раскладки эффектов внутри этих страниц.
|
||||
- `SND/snd.arc` — обычный архив PBA1 с PCM-страницами;
|
||||
- `SND/snd.idx` — описание раскладки эффектов внутри этих страниц.
|
||||
|
||||
Отдельный IDX предпочтительнее расширения заголовка `snd.arc`: PBA1 остаётся
|
||||
универсальным и не получает специального варианта только для звука, а
|
||||
@@ -381,7 +389,7 @@ typedef struct {
|
||||
У SDLPoP эффект 48 содержит только 7 исходных сэмплов; это свойство самого
|
||||
набора, а не ошибка runtime-индекса.
|
||||
|
||||
## 15. Файл `SND/SOUND.IDX`
|
||||
## 15. Файл `SND/snd.idx`
|
||||
|
||||
IDX занимает один 512-байтовый сектор и после короткого заголовка является
|
||||
точным дисковым дампом 57 записей `pop_snd_tbl`:
|
||||
@@ -472,12 +480,12 @@ SDLPoP-набор — 9. Предел 16 оставляет запас буду
|
||||
|
||||
`pop_sfx_init()` должен выполнять следующую последовательность:
|
||||
|
||||
1. открыть `SND/SOUND.IDX` через существующий путь `POP_PATH_CALL`;
|
||||
1. открыть `SND/snd.idx` через существующий путь `POP_PATH_CALL`;
|
||||
2. прочитать 16-байтовый заголовок, затем 285 байт записей прямо в
|
||||
`pop_snd_tbl`, и проверить полный размер IDX;
|
||||
3. проверить magic, версию, число/размер записей, формат и размер блока;
|
||||
4. получить из IDX фактическое число страниц и проверить диапазон 1..16;
|
||||
5. открыть `SND/SND.ARC` через `POP_PATH_CALL`;
|
||||
5. открыть `SND/snd.arc` через `POP_PATH_CALL`;
|
||||
6. прочитать обычную таблицу PBA1 с ёмкостью `POP_SND_MAX_PAGES`;
|
||||
7. сверить `PSI1.pages` с числом элементов PBA1;
|
||||
8. проверить каждую ненулевую запись;
|
||||
@@ -493,7 +501,7 @@ SDLPoP-набор — 9. Предел 16 оставляет запас буду
|
||||
`pop_snd_pages`.
|
||||
|
||||
При любой ошибке блок EMM и файловый дескриптор освобождаются, таблица не
|
||||
используется, эффекты остаются выключенными. Набор без `SOUND.IDX` считается
|
||||
используется, эффекты остаются выключенными. Набор без `snd.idx` считается
|
||||
неполным; хранить в EXE старую таблицу как fallback не следует, иначе
|
||||
зависимость бинарника от конкретного набора останется.
|
||||
|
||||
@@ -505,9 +513,9 @@ SDLPoP-набор — 9. Предел 16 оставляет запас буду
|
||||
начала/длины на 128 байт;
|
||||
2. вычислить фактическое число страниц и отвергнуть набор больше 16;
|
||||
3. сформировать плотные 57 записей `page/off/len`;
|
||||
4. записать `SND/SOUND.IDX` в формате `PSI1`, включая фактическое число
|
||||
4. записать `SND/snd.idx` в формате `PSI1`, включая фактическое число
|
||||
страниц;
|
||||
5. собрать обычный `SND/SND.ARC` из полученных страниц;
|
||||
5. собрать обычный `SND/snd.arc` из полученных страниц;
|
||||
6. больше не генерировать `gen/pop_sound_tbl.h`.
|
||||
|
||||
Чтобы число страниц не было захардкожено списком `s0.bin`..`s9.bin` в
|
||||
@@ -517,13 +525,13 @@ Makefile, упаковщик звука предпочтительно долж
|
||||
|
||||
Стабильные тип и константы переносятся в обычный internal-заголовок. EXE не
|
||||
должен зависеть от результата упаковки звука: цель выбора набора меняет
|
||||
согласованную пару `SOUND.IDX` + `SND.ARC`.
|
||||
согласованную пару `snd.idx` + `snd.arc`.
|
||||
|
||||
## 20. Этапы реализации эффектов
|
||||
|
||||
### SI0 — формат и host-тест
|
||||
|
||||
- writer/reader отдельного `SOUND.IDX` в формате `PSI1`;
|
||||
- writer/reader отдельного `snd.idx` в формате `PSI1`;
|
||||
- проверка точного пятибайтового LE-формата записи;
|
||||
- сборка и разбор обоих имеющихся DIGISND-наборов;
|
||||
- проверки 10 страниц MSDOS, 9 страниц SDLPoP и отличающихся записей.
|
||||
@@ -545,7 +553,7 @@ Makefile, упаковщик звука предпочтительно долж
|
||||
### SI3 — сборка без перелинковки
|
||||
|
||||
- убрать фиксированный `SND_ATL` из десяти имён;
|
||||
- сделать `SOUND.IDX` и `SND.ARC` согласованными результатами выбора набора;
|
||||
- сделать `snd.idx` и `snd.arc` согласованными результатами выбора набора;
|
||||
- проверить неизменность SHA/даты `sprpop.exe` при смене набора.
|
||||
|
||||
### SI4 — приёмка
|
||||
@@ -561,7 +569,7 @@ Makefile, упаковщик звука предпочтительно долж
|
||||
## 21. Критерии готовности эффектов
|
||||
|
||||
- один `sprpop.exe` работает с MSDOS- и SDLPoP-наборами;
|
||||
- замена согласованной пары `SND/SOUND.IDX` + `SND/SND.ARC` не требует
|
||||
- замена согласованной пары `SND/snd.idx` + `SND/snd.arc` не требует
|
||||
компиляции C и не меняет EXE;
|
||||
- `pop_snd_tbl` больше не генерируется как C-код;
|
||||
- загружается фактическое число страниц в диапазоне 1..16;
|
||||
|
||||
Reference in New Issue
Block a user