Музыка по ходу игры: смерть, зелья, меч, конец уровня, катсцены

Звуки 24..43 в наборе оцифровки пустые — в оригинале это Adlib-музыка, и
в digisnd её нет. На этом и построено подключение: pop_sfx_play для звука
с нулевой длиной кладёт номер в pop_mus_req, а разбирает заявку
pop_music_service() — один вызов на кадр из любого цикла (игра, интро,
катсцена). Всё чтение с диска живёт там.

Ждать полной загрузки джингла нельзя — это фриз посреди игры. Поэтому
pop_music_stream читает первую страницу (33 мс) и сразу пускает трек: она
звучит 1,5 с, а следующая читается те же 33 мс. Остальные доливаются по
одной за кадр.

Расставлено по местам оригинала: смерть (24/28/32), вступление первого
уровня и тень шестого (25), сцены перед уровнями (27/35/40), встреча с
Джафаром (29), зелья (30/33/39), время вышло (36), меч и смерть стража
(37), смерть Джафара (43), конец уровня (41/32), встреча с принцессой
(26). Темы «раз за уровень» сбрасывает pop_music_level_start.

Упакован 21 трек (2,4 МБ). Не озвучен только финал: won — 115 с и 78
страниц EMM, ему нужен кольцевой стриминг (задача MUS-WON на доске).

Проверено в MAME: вступительная тема первого уровня отыгрывается на
старте (курсор дошёл до конца, id 25). Host-тесты: 15 наборов.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-25 21:52:37 +03:00
parent 65797af44c
commit 7e6b38cca6
33 changed files with 300 additions and 35 deletions
+47
View File
@@ -159,6 +159,38 @@ int8_t pop_music_load(uint8_t id) __banked
return (r < 0) ? -1 : 0;
}
/* ЗАПУСК С ПОДКАЧКОЙ НА ХОДУ — для игровых джинглов (смерть, зелья, меч).
* Ждать полной загрузки нельзя: это фриз на треть секунды посреди игры.
* Зато можно начать сразу после ПЕРВОЙ страницы: она звучит 1,5 с, а
* следующая читается 33 мс — запас сорокакратный. Дальше вызывающий
* доливает по странице за кадр (pop_music_load_step, pop_music_loading).
*
* Номера страниц известны сразу после mem_alloc_pages, поэтому таблицу для
* насоса заполняем целиком: данные в этих страницах появятся раньше, чем
* он до них доберётся.
* 0 — играет, -1 — трека нет или память кончилась. */
int8_t pop_music_stream(uint8_t id) __banked
{
uint8_t i, n;
if (pop_music_load_begin(id) != 0) return -1;
if (pop_music_load_step() < 0) return -1; /* первая страница */
n = ld_slot;
pop_mus_left = 0; /* насос — на тишину */
for (i = 0; i < ld_pages; i++)
pop_mus_page[i] = mem_get_page(slot_blk[n], i);
if (n != mus_cur) slot_release(mus_cur);
mus_cur = n;
slot_pages[n] = ld_pages;
slot_blocks[n] = pop_mus_tbl[id].blocks;
slot_id[n] = id;
pop_mus_id = id;
pop_mus_pg = 0;
pop_mus_ptr = 0;
pop_mus_left = slot_blocks[n];
return 0;
}
void pop_music_play(void) __banked
{
uint8_t n, i;
@@ -182,6 +214,21 @@ void pop_music_play(void) __banked
pop_mus_left = slot_blocks[n];
}
void pop_music_service(void) __banked
{
/* Один вызов на кадр из ЛЮБОГО цикла — игрового, интро, катсцены.
* Заявку кладёт pop_sfx_play (звук без оцифровки = музыка оригинала),
* а диск трогаем только здесь. */
if (pop_mus_req) {
uint8_t id = pop_mus_req;
pop_mus_req = 0;
(void)pop_music_stream(id);
} else if (ld_busy) {
(void)pop_music_load_step();
}
}
uint8_t pop_music_busy(void) __banked
{
return (uint8_t)(pop_mus_left != 0);