Klive Z80 AssemblerZX Spectrum Next

ZX Spectrum Next Development

The ZX Spectrum Next assembler in Klive IDE provides a comprehensive development environment for the ZX Spectrum Next platform. This page covers all Next-specific features, including automatic conveniences, the .savenex pragma, and NEX file generation.

Quick Start

The simplest ZX Spectrum Next program in Klive IDE looks like this:

.model next
 
.savenex file "myapp.nex"
 
; Your code starts at $8000 automatically
main:
    ld a, 4
    out (0xFE), a    ; Set border color to green
trap: 
    jr $

When you use .model next, Klive automatically:

  • Sets .savenex ram 768 (768K RAM)
  • Sets .savenex border 7 (white border)
  • Sets .savenex entryaddr $8000 (entry at $8000)
  • Maps unbanked code to bank 2 at address $8000

Automatic Conveniences for .model next

Default .savenex Values

When .model next is specified, these defaults are automatically applied:

ParameterDefault ValueDescription
ram768768K RAM configuration
border7White border color
entryaddr$8000Entry point at $8000

You can override any default by explicitly specifying the .savenex pragma:

.model next
 
.savenex file "myapp.nex"
.savenex border 5        ; Override default (use cyan instead of white)
.savenex ram 1792        ; Override default (use 1792K instead of 768K)
 
; Code...

Unbanked Code (Automatic Bank 2 Mapping)

When you write code without an explicit .bank pragma, it’s considered “unbanked” code and automatically:

  1. Starts at $8000 - The default assembly address is $8000
  2. Maps to Bank 2 - During NEX export, unbanked code is written to bank 2
  3. Uses the range $8000-$bfff - The standard 16KB bank 2 address range

Example - Simple unbanked program:

.model next
 
.savenex file "simple.nex"
 
; This code is unbanked - automatically starts at $8000 and maps to bank 2
main:
    ld a, 3
    call setborder
trap:
    jr $
 
setborder:
    out (0xFE), a
    ret

Address Range Warning (Z0904)

The assembler warns you if unbanked code exceeds the typical bank 2 range ($bfff):

.model next
 
.savenex file "test.nex"
 
.org $c000              ; ⚠️ Warning Z0904: Address $c000 exceeds $bfff
    ld a, 7
trap:
    jr $

The warning message is:

Warning Z0904: Unbanked code address $c000 exceeds typical bank 2 range ($8000-$bfff). 
Consider using .bank pragma for explicit memory layout.

Note: This is a warning, not an error. Your code will still compile and the NEX file will be generated, but you should review whether you intended to extend beyond the standard bank 2 range.

Multiple Unbanked Sections

You can have multiple unbanked code sections at different addresses using .org:

.model next
 
.savenex file "multi.nex"
 
; First section at $8000
    ld a, 1
    call routine1
 
; Second section at $9000
.org $9000
routine1:
    out (0xFE), a
    ret
 
; Third section at $a000
.org $a000
routine2:
    ld a, 2
    ret

All unbanked sections are collected and written to bank 2 in the NEX file at their respective addresses.

Multi-Bank Applications

For complex applications requiring multiple memory banks, use explicit .bank pragmas alongside unbanked code:

.model next
 
.savenex file "screen-tests.nex"
.savenex core "3.1.0"
 
; Unbanked code in bank 2 at $8000
main:
    ; 
    ; Save the current MMU 5 value ($A000-$BFFF)
    ld a,$55
    ld bc,$243b
    out (c),a
    inc b
    in a,(c)
    push af
    ;
    ; Page in the first 8K of 16K Bank $20 to $A000-$BFFF
    di
    nextreg $55,$40
    ;
    ; Invoke the subrouting in Bank $20
    call SetBorder
    ;
    ; Restore the old MMU 5 value
    pop af
    nextreg $55,a
    ei
trap 
    jr $
 
 
; Explicit bank $20 code
.bank $20
.org $0000
.disp $a000
 
SetBorder
    ld a,3
    out ($fe),a
    ret

How Multi-Bank Code Works

  • Unbanked code exports to bank 2 at the addresses where it’s assembled ($8000-$bfff typically)
  • .bank sections export to their specified bank (e.g., bank 5) at the addresses defined by .org and .disp
  • Both can coexist in the same source file
  • Each bank section is independent

SAVENEX Pragma Reference

