Реплики сцены с принцессой: вернуть подкачку в кадр
Регрессия 4086dde: тот коммит перенёс шаг постраничной подкачки «в паузу
кадра» — внутрь цикла ожидания тика насоса — и одновременно ввёл защиту от
промотки (snd_want подтягивается к snd_done). Вместе это убило подкачку:
паузы в этой сцене почти нет, цикл ожидания выходит сразу, шаг не
вызывается. Реплики Джафара не успевали загрузиться к своему тику,
pop_music_play() молча ничего не делал, и после первой реплики сцена шла
в тишине.
Замер в MAME (адреса статиков pop_music.c — от public _pop_mus_page по
смещениям из .sym): до фикса ld_next стоял на нуле 20 секунд при активной
загрузке; после — 11 страниц из 11, mus_ready=1, и звучат все три реплики
m50 → m53 → m52.
Фикс: один безусловный load_step в кадре сцены; шаг в паузе оставлен, он
бесплатный, когда время есть.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -3593,3 +3593,39 @@ FIRST_LEVEL`. Рестарт ТОГО ЖЕ уровня (смерть, чекп
|
|||||||
пишет. Всё, что нарисовано текстом, обязано рисоваться ПОСЛЕ перехода, иначе
|
пишет. Всё, что нарисовано текстом, обязано рисоваться ПОСЛЕ перехода, иначе
|
||||||
переезжает только фон (так вышла пустая таблица рекордов, см.
|
переезжает только фон (так вышла пустая таблица рекордов, см.
|
||||||
[HOF-ENTRY](TASKS_CLOSED.md#hof-entry)).
|
[HOF-ENTRY](TASKS_CLOSED.md#hof-entry)).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<a id="pv-music-stall"></a>
|
||||||
|
## PV-MUSIC-STALL. В сцене с принцессой звучала только первая реплика — **ЗАКРЫТ 2026-08-26**
|
||||||
|
|
||||||
|
**Симптом (пользователь).** «Музыка после открытия двери для входа Джафара
|
||||||
|
пропала» — дальше сцена шла в тишине до конца: не звучали ни реплика входа
|
||||||
|
Джафара (m53), ни его ухода (m52).
|
||||||
|
|
||||||
|
**Корень.** Регрессия коммита `4086dde` («убрана промотка кадров»). До него
|
||||||
|
шаг постраничной подкачки стоял БЕЗУСЛОВНО в теле кадра сцены (плюс там же
|
||||||
|
вызывался `pop_music_service`). Тот коммит перенёс шаг «в паузу кадра» —
|
||||||
|
внутрь цикла ожидания тика насоса — и одновременно ввёл правильную защиту от
|
||||||
|
промотки (`if (snd_done > snd_want) snd_want = snd_done`). Вместе это и убило
|
||||||
|
подкачку: пауза в этой сцене почти не выпадает, цикл ожидания выходит сразу,
|
||||||
|
и шаг не вызывается.
|
||||||
|
|
||||||
|
**Замер, который это показал** (адреса статиков `pop_music.c` вычислены от
|
||||||
|
public `_pop_mus_page` по смещениям из `.sym`):
|
||||||
|
|
||||||
|
| | до фикса | после фикса |
|
||||||
|
|---|---|---|
|
||||||
|
| `ld_next` (прочитано страниц m53) | **0** за 20 с | **11 из 11** |
|
||||||
|
| `mus_ready` | 0 | 1 |
|
||||||
|
| что звучит | только m50 | m50 → m53 → m52 |
|
||||||
|
|
||||||
|
**Фикс.** Один безусловный `pop_music_load_step()` в кадре сцены (шаг в паузе
|
||||||
|
оставлен: он бесплатный, когда время есть). Страница стоит 33 мс против
|
||||||
|
кадра сцены в 100-133 мс, а шкала работает по факту прошедшего времени,
|
||||||
|
поэтому сцена от этого не разъезжается.
|
||||||
|
|
||||||
|
**Ловушка отладки, стоившая ложного диагноза.** Пока машина стоит на
|
||||||
|
брейкпоинте, значения в памяти застывают — картина «`busy=0` при `next=3` из
|
||||||
|
20» выглядела как обрыв чтения с ошибкой, хотя это был просто стоп-кадр.
|
||||||
|
Прежде чем толковать значения, проверять `status`: `state=run` или `stop`.
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
| [BUG-SHADOW-SET](#bug-shadow-set) | Тень на 12-м уровне дерётся спрайтами СТРАЖА: SHADOW.DAT у нас нет вовсе | порт | открыт, разбор готов |
|
| [BUG-SHADOW-SET](#bug-shadow-set) | Тень на 12-м уровне дерётся спрайтами СТРАЖА: SHADOW.DAT у нас нет вовсе | порт | открыт, разбор готов |
|
||||||
| [PAL-L1-AFTER-INTRO](#pal-l1-after-intro) | вход в игру на уровень 1 после интро — игровая палитра не установлена (чёрный экран) | палитра/fade | открыт: воспроизведение нестабильно, корень не установлен |
|
| [PAL-L1-AFTER-INTRO](#pal-l1-after-intro) | вход в игру на уровень 1 после интро — игровая палитра не установлена (чёрный экран) | палитра/fade | открыт: воспроизведение нестабильно, корень не установлен |
|
||||||
| [PAL-DUNGEON-STALE](#pal-dungeon-stale) | переход 3→4 (подземелье→дворец): остаётся палитра подземелья | палитра/fade | открыт: КОРЕНЬ ЯСЕН — fade_in восстанавливает из протухшего снимка |
|
| [PAL-DUNGEON-STALE](#pal-dungeon-stale) | переход 3→4 (подземелье→дворец): остаётся палитра подземелья | палитра/fade | открыт: КОРЕНЬ ЯСЕН — fade_in восстанавливает из протухшего снимка |
|
||||||
| [CUTSCENE-LTR](#cutscene-ltr) | `Marry Jaffar` → title → credits должны проявляться полосами слева направо | заставка | открыт: зафиксировано 2026-08-24, взять после текущего цикла анимации PV |
|
|
||||||
| [BUG-CORPSE-AIR](#bug-corpse-air) | труп Кида висит в воздухе, когда убившая его плита улетела вниз | физика | открыт |
|
| [BUG-CORPSE-AIR](#bug-corpse-air) | труп Кида висит в воздухе, когда убившая его плита улетела вниз | физика | открыт |
|
||||||
| [LOOSE-ROOM-CHANGE](#loose-room-change) | расшатанная плита не доваливается, если Кид ушёл в соседнюю комнату | порт | закрыт 2026-08-13, кроме [LOOSE-SEAM-ANIM](#loose-seam-anim) |
|
| [LOOSE-ROOM-CHANGE](#loose-room-change) | расшатанная плита не доваливается, если Кид ушёл в соседнюю комнату | порт | закрыт 2026-08-13, кроме [LOOSE-SEAM-ANIM](#loose-seam-anim) |
|
||||||
| [JUMP-FLOOR-LEGS](#jump-floor-legs) | в прыжке с пола ноги Кида рисуются ПОВЕРХ кромки пола, а должны за ней | окклюзия | **корень найден и починен, ждёт проверки в MAME** |
|
| [JUMP-FLOOR-LEGS](#jump-floor-legs) | в прыжке с пола ноги Кида рисуются ПОВЕРХ кромки пола, а должны за ней | окклюзия | **корень найден и починен, ждёт проверки в MAME** |
|
||||||
@@ -169,40 +168,9 @@ Rx-overrun не срабатывала. Гашение бита отладчи
|
|||||||
---
|
---
|
||||||
|
|
||||||
<a id="pv-music-stall"></a>
|
<a id="pv-music-stall"></a>
|
||||||
## PV-MUSIC-STALL. В сцене с принцессой звучит только первая реплика
|
## PV-MUSIC-STALL. В сцене с принцессой звучала только первая реплика — ЗАКРЫТ 2026-08-26
|
||||||
|
|
||||||
**Наблюдение пользователя (2026-08-26).** «Музыка после открытия двери для
|
Разбор — [`BUGS_CLOSED.md`](BUGS_CLOSED.md#pv-music-stall).
|
||||||
входа Джафара пропала» — и дальше сцена идёт в тишине до самого конца.
|
|
||||||
|
|
||||||
**Что измерено** (MAME, чтение переменных `pop_music.c` мостом; адреса
|
|
||||||
считаны от `_pop_mus_page` по `.sym`):
|
|
||||||
|
|
||||||
| момент | `ld_busy` | `mus_ready` | `slot_id[]` |
|
|
||||||
|---|---|---|---|
|
|
||||||
| m50 играет, тик 60 — старт загрузки m53 | 1 | 0 | {55, 50} |
|
|
||||||
| через 28 с | 1 | 0 | {55, 50} |
|
|
||||||
| конец сцены | 0 | 0 | {55, 50} |
|
|
||||||
|
|
||||||
То есть **m53 и m52 вообще не доходят до слотов**: постраничная загрузка
|
|
||||||
(`pop_music_load_begin` + `pop_music_load_step`) за 17 секунд сцены (1040
|
|
||||||
тиков) не успевает прочитать 11 страниц, `mus_ready` так и остаётся нулём, и
|
|
||||||
`pop_music_play()` на своём тике молча ничего не делает. Блок при этом
|
|
||||||
выделяется (`slot_blk[0] != 0`), то есть память и `open` ни при чём —
|
|
||||||
не хватает именно ШАГОВ чтения.
|
|
||||||
|
|
||||||
Начатую загрузку m53 затем отменяет заявка на m52 (`load_begin` начинается с
|
|
||||||
`if (ld_busy) load_abort()`), поэтому не звучит и она.
|
|
||||||
|
|
||||||
**Где искать.** `intro_pv_animated()` (pop_intro.c): `pop_music_load_step()`
|
|
||||||
вызывается ТОЛЬКО внутри цикла ожидания тика насоса, а тот выполняется лишь
|
|
||||||
пока кадр «в плюсе» по времени; после каждой подкачки сцена уходит в долг
|
|
||||||
(«ДОЛГ НЕ ДОГОНЯЕМ»), и следующий шаг случается через несколько кадров.
|
|
||||||
Замер 33 мс на страницу делался на железе — в MAME чтение заметно дороже.
|
|
||||||
|
|
||||||
**Варианты, которые надо взвесить, а не хвататься за первый.** Читать по
|
|
||||||
несколько страниц за ожидание; начинать загрузку раньше (m53 — ещё до сцены,
|
|
||||||
вместе с m50); либо признать, что реплика длиной 16 с не обязана грузиться
|
|
||||||
по странице за кадр, и читать её целиком под чёрным экраном.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -849,6 +849,22 @@ static int intro_pv_animated(void)
|
|||||||
torch_right, sand_frame, flash,
|
torch_right, sand_frame, flash,
|
||||||
render_tick);
|
render_tick);
|
||||||
pop_sfx_tick(); /* как в оригинале — в конце отрисовки кадра */
|
pop_sfx_tick(); /* как в оригинале — в конце отрисовки кадра */
|
||||||
|
/* ГАРАНТИРОВАННЫЙ ШАГ ПОДКАЧКИ, а не «если останется время».
|
||||||
|
*
|
||||||
|
* Ниже страница следующей реплики читается в ПАУЗЕ кадра, и это
|
||||||
|
* верно ровно до тех пор, пока пауза есть. В этой сцене её почти
|
||||||
|
* нет: кадр дорогой, шкала работает по принципу «долг не догоняем»
|
||||||
|
* (snd_want подтягивается к snd_done), и цикл ожидания выходит
|
||||||
|
* сразу. Замер в MAME 2026-08-26: ОДНА страница за семь секунд,
|
||||||
|
* то есть одиннадцать страниц m53 не успевали за всю сцену —
|
||||||
|
* pop_music_play() на своём тике не находил готового трека, и
|
||||||
|
* реплики Джафара пропадали совсем.
|
||||||
|
*
|
||||||
|
* Страница стоит 33 мс против кадра сцены в 100-133 мс, поэтому
|
||||||
|
* один безусловный шаг в кадр сцену не ломает: он лишь тратит
|
||||||
|
* часть той же паузы, а если паузы не было — добавляет к кадру
|
||||||
|
* четверть его длины, и шкала это учтёт сама. */
|
||||||
|
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; pop_pal_fade_in(INTRO_FADE); }
|
||||||
|
|||||||
Reference in New Issue
Block a user