bd116d7361
- update.
225 lines
9.7 KiB
Markdown
225 lines
9.7 KiB
Markdown
# 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 <this repo> 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 <<EOF
|
||
#include <stdio.h>
|
||
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:
|
||
* `<stdio.h>` — puts / printf / FILE\* + Sprinter-specific dec/hex helpers
|
||
* `<stdlib.h>` — atoi / atof / malloc / qsort / ... (from SDCC z80.lib)
|
||
* `<string.h>` / `<ctype.h>` / `<math.h>` — from SDCC z80.lib
|
||
* `<unistd.h>` — read / write / close / lseek / unlink
|
||
* `<fcntl.h>` — open / creat + O\_RDONLY / O\_CREAT / ...
|
||
* `<errno.h>` — errno + error names + strerror
|
||
* `<sys/stat.h>` — stat / fstat
|
||
* `<setjmp.h>` / `<assert.h>` — from SDCC
|
||
|
||
Sprinter-specific:
|
||
* `<conio.h>` — putch / cputs / cprintf, textcolor / textbackground / textattr, kbhit / getch, clrscr, gotoxy, wherex/y
|
||
* `<gfx.h>` — gfx_init/done, palette, putpixel, hline/vline/rect/fill_rect/line, text — for both 320 and 640 modes (gfx_\*16 variants)
|
||
* `<mouse.h>` — full 14-function driver wrapper + mouse_cursor_t with bitmap support
|
||
* `<dir.h>` — chdir / getcwd / mkdir / rmdir / ffirst / fnext / ffblk
|
||
* `<time.h>` — getdatetime / setdatetime + POSIX time / localtime / etc.
|
||
* `<sprinter.h>` — raw ports, ESTEX/BIOS function numbers, env API
|
||
* `<sprinter_exit.h>` — exit / \_exit / atexit
|
||
* `<sprinter_mem.h>` — mem\_alloc\_pages / mem\_free\_block / bank\_read / bank\_write
|
||
* `<sprinter_compat.h>` — 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.
|