SprPoP: заставка и музыка сразу после запуска, а не через несколько секунд
От запуска до проявления титула проходило ~3 с чёрного экрана в тишине: pop_boot читал ВСЕ ресурсы игры до первого пикселя, а pop_title_show перед fade_in вычитывал целиком трек заставки (248 КБ). Старт разбит на три фазы (sprpop_cold.c): - pop_boot() — настройки, POP.CFG, графика, чёрный экран, FONT.ATL; - pop_boot_sound() — snd.idx + ОДНА страница snd.arc, индекс музыки, CBL; - pop_boot_rest() — остальные страницы звука, kid.ani, Тень, атласы Кида; идемпотентно, между кусками доливает трек. pop_title_show теперь: fade_in -> pop_boot_sound -> pop_music_stream(54) -> pop_boot_rest под стоящим титулом. Порядок «сначала fade_in, потом тема» сохранён как у show_title (seg000.c:1981). Первый такт заставки укорочен на фактически потраченное время (часы насоса 85,4 Гц -> кадры луча сдвигами), иначе сцена уехала бы относительно музыки. title_wait доливает трек по полстраницы за кадр. Музыка играет с ПЕРВОЙ страницы: pop_music_stream уже был (игровые джинглы), кольцо won не понадобилось — m54 это 16 страниц из 20 доступных. Звук поднимается в два приёма (pop_sfx_init_begin/finish): насосу для тишины нужен ровно один блок, и упаковщик обязан класть его первым блоком страницы 0 (tools/pop_idx.py) — значит для открытия CBL хватает ОДНОЙ страницы (33 мс вместо 440). Пока набор неполон, pop_sfx_play пропускает эффекты; заявки на музыку проходят. Четыре загрузки из boot УБРАНЫ, а не отложены: атлас фона, страж, уровень 1 и pop_pal_game_load — их и так делает pop_level_switch на входе в любой уровень (а pop_new_game_load ещё и палитру перед ним), и оба маршрута в игру, LEVEL_LOAD и DEMO, упираются в него. Это ~0,77 с на ровном месте. Так же устроен оригинал: init_game_main до заставки читает только меч, пламя, звуки и палитры, а chtab_5/6/7 грузит load_lev_spr на старте уровня. Страховка на случай пропуска заставки в первую секунду — идемпотентный pop_boot_rest() в начале pop_new_game_load и pop_level_switch. FONT.ATL остаётся в минимальной фазе, и это не про шрифт: снимок палитры физически лежит в хвосте его страницы (pop_ui.c), а вся машинерия яркости начинается с `if (!font_ready) return`. С отложенным шрифтом заставка возникала разом на полной яркости — поймано пользователем. Проверено в MAME: титул виден сразу и проявляется полосами, pop_mus_left убывает (трек стримится), pop_snd_pages=10 (набор дочитался), цепочка титул -> интро -> пропуск -> уровень 1 работает. Банк 8: 95,5 % (732 Б). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DSYUpuaQpKr48kBav2iiV4
This commit is contained in:
@@ -18,6 +18,11 @@
|
||||
#include <sprite.h> /* gfx_w0_map — залить блок тишины */
|
||||
|
||||
static uint8_t snd_blk; /* блок EMM под весь набор */
|
||||
/* Раздельная загрузка (см. шапку pop_sfx.h): сколько страниц обещал индекс
|
||||
* и сколько уже прочитано. 0 в want — begin не проходил либо поднялась
|
||||
* только страница тишины (набора нет), и дочитывать нечего. */
|
||||
static uint8_t snd_want_pages;
|
||||
static uint8_t snd_done_pages;
|
||||
|
||||
/* --- ИНДЕКС НАБОРА (SND/snd.idx, формат PSI1) ----------------------- *
|
||||
*
|
||||
@@ -142,11 +147,13 @@ static int8_t snd_silence_only(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pop_sfx_init(void) __banked
|
||||
/* ПЕРВАЯ ПОЛОВИНА: индекс + страница 0 (в ней блок тишины). После неё
|
||||
* звук можно открывать, и музыка играет; эффекты — после finish. */
|
||||
int pop_sfx_init_begin(void) __banked
|
||||
{
|
||||
uint8_t i, blk, pages;
|
||||
uint8_t blk, pages;
|
||||
|
||||
if (pop_snd_ok) return 0;
|
||||
if (snd_blk) return 0; /* набор уже поднимали */
|
||||
|
||||
/* СНАЧАЛА ИНДЕКС, ПОТОМ ДАННЫЕ: сколько страниц читать и куда какой
|
||||
* эффект лёг — знает только он. Набора без индекса не бывает:
|
||||
@@ -179,24 +186,58 @@ int pop_sfx_init(void) __banked
|
||||
if (pop_arc_open_id(&arc, POP_ARC_SND, tbl, POP_SND_MAX_PAGES) !=
|
||||
(int8_t)pages)
|
||||
return -1;
|
||||
/* Блок выделяем СРАЗУ на весь набор: номера страниц отдаёт
|
||||
* mem_get_page по индексу, и finish дочитает в те же самые. */
|
||||
blk = mem_alloc_pages(pages);
|
||||
if (!blk) { pop_arc_close(&arc); return -1; }
|
||||
for (i = 0; i < pages; i++) {
|
||||
pop_snd_page[i] = mem_get_page(blk, i);
|
||||
if (!pop_snd_page[i] ||
|
||||
pop_arc_read(&arc, tbl, i, 0, pop_snd_page[i], 0, 0) != 16384) {
|
||||
pop_arc_close(&arc);
|
||||
mem_free_block(blk);
|
||||
return -1;
|
||||
}
|
||||
pop_snd_page[POP_SND_SILENCE_PAGE] = mem_get_page(blk, 0);
|
||||
if (!pop_snd_page[POP_SND_SILENCE_PAGE] ||
|
||||
pop_arc_read(&arc, tbl, 0, 0,
|
||||
pop_snd_page[POP_SND_SILENCE_PAGE], 0, 0) != 16384) {
|
||||
pop_arc_close(&arc);
|
||||
mem_free_block(blk);
|
||||
return -1;
|
||||
}
|
||||
pop_arc_close(&arc);
|
||||
}
|
||||
snd_blk = blk;
|
||||
snd_want_pages = pages;
|
||||
snd_done_pages = 1;
|
||||
/* pop_snd_pages НЕ ставим: набор ещё неполон, и до finish эффекты
|
||||
* запускать нельзя (страницы выделены, но не прочитаны). */
|
||||
pop_snd_want = 1; /* набор есть — звук по умолчанию включён */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ВТОРАЯ ПОЛОВИНА: дочитать остальные страницы и разрешить эффекты.
|
||||
* Идемпотентна; архив открывается второй раз (51 мс) — это дешевле, чем
|
||||
* держать открытый манипулятор через всю заставку при лимите в восемь. */
|
||||
int pop_sfx_init_finish(void) __banked
|
||||
{
|
||||
pop_arc_t arc;
|
||||
uint8_t tbl[POP_SND_MAX_PAGES * POP_ARC_REC];
|
||||
uint8_t i;
|
||||
|
||||
if (pop_snd_pages) return 0; /* набор уже полный */
|
||||
if (!snd_want_pages) return -1; /* begin не проходил либо только тишина */
|
||||
if (snd_done_pages < snd_want_pages) {
|
||||
if (pop_arc_open_id(&arc, POP_ARC_SND, tbl, POP_SND_MAX_PAGES) !=
|
||||
(int8_t)snd_want_pages)
|
||||
return -1;
|
||||
for (i = snd_done_pages; i < snd_want_pages; i++) {
|
||||
pop_snd_page[i] = mem_get_page(snd_blk, i);
|
||||
if (!pop_snd_page[i] ||
|
||||
pop_arc_read(&arc, tbl, i, 0, pop_snd_page[i], 0, 0) != 16384) {
|
||||
pop_arc_close(&arc);
|
||||
return -1; /* страницы не отдаём: тишина в стр.0 жива */
|
||||
}
|
||||
snd_done_pages = (uint8_t)(i + 1);
|
||||
}
|
||||
pop_arc_close(&arc);
|
||||
}
|
||||
/* Число страниц ставим ПОСЛЕДНИМ: до этого момента насос обязан
|
||||
* видеть 0 и не пытаться ходить по полузаполненной таблице. */
|
||||
pop_snd_pages = pages;
|
||||
pop_snd_want = 1; /* набор есть — звук по умолчанию включён */
|
||||
pop_snd_pages = snd_want_pages;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user