/*
 * text.c — wrappers for the Sprinter BIOS text-output calls (RST 8,
 * 081h..08Eh "LP_*").  See <bios/text.h> for the full opcode -> name
 * mapping and semantics.
 *
 * ABI recap (docs/converted/bios.txt):
 *   - 081h/082h/083h explicitly preserve HL and IX -> no push/pop ix
 *     needed, and the result is the smallest/fastest of the set.
 *   - 084h/08Eh (place get/set) are used without push/pop ix elsewhere
 *     in this libc (libc/conio/conio.c gotoxy/wherex/wherey via the same
 *     opcodes) — empirically safe, followed here too.
 *   - Everything else clobbers IX like any other BIOS/ESTEX call, so
 *     every RST 8 below is bracketed with push ix / pop ix.
 *
 * Stack-argument layout: SDCC __sdcccall(1) places the first 8-bit arg
 * in A, the second (only if the first was also 8-bit) in L; every arg
 * beyond that lands on the stack in left-to-right declaration order,
 * starting at [SP+2] (right after the 2-byte return address) — verified
 * empirically via `sdcc -S` for 2..6 uint8 args and for pointer+N uint8
 * args.  IY is used as a scratch index register to read those without
 * disturbing IX (the caller's frame pointer).
 */

#include <bios/text.h>

void bios_fillcharattr(char ch, uint8_t attr, uint8_t count) __naked
{
    (void)ch; (void)attr; (void)count;
    __asm
        ;; ch->A, attr->L, count on stack at [SP+2].
        ;; LP_PRINT_ALL (081h): A=ch, E=attr, B=count.  Preserves HL,IX.
        ld    iy, #2
        add   iy, sp
        ld    b, 0 (iy)             ; B = count
        ld    e, l                  ; E = attr
        ld    c, #0x81
        rst   #0x08
        pop   hl                    ; return address
        inc   sp                    ; consume count byte
        jp    (hl)
    __endasm;
}

void bios_fillchar(char ch, uint8_t count) __naked
{
    (void)ch; (void)count;
    __asm
        ;; ch->A, count->L.  LP_PRINT_SYM (082h): A=ch, B=count.
        ;; Preserves HL,IX.
        ld    b, l
        ld    c, #0x82
        rst   #0x08
        ret
    __endasm;
}

void bios_fillattr(uint8_t attr, uint8_t count) __naked
{
    (void)attr; (void)count;
    __asm
        ;; attr->A, count->L.  LP_PRINT_ATR (083h): E=attr, B=count.
        ;; Preserves HL,IX.
        ld    e, a
        ld    b, l
        ld    c, #0x83
        rst   #0x08
        ret
    __endasm;
}

void bios_set_place(uint8_t row, uint8_t col) __naked
{
    (void)row; (void)col;
    __asm
        ;; row->A, col->L.  LP_SET_PLACE (084h): D=row, E=col.
        ld    d, a
        ld    e, l
        ld    c, #0x84
        rst   #0x08
        ret
    __endasm;
}

uint16_t bios_get_place(void) __naked
{
    __asm
        ;; LP_GET_PLACE (08Eh): returns D=row, E=col — already the
        ;; uint16_t return convention (DE); nothing left to rearrange.
        ld    c, #0x8E
        rst   #0x08
        ret
    __endasm;
}

void bios_writeattr(const char *s, uint8_t len, uint8_t attr) __naked
{
    (void)s; (void)len; (void)attr;
    __asm
        ;; s->HL, len/attr on stack at [SP+2]/[SP+3].
        ;; LP_PRINT_LN (085h): HL=s, B=len, E=attr.
        ld    iy, #2
        add   iy, sp
        ld    b, 0 (iy)             ; B = len
        ld    e, 1 (iy)             ; E = attr
        push  ix
        ld    c, #0x85
        rst   #0x08
        pop   ix
        pop   hl                    ; return address
        inc   sp
        inc   sp                    ; consume len + attr
        jp    (hl)
    __endasm;
}

void bios_write(const char *s, uint8_t len) __naked
{
    (void)s; (void)len;
    __asm
        ;; s->HL, len on stack at [SP+2].
        ;; LP_PRINT_LN2 (086h): HL=s, B=len.
        ld    iy, #2
        add   iy, sp
        ld    b, 0 (iy)             ; B = len
        push  ix
        ld    c, #0x86
        rst   #0x08
        pop   ix
        pop   hl
        inc   sp
        jp    (hl)
    __endasm;
}

void bios_writeattr_until(const char *s, uint8_t len, uint8_t attr, char sep) __naked
{
    (void)s; (void)len; (void)attr; (void)sep;
    __asm
        ;; s->HL, len/attr/sep on stack at [SP+2..4].
        ;; LP_PRINT_LN3 (087h): HL=s, B=len, E=attr, D=sep.
        ;; Pads with spaces after sep up to len.
        ld    iy, #2
        add   iy, sp
        ld    b, 0 (iy)             ; B = len
        ld    e, 1 (iy)             ; E = attr
        ld    d, 2 (iy)             ; D = sep
        push  ix
        ld    c, #0x87
        rst   #0x08
        pop   ix
        pop   hl
        inc   sp
        inc   sp
        inc   sp                   ; consume len + attr + sep
        jp    (hl)
    __endasm;
}

