Files
snark13 c71e249a4e 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>
2026-06-03 16:13:21 +03:00

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 $3D and map it via $3A SETWIN2 before switching the stack — BIOS calls need the stack in W2, ESTEX calls don't.
  • big: crt0_banked.s with BANK_W1=1 prepended — banks live at 0x{N}4000 and trampolines use port 0xA2.
  • huge: crt0_banked.s (default BANK_W1=0) — banks at 0x{N}C000 via port 0xE2. Also includes the small-mode W2 auto-allocate.

For manual see sprinter-cc --memory-manual SPEC syntax in sprinter_cc.md.