/*
 * _gfx_rectfill256 — диспетчер заливки прямоугольника (x,y,w,h,color),
 * mode 0x81: выбирает ориентацию с меньшим числом выстрелов и передаёт
 * управление leaf-заливке (tail-jump, стек не трогается — ABI идентичен):
 *   w>h && w<=256  → _gfx_recthfill256 (h горизонтальных строк)
 *   иначе          → _gfx_rectvfill256 (w вертикальных колонок)
 *
 * ---- ЦЕНА ПРОВЕРКИ и когда звать leaf'ы напрямую -------------------
 * Проверка + tail-jump: ~160Т (быстрый путь w<h) … ~245Т (w>256),
 * типично ~200Т ≈ 9.5 мкс @21МГц.  Один выстрел-линия стоит ~55-65Т
 * CPU-оверхеда, т.е. проверка окупается, когда выбор ориентации
 * экономит |w−h| >= ~4 линии.  На мелких/почти квадратных
 * прямоугольниках (|w−h| < 4) или когда форма известна заранее —
 * выгоднее прямой вызов _gfx_recthfill256 / _gfx_rectvfill256
 * (контракты — в их шапках: recthfill требует 1<=w<=256).
 * Полный бюджет тактов/размеров всех вариантов: docs/accel-fill-budget.md.
 *
 * __sdcccall(1): x→HL, y→DE(E=y); w→4/5(ix), h→6/7(ix), color→8(ix).
 * Диспетчер сохраняет HL/DE и стек как есть; leaf делает свой
 * push ix и callee-pops.  Pre/контракты — как у leaf'ов (W3 замаплен,
 * без клиппинга, w,h >= 0).
 */

#include "../_bgi.h"

void _gfx_rectfill256(int x, int y, int w, int h, uint8_t color) __naked
{
    __asm
        .globl __gfx_recthfill256
        .globl __gfx_rectvfill256
        push  ix
        ld    ix, #0
        add   ix, sp             ; только чтобы прочитать w/h; HL/DE не трогаем

        ;; --- w>h && w<=256 ? (unsigned, w/h >= 0) ---
        ld    a, 4 (ix)
        sub   a, 6 (ix)
        ld    b, a               ; (w-h) низкий
        ld    a, 5 (ix)
        sbc   a, 7 (ix)          ; CF=1 если w<h
        jr    C, disp_v
        or    a, b
        jr    Z, disp_v          ; w==h -> не (w>h)
        ld    a, 5 (ix)          ; w high
        cp    a, #2
        jr    NC, disp_v         ; w >= 512
        dec   a
        jr    NZ, disp_h         ; high==0 -> w<256
        ld    a, 4 (ix)
        or    a, a
        jr    NZ, disp_v         ; high==1,low!=0 -> w>256
                                 ; w==256 -> горизонталь (низкий байт 0 = «256»)
    disp_h:
        pop   ix
        jp    __gfx_recthfill256 ; tail-jump: аргументы на стеке как есть
    disp_v:
        pop   ix
        jp    __gfx_rectvfill256
    __endasm;
}

#if 0
/* ================================================================
 * Старый вариант (до 2026-07-10): полный брекет (арм+выстрел+выкл)
 * на КАЖДУЮ линию через call _gfx_*fill256_segment — ~100Т+call на
 * линию.  Оставлен закомментированным для отката/сравнения.
 * (Промежуточный monolith-вариант с chunked-ветками жил здесь
 * 2026-07-10 и разъехался по _gfx_recthfill256.c/_gfx_rectvfill256.c.)
 * ================================================================ */
void _gfx_rectfill256(int x, int y, int w, int h, uint8_t color) __naked
{
    __asm
        .globl __gfx_addr_base
        .globl __gfx_hfill256_segment
        .globl __gfx_vfill256_segment
        push  ix
        ld    ix, #0
        add   ix, sp
        ld    bc, (__gfx_addr_base)
        add   hl, bc             ; HL = base + x  (бегущий addr)
        ld    a, 8 (ix)
        ld    c, a               ; C = color

        ;; --- ветка: w>h && w<=256 ? (unsigned, w/h >= 0) ---
        ld    a, 4 (ix)
        sub   a, 6 (ix)
        ld    b, a               ; (w-h) низкий
        ld    a, 5 (ix)
        sbc   a, 7 (ix)          ; CF=1 если w<h
        jr    C, rf_vbranch
        or    a, b
        jr    Z, rf_vbranch      ; w==h -> не (w>h)
        ld    a, 5 (ix)          ; w high
        cp    a, #2
        jr    NC, rf_vbranch     ; w >= 512
        dec   a
        jr    NZ, rf_hbranch     ; high==0 -> w<256
        ld    a, 4 (ix)
        or    a, a
        jr    NZ, rf_vbranch     ; high==1,low!=0 -> w>256

    rf_hbranch:
        ld    a, 4 (ix)
        ld    b, a               ; B = len = w (256 -> 0)
    rf_hloop:
        ld    a, 6 (ix)
        or    a, 7 (ix)
        jr    Z, rf_done         ; h == 0
        call  __gfx_hfill256_segment
        inc   e                  ; y++
        ld    a, 6 (ix)
        sub   a, #1
        ld    6 (ix), a
        ld    a, 7 (ix)
        sbc   a, #0
        ld    7 (ix), a
        jr    rf_hloop

    rf_vbranch:
        ld    a, 6 (ix)
        ld    b, a               ; B = len = h (256 -> 0)
    rf_vloop:
        ld    a, 4 (ix)
        or    a, 5 (ix)
        jr    Z, rf_done         ; w == 0
        call  __gfx_vfill256_segment
        inc   hl                 ; addr++
        ld    a, 4 (ix)
        sub   a, #1
        ld    4 (ix), a
        ld    a, 5 (ix)
        sbc   a, #0
        ld    5 (ix), a
        jr    rf_vloop

    rf_done:
        pop   ix
        pop   hl
        pop   af
        pop   af
        inc   sp
        jp    (hl)
    __endasm;
}
#endif
