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:
@@ -27,6 +27,7 @@
|
|||||||
#include "pop_settings.h"
|
#include "pop_settings.h"
|
||||||
#include "pop_cfg.h"
|
#include "pop_cfg.h"
|
||||||
#include "pop_qsave.h"
|
#include "pop_qsave.h"
|
||||||
|
#include "pop_music.h" /* pop_music_service — подкачка кольца, см. ui_wait_frame */
|
||||||
#include "pop_status.h"
|
#include "pop_status.h"
|
||||||
#include "pop_sfx.h"
|
#include "pop_sfx.h"
|
||||||
|
|
||||||
@@ -207,9 +208,27 @@ static uint8_t ui_begin(void)
|
|||||||
return back;
|
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)
|
static void ui_end(uint8_t back)
|
||||||
{
|
{
|
||||||
pop_wait_edge(); /* готовый кадр показать только на фронте */
|
ui_wait_frame(); /* готовый кадр показать только на фронте */
|
||||||
gfx_set_visible_page(back);
|
gfx_set_visible_page(back);
|
||||||
(void)pop_sfx_start();
|
(void)pop_sfx_start();
|
||||||
}
|
}
|
||||||
@@ -227,7 +246,7 @@ static void ui_wait_release(void)
|
|||||||
kbd_raw_down(KBD_SPACE) ||
|
kbd_raw_down(KBD_SPACE) ||
|
||||||
kbd_raw_down(KBD_UP) || kbd_raw_down(KBD_DOWN) ||
|
kbd_raw_down(KBD_UP) || kbd_raw_down(KBD_DOWN) ||
|
||||||
kbd_raw_down(KBD_LEFT) || kbd_raw_down(KBD_RIGHT))
|
kbd_raw_down(KBD_LEFT) || kbd_raw_down(KBD_RIGHT))
|
||||||
pop_wait_edge();
|
ui_wait_frame();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Действие = Enter ИЛИ Space: в оригинале выбор подтверждается обеими, и
|
/* Действие = Enter ИЛИ Space: в оригинале выбор подтверждается обеими, и
|
||||||
@@ -250,7 +269,7 @@ static void ui_wait_ack(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
esc_prev = esc; act_prev = act;
|
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);
|
confirm_draw(question, sel);
|
||||||
menu_sound(MENU_SND_MOVE);
|
menu_sound(MENU_SND_MOVE);
|
||||||
}
|
}
|
||||||
pop_wait_edge();
|
ui_wait_frame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -609,7 +628,7 @@ static uint8_t settings_process(void)
|
|||||||
settings_draw(sel);
|
settings_draw(sel);
|
||||||
menu_sound(sound);
|
menu_sound(sound);
|
||||||
}
|
}
|
||||||
pop_wait_edge();
|
ui_wait_frame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -641,14 +660,14 @@ static void menu_erase(uint8_t entry_page)
|
|||||||
/* Из shadow видимой страницы берём кадр без текстов. */
|
/* Из shadow видимой страницы берём кадр без текстов. */
|
||||||
gfx_set_draw_page(hidden);
|
gfx_set_draw_page(hidden);
|
||||||
gfx_copy_page(&full, GFX_COPY_DIRECT);
|
gfx_copy_page(&full, GFX_COPY_DIRECT);
|
||||||
pop_wait_edge();
|
ui_wait_frame();
|
||||||
gfx_set_visible_page(hidden);
|
gfx_set_visible_page(hidden);
|
||||||
|
|
||||||
/* Теперь чистая hidden — источник для второй страницы. */
|
/* Теперь чистая hidden — источник для второй страницы. */
|
||||||
gfx_set_draw_page(visible);
|
gfx_set_draw_page(visible);
|
||||||
gfx_copy_page(&full, GFX_COPY_DIRECT);
|
gfx_copy_page(&full, GFX_COPY_DIRECT);
|
||||||
if (entry_page != hidden) {
|
if (entry_page != hidden) {
|
||||||
pop_wait_edge();
|
ui_wait_frame();
|
||||||
gfx_set_visible_page(entry_page);
|
gfx_set_visible_page(entry_page);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -679,7 +698,7 @@ int8_t pop_menu_process(void) __banked
|
|||||||
|
|
||||||
/* Открыли по НАЖАТИЮ Esc: дождаться отпускания, иначе то же нажатие
|
/* Открыли по НАЖАТИЮ Esc: дождаться отпускания, иначе то же нажатие
|
||||||
* закроет меню раньше первого кадра. pop_wait_edge опрашивает FIFO. */
|
* закроет меню раньше первого кадра. 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();
|
entry_page = gfx_get_visible_page();
|
||||||
saved_page = gfx_get_draw_page();
|
saved_page = gfx_get_draw_page();
|
||||||
@@ -742,7 +761,7 @@ int8_t pop_menu_process(void) __banked
|
|||||||
menu_draw(sel);
|
menu_draw(sel);
|
||||||
menu_sound(sound);
|
menu_sound(sound);
|
||||||
}
|
}
|
||||||
pop_wait_edge();
|
ui_wait_frame();
|
||||||
pop_pace_end(pop_pace_n(0)); /* игра стоит — обычный темп */
|
pop_pace_end(pop_pace_n(0)); /* игра стоит — обычный темп */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "pop_arc.h"
|
#include "pop_arc.h"
|
||||||
#include "pop_ui.h"
|
#include "pop_ui.h"
|
||||||
#include "pop_status.h"
|
#include "pop_status.h"
|
||||||
|
#include "pop_music.h" /* pop_music_service — подкачка кольца в долгих фейдах */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t base;
|
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);
|
pop_ui_palette_dim(step, 0);
|
||||||
shown = step;
|
shown = step;
|
||||||
}
|
}
|
||||||
|
/* Fade — это 2,13 с, и всё это время главный цикл стоит. Кольцо
|
||||||
|
* потокового трека дочитывает pop_music_service, иначе музыка
|
||||||
|
* замолкает прямо посреди перехода (та же причина, что у меню:
|
||||||
|
* ui_wait_frame в pop_menu.c). */
|
||||||
|
pop_music_service();
|
||||||
gfx_wait_vsync();
|
gfx_wait_vsync();
|
||||||
if (skip) {
|
if (skip) {
|
||||||
kbd_raw_sync();
|
kbd_raw_sync();
|
||||||
@@ -429,6 +435,7 @@ uint8_t pop_screen_present_ltr(void) __banked
|
|||||||
stripe.x = x;
|
stripe.x = x;
|
||||||
stripe.w = (uint16_t)((GFX_WIDTH - x < 4) ? GFX_WIDTH - x : 4);
|
stripe.w = (uint16_t)((GFX_WIDTH - x < 4) ? GFX_WIDTH - x : 4);
|
||||||
gfx_copy_page(&stripe, GFX_COPY_DIRECT);
|
gfx_copy_page(&stripe, GFX_COPY_DIRECT);
|
||||||
|
pop_music_service(); /* 80 кадров перехода — см. fade_run */
|
||||||
gfx_wait_vsync();
|
gfx_wait_vsync();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user