Музыка: озвучена вся заставка, тайминги сведены со шкалой оригинала
Добавлены треки 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>
This commit is contained in:
@@ -14,9 +14,9 @@
|
||||
* Музыка ПО ХОДУ игры (джинглы смерти, зелья) — отдельный вопрос, её
|
||||
* придётся либо гасить эффектами, либо уводить на AY.
|
||||
*
|
||||
* ФОРМАТ на диске — пачка кусков m<id>_<nn>.bin по 16 КБ (bank_load_file
|
||||
* читает файл только целиком и только в одну страницу). Каталог с
|
||||
* длинами генерирует toolchain/pop_pack_music.py в pop_music_tbl.h.
|
||||
* ФОРМАТ на диске — один файл MUS\m<id>.bin на трек, читается порциями по
|
||||
* 16 КБ из одного открытого fd (bank_read_page). Каталог с длинами
|
||||
* генерирует toolchain/pop_pack_music.py в pop_music_tbl.h.
|
||||
*/
|
||||
#ifndef POP_MUSIC_H
|
||||
#define POP_MUSIC_H
|
||||
@@ -29,7 +29,11 @@
|
||||
#define POP_MUS_PAGES 20
|
||||
|
||||
/* Номера треков — нумерация оригинала (SDLPoP data/music/names.txt). */
|
||||
#define POP_MUS_STORY_1 55 /* «In the absence of the Sultan...» */
|
||||
#define POP_MUS_INTRO 54 /* тема заставки, звучит на титрах */
|
||||
#define POP_MUS_STORY_1 55 /* «In the absence of the Sultan...» */
|
||||
#define POP_MUS_STORY_2 50 /* принцесса ждёт */
|
||||
#define POP_MUS_STORY_3 53 /* входит Джафар */
|
||||
#define POP_MUS_STORY_4 52 /* Джафар уходит */
|
||||
|
||||
/* Курсор проигрывания — читает НАСОС (pop_sfx.c, резидент), пишет
|
||||
* загрузчик. Отдельный от эффектов: они звучат поверх музыки, а не
|
||||
@@ -42,16 +46,34 @@ extern volatile uint16_t pop_mus_left; /* порций до конца, 0
|
||||
* музыка участвует в таблицах приоритета наравне с эффектами. */
|
||||
extern uint8_t pop_mus_id;
|
||||
|
||||
/* Загрузить трек в EMM (НЕ запускает). Звать там, где допустима пауза на
|
||||
* диск: CBL в это время обязан быть закрыт, иначе насос не успевает долить
|
||||
* блок и железо повторяет старый — на слух скрежет (pop_sfx.h).
|
||||
/* ДВА СЛОТА. Заставочные сцены идут цепочкой треков (титры -> история ->
|
||||
* PV из трёх реплик), и загрузка каждого — это полсекунды-секунда диска.
|
||||
* Прятать её в паузу между репликами негде: пауз в оригинале нет, там
|
||||
* следующая реплика начинается сразу. Поэтому слотов два: пока звучит
|
||||
* один, следующий читается во второй, и переключение стоит копирования
|
||||
* двадцати байт таблицы страниц.
|
||||
*
|
||||
* Загрузить трек в свободный слот (НЕ запускает; играющий трек не трогает).
|
||||
* 0 — готово, -1 — нет трека/памяти/файла. */
|
||||
int8_t pop_music_load(uint8_t id) __banked;
|
||||
|
||||
/* Отпустить страницы. Останавливает проигрывание, если оно шло. */
|
||||
/* ТА ЖЕ ЗАГРУЗКА ПО ОДНОЙ СТРАНИЦЕ ЗА ВЫЗОВ — для тех, кому нельзя
|
||||
* замереть на секунду: страница стоит 33 мс, то есть четверть кадра
|
||||
* заставочной сцены, и подкачка следующей реплики не видна.
|
||||
* begin — открыть файл и занять страницы (0 / -1);
|
||||
* step — прочитать очередную: 0 — ещё есть, 1 — трек готов к play,
|
||||
* -1 — ошибка (слот освобождён);
|
||||
* loading — идёт ли чтение (звать step имеет смысл, пока 1).
|
||||
* Оборвать начатое чтение можно pop_music_free. */
|
||||
int8_t pop_music_load_begin(uint8_t id) __banked;
|
||||
int8_t pop_music_load_step(void) __banked;
|
||||
uint8_t pop_music_loading(void) __banked;
|
||||
|
||||
/* Отпустить ОБА слота. Останавливает проигрывание, если оно шло. */
|
||||
void pop_music_free(void) __banked;
|
||||
|
||||
/* Пустить загруженный трек с начала / оборвать. */
|
||||
/* Пустить последний загруженный трек с начала; слот предыдущего при этом
|
||||
* освобождается. Без парного load ничего не делает. */
|
||||
void pop_music_play(void) __banked;
|
||||
void pop_music_stop(void) __banked;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user