/* * cbl_push_accel — пропихнуть n байт из src в CBL акселератором, * записью на спец-страницу EMM 0xFD (маппится в W3 на 0xC000; см. * официальную доку "5.3 COVOX-Blaster" и docs/converted/accel_r.txt). * Звать ИЗ fill()-callback'а — единственный способ получить настоящий * 16-бит сэмпл (порт 0x4F/OTIR этого не умеет). * * Последовательность акселератора (см. libc/gfx/_gfx_hfill256.c — * тот же рабочий паттерн SMC для immediate-размера): LD D,D (режим * размера блока) → immediate LD A,n (патчится SMC — 0 значит 256, * тот же трюк, что и в OTIR) → LD L,L (режим "копирование блока") → * LD A,(HL) / LD (DE),A (блочное чтение источника → блочная запись * в 0xC000@стр.0xFD) → LD B,B (выкл). Акселератор НЕ продвигает * HL/DE сам — нам это и не нужно, вызов одноразовый. * * W3 сохраняется/восстанавливается вокруг свопа (как bank_read/ * bank_write). Доп. DI/EI не нужны — функция вызывается ИЗ ISR * (прерывания уже замаскированы трамплином до его EI/RETI). */ #include "_cbl.h" void cbl_push_accel(const void *src, uint16_t n) __naked { (void)src; (void)n; __asm ;; HL = src (1-й арг), DE = n (2-й арг) — __sdcccall(1) ld a, e ld (_cblpa_push_size), a ; SMC: 128 остаётся 128, 256 -> 0 in a, (#0xE2) ; сохранить текущий W3 push af ld a, #0xFD ; замапить W3 на спец-страницу CBL out (#0xE2), a ld de, #0xC000 ld d, d ; 0x52 — режим размера блока ld a, #0 ; immediate — патчится SMC выше _cblpa_push_size = . - 1 ld l, l ; 0x6D — режим "копирование блока" ld a, (hl) ; блочное чтение источника ld (de), a ; блочная запись в CBL-порт ld b, b ; 0x40 — выключить акселератор pop af out (#0xE2), a ; вернуть W3 ret __endasm; }