The .savenex pragma provides a declarative way to configure ZX Spectrum Next NEX file generation parameters directly in your assembly source code. This pragma is only available when targeting the ZX Spectrum Next (Model 4).

Overview

The .savenex pragma uses a subcommand syntax where each subcommand configures a specific aspect of the NEX file. You can use multiple .savenex pragmas throughout your source code, and the compiler will collect and merge all declarations into a complete NEX file configuration.

Syntax:

.savenex <subcommand> <parameters>

The pragma is case-insensitive, so .savenex, .SAVENEX, and .SaveNex are all valid.

Subcommands

FILE - Set Output Filename

Specifies the name of the NEX file to be generated.

Syntax:

.savenex file <filename>
  • filename: String literal or expression that evaluates to a string

Example:

.savenex file "myprogram.nex"

RAM - Set RAM Configuration

Specifies the amount of RAM required by the program.

Syntax:

.savenex ram <size>
  • size: Must be either 768 (for 768K RAM) or 1792 (for 1792K RAM)
  • Default when .model next is used: 768

Examples:

.savenex ram 768    ; 768K RAM (default for .model next)
.savenex ram 1792   ; 1792K RAM

BORDER - Set Border Color

Specifies the border color to be set when the program loads.

Syntax:

.savenex border <color>
  • color: Integer value from 0 to 7
  • Default when .model next is used: 7 (white)

Example:

.savenex border 5   ; Cyan border

Border Colors:

ValueColor
0Black
1Blue
2Red
3Magenta
4Green
5Cyan
6Yellow
7White

CORE - Specify Required Core Version

Specifies the minimum ZX Spectrum Next core version required to run the program.

Syntax:

.savenex core <major>, <minor>, <subminor>
; or
.savenex core <version-string>
  • major: Integer value from 0 to 255
  • minor: Integer value from 0 to 255
  • subminor: Integer value from 0 to 255
  • version-string: String literal in the format “major.minor.subminor”

Examples:

.savenex core 3, 1, 10       ; Requires core version 3.1.10 or higher
.savenex core "3.1.10"       ; Alternative string format

Note: Both formats are supported. The string format is convenient when the version comes from a constant or macro, while the comma-separated format allows for calculated values.

STACKADDR - Set Stack Pointer Address

Specifies the initial stack pointer address.

Syntax:

.savenex stackaddr <address>
  • address: Integer value from 0 to 0xFFFF

Example:

.savenex stackaddr 0xFF00

ENTRYADDR - Set Entry Point Address

Specifies the program’s entry point address.

Syntax:

.savenex entryaddr <address>
  • address: Integer value from 0 to 0xFFFF
  • Default when .model next is used: $8000

Example:

.savenex entryaddr 0x8000    ; Entry at $8000 (default for .model next)

ENTRYBANK - Set Entry Bank

Specifies the bank number to be paged in when the program starts.

Syntax:

.savenex entrybank <bank>
  • bank: Integer value from 0 to 111

Example:

.savenex entrybank 5

FILEHANDLE - Set File Handle Mode

Specifies whether to close or keep open the NEX file handle after loading.

Syntax:

.savenex filehandle <mode>
  • mode: Either “close” (close file after loading) or “open” (keep file open, pass handle in BC register)
  • Default: “close” (file is closed after loading)

Examples:

.savenex filehandle "close"  ; Close file after loading (default)
.savenex filehandle "open"   ; Keep file open, pass handle in BC register

NEX File Specification:

  • “close” writes 0x0000 to offset 140 (file is closed by loader)
  • “open” writes 0x0001 to offset 140 (file kept open, handle passed in BC register)

PRESERVE - Preserve Next Registers

Specifies whether to preserve the Next hardware registers after loading.

Syntax:

.savenex preserve <value>
  • value: “on”/“off” or 1/0

Examples:

.savenex preserve "on"
.savenex preserve 1
.savenex preserve "off"
.savenex preserve 0

SCREEN - Configure Loading Screen

Specifies a loading screen to display while the program loads.

Syntax:

.savenex screen <type> [, <filename> [, <palette-offset>]]
  • type: Screen type - one of: “layer2”, “ula”, “lores”, “hires-color”, “hires-mono”
  • filename: (Optional) Filename of the screen data
  • palette-offset: (Optional) Offset in the palette file (0-255)

Examples:

.savenex screen "layer2"
.savenex screen "layer2", "loading.scr"
.savenex screen "layer2", "loading.scr", 0

