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:
2026-06-03 16:13:21 +03:00
parent f542608b3f
commit c71e249a4e
404 changed files with 75155 additions and 58 deletions
+147
View File
@@ -0,0 +1,147 @@
# 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 `sprinter` driver (vendored at `mame/v306/mame.arm`)
* DSS / ESTEX: 1.71.57 (matches `mame/v306/IMG/dss171u.img`)
### What's included
Toolchain:
* `bin/sprinter-cc` — Bash driver
* `toolchain/mkexe/mkexe` — host C utility, packs `.ihx``.exe`
* `toolchain/check_banks.py` — post-link bank size enforcement
Runtime (`runtime/`):
* `crt0.s` — default startup for tiny / big modes, parses argv
* `crt0_minimal.s` — opt-out for very small programs (no argv)
* `crt0_small.s` — for small / huge modes, allocates W2 via ESTEX `$3A`
* `crt0_banked.s` — parameterised: handles W3 banks (huge) or W1 banks (big)
via assemble-time `BANK_W1` flag
* `bank.s``___sdcc_bcall_ehl` trampoline (banking-aware,
preserves uint8_t return value in A)
* `heap.s` + `heap_top.s` — 32 KB W2-resident heap, configurable upper bound
via `sprinter-cc --stack-size`
Libraries (`libc/`):
* `libsprinter.lib` archives: 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 plans
* `solid_c_compatibility.md` — Solid-C compatibility gap analysis
* `im2_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 KB` programs 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 `tiny` hello 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), b` on 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/putch` apply `g_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,B` instruction
trick is wrapped in self-modifying-code primitives in `gfx_lines.c` (the block
length byte must literally follow `LD 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]`,
not `byte[c*8 + r]` as the obvious reading suggests.
### Limitations / known issues
* **No interrupt handlers in v1** — scheduled for v2. `examples/rt_test` uses
busy-wait sleep via ESTEX `$30` instead.
* **MAME's mouse driver stubs `$0E GET_SENSITIVE`** — returns 0 instead of the
current value. Workaround: always call `mouse_set_sensitivity(h, v)` with
known values at startup; don't trust `mouse_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, so
`mouse_get_cursor()` returns width/height/hot_x/hot_y as 0.
* **Several Solid-C functions not yet ported** — see
`docs/solid_c_compatibility.md` for 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` / `putchar` no longer apply `g_text_attr` (switched to fast PCHARS).
Programs that depended on coloured stdio must use `cputs` / `cprintf` /
`putch` instead, or call `textattr(...)` followed by clrscr.
* `runtime/bank.s` is no longer bundled in `sprinter.lib` — it's assembled
per-build by `sprinter-cc` with the right `BANK_W1` flag 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 `+pps` Sprinter 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:
1. IM2 interrupt handlers (`irq_install` / `irq_remove`) — design in
`docs/im2_isr_design.md`
2. Turbo-C-style BGI graphics API (`initgraph` / `setcolor` / `circle` /
`getimage` / `putimage` / `setviewport` / `setlinestyle` / ...)
3. Audio API (AY-3-8910 + COVOX, requires IM2)
4. ISA-8 slot drivers (sound, network — requires IM2)
5. Remaining Solid-C compatibility (Phase 2/3 in `docs/solid_c_compatibility.md`):
`ungetc`, `getdate/gettime/setdate/settime`, `absread/abswrite`,
`scanf` family, `fdopen` / `freopen` / `fclosall`