/* * _irq_tramp — вход IM2-прерывания (вектор 0xFF, все источники). * * До выяснения источника трогаем только AF: клавиатура (бит 0 порта * 0x19) и CBL (бит 7 порта 0xFE) уходят напрямую в DSS. Кадровое * прерывание: полный сейв обоих наборов + IX/IY, вызов user-handler'а, * симметричный restore. В конце ВСЕГДА jp на старый обработчик DSS * (он делает свой save/restore и завершает EI/RETI) — клавиатурный * FIFO, SYSTIME и курсор мыши продолжают обслуживаться. * * Операнд финального jp (_irq_dss_target) — SMC, патчится из * irq_install; модуль в _CODE (RAM на Sprinter, W2 в tiny/big). */ #include "_irq.h" void _irq_tramp(void) __naked { __asm push af in a, (#0x19) rrca ; бит 0 — клавиатурный байт принят? jr C, _irq_chain in a, (#0xFE) rlca ; бит 7 — запрос сэмпла CBL? jr C, _irq_chain ;; --- кадровое прерывание --- push bc push de push hl ld hl, (__irq_user) ld a, h or a, l jr Z, _irq_pop3 ; handler не установлен ;; Сохранить теневой набор и индексные — user-код клобберит всё. .db 0x08 ; ex af,af (теневой AF) push af exx push bc push de push hl push ix push iy ld hl, (__irq_user) call _irq_call_hl pop iy pop ix pop hl pop de pop bc exx pop af .db 0x08 ; ex af,af (теневой AF) _irq_pop3: pop hl pop de pop bc _irq_chain: pop af ;; Всегда к DSS — EI/RETI за ним. .db 0xC3 ; jp nn __irq_dss_target:: .dw 0x0038 ; патчится в irq_install _irq_call_hl: jp (hl) __endasm; }