SprPoP: три находки прогона 2026-08-31 — звук мигания, часы в быстрых режимах, полоса HP после рестарта

Разбор без правок кода; все три отмечены как задачи по решению пользователя.

SND-SPEAKER-38 (TASKS_OPEN, P1).  Надпись «Press Button» мигает молча.
Наш код не виноват: pop_dead_prompt зовёт звук 38 на каждом появлении,
как оригинал, но слот 38 в наборе ПУСТ.  Причина — три параллельных
набора звука у оригинала: оцифровка (0-23, 44-49, 51), мелодии (24-43
частично, 50, 52-56) и ноты PC-спикера (весь диапазон).  Звук 38 есть
ТОЛЬКО среди нот спикера, поэтому провалился между нашими конвейерами.
Полная ревизия: не оцифровка и не мелодия — номера 31, 34, 38, 42, из них
31/34/42 пустые заглушки, реально звучит ровно один — 38.  Решение
выбрано пользователем: синтезировать ноты в PCM и класть в наш атлас;
формат разобран по спецификации Princed и записан в задачу.

TIME-SPEED (TASKS_OPEN, P1).  Часы уменьшаются на каждом логическом кадре
(как оригинал), но длину кадра у нас меняет режим скорости — в FAST
минута проходит на треть быстрее.  Разная длина кадра в игре и в бою есть
и в оригинале (поправка пользователя), поэтому замедление часов в бою не
трогаем; вопрос только в наших добавочных режимах.  Два варианта с
рекомендацией оставить как есть.

