Добавлены треки 54 (тема титров), 50/53/52 (три реплики сцены с
принцессой и Джафаром) — заставка звучит целиком, как в оригинале.
pop_music: два слота EMM. Реплики идут встык, паузы под загрузку нет,
поэтому следующая читается в НЕ играющий слот, а play подменяет
резидентную таблицу страниц. Своей копии таблицы слот не держит — её
хранит блок EMM. Плюс постраничная загрузка (load_begin/load_step):
страница стоит 33 мс, четверть логического кадра сцены, и подкачка
посреди анимации не видна.
Тайминги: все длительности сцен — в тиках оригинала (60 Гц), перевод в
кадры луча делает POP_T60. Пока сцены были немыми, разбег в 20 % был
незаметен; с музыкой реплика кончалась раньше картинки. Переведены
титры, история, хвост после PV и пейсинг самой PV-сцены.
Паузы, которые оригинал отмеряет концом сэмпла, теперь равны реальной
длине наших записей: конец m50 на тике 846, вход Джафара 1046, уход
2073, конец сцены 2500 (было 1959). Fade перед PV сдвинут так, чтобы
полная темнота наступала в тот же момент трека, что у SDLPoP: их fade
длиннее нашего на 123 тика, наш полосовой переход длиннее на 16.
Финальная сцена: убраны песочные часы — end_sequence_anim не трогает
hourglass_state, а reset_cutscene его обнулил. Уровень пройден, время
больше не идёт.
Проверено в MAME: цепочка 54 -> 55 -> 50 -> 53 -> 52 отыгрывается
целиком, интро доходит до демо-режима. Host-тесты: 15 наборов.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ЗАМЕР, из которого всё выросло (MAME, 2026-08-25): `open` стоит 51,4 мс,
а чтение 16 КБ из уже открытого файла — 32,6 мс. То есть 61 % времени
загрузки уходит на ОТКРЫТИЕ, а не на данные, и чистая скорость чтения —
491 КБ/с, а не 260. На диске игры 343 файла; одна только стартовая пачка
(kid+shadow+bg+sound+guard, ~142 файла) — это 7,3 секунды чистого open.
* toolchain/pop_pack_arc.py + pop_arc.c/h (банк 8) — формат PBA1:
заголовок 512 Б, магия, count, записи по 4 байта (offset в СЕКТОРАХ —
архив бывает больше 64 КБ; size в байтах — ресурс всегда <= 16 КБ,
он обязан лезть в EMM-страницу). Таблицу держит вызывающий на своём
стеке: в W2 её класть нельзя, а стека в точке загрузки израсходовано
75 байт из 1279 (замер там же).
* libc: bank_read_page — чтение из УЖЕ ОТКРЫТОГО файла в EMM-страницу.
bank_load_file переписана через неё, поэтому дублирования работы с W3
не осталось и резидент почти не вырос.
* Набор эффектов: 10 файлов -> SND\snd.arc, один open вместо десяти.
* Музыка: трек лежит ОДНИМ файлом и читается порциями по странице —
нарезка на куски больше не нужна. Этот же путь понадобится финалу
`won` (1,2 МБ), который в память целиком не влезает.
* Менеджер звука приведён к оригиналу: играющая музыка участвует в
таблицах приоритета наравне с эффектами (seg000:1672 + data.h:433).
Почти вся музыка НЕперебиваема, поэтому поверх неё эффект не стартует —
ровно как в SDLPoP; раньше эффект её перебивал.
* ALLOCS 3000 -> 6000 (решение пользователя): сборка +20 с, резидент
-161 байт. Куча 87 -> 248 Б.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Путь C из sound_plan.md вместо ранее выбранного A (ноты спикера на AY).
Причина смены: появились готовые записи DOS-версии, и строка «нужен
синтезатор на хосте», из-за которой C считался дорогим, отпала —
осталось `ffmpeg -ac 1 -ar 10937 -f u8`. Оцифровки музыки в самой игре
нет вовсе: digisnd*.dat содержит только эффекты, музыка лежит MIDI под
Adlib, так что конвертировать ресурс игры всё равно было не из чего.
* toolchain/pop_pack_music.py — запись flac -> сырой u8 на 10 937,5 Гц
(частота CBL, чтобы её не переключать никогда), нарезка на куски
MUS\m<id>_<nn>.bin по 16 КБ: bank_load_file читает файл только целиком
и только в одну страницу. Каталог -> pop_music_tbl.h; длина трека
хранится ПОРЦИЯМИ по 128 байт — 169 КБ в uint16 не влезает, 1350
блоков влезает (32-бит арифметики на Z80 избегаем).
* pop_music.c (банк 9) — загрузка трека в EMM и курсор; pop_sfx_fill
(резидент) получил третий источник: эффект важнее музыки, музыка
важнее тишины. Эффект музыку не сбрасывает — её курсор стоит, пока
тот доигрывает, и она продолжается с места.
* story_1_absence звучит на первом экране истории, где была тишина.
Грузим ПОСЛЕ сборки картинки: чтение идёт через ESTEX, и при открытом
CBL насос не успел бы долить блок.
Проверено записью звука из MAME: корреляция огибающих с эталоном 0,836
при сдвиге 1,8 с, RMS 22,6 против 18,3 (разница — 8-битное квантование).
Эффекты двери в PV-сцене после трека звучат по-прежнему.
Бюджет: резидент +83 Б кода и +25 Б данных, запас W2 151 Б (кучи в
приложении нет, malloc не слинкован); банк 9 занят на 88 %.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>