Files
snark13 b851e22fa6 Drop print_hex.c — replaced by hex8() from hex_print.c
print_hex(uint8_t) was an early bare-metal helper doing exactly what
hex8() in the freshly-ported hex_print.c does (two-digit hex via
putchar()).  hex8() is smaller (asm cp/sbc/daa nibble trick, no LUT)
and consistent with the dec8/hex16/dec16/hex32/dec32 family.

  • Replaced print_hex() calls with hex8() in examples/banked and
    examples/bankedbg.
  • Removed libc/stdio/print_hex.c, dropped its prototype from
    sprinter.h and its entry from lib/Makefile.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-04 09:28:39 +03:00

156 lines
5.6 KiB
C

/*
* sprinter.h — low-level Sprinter platform definitions for C programs.
*
* Numbers and behaviour cross-checked against docs/converted/ (IvanMak.txt,
* DiskSyscalls.txt, BIOS_v3.txt, ProgrammerManual.txt).
*/
#ifndef SPRINTER_H
#define SPRINTER_H
#include <stdint.h>
/* ---- I/O ports ----------------------------------------------------- */
/* Memory window page-select ports (write 8-bit physical page number). */
#define PORT_PAGE_W0 0x82 /* window 0: 0x0000-0x3FFF (ESTEX system) */
#define PORT_PAGE_W1 0xA2 /* window 1: 0x4000-0x7FFF (HOME) */
#define PORT_PAGE_W2 0xC2 /* window 2: 0x8000-0xBFFF (stack+heap) */
#define PORT_PAGE_W3 0xE2 /* window 3: 0xC000-0xFFFF (paged) */
/* Graphics ports (used in stage 3+). */
#define PORT_RGADR 0x89 /* graphic Y / Spectrum-page selector */
#define PORT_RGMOD 0xC9 /* bit 0 = active screen page 0/1 */
/* ---- ESTEX RST 10h function numbers -------------------------------- */
/* Full list in docs/converted/DiskSyscalls.txt (DSS v1.6). */
#define ESTEX_VERSION 0x00
#define ESTEX_CHDISK 0x01
#define ESTEX_CURDISK 0x02
#define ESTEX_DSKINFO 0x03
#define ESTEX_CREATE 0x0A
#define ESTEX_CREATE_NEW 0x0B
#define ESTEX_DELETE 0x0E
#define ESTEX_RENAME 0x10
#define ESTEX_OPEN 0x11
#define ESTEX_CLOSE 0x12
#define ESTEX_READ 0x13
#define ESTEX_WRITE 0x14
#define ESTEX_MOVE_FP 0x15
#define ESTEX_ATTRIB 0x16
#define ESTEX_F_FIRST 0x19
#define ESTEX_F_NEXT 0x1A
#define ESTEX_MKDIR 0x1B
#define ESTEX_RMDIR 0x1C
#define ESTEX_CHDIR 0x1D
#define ESTEX_CURDIR 0x1E
#define ESTEX_SYSTIME 0x21
#define ESTEX_WAITKEY 0x30
#define ESTEX_SCANKEY 0x31
#define ESTEX_ECHOKEY 0x32
#define ESTEX_CTRLKEY 0x33
#define ESTEX_SETWIN 0x38
#define ESTEX_SETWIN1 0x39
#define ESTEX_SETWIN2 0x3A
#define ESTEX_SETWIN3 0x3B
#define ESTEX_INFOMEM 0x3C
#define ESTEX_GETMEM 0x3D
#define ESTEX_FREEMEM 0x3E
#define ESTEX_SETMEM 0x3F
#define ESTEX_EXEC 0x40
#define ESTEX_EXIT 0x41
#define ESTEX_WAIT 0x42
#define ESTEX_ENV 0x46 /* env API: B=0 sysenv, B=1 getenv, B=2 putenv */
#define ESTEX_SETVMOD 0x50
#define ESTEX_GETVMOD 0x51
#define ESTEX_LOCATE 0x52
#define ESTEX_CURSOR 0x53
#define ESTEX_SELPAGE 0x54
#define ESTEX_SCROLL 0x55
#define ESTEX_CLEAR 0x56
#define ESTEX_RDCHAR 0x57
#define ESTEX_WRCHAR 0x58
#define ESTEX_WINCOPY 0x59
#define ESTEX_WINREST 0x5A
#define ESTEX_PUTCHAR 0x5B
#define ESTEX_PCHARS 0x5C
#define ESTEX_PRINT 0x5F
/* ---- BIOS RST 8 function numbers ----------------------------------- */
/* Full list in docs/converted/BIOS_v3.txt (BIOS v3.00). */
#define BIOS_EMM_INFO 0xC0 /* HL=total pages, BC=free pages */
#define BIOS_EMM_INIT 0xC1
#define BIOS_EMM_ALLOC 0xC2 /* B=npages -> A=blk_id */
#define BIOS_EMM_FREE 0xC3 /* A=blk_id */
#define BIOS_EMM_GETPAGE 0xC4 /* A=blk_id, B=log -> A=physical */
#define BIOS_EMM_LIST 0xC5
#define BIOS_EMM_PORT_FOR 0xC6 /* A=window -> C=port, B=current page */
#define BIOS_EMM_NEXTPAGE 0xC7
/* ---- Inline paging intrinsics -------------------------------------- */
/*
* Each generates a single "OUT (port), A" + the load of the literal.
* Wrap in DI/EI yourself for graphics-grade timing; for one-shot setup
* the inline form is fine.
*/
__sfr __at PORT_PAGE_W0 _io_page_w0;
__sfr __at PORT_PAGE_W1 _io_page_w1;
__sfr __at PORT_PAGE_W2 _io_page_w2;
__sfr __at PORT_PAGE_W3 _io_page_w3;
static inline void sprinter_page_w0(uint8_t page) { _io_page_w0 = page; }
static inline void sprinter_page_w1(uint8_t page) { _io_page_w1 = page; }
static inline void sprinter_page_w2(uint8_t page) { _io_page_w2 = page; }
static inline void sprinter_page_w3(uint8_t page) { _io_page_w3 = page; }
/* ---- Sprinter-specific debug helpers ------------------------------ */
/* Use hex8() / hex16() / hex32() from <stdio.h> for hex debug output. */
#ifdef DEBUG_RT
/*
* Runtime diagnostics — exposed only when the program is built with
* `sprinter-cc --debug`. The flag below is set by crt0 before main().
*
* 0 — crt0 did NOT self-allocate a W2 page (tiny mode never needs to,
* and in small mode DSS itself maps W2 when the image > 16 KB).
* 1 — crt0 had to allocate and map a W2 page via ESTEX $3D + $3A
* (small mode with image ≤ 16 KB).
*/
extern uint8_t w2_self_allocated;
#endif
/* ---- Environment (ESTEX $46) -------------------------------------- */
/*
* getenv(name) — return pointer to value, or NULL if not set.
* Returned buffer is ESTEX-owned (shared static);
* copy if needed before the next getenv() call.
* putenv("name=value") — add/replace. Pass "name" with no '=' to remove.
* sysenv(buf) — copy the WHOLE environment into caller's buf,
* as a series of NUL-terminated "NAME=value"
* strings followed by an extra NUL marking end:
* "PATH=...\0SOLID=H\0\0"
* Caller is responsible for sizing buf large
* enough for the entire environment.
*
* Return values:
* getenv: pointer to value (NUL-terminated) on success,
* NULL when the variable is not present (errno unchanged),
* NULL with errno set on real error.
* putenv: 0 on success, -1 on error (errno set).
* sysenv: buf on success, (char*)-1 on error (errno set).
*/
char *getenv(const char *name);
int putenv(const char *namevalue);
char *sysenv(char *buf);
#endif /* SPRINTER_H */