# 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`
