Files
snark13 bd116d7361 ChangeLog:
- update.
2026-06-10 10:41:03 +03:00

225 lines
9.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.