Статус-строка: LEVEL N и лейбл QS/QL до дисковой операции
* pop_status_level() — порт show_level (seg008:25A8): «LEVEL N» на старте уровня. Демо-уровень 0 и номера от 14 молчат, тринадцатый показывается двенадцатым, бесшовный переход 12->13 пропускается и гасит флаг за собой. Первое сообщение с ПАРАМЕТРОМ: строка собирается вручную (dec2, без printf и без деления), номер хранится снимком st_arg — иначе вторая страница дабл-буфера нарисовала бы другое число. * pop_status_show_now() — печать немедленно, в ВИДИМУЮ страницу. QuickSave/QuickLoad заявляют лейбл ПЕРВЫМ действием, до mem_alloc/ESTEX: запись снимка занимает доли секунды, и раньше игрок видел сначала необъяснённый фриз, а надпись — уже после него. Отказ переписывает строку на NO QUICKSAVE/NO QUICKLOAD обычной заявкой. Расхождение с оригиналом (он печатает по результату) — impl_diff.md. Проверено в MAME: watchpoint ловит заявку внутри pop_status_show_now, step_out возвращает в pop_qsave_process — и QUICKSAVE уже на экране, диск ещё не тронут. Бюджет прежний: _CODE 23981, куча 266 Б. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -58,6 +58,7 @@
|
||||
#define MSG_TOP (MSG_BASE - POP_FONT_BIG_ASCENT - 2)
|
||||
#define MSG_BOTTOM (MSG_BASE)
|
||||
|
||||
/* POP_MSG_LEVEL здесь пустой: его строка собирается с номером уровня. */
|
||||
static const char * const status_text[POP_MSG_N] = {
|
||||
"",
|
||||
"QUICKSAVE",
|
||||
@@ -65,13 +66,15 @@ static const char * const status_text[POP_MSG_N] = {
|
||||
"QUICKLOAD",
|
||||
"NO QUICKLOAD",
|
||||
"SOUND ON",
|
||||
"SOUND OFF"
|
||||
"SOUND OFF",
|
||||
""
|
||||
};
|
||||
|
||||
uint8_t pop_status_msg; /* заявка (пишут откуда угодно) */
|
||||
uint8_t pop_status_ticks; /* сколько кадров ещё висит; читает HP */
|
||||
static uint8_t st_shown; /* что реально нарисовано */
|
||||
static uint8_t st_dirty; /* бит на страницу дабл-буфера */
|
||||
static uint8_t st_arg; /* номер уровня для POP_MSG_LEVEL */
|
||||
|
||||
/* ---- верхняя полоса: отладочная строка --------------------------------- *
|
||||
*
|
||||
@@ -151,17 +154,77 @@ static void dec2(uint8_t v, char *buf)
|
||||
|
||||
/* ---- нижняя полоса ----------------------------------------------------- */
|
||||
|
||||
/* «LEVEL N» собирается вручную: printf сюда не тянем, а номер — единственное
|
||||
* переменное место во всём наборе сообщений. */
|
||||
static void level_text(char *buf)
|
||||
{
|
||||
buf[0] = 'L'; buf[1] = 'E'; buf[2] = 'V'; buf[3] = 'E'; buf[4] = 'L';
|
||||
buf[5] = ' ';
|
||||
dec2(st_arg, buf + 6);
|
||||
}
|
||||
|
||||
static void status_draw(void)
|
||||
{
|
||||
char buf[9];
|
||||
const char *text;
|
||||
|
||||
wipe(POP_STATUS_L, MSG_TOP, POP_STATUS_R, MSG_BOTTOM);
|
||||
if (!st_shown) return;
|
||||
if (st_shown == POP_MSG_LEVEL) { level_text(buf); text = buf; }
|
||||
else { text = status_text[st_shown]; }
|
||||
gfx_set_bank(GFX_BANK_TRANSPARENT);
|
||||
pop_text_map();
|
||||
pop_text_center_mapped(POP_TEXT_BIG, (POP_STATUS_L + POP_STATUS_R) / 2,
|
||||
MSG_BASE, status_text[st_shown]);
|
||||
MSG_BASE, text);
|
||||
pop_text_unmap();
|
||||
}
|
||||
|
||||
/* Порт show_level (seg008:25A8). Демо-уровень 0 и номера от 14 не
|
||||
* показываются вовсе, тринадцатый представляется двенадцатым, а бесшовный
|
||||
* переход 12->13 молчит — и, как в оригинале, гасит флаг за собой. */
|
||||
void pop_status_level(void) __banked
|
||||
{
|
||||
uint8_t n = pop_current_level;
|
||||
uint8_t quiet = pop_seamless;
|
||||
|
||||
pop_seamless = 0;
|
||||
if (quiet || n == 0 || n >= POP_LEVEL_LAST) return;
|
||||
if (n == 13) n = 12;
|
||||
st_arg = n;
|
||||
pop_status_msg = POP_MSG_LEVEL;
|
||||
}
|
||||
|
||||
/* Показать сообщение НЕМЕДЛЕННО, не дожидаясь конца кадра.
|
||||
*
|
||||
* Обычный путь (заявка в pop_status_msg + pop_status_frame) печатает строку
|
||||
* там же, где рисуется кадр, — то есть уже ПОСЛЕ длинной операции. На
|
||||
* QuickSave это выглядело так: игра замирает на полсекунды, и только потом
|
||||
* появляется «QUICKSAVE», когда объяснять фриз уже поздно. Здесь строка
|
||||
* выкладывается сразу, до дисковой работы.
|
||||
*
|
||||
* Рисуем в ВИДИМУЮ страницу: игрок смотрит именно на неё, а до следующего
|
||||
* флипа кадра ещё вся операция. Скрытой странице сообщение остаётся
|
||||
* должным — её закроет обычный кадровый проход. */
|
||||
void pop_status_show_now(uint8_t msg) __banked
|
||||
{
|
||||
uint8_t visible, saved_page, saved_bank;
|
||||
|
||||
pop_status_msg = msg;
|
||||
if (!pop_ui_ready()) return; /* шрифта нет — останется заявкой */
|
||||
st_shown = msg;
|
||||
pop_status_ticks = (uint8_t)(msg ? MSG_TICKS : 0);
|
||||
st_dirty = 3;
|
||||
|
||||
visible = (uint8_t)(gfx_get_visible_page() & 1);
|
||||
saved_page = gfx_get_draw_page();
|
||||
saved_bank = gfx_get_bank();
|
||||
gfx_set_draw_page(visible);
|
||||
status_draw();
|
||||
st_dirty = (uint8_t)(st_dirty & ~(1 << visible));
|
||||
gfx_set_draw_page(saved_page);
|
||||
gfx_set_bank(saved_bank);
|
||||
}
|
||||
|
||||
/* ---- верхняя полоса ---------------------------------------------------- */
|
||||
|
||||
/* right — граница зоны (первый столбец СЛЕДУЮЩЕЙ подписи), w — её ширина. */
|
||||
|
||||
Reference in New Issue
Block a user