From 747783c422f556cbd698ab271d67d73e030351ed Mon Sep 17 00:00:00 2001 From: Alexander Petrov Date: Wed, 26 Aug 2026 17:00:16 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B5=D0=BF=D0=BB=D0=B8=D0=BA=D0=B8=20?= =?UTF-8?q?=D1=81=D1=86=D0=B5=D0=BD=D1=8B=20=D1=81=20=D0=BF=D1=80=D0=B8?= =?UTF-8?q?=D0=BD=D1=86=D0=B5=D1=81=D1=81=D0=BE=D0=B9:=20=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D0=BD=D1=83=D1=82=D1=8C=20=D0=BF=D0=BE=D0=B4=D0=BA=D0=B0?= =?UTF-8?q?=D1=87=D0=BA=D1=83=20=D0=B2=20=D0=BA=D0=B0=D0=B4=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Регрессия 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 --- applications/PoP/roomtest/BUGS_CLOSED.md | 36 ++++++++++++++++++++++++ applications/PoP/roomtest/BUGS_OPEN.md | 36 ++---------------------- applications/PoP/roomtest/pop_intro.c | 16 +++++++++++ 3 files changed, 54 insertions(+), 34 deletions(-) diff --git a/applications/PoP/roomtest/BUGS_CLOSED.md b/applications/PoP/roomtest/BUGS_CLOSED.md index 6fe46e4..b83936f 100644 --- a/applications/PoP/roomtest/BUGS_CLOSED.md +++ b/applications/PoP/roomtest/BUGS_CLOSED.md @@ -3593,3 +3593,39 @@ FIRST_LEVEL`. Рестарт ТОГО ЖЕ уровня (смерть, чекп пишет. Всё, что нарисовано текстом, обязано рисоваться ПОСЛЕ перехода, иначе переезжает только фон (так вышла пустая таблица рекордов, см. [HOF-ENTRY](TASKS_CLOSED.md#hof-entry)). + +--- + + +## 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`. diff --git a/applications/PoP/roomtest/BUGS_OPEN.md b/applications/PoP/roomtest/BUGS_OPEN.md index c3051d2..9934154 100644 --- a/applications/PoP/roomtest/BUGS_OPEN.md +++ b/applications/PoP/roomtest/BUGS_OPEN.md @@ -26,7 +26,6 @@ | [BUG-SHADOW-SET](#bug-shadow-set) | Тень на 12-м уровне дерётся спрайтами СТРАЖА: SHADOW.DAT у нас нет вовсе | порт | открыт, разбор готов | | [PAL-L1-AFTER-INTRO](#pal-l1-after-intro) | вход в игру на уровень 1 после интро — игровая палитра не установлена (чёрный экран) | палитра/fade | открыт: воспроизведение нестабильно, корень не установлен | | [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) | труп Кида висит в воздухе, когда убившая его плита улетела вниз | физика | открыт | | [LOOSE-ROOM-CHANGE](#loose-room-change) | расшатанная плита не доваливается, если Кид ушёл в соседнюю комнату | порт | закрыт 2026-08-13, кроме [LOOSE-SEAM-ANIM](#loose-seam-anim) | | [JUMP-FLOOR-LEGS](#jump-floor-legs) | в прыжке с пола ноги Кида рисуются ПОВЕРХ кромки пола, а должны за ней | окклюзия | **корень найден и починен, ждёт проверки в MAME** | @@ -169,40 +168,9 @@ Rx-overrun не срабатывала. Гашение бита отладчи --- -## PV-MUSIC-STALL. В сцене с принцессой звучит только первая реплика +## PV-MUSIC-STALL. В сцене с принцессой звучала только первая реплика — ЗАКРЫТ 2026-08-26 -**Наблюдение пользователя (2026-08-26).** «Музыка после открытия двери для -входа Джафара пропала» — и дальше сцена идёт в тишине до самого конца. - -**Что измерено** (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 с не обязана грузиться -по странице за кадр, и читать её целиком под чёрным экраном. +Разбор — [`BUGS_CLOSED.md`](BUGS_CLOSED.md#pv-music-stall). --- diff --git a/applications/PoP/roomtest/pop_intro.c b/applications/PoP/roomtest/pop_intro.c index f12f7ea..1a17e39 100644 --- a/applications/PoP/roomtest/pop_intro.c +++ b/applications/PoP/roomtest/pop_intro.c @@ -849,6 +849,22 @@ static int intro_pv_animated(void) torch_right, sand_frame, flash, render_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); }