/* * _irq_tramp — вход IM2-прерывания (вектор 0xFF, все источники). * * До выяснения источника трогаем только 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 и курсор мыши живут. * * CBL-фильтр по биту 7 порта 0xFE УБРАН: при выключенном CBL бит * подтянут к 1 (MAME kbd_fe_r: data |= 0xE0), и каждое кадровое * прерывание ложно уходило бы в чейн — user-handler не вызывался бы * никогда. Вернуть вместе с поддержкой CBL в Phase 2. * * Операнд финального 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 ;; --- кадровое прерывание --- 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 (IM 1, обработчик 0x0038) — EI/RETI за ним. .db 0xC3 ; jp nn __irq_dss_target:: .dw 0x0038 ; SMC: подтверждается в irq_install _irq_call_hl: jp (hl) __endasm; }