SprPoP: музыка не замолкает в меню и в долгих фейдах

Насос CBL идёт из прерывания (и его запрос защёлкивается до подтверждения —
проверено по MAME irqack_cb), поэтому сам звук главному циклу не нужен.  А
вот ПОТОКОВЫЙ трек — титульная тема играется кольцом — дочитывается с диска
только в pop_music_service: страница ложится в слот, который насос уже
прошёл.  Этот вызов был лишь в игровом цикле, HOF и сценах, но не в меню и
не в фейдах, а там главный цикл стоит секундами — кольцо опустошалось, и
музыка замолкала до закрытия меню (жалоба пользователя).

Добавлено: ui_wait_frame() в pop_menu.c (обслужить музыку + ждать фронт,
заменил все ожидания кадра в меню) и pop_music_service() в fade_run и
transition_ltr (pop_ui.c) — темп тот же, 50 раз в секунду, как в игровом
цикле.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-28 17:18:44 +03:00
parent 50570881f5
commit d23126983e
2 changed files with 35 additions and 9 deletions
+28 -9
View File
@@ -27,6 +27,7 @@
#include "pop_settings.h"
#include "pop_cfg.h"
#include "pop_qsave.h"
#include "pop_music.h" /* pop_music_service — подкачка кольца, см. ui_wait_frame */
#include "pop_status.h"
#include "pop_sfx.h"
@@ -207,9 +208,27 @@ static uint8_t ui_begin(void)
return back;
}
/* КАДР МЕНЮ: перед ожиданием фронта — обслужить музыку.
*
* Насос CBL живёт в прерывании и главный цикл ему не нужен, НО потоковый
* трек (титульная тема играется КОЛЬЦОМ, pop_music.c) дочитывается с диска
* именно из pop_music_service: очередная страница попадает в слот, который
* насос уже прошёл. Пока открыто меню, главный цикл стоит, и без этого
* вызова кольцо опустошалось за несколько секунд — музыка замолкала до
* закрытия меню, а на перемещениях по пунктам это слышно как паузы
* (жалоба пользователя 2026-08-28).
*
* Место — рядом с ожиданием кадра: получается тот же темп 50 раз в
* секунду, что и в игровом цикле, и подкачка не чаще, чем нужна. */
static void ui_wait_frame(void)
{
pop_music_service();
pop_wait_edge();
}
static void ui_end(uint8_t back)
{
pop_wait_edge(); /* готовый кадр показать только на фронте */
ui_wait_frame(); /* готовый кадр показать только на фронте */
gfx_set_visible_page(back);
(void)pop_sfx_start();
}
@@ -227,7 +246,7 @@ static void ui_wait_release(void)
kbd_raw_down(KBD_SPACE) ||
kbd_raw_down(KBD_UP) || kbd_raw_down(KBD_DOWN) ||
kbd_raw_down(KBD_LEFT) || kbd_raw_down(KBD_RIGHT))
pop_wait_edge();
ui_wait_frame();
}
/* Действие = Enter ИЛИ Space: в оригинале выбор подтверждается обеими, и
@@ -250,7 +269,7 @@ static void ui_wait_ack(void)
return;
}
esc_prev = esc; act_prev = act;
pop_wait_edge();
ui_wait_frame();
}
}
@@ -478,7 +497,7 @@ static uint8_t ui_confirm(const char *question)
confirm_draw(question, sel);
menu_sound(MENU_SND_MOVE);
}
pop_wait_edge();
ui_wait_frame();
}
}
@@ -609,7 +628,7 @@ static uint8_t settings_process(void)
settings_draw(sel);
menu_sound(sound);
}
pop_wait_edge();
ui_wait_frame();
}
}
@@ -641,14 +660,14 @@ static void menu_erase(uint8_t entry_page)
/* Из shadow видимой страницы берём кадр без текстов. */
gfx_set_draw_page(hidden);
gfx_copy_page(&full, GFX_COPY_DIRECT);
pop_wait_edge();
ui_wait_frame();
gfx_set_visible_page(hidden);
/* Теперь чистая hidden — источник для второй страницы. */
gfx_set_draw_page(visible);
gfx_copy_page(&full, GFX_COPY_DIRECT);
if (entry_page != hidden) {
pop_wait_edge();
ui_wait_frame();
gfx_set_visible_page(entry_page);
}
}
@@ -679,7 +698,7 @@ int8_t pop_menu_process(void) __banked
/* Открыли по НАЖАТИЮ Esc: дождаться отпускания, иначе то же нажатие
* закроет меню раньше первого кадра. pop_wait_edge опрашивает FIFO. */
while (kbd_raw_down(KBD_ESC)) pop_wait_edge();
while (kbd_raw_down(KBD_ESC)) ui_wait_frame();
entry_page = gfx_get_visible_page();
saved_page = gfx_get_draw_page();
@@ -742,7 +761,7 @@ int8_t pop_menu_process(void) __banked
menu_draw(sel);
menu_sound(sound);
}
pop_wait_edge();
ui_wait_frame();
pop_pace_end(pop_pace_n(0)); /* игра стоит — обычный темп */
}
+7
View File
@@ -16,6 +16,7 @@
#include "pop_arc.h"
#include "pop_ui.h"
#include "pop_status.h"
#include "pop_music.h" /* pop_music_service — подкачка кольца в долгих фейдах */
typedef struct {
uint8_t base;
@@ -292,6 +293,11 @@ static uint8_t fade_run(uint8_t frames, uint8_t up, uint8_t skip)
pop_ui_palette_dim(step, 0);
shown = step;
}
/* Fade — это 2,13 с, и всё это время главный цикл стоит. Кольцо
* потокового трека дочитывает pop_music_service, иначе музыка
* замолкает прямо посреди перехода (та же причина, что у меню:
* ui_wait_frame в pop_menu.c). */
pop_music_service();
gfx_wait_vsync();
if (skip) {
kbd_raw_sync();
@@ -429,6 +435,7 @@ uint8_t pop_screen_present_ltr(void) __banked
stripe.x = x;
stripe.w = (uint16_t)((GFX_WIDTH - x < 4) ? GFX_WIDTH - x : 4);
gfx_copy_page(&stripe, GFX_COPY_DIRECT);
pop_music_service(); /* 80 кадров перехода — см. fade_run */
gfx_wait_vsync();
}
return 0;