Меню, статус-строка и оболочка игры: title/intro/cutscene/HoF, POP.CFG, палитры

Эта сессия (меню + текст в служебных полосах):

* Меню: рамка выделения считается от силуэта текста (SEL_PAD сверху и
  снизу), а не «на глаз»; все экраны центрируются в игровых 200 строках
  (UI_CENTER_TOP/UI_CENTER_FIELD) и в них помещаются; Enter и Space —
  равноправные клавиши действия (ui_action_down).
* Settings: убраны SHOW SPRINTER SCREEN и BACK, добавлены DEBUG BAR и
  ABOUT.  About показывает тот же текст, что стартовый Sprinter screen,
  минус строка про клавиши — общий about_text(), чтобы экраны не
  разъехались.  CONTROLS собирается таблицей и центрируется по
  фактическому числу строк.
* GAME PAUSED переехала в нижнюю статус-строку, как в оригинале
  (SDLPoP rect_bottom_text = {193,70,202,250}): это состояние программы,
  а не пункт меню.  POP_HP_Y вынесен в pop_cdraw.h — полосу делят два
  модуля.
* pop_status.c (банк 9) — текст в обеих служебных полосах.  Нижняя:
  порт display_text_bottom + таймера (QUICKSAVE/QUICKLOAD/SOUND ON/OFF,
  24 тика).  Верхняя отладочная переведена с палочек на текст
  «Level ##, Room ##, Speed: …, Sound: …, Immortal #» малым шрифтом, с
  своим форматированием чисел (без printf и без деления).
  Заявка сообщения — запись одного байта pop_status_msg: резидент W1/W2
  не растёт, весь рендер в банке.  Бюджет после правок не изменился
  (_CODE 23981, куча 267 Б).
* Цена вывода: блит глифа ~4,6 тыс. тактов независимо от размера, поэтому
  всё change-driven, отладочная строка перерисовывается ПО ПОЛЯМ, пробелы
  не блитятся вовсе, а вход в комнату заливает только игровое поле
  (pop_screen_fill_field) — борта от комнаты к комнате не меняются.
* Интро: в PV-сцене зазвучали пропавшие эффекты оригинала — закрытие
  ворот (4) и открытие двери покоев (51), из которой входит Джафар.
* docs/status_line_text.md — полная инвентаризация ВСЕХ текстов SDLPoP в
  статус-строке: геометрия, семантика text_time_total как идентификатора
  сообщения, мигание, рестарт по истечении 36/288.

Вместе с этим выкладывается накопленная работа по оболочке полной игры:
автомат состояний (pop_app), title, intro/PV и cutscene, attract-demo,
Hall of Fame, глобальный таймер, настройки и POP.CFG, модуль палитр и
fade, звуковой набор, host-тесты на новые швы.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-25 13:58:36 +03:00
parent 7fd7f28ffc
commit 47a4b084c4
205 changed files with 8446 additions and 418 deletions
+47
View File
@@ -505,6 +505,53 @@ BUG-CHEAT-FIGHT-1 (выход из боя), и лечится там же.
«страж давит сильнее». Режим NORMAL (дефолт) даёт 102,4 мс — см.
`frame_pacing_plan.md`.
## PV intro: единые 12,5 FPS вместо переменных 10/7,5/8,57 FPS
**Оригинал.** `proc_cutscene_frame()` двигает последовательности через
`cutscene_frame_time`: 6 тиков 60 Гц в начале, 8 после первой речи и 7 во
время заклинания. Это соответственно 10, 7,5 и примерно 8,57 FPS.
**У нас (осознанное временное отличие).** Один логический кадр PV держится
четыре физических кадра Sprinter: номинально 50/4 = 12,5 FPS. Молния живёт
на отдельной физической шкале и не растягивается этим делителем. Если полная
отрисовка пересечёт дополнительный фронт, реальная частота может упасть до
10 FPS — это допустимо на текущем этапе, но должно быть измерено.
**TODO.** Перевести PV-сцену на тот же anchor-based механизм точного темпа,
который gameplay использует через `pop_beam_sample/pop_pace_end`: измерять
число реально прошедших фронтов во время сборки кадра, держать период ровно
четыре фронта при укладывании в бюджет и явно учитывать overrun. После замера
можно вернуть точные переменные интервалы SDLPoP без накопления фазы.
## Межуровневые PV-сцены: сохранён реальный период 100 мс
Это правило не относится к временному темпу основного Princess/Jaffar intro
выше. `reset_cutscene()` SDLPoP задаёт для сцен перед уровнями период
6 кадров при 60 Гц, то есть 100 мс. На Sprinter тот же период получается
ровно как 5 кадров при 50 Гц.
Суммы вызовов `proc_cutscene_frame()` перенесены без изменения реального
времени: сцены 2/4/6 и обе ветки 12 содержат 26 логических кадров (130
физических, 2,6 с), сцена 8 — 60 (300, 6,0 с), сцена 9 — 72 (360, 7,2 с).
Fade in/out в эти числа не входят, как и в оригинале.
## Gameplay: загрузка уровней через чёрный cut, без fade
**Оригинал.** На границах игровых уровней использует fade out/in.
**У нас (решение пользователя 2026-08-24).** Вход в первый уровень и
переход между уровнями выполняются как `старый кадр -> чёрная палитра ->
подготовка -> новый кадр с новой палитрой`. Fade на этих двух маршрутах
отсутствует. Сюжетные title/story/PV переходы сохраняют собственные fade и
left-to-right эффекты.
Чёрная палитра устанавливается до любого HDD I/O. Загрузчики guard и
tileset сами физически правят отдельные цветовые слоты, поэтому после них
чёрный экран подтверждается повторно. Зеркальные атласы уровня 9 готовятся
до финального источника палитры. CBL открывается последним: старый порядок
`level_switch -> CBL open -> BIOS fade` давал скрежет повторяющейся половины
аппаратного буфера на входе в Level 1; после перестановки баг исчез в MAME.
## Тень: кайма силуэта не подкрашивается фоном
**Оригинал.** Спрайт Тени не хранится — он кладётся ДВАЖДЫ: обычным