/* * 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 /* ---- 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 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 */