/*
 * _bgi_hspan_raw — горизонтальная линия len пикселей от (x,y), mode 0x81,
 * через Fill-burst'ы акселератора (до 256 байт за выстрел).
 *
 * Это «сырой» leaf-примитив: максимально тонкий, БЕЗ клиппинга.  Всю
 * защиту берёт на себя вызывающий (см. ОГРАНИЧЕНИЯ).  Проверенный путь:
 * _bgi_fill_span (клиппит сам) и _bgi_lineseg (ортогональ) → сюда.
 *
 * ---- ОГРАНИЧЕНИЯ ВЫЗОВА (ответственность вызывающего) --------------
 *  - W3-скобка: вызывать ТОЛЬКО между _bgi_begin/_bgi_end (W3 замаплен
 *    на видеобанк; DI/EI вокруг каждого выстрела ставит сам сегмент).
 *  - Клиппинга НЕТ.  Требуется 0 <= x и x+len <= 320 (иначе burst
 *    вылезет за строку и затрёт соседнюю видеопамять).  Отрицательный x
 *    и x+len>320 НЕ обрезаются — координаты обязаны быть уже валидны.
 *  - Диапазон len: 1..320.  len==0: safe-версия (с проверками) тихо
 *    вернётся; fast (GFX_NOCHECK) из-за конвенции акселератора (B=0 =
 *    «256») отрисует 256 точек.  len<0 / len>320 — UB.
 *  - Встроенная проверка (если НЕ задан GFX_NOCHECK) отсекает лишь
 *    грубый выход за экран по одной координате: (unsigned)y>=256 и
 *    (unsigned)x>=320 → тихий возврат.  Это НЕ клиппинг диапазона —
 *    частичного отрезка/правого края не режет.
 *
 * ---- ABI ----------------------------------------------------------
 *  __sdcccall(1): x→HL, y→DE(E=y), len→стек(4/5(ix)), color→стек(6(ix)),
 *  __naked → callee-pops 3 байта аргументов (len + color) вручную.
 *  Значения уходят в _gfx_hfill256_segment через регистры (HL=addr,
 *  C=color, B=len, E=y) — без глобального скретча; сегмент клоббер только
 *  A/F, поэтому HL/E переживают выстрел (см. _gfx_hfill256.c).
 *
 * ---- Логика двух burst'ов (len 257..320) --------------------------
 *  Сначала 256 точек на addr (B=0), затем inc h (addr+256) и хвост
 *  (len-256) точек.  Усечение len до младшего байта само даёт (len-256)
 *  для 257..320; при len==256 младший байт 0 → одиночный burst «256».
 */

#include "../_bgi.h"

void _bgi_hspan_raw(int x, int y, int len, uint8_t color) __naked __preserves_regs(d,e)
{
    __asm
        .globl __gfx_addr_base
        .globl __gfx_hfill256_segment
        push  ix
        ld    ix, #0
        add   ix, sp
#ifndef GFX_NOCHECK
        ld    a, d
        or    a, a
        jr    NZ, hs_ret         ; (unsigned)y >= 256
        ld    a, l
        sub   a, #0x40
        ld    a, h
        sbc   a, #0x01
        jr    NC, hs_ret         ; (unsigned)x >= 320
        ld    a, 4 (ix)
        or    a, 5 (ix)
        jr    Z, hs_ret          ; len == 0 (иначе B=0 → «256»)
#endif
        ld    c, l
        ld    b, h               ; BC = x
        ld    hl, (__gfx_addr_base)
        add   hl, bc             ; HL = base + x
        ld    a, 6 (ix)
        ld    c, a               ; C = color
        ld    a, 5 (ix)
        or    a, a
        jr    Z, hs_single       ; len < 256
        ld    a, 4 (ix)
        or    a, a
        jr    Z, hs_single       ; len == 256 (B=0)
        ;; 257..320: два burst-a
        ld    b, #0              ; 256
        call  __gfx_hfill256_segment
        inc   h                  ; addr + 256
    hs_single:
        ld    a, 4 (ix)
        ld    b, a               ; B = len (0 если ==256)
        call  __gfx_hfill256_segment
    hs_ret:
        pop   ix
        pop   hl
        pop   af
        inc   sp
        jp    (hl)
    __endasm;
}
