/* * text.c — wrappers for the Sprinter BIOS text-output calls (RST 8, * 081h..08Eh "LP_*"). See 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 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; }