Звуковые эффекты PoP: оцифровка оригинала через CBL
Набор 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>
This commit is contained in:
@@ -282,59 +282,9 @@ int main(void)
|
||||
* стоит, можно спокойно разбирать позу Kid и окклюзию. */
|
||||
if (kbd_raw_down(0x16)) frozen = 1;
|
||||
if (kbd_raw_down(0x1E)) frozen = 0;
|
||||
{ /* Читы (seg000: switch под if (cheats_enabled)). Все — по
|
||||
* ФРОНТУ нажатия, иначе срабатывали бы каждый кадр.
|
||||
* K — убить стража;
|
||||
* I — бессмертие Кида (наш отладочный, в оригинале его нет:
|
||||
* иначе боёвку проверять получается ровно три раза);
|
||||
* S — выдать меч, не бегая за ним в комнату 15. Штатно меч
|
||||
* берётся с пола (pop_have_sword ставит подбор);
|
||||
* Shift+L — следующий уровень (seg000:698, ветка next_level =
|
||||
* current_level + 1). Единственный вменяемый способ
|
||||
* тестировать уровни 2..15. NB: L без Shift — отладочный
|
||||
* «осторожный шаг вправо» (pop_ctrl KBD_DBG_STEPR); с
|
||||
* Shift шаг тоже пройдёт, но уровень тут же сменится, так
|
||||
* что конфликта на практике нет;
|
||||
* [ / ] — подвинуть Кида на ПИКСЕЛЬ влево/вправо (seg000:1828,
|
||||
* `--Char.x` / `++Char.x`). Нужен потому, что мост MAME
|
||||
* теряет нажатия при быстрой отправке, и подогнать Кида в
|
||||
* нужную позу скриптом нельзя (на это упёрлись BUG-LOOSE-2
|
||||
* и BUG-GATE-PASS-1). Пишем прямо в Kid.x: геометрию
|
||||
* персонажа в этом порте задаёт не диспетчер (грабли
|
||||
* L1-EXIT). Колонку не трогаем — её пересчитает физика
|
||||
* следующего кадра. */
|
||||
uint8_t k = kbd_raw_down(KBD_CHEAT_KILL);
|
||||
uint8_t i = kbd_raw_down(KBD_CHEAT_IMMO);
|
||||
uint8_t s = kbd_raw_down(KBD_CHEAT_SWORD);
|
||||
uint8_t nl = (uint8_t)(kbd_raw_down(KBD_CHEAT_NEXTLVL) &&
|
||||
(kbd_raw_down(KBD_LSHIFT) || kbd_raw_down(KBD_RSHIFT)));
|
||||
uint8_t up = kbd_raw_down(KBD_CHEAT_UPSIDE);
|
||||
uint8_t xd = kbd_raw_down(KBD_CHEAT_XDEC);
|
||||
uint8_t xi = kbd_raw_down(KBD_CHEAT_XINC);
|
||||
if (pop_cheats && k && !cheat_prev) pop_guard_kill();
|
||||
/* Бессмертие по кругу: 0 выкл -> 1 «только бой» -> 2 «бой и
|
||||
* мелкий урон» -> 0. Что означают уровни — pop_state.h. */
|
||||
if (pop_cheats && i && !immo_prev)
|
||||
pop_immortal = (uint8_t)(pop_immortal >= 2 ? 0 : pop_immortal + 1);
|
||||
if (pop_cheats && s && !sword_prev) pop_have_sword = 1;
|
||||
if (pop_cheats && nl && !nlvl_prev && pop_current_level < POP_LAST_LEVEL)
|
||||
pop_next_level = (uint8_t)(pop_current_level + 1);
|
||||
/* U — переворот экрана (seg000:0793 — чит и в оригинале).
|
||||
* Тот же путь, что у зелья типа 4: флаг + пометка «перевернулись». */
|
||||
if (pop_cheats && up && !upsd_prev) { /* тот же путь, что у зелья */
|
||||
pop_upside_want = (uint8_t)!pop_upside_want;
|
||||
pop_upside_dirty = 1;
|
||||
}
|
||||
if (pop_cheats && xd && !xdec_prev) Kid.x = (uint8_t)(Kid.x - 1);
|
||||
if (pop_cheats && xi && !xinc_prev) Kid.x = (uint8_t)(Kid.x + 1);
|
||||
cheat_prev = k;
|
||||
immo_prev = i;
|
||||
sword_prev = s;
|
||||
nlvl_prev = nl;
|
||||
upsd_prev = up;
|
||||
xdec_prev = xd;
|
||||
xinc_prev = xi;
|
||||
}
|
||||
/* Читы — В БАНКЕ (roomtest_cold.c): они дёргаются раз в кадр, а места
|
||||
* в резиденте W1/W2 нет (см. TASKS_OPEN, MEM). */
|
||||
pop_cheat_tick();
|
||||
if (frozen) {
|
||||
PROF(0); /* чёрный: ждём vsync */
|
||||
/* Заморозка — тоже полноценный логический кадр: иначе якорь
|
||||
|
||||
Reference in New Issue
Block a user