void bios_write_until(const char *s, uint8_t len, char sep) __naked
{
    (void)s; (void)len; (void)sep;
    __asm
        ;; s->HL, len/sep on stack at [SP+2..3].
        ;; LP_PRINT_LN4 (088h): HL=s, B=len, D=sep.  Pads with spaces.
        ld    iy, #2
        add   iy, sp
        ld    b, 0 (iy)             ; B = len
        ld    d, 1 (iy)             ; D = sep
        push  ix
        ld    c, #0x88
        rst   #0x08
        pop   ix
        pop   hl
        inc   sp
        inc   sp
        jp    (hl)
    __endasm;
}

void bios_clearwin(uint8_t row, uint8_t col, uint8_t height, uint8_t width,
                    uint8_t attr) __naked
{
    (void)row; (void)col; (void)height; (void)width; (void)attr;
    __asm
        ;; row->A, col->L, height/width/attr on stack at [SP+2..4].
        ;; LP_CLS_WIN (089h): D=row, E=col, H=height, L=width, B=attr.
        ld    iy, #2
        add   iy, sp
        ld    h, 0 (iy)             ; H = height
        ld    c, 1 (iy)             ; stash width (L is still col for now)
        ld    e, l                  ; E = col
        ld    d, a                  ; D = row
        ld    l, c                  ; L = width
        ld    b, 2 (iy)             ; B = attr
        push  ix
        ld    c, #0x89
        rst   #0x08
        pop   ix
        pop   hl
        inc   sp
        inc   sp
        inc   sp                   ; consume height + width + attr
        jp    (hl)
    __endasm;
}

void bios_scrollwin(uint8_t dir, uint8_t row, uint8_t count) __naked
{
    (void)dir; (void)row; (void)count;
    __asm
        ;; dir->A, row->L, count on stack at [SP+2].
        ;; LP_SCROLL_UD (08Ah): B=dir(1 up/2 down), D=row, E=count.
        ld    iy, #2
        add   iy, sp
        ld    e, 0 (iy)             ; E = count
        ld    d, l                  ; D = row
        ld    b, a                  ; B = dir
        push  ix
        ld    c, #0x8A
        rst   #0x08
        pop   ix
        pop   hl
        inc   sp
        jp    (hl)
    __endasm;
}

void bios_writeattr_stop(const char *s, uint8_t maxlen, uint8_t attr,
                          char sep) __naked
{
    (void)s; (void)maxlen; (void)attr; (void)sep;
    __asm
        ;; s->HL, maxlen/attr/sep on stack at [SP+2..4].
        ;; LP_PRINT_LN5 (08Bh): HL=s, B=maxlen, E=attr, D=sep.
        ;; Stops at sep (no padding).
        ld    iy, #2
        add   iy, sp
        ld    b, 0 (iy)             ; B = maxlen
        ld    e, 1 (iy)             ; E = attr
        ld    d, 2 (iy)             ; D = sep
        push  ix
        ld    c, #0x8B
        rst   #0x08
        pop   ix
        pop   hl
        inc   sp
        inc   sp
        inc   sp
        jp    (hl)
    __endasm;
}

void bios_write_stop(const char *s, uint8_t maxlen, char sep) __naked
{
    (void)s; (void)maxlen; (void)sep;
    __asm
        ;; s->HL, maxlen/sep on stack at [SP+2..3].
        ;; LP_PRINT_LN6 (08Ch): HL=s, B=maxlen, D=sep.  Stops at sep.
        ld    iy, #2
        add   iy, sp
        ld    b, 0 (iy)             ; B = maxlen
        ld    d, 1 (iy)             ; D = sep
        push  ix
        ld    c, #0x8C
        rst   #0x08
        pop   ix
        pop   hl
        inc   sp
        inc   sp
        jp    (hl)
    __endasm;
}

void bios_clearwin_ch(uint8_t row, uint8_t col, uint8_t height,
                       uint8_t width, uint8_t attr, char fillch) __naked
{
    (void)row; (void)col; (void)height; (void)width; (void)attr; (void)fillch;
    __asm
        ;; row->A, col->L, height/width/attr/fillch on stack [SP+2..5].
        ;; LP_CLS_WIN2 (08Dh): D=row, E=col, H=height, L=width, B=attr,
        ;; A=fillch.
        ld    iy, #2
        add   iy, sp
        ld    d, a                  ; D = row (free A for fillch later)
        ld    e, l                  ; E = col (free L for width later)
        ld    h, 0 (iy)             ; H = height
        ld    c, 1 (iy)             ; stash width
        ld    b, 2 (iy)             ; B = attr
        ld    a, 3 (iy)             ; A = fillch
        ld    l, c                  ; L = width
        push  ix
        ld    c, #0x8D
        rst   #0x08
        pop   ix
        pop   hl
        inc   sp
        inc   sp
        inc   sp
        inc   sp                   ; consume height + width + attr + fillch
        jp    (hl)
    __endasm;
}
