From d23126983e909cb0ad481bbc5adc2c15f70143ab Mon Sep 17 00:00:00 2001 From: Alexander Petrov Date: Fri, 28 Aug 2026 17:18:44 +0300 Subject: [PATCH] =?UTF-8?q?SprPoP:=20=D0=BC=D1=83=D0=B7=D1=8B=D0=BA=D0=B0?= =?UTF-8?q?=20=D0=BD=D0=B5=20=D0=B7=D0=B0=D0=BC=D0=BE=D0=BB=D0=BA=D0=B0?= =?UTF-8?q?=D0=B5=D1=82=20=D0=B2=20=D0=BC=D0=B5=D0=BD=D1=8E=20=D0=B8=20?= =?UTF-8?q?=D0=B2=20=D0=B4=D0=BE=D0=BB=D0=B3=D0=B8=D1=85=20=D1=84=D0=B5?= =?UTF-8?q?=D0=B9=D0=B4=D0=B0=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Насос 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 --- applications/SprPoP/src/pop_menu.c | 37 ++++++++++++++++++++++-------- applications/SprPoP/src/pop_ui.c | 7 ++++++ 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/applications/SprPoP/src/pop_menu.c b/applications/SprPoP/src/pop_menu.c index a97e77f..82fda82 100644 --- a/applications/SprPoP/src/pop_menu.c +++ b/applications/SprPoP/src/pop_menu.c @@ -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)); /* игра стоит — обычный темп */ } diff --git a/applications/SprPoP/src/pop_ui.c b/applications/SprPoP/src/pop_ui.c index eda9198..ca4354a 100644 --- a/applications/SprPoP/src/pop_ui.c +++ b/applications/SprPoP/src/pop_ui.c @@ -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;