snark13 ca67895667 SprPoP: починена сборка host-тестов
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
2026-08-31 19:57:42 +03:00

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

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 APIinitgraph / 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.

S
Description
No description provided
Readme MIT 36 MiB
Languages
C 65.4%
Python 24.8%
Shell 3.1%
Assembly 3%
Makefile 2.7%
Other 1%