SprPoP: единые часы в сцене с Джафаром + конец уровня ждёт свою мелодию
1. СЦЕНА С ДЖАФАРОМ — ОДНИ ЧАСЫ, КАДРЫ ЛУЧА. Было две шкалы, и выбор между ними делался гонкой на старте сцены: одна выборка pop_snd_tick через кадр, «успел ли диск раскрутить звук». От прогона к прогону сцена шла то по тикам насоса CBL, то по кадрам луча, и кода реплики приходилась каждый раз на другое место картинки (наблюдение пользователя). Насос был нужен потому, что кадр рисовался дольше своего интервала; теперь отрисовка разложена по интервалам (pv_restore_bg), и счёт кадров честен — ветка насоса убрана целиком. 2. ПОДКАЧКА ТРЕКА — ПОЛСТРАНИЦЫ ЗА ШАГ (pop_music_load_step). 8 КБ ≈ 16 мс влезают в кадровый интервал, целая страница (33 мс) не влезала и растягивала кадр сцены. В сцене шаг остаётся безусловным (иначе реплики не успевали грузиться, memory pv_music_stall_regression) и оплачивается ровно одним интервалом. 3. КОНЕЦ УРОВНЯ ЖДЁТ МЕЛОДИЮ. Оригинал (seg003:387, play_level_2) не сменяет уровень, пока `check_sound_playing()`: экран пройденного уровня живёт с анимацией факелов, пока звучит трек. Мы уходили на смену сразу и обрывали мелодию на первых нотах. Теперь ждём большего из двух: pop_music_busy() и счётчика pop_endmus_left по длине записи (gen/pop_music_ticks.h) — второе нужно потому, что при ВЫКЛЮЧЕННОЙ музыке busy ложен, а оригинал выдерживает паузу и молча. Стартовый уровень возвращён на 1 (отладочный LEVEL=14 был только для замера). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -49,6 +49,7 @@ static uint8_t ld_busy;
|
||||
static int ld_fd;
|
||||
static uint8_t ld_slot;
|
||||
static uint8_t ld_next; /* следующая страница к чтению */
|
||||
static uint8_t ld_half; /* 0 = впереди первая половина страницы */
|
||||
static uint8_t ld_pages;
|
||||
static uint8_t ld_id;
|
||||
|
||||
@@ -110,13 +111,14 @@ void pop_music_free(void) __banked
|
||||
* ПОСТРАНИЧНО, А НЕ ЦЕЛИКОМ. Реплики сцены с принцессой идут встык, и
|
||||
* следующую надо читать, пока звучит текущая. Трек — до 320 КБ, целиком
|
||||
* это 0,7 с диска: на 7,5 кадрах в секунду сцена встала бы на пять кадров.
|
||||
* Одна страница стоит 33 мс — меньше четверти кадра, и подкачка растворя-
|
||||
* ется в анимации. Кто может позволить себе паузу (титры, чёрный экран
|
||||
* Шаг стоит 16 мс (полстраницы, см. pop_music_load_step) — меньше одного
|
||||
* кадрового интервала, и подкачка растворяется в анимации. Кто может позволить себе паузу (титры, чёрный экран
|
||||
* между сценами), зовёт pop_music_load — тот же цикл, но целиком. */
|
||||
static void load_abort(void)
|
||||
{
|
||||
if (ld_busy) close(ld_fd);
|
||||
ld_busy = 0;
|
||||
ld_half = 0;
|
||||
slot_release(ld_slot);
|
||||
}
|
||||
|
||||
@@ -146,23 +148,35 @@ int8_t pop_music_load_begin(uint8_t id) __banked
|
||||
ld_busy = 1;
|
||||
ld_slot = n;
|
||||
ld_next = 0;
|
||||
ld_half = 0;
|
||||
ld_pages = pages;
|
||||
ld_id = id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ШАГ = ПОЛСТРАНИЦЫ (8 КБ, ~16 мс), а не страница (~33 мс).
|
||||
*
|
||||
* Шаг вызывают раз в кадр из циклов, где кадр разложен на блоки по одному
|
||||
* кадровому интервалу (20 мс): катсцены после перехода на блочную
|
||||
* отрисовку, см. pop_intro.c/pv_restore_bg. Целая страница в интервал не
|
||||
* влезала и незаметно растягивала кадр сцены; половина влезает, а цена —
|
||||
* вдвое больше вызовов (11 страниц реплики = 22 кадра вместо 11, то есть
|
||||
* меньше полусекунды). Игровому циклу это безразлично: там логический
|
||||
* кадр 80-100 мс. */
|
||||
int8_t pop_music_load_step(void) __banked
|
||||
{
|
||||
uint8_t p;
|
||||
|
||||
if (!ld_busy) return 1; /* нечего грузить */
|
||||
p = mem_get_page(slot_blk[ld_slot], ld_next);
|
||||
/* Последняя страница короче — читаем сколько есть; ошибку ловим по
|
||||
* отрицательному коду, а не по «не 16384». */
|
||||
if (!p || bank_read_page(ld_fd, p, 0, 16384) < 0) {
|
||||
/* Последняя страница короче — читаем сколько есть (вторая половина
|
||||
* может дать и ноль байт); ошибку ловим по отрицательному коду. */
|
||||
if (!p || bank_read_page(ld_fd, p, ld_half ? 8192 : 0, 8192) < 0) {
|
||||
load_abort();
|
||||
return -1;
|
||||
}
|
||||
if (!ld_half) { ld_half = 1; return 0; } /* дочитаем в следующий раз */
|
||||
ld_half = 0;
|
||||
if (++ld_next < ld_pages) return 0;
|
||||
|
||||
close(ld_fd);
|
||||
|
||||
Reference in New Issue
Block a user