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

Звуки 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
+35 -1
View File
@@ -831,6 +831,7 @@ static int intro_pv_animated(void)
torch_right, sand_frame, flash,
render_tick);
pop_sfx_tick(); /* как в оригинале — в конце отрисовки кадра */
pop_music_service(); /* заявки на музыку из сцены (эффект без оцифровки) */
/* Страницу следующей реплики читаем ЗДЕСЬ, до досыпания кадра:
* 33 мс диска укладываются в паузу логического кадра (133 мс) и
* анимации не стоят. */
@@ -1252,6 +1253,8 @@ static uint8_t cut_run(uint16_t frames, uint8_t kid_visible)
gfx_set_visible_page(back);
for (hold = 1; hold < CUT_FRAME_VSYNC; hold++) gfx_wait_vsync();
pop_sfx_tick();
pop_music_service(); /* «встреча с принцессой» — трек, а не эффект */
cut_torch_l = (uint8_t)((cut_torch_l + 1) % 9);
cut_torch_r = (uint8_t)((cut_torch_r + 1) % 9);
cut_sand = (uint8_t)((cut_sand + 1) % 3);
@@ -1519,8 +1522,24 @@ void pop_pre_cutscene_show(pop_pre_cutscene_t scene) __banked
const pop_cs_cmd_t *script = 0;
pop_sfx_pause();
/* Музыка сцены — как в оригинале: 27 для 2/4/6/12 (seg001:401),
* 35 для 8/9 (seg001:298), 40 для короткой «времени мало» (seg001:388).
* Экран в этот момент чёрный, поэтому читаем трек целиком: пауза на
* диск здесь никому не мешает. */
{
uint8_t track = 27;
if (scene == POP_PRE_8 || scene == POP_PRE_9) track = 35;
else if (scene == POP_PRE_12_SHORT) track = 40;
if (pop_music_load(track) == 0) {
(void)pop_sfx_start();
pop_music_play();
}
}
if (scene == POP_PRE_2_6 || scene == POP_PRE_4 || scene == POP_PRE_12) {
if (pre_princess_animated(scene) >= 0) {
pop_music_free();
pop_sfx_pause();
intro_restore_game_palette();
return;
}
@@ -1530,6 +1549,8 @@ void pop_pre_cutscene_show(pop_pre_cutscene_t scene) __banked
if (scene == POP_PRE_8 || scene == POP_PRE_9) {
int done = (scene == POP_PRE_8) ? cut_scene_8() : cut_scene_9();
if (done == 0) {
pop_music_free();
pop_sfx_pause();
intro_restore_game_palette();
return;
}
@@ -1539,16 +1560,29 @@ void pop_pre_cutscene_show(pop_pre_cutscene_t scene) __banked
else if (scene == POP_PRE_8) script = pre_8;
else if (scene == POP_PRE_9) script = pre_9;
else if (scene == POP_PRE_12_SHORT) script = pre_12_short;
if (!script) return;
if (!script) {
pop_music_free();
pop_sfx_pause();
return;
}
intro_run(script);
pop_music_free();
pop_sfx_pause();
intro_restore_game_palette();
}
void pop_time_expired_show(void) __banked
{
pop_sfx_pause();
/* time_expired (seg001:365) начинается с play_sound(sound_36). */
if (pop_music_load(36) == 0) {
(void)pop_sfx_start();
pop_music_play();
}
intro_run(time_expired_script);
pop_music_free();
pop_sfx_pause();
intro_restore_game_palette();
}