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