SprPoP: меню больше не глушит звук на время перерисовки

ui_begin() звал pop_sfx_pause() перед полностраничной accel-копией, и это
слышно: pause закрывает CBL целиком (cbl_close), курсор трека стоит, и
короткая мелодия начала уровня замирала ровно на время перерисовки меню —
а на перемещении по пунктам это повторялось на каждом кадре меню.

Обоснование заплатки устарело.  Лист, который зовёт gfx_copy_page
(_bgi_scroll_rows_raw), режет DI бандами по 16 строк — ~1,6 мс против
дедлайна насоса 11,7 мс (85,4 порции в секунду), между бандами есть окно
прерываний.  Тот же полностраничный копир каждый кадр делают игровой цикл
и катсцены, и звук там не рвётся.  Скрежет, под который заплатка ставилась,
шёл от чтения насосом мусора и вылечен отдельно.

Парный pop_sfx_start() в ui_end оставлен: он идемпотентен и чинит вход в
меню при закрытом выводе (например сразу после загрузки уровня).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-28 17:29:04 +03:00
parent d23126983e
commit ea07a8d7b0
+19 -4
View File
@@ -197,10 +197,21 @@ static uint8_t ui_begin(void)
gfx_rect_t full; gfx_rect_t full;
uint8_t back = (uint8_t)(gfx_get_visible_page() ^ 1); uint8_t back = (uint8_t)(gfx_get_visible_page() ^ 1);
/* Полностраничная accel-копия держит DI дольше половины CBL-буфера. /* ЗВУК ЗДЕСЬ БОЛЬШЕ НЕ ГЛУШИМ (снято 2026-08-28).
* Закрываем вывод, иначе железо повторяет старые 128 байт (скрежет). *
* ui_end откроет его уже с заново заполненной тишиной. */ * Был вызов pop_sfx_pause() с обоснованием «полностраничная accel-копия
pop_sfx_pause(); * держит DI дольше половины CBL-буфера, иначе железо повторяет старые
* 128 байт». Обоснование устарело: лист, который зовёт gfx_copy_page
* (_bgi_scroll_rows_raw), режет DI бандами по 16 строк — это ~1,6 мс
* против дедлайна насоса 11,7 мс, и окно прерываний между бандами есть.
* Тот же полностраничный копир каждый кадр делают игровой цикл и
* катсцены, и звук там не рвётся.
*
* А цена была слышимой: pause закрывает CBL целиком (cbl_close), курсор
* трека остаётся на месте, и короткая мелодия начала уровня замирала
* ровно на время перерисовки меню — «тормозится на кусочек» (жалоба
* пользователя 2026-08-28). У оригинала такого нет и быть не может:
* там нет насоса, который надо кормить руками. */
gfx_set_draw_page(back); gfx_set_draw_page(back);
full.x = 0; full.y = 0; full.w = GFX_WIDTH; full.h = GFX_HEIGHT; full.x = 0; full.y = 0; full.w = GFX_WIDTH; full.h = GFX_HEIGHT;
gfx_copy_page(&full, GFX_COPY_DIRECT); gfx_copy_page(&full, GFX_COPY_DIRECT);
@@ -230,6 +241,10 @@ static void ui_end(uint8_t back)
{ {
ui_wait_frame(); /* готовый кадр показать только на фронте */ ui_wait_frame(); /* готовый кадр показать только на фронте */
gfx_set_visible_page(back); gfx_set_visible_page(back);
/* Парный к снятому pop_sfx_pause (см. ui_begin) вызов оставлен: он
* идемпотентен (открытый CBL возвращает 0 сразу) и чинит случай, когда
* в меню вошли при закрытом выводе — например сразу после загрузки
* уровня, которая глушит звук намеренно. */
(void)pop_sfx_start(); (void)pop_sfx_start();
} }