/*
 * _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;
}