PALETTE - Set Palette File

Specifies a palette file to load.

Syntax:

.savenex palette <filename>
  • filename: String literal with the palette filename

Example:

.savenex palette "colors.nxp"

COPPER - Set Copper Code File

Specifies a copper code file to load and execute.

Syntax:

.savenex copper <filename>
  • filename: String literal with the copper code filename

Example:

.savenex copper "effects.cu"

BAR - Configure Loading Bar

Configures the loading bar display.

Syntax:

.savenex bar <enabled> [, <color> [, <delay> [, <start-delay>]]]
  • enabled: “on”/“off” or 1/0
  • color: (Optional) Bar color (0-255)
  • delay: (Optional) Delay per bar step (0-255)
  • start-delay: (Optional) Delay before starting (0-255)

Examples:

.savenex bar "on"
.savenex bar "on", 2
.savenex bar "on", 2, 50
.savenex bar "on", 2, 50, 100

NEX File Format

The NEX file format (see details here) is the native executable format for the ZX Spectrum Next. It’s a container format that includes:

  • Header Information: File version, RAM requirements, entry points, etc.
  • Screen Data: Optional loading screen in various formats
  • Palette Data: Optional palette information
  • Copper Code: Optional copper coprocessor code
  • Loading Bar: Optional visual feedback during loading
  • Program Banks: The actual program code and data organized in 16K banks

NEX File Version

The .savenex pragma targets NEX file format version 1.2, which is the current standard for ZX Spectrum Next executables.

Bank Organization

The NEX file organizes code and data into 16K banks that correspond to the Next’s memory management system:

  • Banks 0-1: ROM (read-only, system)
  • Bank 2: Default user code bank (unbanked code maps here automatically)
  • Banks 3-4: Standard RAM banks
  • Banks 5-111: Extended RAM banks available for paging

How Unbanked Code Maps to Bank 2

When you use .model next and write code without explicit .bank pragmas:

  1. Your code is assembled at addresses starting from $8000
  2. During NEX export, this “unbanked” code is written to bank 2
  3. The offset calculation is: bank2_offset = address - $8000
  4. Code at $8000 goes to offset 0 in bank 2
  5. Code at $9000 goes to offset $1000 in bank 2
  6. And so on…

Example:

.model next
.savenex file "test.nex"
 
; Code at $8000 → bank 2, offset $0000
main:
    ld a, 1
 
; Code at $9000 → bank 2, offset $1000
.org $9000
routine:
    ld a, 2

Loading Process

When a NEX file loads on the ZX Spectrum Next:

  1. The NEX loader reads the header to determine requirements
  2. If specified, the loading screen is displayed
  3. If enabled, the loading bar provides visual feedback
  4. Program banks are loaded into the specified memory locations
  5. Hardware registers are configured according to the NEX header
  6. Control is transferred to the entry point address with the entry bank paged in

Default Values

Default values for .savenex parameters depend on whether you’re using .model next:

With .model next (Automatic Conveniences)

ParameterDefault ValueDescription
ram768768K RAM
border7White border
entryaddr$8000Entry point at $8000
entryBank0Bank 0
fileHandle”close”Close NEX file after loading
preserveRegsfalseDon’t preserve registers

Without .model next (Traditional Mode)

ParameterDefault ValueDescription
ram(none)Must be specified
border0Black border
entryaddr(none)Must be specified
entryBank0Bank 0
fileHandle”close”Close NEX file after loading
preserveRegsfalseDon’t preserve registers

Error Handling

The assembler will generate errors if:

  • You use .savenex when not targeting the ZX Spectrum Next (Model 4)
  • Invalid values are provided (e.g., border color > 7, bank > 111)
  • Required parameters are missing
  • Invalid screen types or modes are specified
  • Version numbers exceed 255

The assembler will generate warnings if:

  • Z0904: Unbanked code address exceeds $bfff (typical bank 2 range)

Notes

  • The .savenex pragma only configures the NEX file parameters; it doesn’t generate the actual NEX file. The file generation happens during the export process.
  • Multiple .savenex pragmas with the same subcommand will use the last value specified.
  • Expression support allows you to use symbols, calculations, and other expressions for numeric parameters.
  • String parameters can be string literals or expressions that evaluate to strings.
  • Unbanked code is automatically tracked and exported to bank 2 during NEX file generation.
  • You can mix unbanked code and explicit .bank sections in the same source file.

See Also