tests/host не линковались: не разрешались pop_chdir_home (его тянет pop_kboot из банка 10) и kbd_raw_keypad_as_ext (тянет pop_ctrl из libc). Поломка предсуществующая — воспроизводится и на коммите до всех правок этой сессии. Ни файловой системы, ни клавиатуры в хостовых тестах нет, поэтому обе заглушены пустышками в общей обвязке. Теперь все пятнадцать наборов проходят: geom 3144 проверки, phys 1733, char 72, grab 55, jaffar 44, shadow 45, app 58, cfg 51, demo 30, flow 27, timer 28, cutscene 13, gate 10, mouse 17, wall 1. Это условие для дальнейшей работы: логику движка снова можно проверять за секунды, без сборки образа и ручного прохождения в MAME. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011MsUsEFAQfsjjQpJ7RtKVY
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/sysenvover ESTEX$46. - Time:
getdatetime/setdatetime+ POSIXtime/localtime/mktime/asctime/ctime. - Misc:
errno/strerror/perror,atexit,setjmp/longjmp,sleep, full argv parsing in crt0.
Quick start
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:
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 |
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:
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
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, consecutive 1..15;
crt0 bank count is generated automatically)
--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 ourgfx_*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 itemsdocs/solid_c_compatibility.md— gap analysis vs Solid-C 2004docs/im2_isr_design.md— interrupt handler design (v2)docs/converted/— source documentation (ESTEX, BIOS, architecture) converted to plain text forgrepdocs/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 (seethird_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.