c71e249a4e
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>
7.1 KiB
7.1 KiB
Sprinter C Compiler — Release Notes
v1.0 (2026-06-01)
First public release. Production-ready toolchain for writing C programs that target Sprinter / ESTEX DSS. Built on top of vendored SDCC 4.5; this repository adds everything Sprinter-specific.
Highlights
- One-line builds:
sprinter-cc -o foo.exe foo.c— pulls in crt0, libsprinter, packs the resulting .ihx into a SprintEXE. - 27 working examples covering every API surface — used as regression tests while the toolchain was developed.
- Five memory modes (
tiny / small / big / huge / manual) handle programs from a few KB up to 32 KB of code + arbitrarily many 16 KB banks. - Full Sprinter API coverage: console, files & directories, environment, date/time, mouse, graphics (both 320×256×256 and 640×256×16 modes including the hardware accelerator), bitmap-font text, banking, paging.
Component versions
- SDCC: 4.5.0 (vendored binary)
- SprintEXE format: as documented in
docs/converted/ProgrammerManual.txt - MAME: 0.283 with
sprinterdriver (vendored atmame/v306/mame.arm) - DSS / ESTEX: 1.71.57 (matches
mame/v306/IMG/dss171u.img)
What's included
Toolchain:
bin/sprinter-cc— Bash drivertoolchain/mkexe/mkexe— host C utility, packs.ihx→.exetoolchain/check_banks.py— post-link bank size enforcement
Runtime (runtime/):
crt0.s— default startup for tiny / big modes, parses argvcrt0_minimal.s— opt-out for very small programs (no argv)crt0_small.s— for small / huge modes, allocates W2 via ESTEX$3Acrt0_banked.s— parameterised: handles W3 banks (huge) or W1 banks (big) via assemble-timeBANK_W1flagbank.s—___sdcc_bcall_ehltrampoline (banking-aware, preserves uint8_t return value in A)heap.s+heap_top.s— 32 KB W2-resident heap, configurable upper bound viasprinter-cc --stack-size
Libraries (libc/):
libsprinter.libarchives: io (open/read/lseek/close/unlink/stat/atexit/setjmp/ errno/sleep/time/env/conio/fsdir/dir/mouse), stdio (putchar/puts/getchar/print_hex/ file/cprintf/solid_helpers), mem (mem_alloc/bank_io), gfx (gfx_core/gfx_lines/ gfx_16/gfx_text)
Headers (libc/include/):
- Standard:
stdio.h,unistd.h,fcntl.h,errno.h,time.h,sys/stat.h - Sprinter-specific:
conio.h,gfx.h,mouse.h,dir.h,sprinter.h,sprinter_exit.h,sprinter_mem.h - Compatibility:
sprinter_compat.h— Solid-C aliases and types
Examples (27 in examples/):
- I/O: hello, argv, cat, seek, ls, filetest, stattest, errno
- Memory & banking: mem_test, malloc, banked, bankedbg, banklocl
- Mouse: mouse, gfx_mous
- Graphics: gfx_demo, gfx_d16, gfx_text
- Misc: timedir, ptime, openenv, conio, attrprob, strtest, stdlib, assrtest, rt_test
Documentation (docs/):
TODO.md— roadmap, v2 planssolid_c_compatibility.md— Solid-C compatibility gap analysisim2_isr_design.md— interrupt design (v2)converted/— searchable plain-text copies of original Russian documentation
Notable design decisions
- DSS allocates pages by program size —
< 16 KBprograms get only one 16 KB page. Memory modes encode the four possible layouts. - One libsprinter.lib for all modes — SDCC's linker drops unused .rel members,
so a
tinyhello program only pulls in what it needs (~700 bytes overhead). - Banking trampoline ABI: 1-byte saved page + 2-byte bjump return between
the bcall ret and the callee's stack arguments.
pop bc; out (c), bon the way back preserves A (a previous version clobbered A and silently lost uint8_t return values). - Text I/O is Turbo-C-style split:
puts/printf/putchar(fast, via PCHARS) ignore text attribute;cputs/cprintf/putchapplyg_text_attr. Same convention as Borland C 2.x — programs port over with minimal changes. - Graphics accelerator: the
LD D,D / LD C,C / LD E,E / LD B,Binstruction trick is wrapped in self-modifying-code primitives ingfx_lines.c(the block length byte must literally followLD A,#imm; we patch it at runtime). - Mouse cursor format (verified empirically): 1 byte per pixel,
0xFF = transparent; the driver stores the bitmap in a dedicated video bank. - Video mode bitmaps: BIOS font is interleaved —
byte[r*256 + c], notbyte[c*8 + r]as the obvious reading suggests.
Limitations / known issues
- No interrupt handlers in v1 — scheduled for v2.
examples/rt_testuses busy-wait sleep via ESTEX$30instead. - MAME's mouse driver stubs
$0E GET_SENSITIVE— returns 0 instead of the current value. Workaround: always callmouse_set_sensitivity(h, v)with known values at startup; don't trustmouse_get_sensitivity_*()reads. - MAME's mouse driver
$0B RETURN_CURSOR— writes the bitmap to the IX buffer but does not update the H/L/D/E result registers, somouse_get_cursor()returns width/height/hot_x/hot_y as 0. - Several Solid-C functions not yet ported — see
docs/solid_c_compatibility.mdfor the categorised list. - No fprintf / scanf family — workaround:
sprintf(buf, ...) + fputs(buf, fp). - No double-buffering wrapper — Sprinter hardware supports it (port
0xC9), the user-facing wrapper is part of the v2 BGI-style API.
Migration notes from pre-1.0 trees
If you were tracking the project during development:
- All example directories were renamed to satisfy 8.3 filenames on the floppy:
banked_big → bankedbg,seek_demo → seek,malloc_test → malloc,time_dir_test → timedir,bank_local_data → banklocl,gfx_demo16 → gfx_d16,gfx_text_demo → gfx_text,gfx_mouse_test → gfx_mous, etc. puts/putcharno longer applyg_text_attr(switched to fast PCHARS). Programs that depended on coloured stdio must usecputs/cprintf/putchinstead, or calltextattr(...)followed by clrscr.runtime/bank.sis no longer bundled insprinter.lib— it's assembled per-build bysprinter-ccwith the rightBANK_W1flag for the chosen memory mode.
Acknowledgements
- Peters Plus team (Иван Мак, Дмитрий Паринов) for designing Sprinter and publishing the architecture / BIOS / DSS documentation that made this toolchain possible.
- Dmitry M. for the z88dk
+ppsSprinter target — first proof-of-concept for cross-compiling C to SprintEXE; several conventions were borrowed. - The SDCC team for the Z80 backend that does the heavy lifting.
- The MAME team for emulating the Sprinter Sp2000 well enough for full toolchain regression testing without hardware.
v2.0 (planned)
Scope:
- IM2 interrupt handlers (
irq_install/irq_remove) — design indocs/im2_isr_design.md - Turbo-C-style BGI graphics API (
initgraph/setcolor/circle/getimage/putimage/setviewport/setlinestyle/ ...) - Audio API (AY-3-8910 + COVOX, requires IM2)
- ISA-8 slot drivers (sound, network — requires IM2)
- Remaining Solid-C compatibility (Phase 2/3 in
docs/solid_c_compatibility.md):ungetc,getdate/gettime/setdate/settime,absread/abswrite,scanffamily,fdopen/freopen/fclosall