Финальная тема won: кольцевой стриминг с диска

Последний неозвученный кусок игры. 115 секунд и 1,2 МБ в память не влезают
никак, поэтому тема играется кольцом из шести страниц (96 КБ = 9 с): насос
идёт по кругу, а pop_music_service дочитывает файл в те страницы, которые
насос уже прошёл. Страница звучит 1,5 с и читается 33 мс — запас
сорокакратный; дистанция считается без отдельных счётчиков, потому что
страница это ровно 128 блоков насоса.

Три вещи, всплывшие при живой проверке:

- кольцо обязано сниматься при любом обычном запуске трека, иначе
  следующая тема играет по кругу первых шести страниц (поймано на титрах
  сразу после победы);
- живые сцены комнаты принцессы теперь открывают CBL сами (cut_begin):
  pop_ending_show глушит звук первым действием, и «arrived to princess»
  не звучал вовсе;
- тема дослушивается до конца с возможностью прервать клавишей — как
  seg001:637. У оригинала там стоит ввод имени в таблицу рекордов; когда
  он появится, ожидание переедет за него (задача HOF-ENTRY).

Проверено в MAME на сборке LEVEL=14: после встречи с принцессой звучит
тема победы (id 56, кольцо 6), курсор уходит далеко за размер кольца —
подкачка успевает. Host-тесты: 15 наборов.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-26 12:32:40 +03:00
parent 5d912f0f3f
commit faec9a7d3a
10 changed files with 256 additions and 17 deletions
+35 -2
View File
@@ -1323,6 +1323,10 @@ static int cut_begin(uint8_t hg_state)
intro_commit_palette();
if (intro_pv_draw_base() != 0) return -1;
if (cut_load() != 0) return -1;
/* Атласы сцены прочитаны — можно открывать вывод. Без этого сцена шла
* молча: pop_ending_show глушит CBL первым действием, а включить его
* обратно было некому, и «arrived to princess» (26) не звучал вовсе. */
(void)pop_sfx_start();
return 0;
}
@@ -1500,6 +1504,7 @@ static uint8_t intro_run(const pop_cs_cmd_t *script)
} else if (ev == POP_CS_EVENT_FADE_IN) pop_pal_fade_in(INTRO_FADE);
else if (ev == POP_CS_EVENT_FADE_OUT) pop_pal_fade_out(INTRO_FADE);
else if (ev == POP_CS_EVENT_FLASH) intro_flash(arg);
pop_music_service(); /* подкачка потокового трека (финал) */
gfx_wait_vsync();
}
@@ -1730,7 +1735,35 @@ void pop_ending_show(void) __banked
/* Встреча с принцессой — живая сцена (end_sequence_anim). Дальше по
* скрипту идёт только текст HAIL, поэтому статический сценарий ниже
* начинается с него; при нехватке ресурсов отыгрывается целиком. */
if (cut_ending() == 0) intro_run(ending_hail_script);
else intro_run(ending_script);
if (cut_ending() == 0) {
/* ПОБЕДНАЯ ТЕМА (56) — потоком с диска: 115 секунд и 1,2 МБ в память
* не влезают никак. Оригинал пускает её здесь же, сразу после
* встречи с принцессой и до экрана HAIL (seg001:583). Дальше
* страницы дочитывает pop_music_service из циклов сцен. */
(void)pop_sfx_start();
(void)pop_music_ring_start(POP_MUS_WON);
intro_run(ending_hail_script);
/* ДОСЛУШАТЬ. Оригинал не обрывает победную тему переходом в меню:
* `while (check_sound_playing() && !key_test_quit())` (seg001:637),
* и лишь потом гасит экран. Клавишей прервать можно.
*
* У ОРИГИНАЛА между титрами и этим ожиданием стоит таблица рекордов
* с вводом имени, и тема играет сквозь неё. Наша таблица пока без
* ввода, поэтому ждём здесь; когда ввод появится — ожидание
* переедет за него (задача HOF-ENTRY). */
{
intro_skip_t tail;
intro_skip_begin(&tail);
while (pop_music_busy() && !intro_skip_requested(&tail)) {
pop_music_service(); /* поток дочитывается по ходу */
pop_wait_edge();
}
}
} else {
intro_run(ending_script);
}
pop_music_free();
pop_sfx_pause();
intro_restore_game_palette();
}