# Sprinter C Compiler — v1.0 C toolchain for **Sprinter** — the Z80-based home computer by Peters Plus, running ESTEX DSS. Host: macOS / Linux. Target: `.EXE` files in SprintEXE format. Built on top of **SDCC 4.5** (vendored in `third_party/sdcc/`). This repository adds everything Sprinter-specific: crt0, linker integration, libc wrappers over ESTEX, banked-call trampolines, graphics & accelerator API, mouse driver wrappers, and the `mkexe` utility for producing SprintEXE images. ## What you get * **`bin/sprinter-cc`** — one-line driver: `sprinter-cc -o foo.exe foo.c` * **Memory modes**: `tiny`, `small`, `big`, `huge`, `manual` — see below. * **stdio + conio**: printf, puts, putchar, getchar, fopen/fread/..., cprintf, cputs, putch, textcolor/textbackground/textattr, gotoxy, kbhit/getch. * **Graphics**: 320×256×256 and 640×256×16 modes, accelerator-backed primitives (hline / vline / rect / fill_rect / line via Bresenham, plus clear), bitmap-font text in both modes via BIOS character generator. * **File I/O**: POSIX (`open`/`read`/`write`/`close`/`lseek`/`unlink`/`creat`), FILE\* streams (`fopen`/`fgets`/`fwrite`/...), directory listing (`ffirst`/`fnext`), `chdir`/`getcwd`/`mkdir`/`rmdir`, `stat`/`fstat`. * **Memory**: 32 KB heap (W2-resident), banking-aware page allocator (`mem_alloc_pages`/`bank_read`/`bank_write`), explicit memory modes for sub-16 KB programs. * **Mouse**: full Sprinter driver wrapper (14 functions including custom cursor bitmaps). * **Environment**: `getenv`/`putenv`/`sysenv` over ESTEX `$46`. * **Time**: `getdatetime`/`setdatetime` + POSIX `time`/`localtime`/`mktime`/`asctime`/`ctime`. * **Misc**: `errno`/`strerror`/`perror`, `atexit`, `setjmp`/`longjmp`, `sleep`, full argv parsing in crt0. ## Quick start ```sh git clone sprinter-c cd sprinter-c make sdcc # one-time: fetch SDCC 4.5 binary (~25 MB) make all # build mkexe + libsprinter.lib + 27 examples make floppy # pack everything into mame/v306/IMG/mc.img cd mame/v306 && ./run_mame.sh # boot Sprinter in MAME ``` Compile a single program: ```sh cat > hello.c < int main(void) { puts("Hello, Sprinter!"); return 0; } EOF bin/sprinter-cc -o hello.exe hello.c ``` That's it — `hello.exe` is now a valid SprintEXE you can `RUN HELLO` from the ESTEX shell. ## Memory modes Sprinter's address space is four 16 KB windows (W0 / W1 / W2 / W3). DSS allocates pages by program size — small programs get only one page. Pick a memory mode based on what your program needs: | Mode | Code lives in | Banking | Use when | Note | |---|---|---|---|---| | `tiny` (default) | W2 (0x8100+) | no | code+data < 14 KB | | | `small` | W1-W2 (0x4100+) | no | code+data < 30 KB | | | `big` | W2 + W1 banking | yes (W1) | tiny + extra code modules | | | `huge` | W1-W2 + W3 banking | yes (W3) | small + extra code modules | | | `manual` | user-specified | optional | special layouts | Not implemented | ```sh sprinter-cc --memory small -o big.exe bigprog.c sprinter-cc --memory huge -o app.exe main.c --bank 1=engine.c --bank 2=ai.c ``` Banked functions are declared with `__banked`: ```c void engine_tick(int dt) __banked; // lives in BANK1, automatically swapped ``` ## Examples (27 total) | Example | What it demonstrates | |---|---| | `hello` | Hello world with stdio + conio Turbo-C-style colors | | `argv` | argv parsing in crt0 | | `cat` | File I/O — read & print TEST.TXT | | `seek` | 32-bit lseek over a 100 KB file | | `ls` | Directory listing via ffirst/fnext | | `filetest` | FILE\* streams (fopen/fread/...) | | `stattest` | `stat`/`fstat` on files and directories | | `errno` | errno / strerror / perror | | `mem_test` | Page allocator + bank\_read/bank\_write | | `malloc` | Heap stress test (200+ allocations) | | `banked` | Banked code in W3 (huge mode) | | `bankedbg` | Banked code in W1 (big mode) | | `banklocl` | Bank-local static data and BSS | | `mouse` | Mouse driver in text mode | | `gfx_mous` | Mouse with custom bitmap cursor in graphics mode | | `gfx_demo` | 320×256×256 lines / rects / accelerator | | `gfx_d16` | 640×256×16 same primitives | | `gfx_text` | Bitmap-font text on graphics screen | | `timedir` | Date/time + directory listing | | `ptime` | POSIX time API | | `openenv` | open() flags + environment vars | | `conio` | conio API smoke test | | `attrprob` | Probe Sprinter text attribute byte layout | | `strtest` | string.h test (from SDCC's z80.lib) | | `stdlib` | stdlib.h test (qsort / rand / strtol / etc.) | | `assrtest` | assert() | | `rt_test` | Runtime helpers (sleep, setjmp, atexit) | ## Headers Standard: * `` — puts / printf / FILE\* + Sprinter-specific dec/hex helpers * `` — atoi / atof / malloc / qsort / ... (from SDCC z80.lib) * `` / `` / `` — from SDCC z80.lib * `` — read / write / close / lseek / unlink * `` — open / creat + O\_RDONLY / O\_CREAT / ... * `` — errno + error names + strerror * `` — stat / fstat * `` / `` — from SDCC Sprinter-specific: * `` — putch / cputs / cprintf, textcolor / textbackground / textattr, kbhit / getch, clrscr, gotoxy, wherex/y * `` — gfx_init/done, palette, putpixel, hline/vline/rect/fill_rect/line, text — for both 320 and 640 modes (gfx_\*16 variants) * `` — full 14-function driver wrapper + mouse_cursor_t with bitmap support * `` — chdir / getcwd / mkdir / rmdir / ffirst / fnext / ffblk * `` — getdatetime / setdatetime + POSIX time / localtime / etc. * `` — raw ports, ESTEX/BIOS function numbers, env API * `` — exit / \_exit / atexit * `` — mem\_alloc\_pages / mem\_free\_block / bank\_read / bank\_write * `` — Solid-C compatibility layer (aliases + BOOL/WORD/uint types) ## Toolchain commands ```sh make all # build mkexe + lib + every example make floppy # repack mame/v306/IMG/mc.img with all .exe files make check # 17 mkexe unit-tests make clean # remove all build artefacts make sdcc # one-time: fetch SDCC 4.5 binary ``` ### sprinter-cc options ``` sprinter-cc -o foo.exe foo.c [more.c ...] [options] --memory MODE tiny | small | big | huge | manual (default: tiny) --memory-manual SPEC explicit placement (CODE=W1|W2,DATA=W1|W2|SAME,BANKED=W1|W3) --stack-size N bytes reserved for the stack (default ~1278) --crt0=TYPE default | minimal | banked | small --bank N=FILE.c compile FILE.c into bank N (repeatable, max 15) --debug enable runtime diagnostics (defines DEBUG_RT) -I PATH extra include path -L 0xADDR / -E / -S override load / entry / stack addresses -Wl FLAG pass FLAG to sdldz80 --mkexe FLAG pass FLAG to mkexe (e.g. --mkexe -p --mkexe 0 for bank padding) -v verbose ``` ## Status What works in v1.0: * Compile / link / pack to SprintEXE — verified on all 27 examples * Four memory modes (tiny / small / big / huge) * Graphics (both modes) with accelerator * Mouse (text + graphics cursor) * File I/O, directories, environment, time * All headers listed above Deferred to v2.0 (see `docs/TODO.md`): * **Turbo-C-style BGI graphics API** — `initgraph` / `setcolor` / `circle` / `getimage` / `putimage` / etc. on top of our `gfx_*` primitives * Remaining Solid-C compatibility gaps (Phase 2/3) — see `docs/solid_c_compatibility.md` * Manual memory mode * Rewrite FILE\* stream API (current implementation is very primitive and doesn't use buffers) Deferred to v3.0: * **IM2 interrupt handlers** — research complete (`docs/im2_isr_design.md`), implementation scheduled for v3 * **Audio API** (AY-3-8910 + COVOX) — requires IM2 * **ISA-8 slot drivers** — requires IM2 (???) ## Documentation * `docs/TODO.md` — roadmap and open work items * `docs/solid_c_compatibility.md` — gap analysis vs Solid-C 2004 * `docs/im2_isr_design.md` — interrupt handler design (v2) * `docs/converted/` — source documentation (ESTEX, BIOS, architecture) converted to plain text for `grep` * `docs/reference/`, `docs/samples/`, `docs/memory management/` — original Russian docs and code samples from Peters Plus ## Repository layout ``` bin/sprinter-cc one-line compiler driver (bash) toolchain/mkexe/ host-side tool: .ihx -> .exe SprintEXE toolchain/check_banks.py post-link bank size enforcer runtime/ crt0 variants (default, minimal, small, banked) bank trampolines, heap, heap_top libc/include/ headers libc/io|stdio|mem|gfx/ C and asm sources for libsprinter.lib lib/ Makefile that archives libsprinter.lib via sdar examples/ 27 example programs mame/v306/ MAME binary + Sprinter ROM/HDD images + floppy script third_party/sdcc/ vendored SDCC 4.5 (fetched via `make sdcc`) third_party/solid-c/ reference: original Sprinter native C (for compat target) docs/ documentation ``` ## License This repository contains: * Original code in `bin/`, `toolchain/`, `runtime/`, `libc/`, `lib/`, `examples/` — MIT-licensed. * `third_party/sdcc/` — SDCC 4.5 under GPLv2 with linking exception (see `third_party/sdcc/COPYING.txt`) * `third_party/solid-c/` — original Sprinter Solid C, used only as a reference ## Credits * **Sprinter / Peters Plus** — Иван Мак, Дмитрий Паринов and the original team * **SDCC** — for the underlying Z80 compiler * **MAME** — for the Sprinter Sp2000 emulation --- For questions / patches: see CONTRIBUTING.md (TBD) or open an issue.