Разгрузка W1: смена уровня и служебный слой — в банк 8
_main занимал 3658 байт резидента, и добрая половина этого — события «раз в партию». Вынесены целиком: - pop_level_change — смена уровня (катсцена, гашение, загрузка, палитра, звук): 61 строка, наружу осталось одно условие и вызов; - pop_frame_ui — меню, F10 и QuickSave/Load: 58 строк, плюс туда же уехали edge-состояния клавиш и сами коды клавиш (снаружи они больше не нужны). _CODE 24102 -> 23626, запас W2 вырос с 86 до 559 байт. Заодно три правки по замечаниям: - затемнение фона под меню считалось числом «2», а шкала ступеней выросла с 4 до 32 — фон почти не гас. Теперь доля от шкалы (POP_PAL_DIM_BLACK/2); тем же прошлись по остаткам pop_pal_apply(4); - в катсценах персонажи появлялись только после fade in: первый кадр рисуется ПОД чёрной палитрой, и картинка проявляется целиком, вместе с актёрами (cut_scene_8/9/12_short/ending, pre_room_animated, intro_pv_animated); - отладочная полоса по умолчанию выключена. Host-тесты: 15 наборов. Проверено в MAME: меню открывается и закрывается, фон под ним затемнён, полосы нет. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -128,11 +128,6 @@ static void kbd_idle(void)
|
||||
#define SEQ_STAND 2
|
||||
#define ROOM_1 1
|
||||
#define LINK_DOWN 3 /* сторона links: 0=L,1=R,2=U,3=D */
|
||||
#define KBD_QUICKSAVE 0x0B /* F6, PS/2 set 2 */
|
||||
#define KBD_QUICKLOAD 0x01 /* F9, PS/2 set 2 */
|
||||
#define KBD_MENU 0x76 /* Esc — открыть pause menu (edge) */
|
||||
#define KBD_QUIT 0x09 /* F10 — отладочный немедленный выход (был на Esc,
|
||||
* пока меню не готово рисовать — см. план MS4) */
|
||||
|
||||
|
||||
/* ОТЛАДОЧНЫЙ ОБХОД КОМНАТ: '+'/'-' (цифровой блок либо '='/'-' основного
|
||||
@@ -417,63 +412,20 @@ int main(void)
|
||||
* QuickSave/QuickLoad идут тем же механизмом, что F6/F9 (запрос
|
||||
* подхватит блок ниже в этой же границе кадра), рестарты исполняются
|
||||
* после вычисления back-страницы (как респавн), QUIT рвёт цикл. */
|
||||
/* Меню, F10 и QuickSave/Load — целиком в банке 8 (pop_frame_ui).
|
||||
* Всё это события «раз в партию», а кода на них было полсотни строк
|
||||
* в резиденте; наружу остаются флаги, которые нужны самому циклу. */
|
||||
if (!is_demo) {
|
||||
uint8_t e = kbd_raw_down(KBD_MENU);
|
||||
uint8_t menu_opened;
|
||||
int8_t mrc = POP_MENU_NONE;
|
||||
if (e && !esc_prev) pop_menu_request = 1;
|
||||
esc_prev = e;
|
||||
menu_opened = pop_menu_request;
|
||||
if (menu_opened) {
|
||||
if (!pop_app_dispatch(POP_APP_EV_PAUSE)) {
|
||||
failed = 1; quit = 1; break;
|
||||
}
|
||||
mrc = pop_menu_process();
|
||||
}
|
||||
if (mrc == POP_MENU_QUICKSAVE) pop_qsave_request_save();
|
||||
else if (mrc == POP_MENU_QUICKLOAD) pop_qsave_request_load();
|
||||
else if (mrc == POP_MENU_QUICKLOAD_BACKUP)
|
||||
pop_qsave_request_load_backup();
|
||||
else if (mrc == POP_MENU_RESTART_LEVEL) menu_restart = 1;
|
||||
else if (mrc == POP_MENU_RESTART_GAME) {
|
||||
if (!pop_app_dispatch(POP_APP_EV_RESTART_INTRO)) failed = 1;
|
||||
uint8_t want_restart = 0, dead_reset = 0;
|
||||
int8_t urc = pop_frame_ui(&want_restart, &dead_reset);
|
||||
|
||||
if (want_restart) menu_restart = 1;
|
||||
if (dead_reset) dead_frames = 0;
|
||||
if (urc) {
|
||||
if (urc < 0) failed = 1;
|
||||
if (urc != 1) quit = 1; /* 1 — restart game, без quit */
|
||||
break;
|
||||
}
|
||||
else if (mrc == POP_MENU_QUIT) {
|
||||
if (!pop_app_dispatch(POP_APP_EV_QUIT)) failed = 1;
|
||||
quit = 1;
|
||||
break;
|
||||
}
|
||||
if (menu_opened) {
|
||||
/* Меню переписало обе страницы целиком. Снимки слотов об
|
||||
* этом не знают и продолжают считать, что персонаж на
|
||||
* странице уже нарисован, — стоящий Кид оставался бы
|
||||
* невидимым до первого своего движения. */
|
||||
pop_cd_forget();
|
||||
pop_status_invalidate();
|
||||
if (!pop_app_dispatch(POP_APP_EV_RESUME)) {
|
||||
failed = 1; quit = 1; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* F10 — отладочный немедленный выход (раньше был на Esc, но Esc
|
||||
* теперь открывает меню; уйдёт вместе с отладкой). */
|
||||
if (!is_demo && kbd_raw_down(KBD_QUIT)) {
|
||||
if (!pop_app_dispatch(POP_APP_EV_QUIT)) failed = 1;
|
||||
quit = 1;
|
||||
break;
|
||||
}
|
||||
/* F6/F9 только ставят запрос; файловая операция выполняется здесь,
|
||||
* на границе кадров — вне окон Char и до heal/tick/draw. */
|
||||
if (!is_demo) {
|
||||
uint8_t s = kbd_raw_down(KBD_QUICKSAVE);
|
||||
uint8_t l = kbd_raw_down(KBD_QUICKLOAD);
|
||||
int8_t qrc;
|
||||
if (s && !qs_save_prev) pop_qsave_request_save();
|
||||
if (l && !qs_load_prev) pop_qsave_request_load();
|
||||
qs_save_prev = s; qs_load_prev = l;
|
||||
qrc = pop_qsave_process();
|
||||
if (qrc > 0) dead_frames = 0;
|
||||
}
|
||||
if (frozen) {
|
||||
PROF(0); /* чёрный: ждём vsync */
|
||||
@@ -761,66 +713,12 @@ int main(void)
|
||||
* или доиграли запись — показать текущий кадр и затем вернуться в
|
||||
* title. В частности, не вызываем level_switch(0->1). */
|
||||
if (is_demo && (kid_room == 24 || pop_kid_dead)) demo_finished = 1;
|
||||
if (!is_demo && pop_next_level != pop_current_level) {
|
||||
pop_pre_cutscene_t pre = pop_flow_pre_cutscene(pop_next_level,
|
||||
pop_timer_minutes);
|
||||
/* Смена уровня целиком — в банке (pop_level_switch): грузится
|
||||
* файл, спрайты соперника и тайлсет. До 2/4/6/8/9/12 таблица
|
||||
* flow запускает отдельное состояние CUTSCENE, как play_level()
|
||||
* SDLPoP: следующий уровень не трогаем до завершения/skip. */
|
||||
if (pre != POP_PRE_NONE) {
|
||||
if (!pop_app_dispatch(POP_APP_EV_CUTSCENE_STARTED)) {
|
||||
failed = 1;
|
||||
quit = 1;
|
||||
break;
|
||||
}
|
||||
pop_pre_cutscene_show(pre);
|
||||
if (!pop_app_dispatch(POP_APP_EV_CUTSCENE_FINISHED)) {
|
||||
failed = 1;
|
||||
quit = 1;
|
||||
break;
|
||||
}
|
||||
/* Катсцена оставляет экран чёрным. Новый уровень будет
|
||||
* открыт одним применением его готовой палитры. */
|
||||
reveal_pending = 1;
|
||||
} else {
|
||||
/* CBL глушим ДО первой же операции с палитрой. Палитра идёт
|
||||
* через BIOS ($A4) с запрещёнными прерываниями: насос не
|
||||
* успевает долить блок, железо крутит хвост своего буфера —
|
||||
* на слух скрежет. Раньше pop_sfx_pause() звался только
|
||||
* внутри pop_level_switch, то есть УЖЕ ПОСЛЕ гашения, и
|
||||
* переход без катсцены (в т.ч. телепорт Shift+L) скрежетал
|
||||
* почти всегда — поймано пользователем 2026-08-25. Ветка с
|
||||
* катсценой свободна от этого: pop_pre_cutscene_show глушит
|
||||
* звук первым действием. */
|
||||
pop_sfx_pause();
|
||||
/* Без fade: старый кадр гасим сразу и обязательно даём
|
||||
* показать один чёрный растр ДО диска/перерисовки. */
|
||||
pop_pal_apply(4);
|
||||
pop_wait_edge();
|
||||
reveal_pending = 1;
|
||||
if (!pop_app_dispatch(POP_APP_EV_LEVEL_FINISHED)) {
|
||||
failed = 1;
|
||||
quit = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pop_level_switch() != 0 ||
|
||||
!pop_app_dispatch(POP_APP_EV_LEVEL_READY)) {
|
||||
failed = 1;
|
||||
quit = 1;
|
||||
break;
|
||||
}
|
||||
if (reveal_pending) {
|
||||
/* Обе страницы и snapshot уже принадлежат новому уровню:
|
||||
* включить его корректную палитру одним переходом. */
|
||||
pop_pal_apply(0);
|
||||
reveal_pending = 0;
|
||||
}
|
||||
/* level_switch оставляет CBL закрытым: palette/fade идут через
|
||||
* BIOS и при открытом буфере давали скрежет на первом кадре. */
|
||||
(void)pop_sfx_start();
|
||||
gfx_set_draw_page(back);
|
||||
/* Смена уровня целиком уехала в банк 8 (pop_level_change): это
|
||||
* событие раз в несколько минут, а кода на нём было под сотню строк
|
||||
* в самом горячем месте программы — резидент W1 у нас в дефиците. */
|
||||
if (!is_demo && pop_next_level != pop_current_level &&
|
||||
pop_level_change(back) != 0) {
|
||||
failed = 1; quit = 1; break;
|
||||
}
|
||||
if (!is_demo && pop_kid_dead) { /* demo после смерти завершается, без respawn */
|
||||
dead_frames++;
|
||||
|
||||
Reference in New Issue
Block a user