Memory and Banking

The Z80 sees 64 KiB. Every Spectrum past the 48K has more RAM than that and shows it a window at a time, so writing for one means telling the assembler which physical memory an address currently stands for.

What Each Machine Has

MachineWindowsPage sizePageable
zxnext88 KiBall eight, over up to 256 pages
zx128416 KiB$C000 only, over banks 0–7
zx48416 KiBnone
zx16none, and nothing above $8000

The 64 KiB space is always a uniform tiling: the window size is the page size, so a Next address divides by 8192 to give its slot and a 128K address by 16384 to give its window.

zx48 and zx16 refuse the paging directives outright, rather than accepting them and doing nothing:

Error [E1136]: `bank` is not a directive `zx48` has

Page Selection

Directive
bank <n>Select a 16 KiB bank
bank <n>, <slot>Select it into a slot, on the Next only
page <page>, <slot>Select an 8 KiB page into one of the Next’s eight slots
slot <page>, <slot>The same directive under another name

slot is an alias for page, and takes the same arguments in the same order — the page first, then the slot. slot 9, 4 puts page 9 into slot 4, exactly as page 9, 4 does. The name reads the other way round and does not mean it.

page requires both arguments; page 5 on its own is E1005, which names the form it wants.

bank is valid on the Next as well as the 128K. A 16 KiB bank is the unit the .nex file format uses, and maps to the slot pair 2N/2N+1, so it is not treated as foreign there. On the Next it takes an optional slot, which a 128K refuses:

Error [E1137]: `bank` takes no slot on `zx128`

Give the slot when you mean to put code in the bank. bank 11, 3 moves assembly to $6000, so the bytes that follow belong to bank 11. Bare bank 11 selects the bank but leaves the program counter where it was, so on a Next the bytes carry on landing wherever they were going and the bank stays empty — which an .nex then drops for holding nothing. On a 128K, bare bank moves assembly to $C000, that machine having only the one pageable window.

page/slot on a 128K warn rather than fail:

Warning [W1130]: `page` and `slot` are the Next's 8K paging; `zx128` pages in 16K banks, so use `bank`

They are best-effort mapped, so old source keeps working, but the machine has no 8 KiB paging and the warning is telling you the truth.

The Current Mapping

Three read-only values, usable in any expression:

WrittenIs
_pageThe physical 8 KiB page holding the current address
_bankIts 16 KiB bank — _page / 2
_slotThe 8 KiB slot index, 0–7

The leading underscore is required. Without it the word is read as a label of that name, so ld hl,page reports an undefined label rather than answering with the page number. A label really called page is reached that way, and is yours.

All three are derived from the live slot map at that point in the source, so they follow your paging directives:

    !device zxnext
    org $8000
    db  _page, _slot, _bank     ; 04 04 02 on a Next at reset

After a page 9, 4 the same three read 09 04 04.

They cannot be emitted either side of a paging directive into a flat image. Bytes before and after a page belong to different pages, which a bin cannot express, so the pair is E1085 — see Output Formats. Read them into constants, or build a banked format.

They are well defined on every machine — _bank is the useful one on 16 KiB machines, _page and _slot on the Next — so no target branching is needed to use them.

RAM Size and --ram

A Next has 1 MiB or 2 MiB depending on the machine, and --ram says which you are targeting:

fantasm build main.asm -d zxnext --ram 512k

or ram = "512k" under [assembler] — see The Project File.

This narrows the valid bank range rather than describing the hardware. It defaults to the machine’s maximum, so a Next allows banks 0–127. 512K is 32 banks, and the build tells you when you exceed it:

bank 31    ok
bank 32    Error [E1082]: Invalid address or bank

A program that must run on a 512K machine then fails at your desk rather than on the desk of whoever owns one.

Accepted forms are 2mb, 1mb, 512k, or a bare number in KiB.

Paged Code Under !test

!test blocks run on a paged machine that mirrors the assembler’s slot map, so a test that pages memory reads and executes the right physical page. Runtime NEXTREG MMU writes and the 128K paging port remap slots live, as they would on hardware.

For the default layout every slot maps to a different page, so a test that does no paging behaves exactly as it would against a flat 64 KiB. See Testing.

Limitations

Cross-bank library code is not supported by --gc-modules. A module body placed in a different bank from the code that calls it is untested with elimination on, and is not diagnosed. If you page banks yourself and call across them, leave --gc-modules off — see Modules.

zx16 refuses anything above $8000, which is the machine’s own ceiling rather than a budget you set. -M/max_code_size is the separate limit on how much code there is; see Command Line.

Documentation