Add full compiler toolchain, libc, examples and reference docs
First substantive commit: the entire Sprinter C compiler tree on top of
the bare README+gitignore initial commit.
What's in here:
bin/sprinter-cc — driver script invoking SDCC + linker + mkexe
libc/ — Sprinter-specific libc layer over ESTEX/BIOS
(conio, gfx, io, mem, stdio + headers)
runtime/ — crt0 variants (default/small/banked/minimal)
+ heap + bank trampolines
toolchain/ — mkexe (SprintEXE packer, C + tests)
examples/ — 30 demo programs (gfx, file I/O, env, time, …)
lib/Makefile — builds the libc archive (sprinter.lib)
docs/ — converted Sprinter manuals + asm reference samples
third_party/ — solid-c reference compiler dump + sdcc setup script
release_docs/ — packaging / release notes
gitignore overhaul:
• Drop dangerous blanket patterns: *.asm (would hide docs/samples/*.asm)
and *.exe (case-insensitive match was hiding third_party/solid-c/*.EXE
on macOS APFS). Replaced with examples/*/*.{asm,exe,…} and lib/*.lib.
• Restore tracking of toolchain/mkexe/tests/{one,big}.bin — those are
INPUT fixtures, not build outputs.
• Collapse the duplicated SDCC/C/Sdcc sections into one section per
concern (build outputs / vendored / OS-junk).
• Add .sprinter-cc-*/, build/ (catches lib/build/ too), .claude/.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1,2 +1,221 @@
|
||||
# Sprinter-SDCC
|
||||
# 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 |
|
||||
|---|---|---|---|
|
||||
| `tiny` (default) | W2 (0x8100+) | no | code+data < 14 KB |
|
||||
| `small` | W1 (0x4100+) | no | code+data < 30 KB |
|
||||
| `big` | W2 + W1 banks | yes (W1) | tiny + extra code modules |
|
||||
| `huge` | W1 + W3 banks | yes (W3) | small + extra code modules |
|
||||
| `manual` | user-specified | optional | special layouts |
|
||||
|
||||
```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
|
||||
* All five memory modes (tiny / small / big / huge / manual)
|
||||
* 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`):
|
||||
* **IM2 interrupt handlers** — research complete (`docs/im2_isr_design.md`),
|
||||
implementation scheduled for v2
|
||||
* **Turbo-C-style BGI graphics API** — `initgraph` / `setcolor` / `circle` /
|
||||
`getimage` / `putimage` / etc. on top of our `gfx_*` primitives
|
||||
* **Audio API** (AY-3-8910 + COVOX) — requires IM2
|
||||
* **ISA-8 slot drivers** — requires IM2
|
||||
* Remaining Solid-C compatibility gaps (Phase 2/3) — see `docs/solid_c_compatibility.md`
|
||||
|
||||
## 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
|
||||
* **z88dk +pps** — Дмитрий M. for paving the way with the first Sprinter target
|
||||
* **MAME** — for the Sprinter Sp2000 emulation
|
||||
|
||||
---
|
||||
|
||||
For questions / patches: see CONTRIBUTING.md (TBD) or open an issue.
|
||||
|
||||
Reference in New Issue
Block a user