Files
Sprinter-SDCC/libc/include/bios/text.h
T
snark13 c9d5ea35a4 libc: add bios/text.h BIOS text-output API
Direct __naked z80 wrappers over BIOS LP_PRINT_*/LP_SET_PLACE/LP_GET_PLACE
(RST 8, opcodes 081h-08Eh) for fast text rendering — a single BIOS call
replaces a wrchar() loop for constant-attribute/constant-character runs.
Covered by tests/bios_text.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 17:06:13 +03:00

108 lines
4.9 KiB
C

/*
* bios/text.h — direct wrappers around the Sprinter BIOS text-output
* calls (RST 8, function codes 081h..08Eh, "LP_*" in the vendor docs).
*
* These bypass ESTEX's own PUTCHAR/PCHARS/WRCHAR (see <conio.h>) and talk
* straight to the BIOS character-print routines. Use them when you need
* BIOS-specific behaviour (run-length fills, pad/stop-at-separator field
* printing, raw window clear/scroll) that ESTEX doesn't expose directly.
*
* Coordinates are 0-based (row = vertical, col = horizontal), matching
* ESTEX/BIOS directly.
*
* Original BIOS name -> wrapper, with opcode (docs/converted/bios.txt):
*
* 081h LP_PRINT_ALL -> bios_fillchar fill run: char + attr
* 082h LP_PRINT_SYM -> bios_fillchar_noattr fill run: char only
* 083h LP_PRINT_ATR -> bios_fillattr fill run: attr only
* 084h LP_SET_PLACE -> bios_set_place set BIOS print cursor
* 08Eh LP_GET_PLACE -> bios_get_place read BIOS print cursor
* 085h LP_PRINT_LN -> bios_writeattr write buf + attr
* 086h LP_PRINT_LN2 -> bios_write write buf, keep attr
* 087h LP_PRINT_LN3 -> bios_writeattr_until write to sep, pad + attr
* 088h LP_PRINT_LN4 -> bios_write_until write to sep, pad
* 089h LP_CLS_WIN -> bios_clearwin clear window (space fill)
* 08Ah LP_SCROLL_UD -> bios_scrollwin scroll global window
* 08Bh LP_PRINT_LN5 -> bios_writeattr_stop write to sep, stop + attr
* 08Ch LP_PRINT_LN6 -> bios_write_stop write to sep, stop
* 08Dh LP_CLS_WIN2 -> bios_clearwin_ch clear window (custom fill)
*
* "_until" variants print up to `sep` and then PAD the rest of the field
* with spaces (output is always exactly `len` characters wide).
* "_stop" variants print up to `sep` and STOP there (no padding; `sep`
* itself is not printed; `maxlen` is just an upper bound).
*
* ABI: stack must already be in window 2 (guaranteed by crt0) — required
* by the BIOS for its own page-swap scratch use. All registers (main +
* shadow set) are clobbered except where a function says otherwise.
*/
#ifndef BIOS_TEXT_H
#define BIOS_TEXT_H
#include <stdint.h>
/* bios_scrollwin() direction values (BIOS B register). */
#define BIOS_SCROLL_UP 1
#define BIOS_SCROLL_DOWN 2
/* 081h LP_PRINT_ALL — print `count` copies of `ch` with attribute `attr`
* starting at the current BIOS print position. Preserves HL and IX. */
void bios_fillcharattr(char ch, uint8_t attr, uint8_t count);
/* 082h LP_PRINT_SYM — print `count` copies of `ch`, attribute unchanged
* (whatever is already on screen). Preserves HL and IX. */
void bios_fillchar(char ch, uint8_t count);
/* 083h LP_PRINT_ATR — overwrite `count` cells' attribute with `attr`;
* the characters already on screen are left untouched. Preserves HL
* and IX. */
void bios_fillattr(uint8_t attr, uint8_t count);
/* 084h LP_SET_PLACE — set the BIOS print cursor. Out-of-range values
* wrap (BIOS subtracts the window size, not an error). */
void bios_set_place(uint8_t row, uint8_t col);
/* 08Eh LP_GET_PLACE — read the BIOS print cursor: (row << 8) | col. */
uint16_t bios_get_place(void);
/* 085h LP_PRINT_LN — write `len` bytes from `s` with attribute `attr`,
* starting at the current BIOS print position. `s` must point inside
* window 2 (#4000..#BFFF). */
void bios_writeattr(const char *s, uint8_t len, uint8_t attr);
/* 086h LP_PRINT_LN2 — like bios_writeattr(), attribute unchanged. */
void bios_write(const char *s, uint8_t len);
/* 087h LP_PRINT_LN3 — write from `s` with attribute `attr` until the
* byte `sep` is found, then pad with spaces so exactly `len` characters
* are printed in total. */
void bios_writeattr_until(const char *s, uint8_t len, uint8_t attr, char sep);
/* 088h LP_PRINT_LN4 — like bios_writeattr_until(), attribute unchanged. */
void bios_write_until(const char *s, uint8_t len, char sep);
/* 089h LP_CLS_WIN — clear a `height` x `width` local window at
* (row, col) by writing spaces with attribute `attr`. */
void bios_clearwin(uint8_t row, uint8_t col, uint8_t height, uint8_t width,
uint8_t attr);
/* 08Ah LP_SCROLL_UD — scroll `count` whole rows of the global window,
* starting at `row`, in direction `dir` (BIOS_SCROLL_UP/_DOWN). */
void bios_scrollwin(uint8_t dir, uint8_t row, uint8_t count);
/* 08Bh LP_PRINT_LN5 — write from `s` with attribute `attr`, stopping
* (without padding) as soon as `sep` is seen; `maxlen` bounds the scan. */
void bios_writeattr_stop(const char *s, uint8_t maxlen, uint8_t attr,
char sep);
/* 08Ch LP_PRINT_LN6 — like bios_writeattr_stop(), attribute unchanged. */
void bios_write_stop(const char *s, uint8_t maxlen, char sep);
/* 08Dh LP_CLS_WIN2 — like bios_clearwin(), but fills with `fillch`
* instead of a space. */
void bios_clearwin_ch(uint8_t row, uint8_t col, uint8_t height,
uint8_t width, uint8_t attr, char fillch);
#endif