HP-BAR-RESTART (BUGS_OPEN).  После гибели и Ctrl+A (у нас это рестарт
уровня) на одной из страниц остаётся полоса по результатам боя.  Механизм
перерисовки на месте — счётчик страниц, все холодные пути его взводят.
Подозреваемый: пока висит статус-текст, стирание чистит только края и не
трогает середину, а полоса стража при большом запасе HP заходит именно
туда.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011MsUsEFAQfsjjQpJ7RtKVY
This commit is contained in:
2026-08-31 22:31:32 +03:00
parent b0e7130d0b
commit decbec79de
2 changed files with 132 additions and 0 deletions
+93
View File
@@ -1009,6 +1009,99 @@ tp/10 у факелов таблицей, пустой слот соперник
## P1 — берётся в любой момент
### <a id="time-speed-modes"></a>TIME-SPEED. Часы бегут быстрее в FAST/FASTEST
**Наблюдение (пользователь, 2026-08-31):** «при режиме FAST/FASTEST время
начинает бежать быстрее — похоже, время мы считаем в наших логических
кадрах, и если они отрисовываются чаще, то и время быстрее».
Так и есть. `pop_timer_tick` (`src/pop_timer.c`) уменьшает счётчик на
КАЖДОМ логическом кадре — ровно как оригинал. Но длина логического кадра
у нас зависит от режима скорости (`src/pop_pace.h`):
| режим | обычный кадр | бой |
|---|---|---|
| NORMAL | 4 кадра луча (81,9 мс) | 5 (102,4 мс) |
| FAST | 3 (61,4 мс) | 4 (81,9 мс) |
| FASTEST | 3 (61,4 мс) | 3 (61,4 мс) |
Разная длина кадра в игре и в бою — ПОВЕДЕНИЕ ОРИГИНАЛА (подтверждено
пользователем), и часы, идущие в бою медленнее, трогать не нужно.
Расхождение только в наших добавочных режимах: NORMAL повторяет оригинал,
а FAST/FASTEST ускоряют всё разом, включая ход часов — минута игрового
времени проходит примерно на треть быстрее реальной.
**Варианты.**
1. Оставить как есть: быстрый режим ускоряет игру целиком, это честно и
предсказуемо. Ноль работы и ноль риска.
2. Развязать часы от темпа: тикать не по логическому кадру, а по
накопленным кадрам ЛУЧА (4 кадра луча = 1 тик). Тогда минута остаётся
минутой в любом режиме, а в бою часы по-прежнему замедляются, как в
оригинале. Цена — счётчик-накопитель в `pop_timer_tick`.
**Решать пользователю; по умолчанию — вариант 1** (режимы скорости
отладочные, а вариант 2 разводит наш таймер с оригинальным на уровне
механики).
### <a id="snd-speaker-38"></a>SND-SPEAKER-38. Звук мигания надписи: синтезировать ноты спикера в PCM
**Постановка (пользователь, 2026-08-31):** «когда надпись Press Button
начинает мигать — в SDLPoP воспроизводится звук на каждое моргание, у нас
тишина». Решение выбрано там же: «проще синтезировать как PCM и добавить
в наш SND атлас».
**Наш код НЕ виноват и правки не требует.** `pop_dead_prompt`
(`src/pop_status.c`) уже зовёт звук 38 на каждом появлении строки — ровно
как оригинал. Пусто в НАБОРЕ: в `assets/packed/SND/snd.idx` слот 38 имеет
длину 0, играть нечего.
**Почему его нет.** У оригинала три параллельных набора звука, и номера
разложены по ним не подряд:
| набор | что | номера | у нас |
|---|---|---|---|
| `DIGISND1..3.DAT` | оцифровка | 0–23, 44–49, 51 | берём, это и есть наш SND |
| `MIDISND1..2.DAT` | мелодии | 2430, 32, 33, 3537, 3941, 43, 50, 5256 | берём отдельно, как музыку в `MUS/` |
| `IBM_SND1..2` | ноты PC-спикера | 0–56 (весь диапазон) | НЕ берём вовсе |
Звук 38 есть ТОЛЬКО в наборе спикера — ни оцифровки, ни мелодии для него
не существует, поэтому он и провалился между двумя нашими конвейерами.
**Полная ревизия недостающего (сделана 2026-08-31).** Номера, которых нет
ни в оцифровке, ни среди мелодий: **31, 34, 38, 42**. Из них 31, 34 и 42 —
пустые заглушки в один байт, нот внутри нет. **Реально звучит ровно один
номер — 38.** То есть задача закрывает единственную дыру в наборе, а не
открывает семейство.
**Формат ресурса** (канон — `docs/PoP/POP-DAT-FormatSpecifications.pdf`,
раздел «Internal PC Speaker»): заголовок 3 байта, из них байт 1 — темп в
долях на две секунды; далее тройки «частота в герцах (2 байта) + длина в
долях (1 байт)», нулевая частота = пауза; в конце маркер `12 00`.
Звук 38 (`IBM_SND1/res10038.bin`, 17 байт) — нисходящий сигнал из четырёх
нот: 2500, 2000, 1500, 1000 Гц по одной доле, темп 72 → около 110 мс.
Для сверки разбора: звук 17 (мягкое приземление) — одна нота 49 Гц на три
доли.
**Что делать.**
1. В `tools/pop_pack_sound.py` — генератор PCM из нот: меандр на нашей
частоте вывода (`RATE`), амплитуда умеренная (сигнал короткий и резкий,
полный размах будет колоть ухо), пауза = уровень тишины `0x80`.
2. Брать из спикера ТОЛЬКО те номера, которых нет ни в оцифровке, ни в
мелодиях — сейчас это ровно 38. Правило важнее списка: если брать всё
подряд, синтез перекроет собой мелодии, которые мы играем из `MUS/`.
3. Дальше всё уже готово: звук ложится в атлас и индекс общим путём,
`snd.idx` пересобирается, EXE не меняется (раскладка читается с диска).
4. Проверка: `make resources` → слот 38 в индексе получил ненулевую длину;
в MAME дождаться мигания надписи после смерти — должен звучать сигнал.
**Цена.** Один короткий звук в наборе (~2 КБ после выравнивания на блок),
кода в игре — ноль.
### <a id="perf-sweep"></a>PERF-SWEEP. Поиск узких мест по ВСЕЙ игре, а не в одной сцене
**Постановка (пользователь, 2026-08-18):** «пока мы тестируем на регресс