Files
Sprinter-SDCC/applications/PoP/roomtest/pop_sfx_cold.c
T
snark13 8458ec65f4 libc/cbl: две точки входа вместо underrun_mode — malloc больше не в резиденте
Линкер тянет .rel целиком, поэтому malloc/free, стоявшие в мёртвой ветке
CBL_UNDERRUN_SILENCE внутри cbl_open, приезжали в резидент КАЖДОМУ
приложению — включая те, что льют тишину сами и кучей не пользуются.

Разведено:
  cbl_open(freq, fmt, pump, fill)          — ничего не аллоцирует;
  cbl_open_silence(freq, fmt, pump, fill)  — аллоцирует буфер тишины;
  _cbl_open_raw(...)                       — общее тело.
Параметр underrun_mode из публичного API убран: режим задаёт выбор функции.

cbl_close больше не зовёт free — иначе malloc возвращался бы тем же путём.
Буфер тишины живёт до выхода из программы и переиспользуется; его размер
запоминается, иначе открытие 16-бит после 8-бит писало бы memset'ом мимо
выделенного куска.  _cbl_open_raw указатель на буфер не трогает вовсе —
иначе cbl_open после cbl_open_silence терял бы уже выделенную память.

В дереве режим SILENCE не использовал никто: все три вызова (cblwav,
cblstream, PoP) передавали CBL_UNDERRUN_APP.

Итог для PoP: _CODE 24329 -> 23716 (−613 Б), свободно в резиденте 129 ->
747 Б.  make size-check чистый (67 программ), звук в MAME проверен —
насос отработал 696 запросов, pop_snd_ok/want = 1/1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 21:53:08 +03:00

99 lines
4.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* pop_sfx_cold.c — ХОЛОДНАЯ половина звука: поднять набор и открыть CBL.
* Отрабатывает один раз за запуск, поэтому живёт в банке 8; горячая
* половина (насос, запуск эффекта) — в резиденте, см. pop_sfx.c.
*/
#include <stdint.h>
#include <sprinter_mem.h>
#include <cbl.h>
#include "pop_sfx.h"
#define POP_SND_FILES /* имена файлов нужны ТОЛЬКО здесь, см. pop_sound_tbl.h */
#include "_pop_sfx.h"
static uint8_t snd_blk; /* блок EMM под весь набор */
int pop_sfx_init(void) __banked
{
uint8_t i, blk;
if (pop_snd_ok) return 0;
/* Одним блоком: страницы блока идут подряд по логическому индексу, и
* таблица звуков адресует их именно так (page = смещение >> 14). */
blk = mem_alloc_pages(POP_SND_PAGES);
if (!blk) return -1;
for (i = 0; i < POP_SND_PAGES; i++) {
pop_snd_page[i] = mem_get_page(blk, i);
if (!pop_snd_page[i] ||
pop_page_read(pop_snd_files[i], pop_snd_page[i], 16384) != 0) {
mem_free_block(blk);
return -1;
}
}
snd_blk = blk;
pop_snd_want = 1; /* набор есть — звук по умолчанию включён */
return 0;
}
/* ЗАПУСТИТЬ ВЫВОД — ОТДЕЛЬНО ОТ ЗАГРУЗКИ, и это не косметика.
*
* Пока идёт чтение файлов, CBL держать открытым НЕЛЬЗЯ: ESTEX уходит в
* диск надолго, насос не успевает долить очередные 128 байт, и железо
* крутит по кругу хвост своего 256-байтового буфера. На слух это
* сплошной скрежет (поймано пользователем на старте, 2026-08-20).
* Поэтому загрузка страниц и открытие CBL разведены: грузим молча,
* включаем звук последним действием, а на время загрузки уровня глушим
* (pop_sfx_pause).
*
* Параметры: 10 937,5 Гц, 8 бит моно — формат данных один в один
* (sound_plan.md). OTIR, а не акселератор: тот нужен только для 16 бит.
* cbl_open, а не cbl_open_silence: тишину насос льёт СВОЮ (первый блок
* набора), и просить у libc буфер через malloc не надо — куча в резиденте
* W2 тесная, и её отказ ронял бы весь звук. Заодно так malloc вообще не
* приезжает в резидент (275 Б, см. libc/cbl/_cbl_open_raw.c). */
int pop_sfx_start(void) __banked
{
if (pop_snd_ok) return 0;
if (!pop_snd_want) return 0; /* выключено пользователем (Ctrl+S) */
if (!snd_blk) return -1; /* набор не загружен */
if (cbl_open(CBL_FREQ_10K9, CBL_FMT_MONO8, CBL_PUMP_OTIR,
pop_sfx_fill) != 0)
return -1;
pop_snd_ok = 1;
return 0;
}
void pop_sfx_pause(void) __banked
{
if (!pop_snd_ok) return;
pop_sfx_stop();
cbl_close();
pop_snd_ok = 0;
}
void pop_sfx_close(void) __banked
{
pop_sfx_pause();
if (snd_blk) { mem_free_block(snd_blk); snd_blk = 0; }
}
/* Ctrl+S — порт `turn_sound_on_off((!is_sound_on) * 15)` из SDLPoP
* (seg000:657). Выключение реально ЗАКРЫВАЕТ CBL, а не глушит сэмпл:
* иначе насос продолжал бы отдавать блоки тишины 85 раз в секунду, а это
* 3,3 % процессорного времени ни за что (замер: 8 001 такт на прерывание
* при периоде 245 759). Открытие обратно дешёвое — cbl_open только
* настраивает железо, страницы набора никуда не девались. */
void pop_sfx_toggle(void) __banked
{
if (pop_snd_want) {
pop_sfx_pause(); /* pause сам не трогает want... */
pop_snd_want = 0; /* ...поэтому гасим его следом */
} else {
pop_snd_want = 1;
/* Набора может не быть вовсе (файлы не прочитались, страницы не
* дались) — тогда откатываем флаг, чтобы индикация не врала. */
if (pop_sfx_start() != 0) pop_snd_want = 0;
}
}