Files
Sprinter-SDCC/release_docs/en/memory_modes.md
T
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

50 lines
2.2 KiB
Markdown

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