/* * _gfx_w0_isr — ISR-стаб для спрайт-страниц в W0 (§9в дизайна). * * Сюда прыгает 3-байтный JP, который atlas_load патчит в 0x38 каждой * атлас-страницы: пока страница подключена в W0, ЛЮБОЕ прерывание * (IM1 напрямую; IM2-трамплин libc/irq чейнит jp 0x0038) попадает в * этот стаб вместо кода ядра DSS. * * Схема (проверена tests/w0page, MAME dev 2026-07-13): * 1) W0 := страница ядра DSS (_gfx_w0_dss); * 2) подложить адрес возврата и прыгнуть в честный 0x0038 — DSS * делает свой save/restore и завершает EI/RETI → возврат в хвост; * 3) хвост: W0 := _gfx_w0_cur (спрайт-страница) — restore ОБЯЗАТЕЛЕН, * он закрывает EI-щель между out(0x82) движка и DI leaf'а. * Вложенное прерывание в хвосте (EI уже сделан DSS) безопасно: W0 в * этот момент = DSS, штатный путь, стаб не реентерится. * * Живёт в _CODE — обязан быть в W2 (режимы tiny/big; в small/huge код * в W1, который прерывание может перемапить — не использовать W0-атласы * с irq_install там; сам стаб зовётся только при странице в W0, т.е. * из окна sprite_update, где W1 стоит программный — работает). */ #include "../_bgi.h" void _gfx_w0_isr(void) __naked { __asm push af ld a, (__gfx_w0_dss) out (#0x82), a ; W0 = ядро DSS pop af push hl ld hl, #w0_isr_ret ex (sp), hl ; вершина стека = возврат, HL цел jp 0x0038 ; честный обработчик (EI/RETI) w0_isr_ret: push af ld a, (__gfx_w0_cur) out (#0x82), a ; вернуть спрайт-страницу pop af ret __endasm; }