libc: IM2 Phase 2b — звук CBL/COVOX через callback fill(), без кольца libc
CBL уже имеет аппаратный буфер 256 Б (2×128, двойная буферизация на стороне железа) — держать поверх него ещё одно кольцо в libc было бы лишней копией. cbl_open(freq, fmt, pump_mode, underrun_mode, fill) регистрирует callback, вызываемый из ISR за очередным блоком; он сам пропихивает данные приложения (откуда угодно) через cbl_push_otir()/ cbl_push_accel() — без промежуточного буфера. - два насоса: OTIR (порт 0x4F) и ACCEL (акселератор, спец-страница EMM 0xFD@0xC000); OTIR+16-бит запрещён (EINVAL) — по исходнику MAME порт данных физически не может собрать 16-бит сэмпл из пары байт; - форматы CBL_FMT_MONO8/16/STEREO8/16, частоты 7.8..109к; - CBL_UNDERRUN_APP (по умолчанию, недолив не наша забота) / CBL_UNDERRUN_SILENCE (буфер тишины malloc'ится только в этом режиме); - tests/cbltest: матрица 64 комбинации (2 насоса × 8 форматов × 4 частоты); tests/cblwav: banked-стрим речи с дискеты (физстраницы кэшированы заранее — mem_get_page нельзя звать из fill()/ISR); tests/cblstream: единственный случай с собственным кольцом уровня приложения (диск нельзя читать из fill()). Verified в MAME 2026-07-07 — все три теста работают. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+55
-14
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* _irq_tramp — вход IM2-прерывания (вектор 0xFF, все источники).
|
||||
* _irq_tramp — вход IM2-прерывания (вектор 0xFF: кадр/клавиатура/CBL).
|
||||
*
|
||||
* До выяснения источника трогаем только AF: клавиатура (бит 0 порта
|
||||
* 0x19 = SIO-A RR0 «Rx Character Available») уходит напрямую в DSS.
|
||||
* Кадровое прерывание: полный сейв обоих наборов + IX/IY, вызов
|
||||
* user-handler'а, симметричный restore. В конце ВСЕГДА jp на
|
||||
* обработчик DSS 0x0038 (DSS работает в IM 1; jp с interrupted-PC на
|
||||
* стеке имитирует RST 38) — он делает свой save/restore и завершает
|
||||
* EI/RETI: клавиатурный FIFO, SYSTIME и курсор мыши живут.
|
||||
* До выяснения источника трогаем только AF:
|
||||
* - клавиатура (бит 0 порта 0x19 = SIO-A RR0 «Rx Character
|
||||
* Available») уходит напрямую в DSS;
|
||||
* - CBL (бит 7 порта 0xFE) проверяется ТОЛЬКО при зарегистрированном
|
||||
* хуке _irq_cbl_hook: при выключенном CBL бит подтянут к 1 (MAME
|
||||
* kbd_fe_r: data |= 0xE0) и проверка ложно срабатывала бы на
|
||||
* каждом кадре. CBL-путь: полный сейв → насос → restore →
|
||||
* EI/RETI, к DSS НЕ чейнится (личное прерывание);
|
||||
* - кадровое: полный сейв → user-handler → restore → чейн.
|
||||
*
|
||||
* CBL-фильтр по биту 7 порта 0xFE УБРАН: при выключенном CBL бит
|
||||
* подтянут к 1 (MAME kbd_fe_r: data |= 0xE0), и каждое кадровое
|
||||
* прерывание ложно уходило бы в чейн — user-handler не вызывался бы
|
||||
* никогда. Вернуть вместе с поддержкой CBL в Phase 2.
|
||||
* Чейн — ВСЕГДА jp на обработчик DSS 0x0038 (DSS работает в IM 1;
|
||||
* jp с interrupted-PC на стеке имитирует RST 38) — он делает свой
|
||||
* save/restore и завершает EI/RETI: клавиатурный FIFO, SYSTIME и
|
||||
* курсор мыши живут.
|
||||
*
|
||||
* Операнд финального jp (_irq_dss_target) — SMC, патчится из
|
||||
* irq_install; модуль в _CODE (RAM на Sprinter, W2 в tiny/big).
|
||||
* _irq_table_ref; модуль в _CODE (RAM на Sprinter, W2 в tiny/big).
|
||||
*/
|
||||
|
||||
#include "_irq.h"
|
||||
@@ -28,6 +30,45 @@ void _irq_tramp(void) __naked
|
||||
rrca ; бит 0 — клавиатурный байт принят?
|
||||
jr C, _irq_chain
|
||||
|
||||
;; --- CBL? --- старший байт хука ненулевой у любого
|
||||
;; W2-адреса — для проверки «хук есть» хватает одного байта.
|
||||
ld a, (__irq_cbl_hook + 1)
|
||||
or a, a
|
||||
jr Z, _irq_frame
|
||||
in a, (#0xFE)
|
||||
rlca ; бит 7 — запрос блока CBL?
|
||||
jr NC, _irq_frame
|
||||
|
||||
;; --- CBL: сейв, насос, restore, EI/RETI (без DSS) ---
|
||||
push bc
|
||||
push de
|
||||
push hl
|
||||
.db 0x08 ; ex af,af (теневой AF)
|
||||
push af
|
||||
exx
|
||||
push bc
|
||||
push de
|
||||
push hl
|
||||
push ix
|
||||
push iy
|
||||
ld hl, (__irq_cbl_hook)
|
||||
call _irq_call_hl
|
||||
pop iy
|
||||
pop ix
|
||||
pop hl
|
||||
pop de
|
||||
pop bc
|
||||
exx
|
||||
pop af
|
||||
.db 0x08 ; ex af,af (теневой AF)
|
||||
pop hl
|
||||
pop de
|
||||
pop bc
|
||||
pop af
|
||||
ei
|
||||
reti
|
||||
|
||||
_irq_frame:
|
||||
;; --- кадровое прерывание ---
|
||||
push bc
|
||||
push de
|
||||
@@ -67,7 +108,7 @@ void _irq_tramp(void) __naked
|
||||
;; Всегда к DSS (IM 1, обработчик 0x0038) — EI/RETI за ним.
|
||||
.db 0xC3 ; jp nn
|
||||
__irq_dss_target::
|
||||
.dw 0x0038 ; SMC: подтверждается в irq_install
|
||||
.dw 0x0038 ; SMC: подтверждается в _irq_table_ref
|
||||
|
||||
_irq_call_hl:
|
||||
jp (hl)
|
||||
|
||||
Reference in New Issue
Block a user