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>
2.2 KiB
Memory modes
Sprinter's CPU address space is four 16 KB windows. ESTEX DSS allocates RAM
pages by program size — programs ≤ 16 KB get only one page, so the
"default" Spectrum-style "code in W1, data in W2" layout silently fails for
small programs. This is why sprinter-cc has explicit memory modes.
The five modes
| Mode | Code at | Data at | Banks in | Use when |
|---|---|---|---|---|
tiny (default) |
W2 (0x8100+) | chained after code | — | code + data ≤ 14 KB |
small |
W1 (0x4100+) | chained after code | — | code + data ≤ 30 KB |
big |
W2 (0x8100+) | chained after code | W1 (0x4000) | tiny + extra banked modules |
huge |
W1 (0x4100+) | W2 (0x8000+) | W3 (0xC000) | small + extra banked modules |
manual |
user-specified | user-specified | user-specified | special cases |
Choosing
Start with tiny. If sprinter-cc says "_CODE too big" or the program
mysteriously fails to start, jump straight to small.
If you have a large code base (>32 KB total) and want to keep most of it
out of the always-resident window, use huge and split modules into banks
with --bank N=mod.c. big is the same idea but with banks in W1 instead
of W3 — useful when you need W3 for hardware (graphics, mapped memory).
Stack and heap
The stack starts at 0xBFFE (top of W2) and grows down. The heap starts
right after BSS and grows up. By default they share W2 with about 1.2 KB
reserved for the stack and the rest for the heap.
--stack-size N reserves more (or less) for the stack at the cost of heap.
What's actually under the hood
Every mode picks a different runtime/crt0_*.s:
tiny:crt0.s— SP = 0xBFFE, parse argv, call main.small:crt0_small.s— read port 0xC2 to see if DSS gave W2. If not, allocate one page via ESTEX$3Dand map it via$3A SETWIN2before switching the stack — BIOS calls need the stack in W2, ESTEX calls don't.big:crt0_banked.swithBANK_W1=1prepended — banks live at0x{N}4000and trampolines use port0xA2.huge:crt0_banked.s(defaultBANK_W1=0) — banks at0x{N}C000via port0xE2. Also includes the small-mode W2 auto-allocate.
For manual see sprinter-cc --memory-manual SPEC syntax in sprinter_cc.md.