SprPoP: заставку можно прервать в любой её точке, F10 — выход
Три места, где нажатие раньше не работало или работало наполовину. FADE. fade_run() был замкнутым циклом на 2,13 с без опроса клавиш, а на стыке экранов их два: пропуск работал внутри сценария, но не между его шагами, и заставка ощущалась невыключаемой. Добавлены прерываемые варианты (pop_ui_fade_*_skip, обёртки в pop_pal) — отдельными функциями, а не флагом в прежних: в меню паузы и на переходе уровня прерывать нечего, и менять там поведение молча не следует. Прерванный fade всё равно доводит палитру до конца, экран не остаётся на промежуточной ступени. Подключено в интерпретаторе сценария, сцене с принцессой, четырёх катсценах cut_*, титрах и таблице рекордов. ПРОЯВЛЕНИЕ ПОЛОСАМИ. pop_screen_present_ltr() была void и нажатие ГЛОТАЛА: полосы схлопывались, картинка появлялась целиком — и всё, вызывающий о нажатии не узнавал. На заставке это выглядело как «клавиша срабатывает наполовину». Теперь возвращает признак прерывания, и он проброшен по маршруту: первый экран истории, титры финала, логотип между «свадьбой» и титрами. Везде считается КРОМКА нажатия от входа, как в сценах: клавиша, которой закончили предыдущий экран, ещё зажата, и принимать её за новое нажатие нельзя — иначе весь маршрут заставки схлопывался бы сам собой. F10 — НЕМЕДЛЕННЫЙ ВЫХОД, откуда угодно. Проверка стоит в kbd_idle(), а этот хук висит на gfx_wait_vsync, то есть вызывается везде, где программа ждёт кадр: заставка, титры, fade, проявление полосами, меню, игра. Одна точка вместо десятка по циклам ожидания. Флаг pop_quit_req резидентный — взводится и читается без трамплина из любого банка. Проверка в НАЧАЛЕ витка автомата обязательна: заставку прерывает любая клавиша, и без неё F10 успевал уронить программу в загрузку уровня перед закрытием. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -910,7 +910,10 @@ static int intro_pv_animated(void)
|
||||
if (pop_music_loading()) (void)pop_music_load_step();
|
||||
/* Первый кадр собран под чёрной палитрой — теперь проявляем его
|
||||
* целиком, вместе с принцессой и факелами. */
|
||||
if (!faded_in) { faded_in = 1; pop_pal_fade_in(INTRO_FADE); }
|
||||
if (!faded_in) {
|
||||
faded_in = 1;
|
||||
if (pop_pal_fade_in_skip(INTRO_FADE)) { result = 1; break; }
|
||||
}
|
||||
/* ПЕЙСИНГ ПО ОРИГИНАЛЬНОЙ ШКАЛЕ. Кадр cutscene — 6/8/7 тиков по
|
||||
* 1/60 с; один тик = 85,4/60 = 1,424 тика насоса, и 57/40 = 1,425
|
||||
* повторяет это с точностью 0,07 % (30 мс на всю сцену) без
|
||||
@@ -952,7 +955,7 @@ static int intro_pv_animated(void)
|
||||
* экране «свадьбы» (seg000:2051). Глушит вызывающий, когда музыка
|
||||
* действительно доиграла. */
|
||||
if (result) { pop_music_free(); pop_sfx_pause(); }
|
||||
if (!result) pop_pal_fade_out(INTRO_FADE);
|
||||
if (!result) (void)pop_pal_fade_out_skip(INTRO_FADE);
|
||||
|
||||
atlas_free(&torch);
|
||||
atlas_free(&hourglass);
|
||||
@@ -1050,7 +1053,7 @@ static int pre_room_animated(uint8_t picture, uint8_t state, uint8_t frames)
|
||||
|
||||
/* Проявляем ПОСЛЕ первого кадра: иначе две секунды fade идут по
|
||||
* пустой комнате, а часы и пламя возникают уже на свету. */
|
||||
if (frame == 0) pop_pal_fade_in(INTRO_FADE);
|
||||
if (frame == 0 && pop_pal_fade_in_skip(INTRO_FADE)) { result = 1; break; }
|
||||
torch_left = (uint8_t)((torch_left + 1) % 9);
|
||||
torch_right = (uint8_t)((torch_right + 1) % 9);
|
||||
sand = (uint8_t)((sand + 1) % 3);
|
||||
@@ -1383,7 +1386,7 @@ static uint8_t cut_aborted;
|
||||
static void cut_end(uint8_t aborted)
|
||||
{
|
||||
cut_aborted = aborted;
|
||||
if (!aborted) pop_pal_fade_out(INTRO_FADE);
|
||||
if (!aborted && pop_pal_fade_out_skip(INTRO_FADE)) cut_aborted = 1;
|
||||
cut_free();
|
||||
}
|
||||
|
||||
@@ -1403,7 +1406,7 @@ static int cut_scene_8(void)
|
||||
* первым кадром цикла. Рисуем его при ещё чёрной палитре — тогда
|
||||
* картинка проявляется целиком, вместе с актёрами. */
|
||||
aborted = cut_run(1, 1);
|
||||
if (!aborted) pop_pal_fade_in(INTRO_FADE);
|
||||
if (!aborted) aborted = pop_pal_fade_in_skip(INTRO_FADE);
|
||||
if (!aborted) aborted = cut_run(19, 1);
|
||||
if (!aborted) {
|
||||
cut_kid_seq(107); /* мышь встаёт и уходит */
|
||||
@@ -1432,7 +1435,7 @@ static int cut_scene_9(void)
|
||||
* первым кадром цикла. Рисуем его при ещё чёрной палитре — тогда
|
||||
* картинка проявляется целиком, вместе с актёрами. */
|
||||
aborted = cut_run(1, 0); /* мышь ещё за кадром */
|
||||
if (!aborted) pop_pal_fade_in(INTRO_FADE);
|
||||
if (!aborted) aborted = pop_pal_fade_in_skip(INTRO_FADE);
|
||||
/* init_mouse_go (seg001:022A): мышь вбегает справа. */
|
||||
cut_kid_init(CHARID_24_MOUSE, 199, 167, 105);
|
||||
if (!aborted) aborted = cut_run(5, 1);
|
||||
@@ -1464,7 +1467,7 @@ static int cut_scene_12_short(void)
|
||||
* первым кадром цикла. Рисуем его при ещё чёрной палитре — тогда
|
||||
* картинка проявляется целиком, вместе с актёрами. */
|
||||
aborted = cut_run(1, 0);
|
||||
if (!aborted) pop_pal_fade_in(INTRO_FADE);
|
||||
if (!aborted) aborted = pop_pal_fade_in_skip(INTRO_FADE);
|
||||
if (!aborted) aborted = cut_run(1, 0);
|
||||
if (!aborted) {
|
||||
cut_shad_seq(98); /* princess turn around [PV1] */
|
||||
@@ -1492,7 +1495,7 @@ static int cut_ending(void)
|
||||
* первым кадром цикла. Рисуем его при ещё чёрной палитре — тогда
|
||||
* картинка проявляется целиком, вместе с актёрами. */
|
||||
aborted = cut_run(1, 1);
|
||||
if (!aborted) pop_pal_fade_in(INTRO_FADE);
|
||||
if (!aborted) aborted = pop_pal_fade_in_skip(INTRO_FADE);
|
||||
pop_sfx_play(26); /* «arrived to princess» */
|
||||
if (!aborted) aborted = cut_run(7, 1);
|
||||
if (!aborted) {
|
||||
@@ -1547,8 +1550,17 @@ static uint8_t intro_run(const pop_cs_cmd_t *script)
|
||||
aborted = 1;
|
||||
break;
|
||||
}
|
||||
} else if (ev == POP_CS_EVENT_FADE_IN) pop_pal_fade_in(INTRO_FADE);
|
||||
else if (ev == POP_CS_EVENT_FADE_OUT) pop_pal_fade_out(INTRO_FADE);
|
||||
} else if (ev == POP_CS_EVENT_FADE_IN || ev == POP_CS_EVENT_FADE_OUT) {
|
||||
/* Fade — 2,13 с, и на стыке экранов их два. Пока он был глухим,
|
||||
* эти секунды не пропускались ничем: пропуск работал внутри
|
||||
* сценария, но не между его шагами. Прерывание здесь означает
|
||||
* то же, что и в самом сценарии — уйти из заставки. */
|
||||
uint8_t cut = (ev == POP_CS_EVENT_FADE_IN)
|
||||
? pop_pal_fade_in_skip(INTRO_FADE)
|
||||
: pop_pal_fade_out_skip(INTRO_FADE);
|
||||
|
||||
if (cut) { pop_cutscene_abort(&cs); aborted = 1; break; }
|
||||
}
|
||||
else if (ev == POP_CS_EVENT_FLASH) intro_flash(arg);
|
||||
pop_music_service(); /* подкачка потокового трека (финал) */
|
||||
gfx_wait_vsync();
|
||||
@@ -1581,8 +1593,9 @@ static uint8_t intro_credits_ltr(void)
|
||||
{
|
||||
uint8_t page = pop_screen_begin();
|
||||
|
||||
if (intro_draw_page(INTRO_STORY_CREDITS, page) == 0)
|
||||
pop_screen_present_ltr();
|
||||
if (intro_draw_page(INTRO_STORY_CREDITS, page) == 0 &&
|
||||
pop_screen_present_ltr())
|
||||
return 1;
|
||||
return intro_wait_frames(POP_T60(0x168));
|
||||
}
|
||||
|
||||
@@ -1602,7 +1615,7 @@ uint8_t pop_intro_show(void) __banked
|
||||
pop_sfx_pause();
|
||||
intro_prepare_palette(INTRO_PAL_STORY);
|
||||
if (intro_draw_new_palette(INTRO_STORY_ABSENCE) == 0)
|
||||
pop_pal_fade_in(INTRO_FADE);
|
||||
(void)pop_pal_fade_in_skip(INTRO_FADE);
|
||||
} else {
|
||||
/* Картинка собрана и ждёт в скрытой странице; читаем следующую
|
||||
* реплику во ВТОРОЙ слот — тема титров при этом продолжает
|
||||
@@ -1618,7 +1631,13 @@ uint8_t pop_intro_show(void) __banked
|
||||
}
|
||||
(void)pop_sfx_start(); /* идемпотентно: титры его уже открыли */
|
||||
pop_music_play();
|
||||
pop_screen_present_ltr();
|
||||
/* Прервали проявление — это не «показать картинку разом», а «хватит
|
||||
* заставки»: маршрут тот же, что и у пропуска внутри сценария. */
|
||||
if (pop_screen_present_ltr()) {
|
||||
pop_music_free();
|
||||
pop_sfx_pause();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (intro_run(intro_before_pv)) {
|
||||
/* Пропуск по клавише. ГЛУШИМ ВЫВОД: сразу за возвратом пойдёт
|
||||
@@ -1678,9 +1697,13 @@ uint8_t pop_intro_show(void) __banked
|
||||
* TITLE_MAIN + логотип + Jordan Mechner и проявляет их полосами
|
||||
* (seg000:2045), и только через 0x78 тиков показывает credits — тоже
|
||||
* полосами. Раньше обе картинки возникали мгновенно. */
|
||||
if (pop_title_logo_ltr() == 0 && intro_wait_frames(POP_T60(0x78))) {
|
||||
intro_restore_game_palette();
|
||||
return 1;
|
||||
{
|
||||
int shown = pop_title_logo_ltr(); /* 1 — прервано, -1 — нет архива */
|
||||
|
||||
if (shown == 1 || (shown == 0 && intro_wait_frames(POP_T60(0x78)))) {
|
||||
intro_restore_game_palette();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (intro_credits_ltr()) {
|
||||
intro_restore_game_palette();
|
||||
|
||||
Reference in New Issue
Block a user