8ea4c32e51
Набор digisnd1..3.dat приведён упаковщиком к 10 937,5 Гц (частота железа), склеен в 8 EMM-страниц с выравниванием каждого звука на 128 — размер блока запроса CBL, поэтому ни один блок не пересекает границу страницы и проигрыватель не знает слова «стык». Насос (pop_sfx.c) резидентный: его зовут из прерывания CBL, из горячих мест физики и из play_seq. Тишину льём свою (первый блок набора), а не через CBL_UNDERRUN_SILENCE с его malloc — куча в резиденте W2 тесная. Открытие CBL разведено с загрузкой (pop_sfx_start отдельно от pop_sfx_init): пока ESTEX читает файлы, насос не успевает долить блок и железо крутит хвост буфера — на слух скрежет. Разведены все места play_sound() SDLPoP, у которых есть оцифровка (id 0..23, 44..49): посадки, падение, удары о стену, зацеп, тряска и провал плит, ворота, дверь уровня, пики, чомпер, кнопки, боёвка, меч, зеркало, скелет, зелье. Таблица соответствий — docs/sound_plan.md §8. Музыкальные id остаются с нулевой длиной до фазы музыки. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
53 lines
3.1 KiB
C
53 lines
3.1 KiB
C
/*
|
|
* pop_sfx.h — звуковые ЭФФЕКТЫ PoP через COVOX-Blaster.
|
|
*
|
|
* Данные — оригинальная оцифровка игры (`digisnd1..3.dat`), приведённая
|
|
* упаковщиком к 10 937,5 Гц. Конвертировать в рантайме нечего: у PoP
|
|
* сэмплы 8 бит БЕЗЗНАКОВЫЕ МОНО, и это ровно формат CBL (см. <cbl.h> и
|
|
* ../docs/sound_plan.md).
|
|
*
|
|
* ОДИН ГОЛОС. Оригинал тоже одноголосый: `play_sound` глушит
|
|
* предыдущий звук (`stop_sounds`, seg009.c), поэтому новый эффект просто
|
|
* перебивает играющий, и никакого микшера не нужно.
|
|
*
|
|
* ПОЧЕМУ ЭТО НЕ ЛОМАЕТ КАДР. Насос живёт в прерывании CBL и отдаёт 128
|
|
* байт раз в ~11,7 мс. Кадровые прерывания при этом теряются (ветка CBL
|
|
* в трамплине делает приватный RETI), но нам всё равно: темп кадра
|
|
* считается ПО ЛУЧУ (pop_pace.h), а не по прерываниям. Если бы пейсинг
|
|
* остался на них — звук сломал бы игру.
|
|
*/
|
|
#ifndef POP_SFX_H
|
|
#define POP_SFX_H
|
|
|
|
#include <stdint.h>
|
|
|
|
/* Поднять набор: занять 8 EMM-страниц и вычитать в них данные. ВЫВОД НЕ
|
|
* ВКЛЮЧАЕТ — см. pop_sfx_start. 0 — OK, -1 — не получилось (тогда всё
|
|
* дальнейшее молча ничего не делает, игра идёт без звука). */
|
|
int pop_sfx_init(void) __banked;
|
|
|
|
/* Включить вывод (открыть CBL). Звать ПОСЛЕ всей загрузки: пока идёт
|
|
* чтение файлов, ESTEX уходит в диск надолго, насос не успевает долить
|
|
* блок, и железо крутит хвост своего буфера — на слух сплошной скрежет.
|
|
* Идемпотентно. */
|
|
int pop_sfx_start(void) __banked;
|
|
|
|
/* Заглушить вывод на время загрузки (закрывает CBL). Парная к start. */
|
|
void pop_sfx_pause(void) __banked;
|
|
|
|
/* Закрыть CBL и отпустить страницы; звать на выходе. */
|
|
void pop_sfx_close(void) __banked;
|
|
|
|
/* Начать эффект с номером id (0..56 — нумерация оригинала, см.
|
|
* sound_plan.md). Перебивает играющий. У звуков без оцифровки (это
|
|
* музыка) длина 0 — вызов просто глушит текущий.
|
|
*
|
|
* НЕ банковая и НЕ __banked: зовётся из горячих мест (play_seq в
|
|
* pop_kid.c, физика, боёвка), и трамплин на каждый шаг Кида не нужен. */
|
|
void pop_sfx_play(uint8_t id);
|
|
|
|
/* Оборвать текущий эффект (порт stop_sounds). */
|
|
void pop_sfx_stop(void);
|
|
|
|
#endif
|