SprPoP: трек заставки переживает загрузку уровня — порядок как в оригинале
ЗАМЕР (MAME, 2026-08-28). Брейк на pop_sfx_fill с печатью totalcycles, 500 подряд вызовов насоса через всю загрузку уровня 1->2 под звучащий трек 27: медиана интервала 245 760 тактов, максимум 245 832 при дедлайне 251 000 (11,7 мс) — НИ ОДНОЙ пропущенной порции. Загрузка уровня насос не морит. Поэтому снята двойная заплатка: * pop_level_switch больше не глушит насос перед pop_level_load_num; * pre_cut_finish больше не досиживает трек на чёрном экране (это делалось только чтобы глушение не обрубило его на полуслове; ценой были ~8 секунд пустого экрана — трек 27 длиннее сцены: 10,7 с против 2,6 с). Взамен восстановлен порядок оригинала (seg003:68-108, play_level): катсцена возвращает управление сразу -> уровень грузится ПОД музыку -> ожидание конца трека на чёрном экране (порт `while (check_sound_playing())` + stop_sounds) -> показ уровня. Общая чернота теперь max(трек, загрузка), а не их сумма, и трек не обрывается. Ожидание со страховкой на ~20 с, чтобы потоковый трек не подвесил переход. Пропуск сцены по-прежнему обрывает музыку — как и было. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1765,15 +1765,21 @@ uint8_t pop_intro_show(void) __banked
|
||||
* дальше, а не чтобы досидеть до конца трека. */
|
||||
static void pre_cut_finish(uint8_t aborted)
|
||||
{
|
||||
if (!aborted) {
|
||||
intro_skip_t tail;
|
||||
|
||||
intro_skip_begin(&tail);
|
||||
while (pop_music_busy() && !intro_skip_requested(&tail))
|
||||
pop_wait_edge();
|
||||
}
|
||||
/* ТРЕК ПЕРЕЖИВАЕТ СЦЕНУ — как в оригинале. load_intro (seg001:690)
|
||||
* ничего не ждёт: гасит экран и возвращает управление, а звук играет
|
||||
* дальше поверх загрузки уровня и первых секунд игры. Мы вместо этого
|
||||
* ДОСИЖИВАЛИ трек на чёрном экране (27 — 10,7 с против 2,6 с картинки),
|
||||
* то есть дарили игроку восемь секунд пустого экрана, и только потом
|
||||
* глушили. ЗАМЕР 2026-08-28: снято вместе с глушением на загрузке
|
||||
* уровня; если загрузка не укладывается в дедлайн насоса (251 000
|
||||
* тактов), вернуть оба места разом.
|
||||
*
|
||||
* Пропуск сцены по-прежнему обрывает и музыку: игрок нажал клавишу,
|
||||
* чтобы идти дальше, а не чтобы дослушать. */
|
||||
if (aborted) {
|
||||
pop_music_free();
|
||||
pop_sfx_pause();
|
||||
}
|
||||
intro_restore_game_palette();
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "pop_ctrl.h" /* pop_ctrl_init/close — ввод поднимает и закрывает boot */
|
||||
#include "pop_shadow.h" /* запечённый набор Тени */
|
||||
#include "pop_sfx.h" /* звуковые эффекты через CBL */
|
||||
#include "pop_music.h" /* pop_music_busy/free — ждём трек заставки */
|
||||
#include "pop_vflip.h" /* сброс зеркальных страниц на смене уровня */
|
||||
#include "pop_cheat.h" /* pop_cheats — режим разработки включает pop_boot */
|
||||
#include "pop_pace.h" /* pop_speed_mode — режим скорости в отладочной метке */
|
||||
@@ -1227,7 +1228,10 @@ int pop_level_switch(void) __banked
|
||||
* дальше, а урон — нет (do_startpos дольёт до потолка). */
|
||||
hitp_beg_lev = hitp_max;
|
||||
pop_checkpoint = 0; /* уровень пройден (seg003:413) */
|
||||
pop_sfx_pause(); /* загрузка уровня — ESTEX надолго, звук глушим */
|
||||
/* ЗАМЕР 2026-08-28: глушение снято ВРЕМЕННО, чтобы измерить
|
||||
* зазоры насоса на загрузке уровня (дедлайн 251 000 тактов).
|
||||
* Если зазоры укладываются — снятие остаётся, и трек заставки
|
||||
* доигрывает поверх загрузки, как в оригинале (seg001:690). */
|
||||
if (pop_level_load_num(pop_next_level) != 0) {
|
||||
pop_next_level = pop_current_level; /* файла нет — остаёмся */
|
||||
} else {
|
||||
@@ -1294,6 +1298,34 @@ int pop_level_switch(void) __banked
|
||||
/* Атомарный commit на границе растра: впервые показать
|
||||
* готовую комнату уже с окончательной палитрой уровня.
|
||||
* Вторую страницу синхронизировать аппаратной копией. */
|
||||
/* ЖДЁМ КОНЦА ТРЕКА ЗАСТАВКИ НА ЧЁРНОМ ЭКРАНЕ — порт
|
||||
* seg003:107:
|
||||
* while (check_sound_playing() && !do_paused()) idle();
|
||||
* stop_sounds();
|
||||
* draw_level_first();
|
||||
* Порядок оригинала важен: загрузка уровня идёт ПОД
|
||||
* звучащий трек, и только потом чернота до его конца. Тогда
|
||||
* общее время черноты = max(трек, загрузка), а не их сумма,
|
||||
* и трек не обрывается на полуслове. Раньше у нас было
|
||||
* наоборот: pre_cut_finish досиживал трек, потом глушил
|
||||
* насос и грузил уровень.
|
||||
*
|
||||
* ЗАМЕР 2026-08-28: 500 подряд вызовов насоса через всю
|
||||
* загрузку — максимальный зазор 245 832 такта при дедлайне
|
||||
* 251 000, ни одной пропущенной порции. Поэтому глушение на
|
||||
* загрузке снято и музыка её переживает.
|
||||
*
|
||||
* Счётчик — страховка от вечного ожидания (потоковый трек,
|
||||
* который никогда не кончится): ~20 с и идём дальше. */
|
||||
{
|
||||
uint16_t mus_guard = 1000;
|
||||
|
||||
while (pop_music_busy() && mus_guard) {
|
||||
mus_guard--;
|
||||
pop_wait_edge();
|
||||
}
|
||||
pop_music_free(); /* порт stop_sounds() */
|
||||
}
|
||||
pop_wait_edge();
|
||||
gfx_set_visible_page(level_prepared_page);
|
||||
gfx_set_draw_page(old_page);
|
||||
|
||||
Reference in New Issue
Block a user