;;; docs design (missing the changes after V1.3 introduction, added directly in docs.xml)
; SAVENEX <command> <command arguments>
; Works only in ZXSPECTRUMNEXT device emulation mode. See DEVICE.
;
; For file format details, check https://specnext.dev/wiki/NEX_file_format
;
; As the file is designed for self-contained distribution of whole applications/games,
; its configuration and assembling is a bit too complex for single directive, and the
; configuration is instead divided into multiple commands, and the assembling goes
; through multiple stages, so some commands must be used in correct sequence.
;
; While the format technically allows to include multiple screen types data, they are
; all loaded at the beginning over each other, so it makes sense to provide only single
; loading screen (sjasmplus enforces that).
;
; More detailed description of each command follows:
;
; SAVENEX OPEN <filename>[,<startAddress>[,<stackAddress>[,<entryBank 0..111>]]]
; Opens a NEX file, defines start address and stack address (if omitted, start address is
; zero = no start, stack address is 0xFFFE, entryBank is zero), and 16k bank to be mapped
; at 0xC000 before code is started.
;
; Only single NEX file can be open at the same time, and to finalize the header content
; the command CLOSE has to be used (does auto-close if source ends).
;
; Entry bank is number of 16k bank (0..111), not native 8k page, default is zero, i.e.
; the default memory map is identical to ZX 128 (ROM, RAM banks 5, 2 and 0).
;
; Make sure your new stack has at least tens of bytes available as those will be used
; already by the NEX loader before executing your entry point (although released back).
;
; SAVENEX CORE <major 0..15>,<minor 0..15>,<subminor 0..255>
; Set minimum required Next core version, can be set any time before CLOSE.
;
; SAVENEX CFG <border 0..7>[,<fileHandle 0/1/$4000+>[,<PreserveNextRegs 0/1>[,<2MbRamReq 0/1>]]]
; Set border colour (during loading), whether the machine should be set to default state
; (PreserveNextRegs = 0 = default), if the app requires extended RAM (224 8k pages) and
; how the file handle of the NEX file should be treated: 0 = default = close, 1 = keep
; open and pass in BC, $4000..$FFFE = keep open, and write into memory at provided address
; (after entry bank is paged in). This can be set any time before CLOSE.
;
; SAVENEX BAR <loadBar 0/1>,<barColour 0..255>[,<startDelay 0..255>[,<bankDelay 0..255>]]
; Loading-bar related setup ("colour" usage depends on screen mode), can be set any time
; before CLOSE.
;
; SAVENEX SCREEN L2 [<Page8kNum 0..223>,<offset>[,<palPage8kNum 0..223>,<palOffset>]]
; Layer 2 loading screen, can be used between OPEN and first AUTO/BANK command.
;
; Palette consists of 512 bytes (256 palette items from index 0), in 9b colour format:
; first byte is %RRRGGGBB, second byte is %P000000B (P is priority flag for Layer 2 colours).
;
; Image data are 48kiB block of memory, the loader will use always banks 9..11 to display
; it (8k pages 18..23), but if you will prepare the data there, it will be also re-saved
; by AUTO command, so either use other banks, and overwrite them with valid data/code
; after using the SCREEN command, or reset pages 18..23 to zero after SCREEN.
;
; If no memory address is specified, the pages 18..23 are stored in file, and if no
; palette address is specified, no-palette flag is set in NEX file.
;
; SAVENEX SCREEN LR [<Page8kNum 0..223>,<offset>[,<palPage8kNum 0..223>,<palOffset>]]
; LoRes (128x96) loading screen, can be used between OPEN and first AUTO/BANK command.
;
; Palette is similar to Layer 2 mode, just LoRes mode doesn't have priority bit.
;
; Image data are 12288 bytes memory block - either consecutive block if specific address
; is provided, or without address the actual bank 5 memory is stored (taking 6144 bytes
; from address 0x4000 and 6144 bytes from address 0x6000).
;
; SAVENEX SCREEN (SCR|SHC|SHR) [<hiResColour 0..7>]
; ULA/Timex modes loading screen, can be used between OPEN and first AUTO/BANK command.
;
; The actual bank 5 memory (pages 10..11) is stored as if the image is displayed, in
; these modes the palette can't be specified.
;
; SCR is classic ZX 6912 bytes long screen from address 0x4000 (page 10 is used, even
; if the slot 1 is modified to other page, so you must prepare the image "in place").
;
; SHC and SHR are Timex HiColor (8x1 attribute) and HiRes (512x192 bitmap) modes, prepare
; data "in place", i.e. 6144 bytes into page 10 and 6144 bytes into page 11 (0x4000 and
; 0x6000 addresses in default memory setup). For HiRes mode you should specify ink colour
; (the paper is complement of ink).
;
; SAVENEX BANK <bank 0..111>[,...]
; Can be used after OPEN or SCREEN and before CLOSE, but the 16ki banks must be saved in
; correct order: 5, 2, 0, 1, 3, 4, 6, 7, ..., 111
;
; SAVENEX AUTO [<fromBank 0..111>[,<toBank 0..111>]]
; Can be used after OPEN or SCREEN and before CLOSE. The sjasmplus will save every
; 16k bank containing at least one non-zero byte; detected in the correct order
; (automatically starting from first possible bank after previous BANK/AUTO commands,
; or from provided "fromBank").
;
; For "fromBank" value use the specified order above in BANK command, i.e. 5, 2, 0, ...
;
; SAVENEX CLOSE [<fileToAppend>]
; Can be used after OPEN. The currently open NEX file will be finalized (header adjusted),
; and optional extra file just appended to the end of NEX file.
DEVICE NONE ; correct commands, but outside of NEXT device
SAVENEX OPEN "savenexSyntax.nex", $8000,$FFE0, 15 ; not in NEXT mode
DEVICE ZXSPECTRUMNEXT
SAVENEX NEPO ; wrong command
;; OPEN <filename>[,<startAddress>,<stackAddress>[,<entryBank 0..111>]]
; errors - [un]expected arguments
SAVENEX
SAVENEX ; no command, but with comment
SAVENEX OPEN
SAVENEX OPEN "savenexSyntax.nex",
SAVENEX OPEN "savenexSyntax.nex", $8000,
SAVENEX OPEN "savenexSyntax.nex", $8000,$FFE0,
SAVENEX OPEN "savenexSyntax.nex", $8000,$FFE0, 15,
SAVENEX OPEN "savenexSyntax.nex", $7170, $F1F0, 112 ; error entryBank
; one correct NEX file to verify simple case (but induce all sorts of warnings)
SAVENEX OPEN "savenexSyntax.nex", $18180,$1F1F0, 'B'
; error = NEX file is already open
SAVENEX OPEN "savenexSyntax.nex", $8180, $F1F0, 'B'
;; CORE <major 0..15>,<minor 0..15>,<subminor 0..255>
; errors - [un]expected arguments
SAVENEX CORE
SAVENEX CORE 0
SAVENEX CORE 0,
SAVENEX CORE 0,0
SAVENEX CORE 0,0,
SAVENEX CORE 0,0,0,
; one correct + one with warnings
SAVENEX CORE 15,15,255
SAVENEX CORE 'a','b',$100+'c' ; warn about values
;; CFG <border 0..7>[,<fileHandle 0/1/$4000+>[,<PreserveNextRegs 0/1>[,<2MbRamReq 0/1>]]]
; errors - [un]expected arguments
SAVENEX CFG
SAVENEX CFG 5,
SAVENEX CFG 5, 1,
SAVENEX CFG 5, 1, 1,
SAVENEX CFG 5, 1, 1, 1,
; correct ones with value warnings, and omitting optional arguments
SAVENEX CFG 9
SAVENEX CFG 5, -1
SAVENEX CFG 5, 1, 2
SAVENEX CFG 5, "hf", 1, 1 ; one completely correct (no warning)
SAVENEX CFG 5, "hf", 1, 'R'
;; BAR <loadBar 0/1>,<barColour 0..255>[,<startDelay 0..255>[,<bankDelay 0..255>]]
; errors - [un]expected arguments
SAVENEX BAR
SAVENEX BAR 1
SAVENEX BAR 1,
SAVENEX BAR 1, 'L',
SAVENEX BAR 1, 'L', 'D',
SAVENEX BAR 1, 'L', 'D', 'd',
; correct ones with value warnings, and omitting optional arguments
SAVENEX BAR 2, 255
SAVENEX BAR 1, 256
SAVENEX BAR 1, 255, 256
SAVENEX BAR 1, 255, 255, 256
SAVENEX BAR 1, 'L', 'D', 'd' ; one fully valid (no warning)
;; SCREEN L2 [<Page8kNum 0..223>,<offset>[,<palPage8kNum 0..223>,<palOffset>]]
; errors - [un]expected arguments
SAVENEX SCREEN
SAVENEX SCREEN NEERCS
SAVENEX SCREEN L2 9
SAVENEX SCREEN L2 9 ,
SAVENEX SCREEN L2 9 , $1FFF ,
SAVENEX SCREEN L2 9 , $1FFF , 10
SAVENEX SCREEN L2 9 , $1FFF , 10 ,
SAVENEX SCREEN L2 9 , $1FFF , 10 , $1800,
; errors - wrong values
SAVENEX SCREEN L2 224, 0, 0, 0 ; pagenum outside of range
SAVENEX SCREEN L2 0, 0, 224, 0 ; pagenum outside of range
SAVENEX SCREEN L2 218, 1, 0, 0 ; values in range, but leaks out of memory
SAVENEX SCREEN L2 0, $1B4001, 0, 0 ; values in range, but leaks out of memory
SAVENEX SCREEN L2 0, 0, 223, 7681 ; values in range, but leaks out of memory
SAVENEX SCREEN L2 0, 0, 0, $1BFE01 ; values in range, but leaks out of memory
SAVENEX SCREEN L2 218, 1 ; values in range, but leaks out of memory
SAVENEX SCREEN L2 0, $1B4001 ; values in range, but leaks out of memory
; not testing correct variants, because it would make impossible to test other types
;; SCREEN LR [<Page8kNum 0..223>,<offset>[,<palPage8kNum 0..223>,<palOffset>]]
; errors - [un]expected arguments
SAVENEX SCREEN LR 5
SAVENEX SCREEN LR 5 ,
SAVENEX SCREEN LR 5 , $1FFF ,
SAVENEX SCREEN LR 5 , $1FFF , 10
SAVENEX SCREEN LR 5 , $1FFF , 10 ,
SAVENEX SCREEN LR 5 , $1FFF , 10 , $1800,
; errors - wrong values
SAVENEX SCREEN LR 224, 0, 0, 0 ; pagenum outside of range
SAVENEX SCREEN LR 0, 0, 224, 0 ; pagenum outside of range
SAVENEX SCREEN LR 222, $1001, 0, 0 ; values in range, but leaks out of memory
SAVENEX SCREEN LR 0, $1BD001, 0, 0 ; values in range, but leaks out of memory
SAVENEX SCREEN LR 0, 0, 223, 7681 ; values in range, but leaks out of memory
SAVENEX SCREEN LR 0, 0, 0, $1BFE01 ; values in range, but leaks out of memory
SAVENEX SCREEN LR 222, $1001 ; values in range, but leaks out of memory
SAVENEX SCREEN LR 0, $1BD001 ; values in range, but leaks out of memory
; not testing correct variants, because it would make impossible to test other types
;; SCREEN (SCR|SHC|SHR) [<hiResColour 0..7>]
; there's basically no syntax error possible with these
;; BANK <bank 0..111>[,...]
; errors - invalid/missing arguments (will eventually also save some banks correctly)
SAVENEX BANK ()
SAVENEX BANK -1
SAVENEX BANK 112
SAVENEX BANK 5, ; bank 5 will be stored
SAVENEX BANK 0, 2, 3 ; bank 0 will be stored, 2 = wrong order
; revisit screen errors - here no screen should work because bank was written already
SAVENEX SCREEN L2
SAVENEX SCREEN LR
SAVENEX SCREEN SCR
SAVENEX SCREEN SHC
SAVENEX SCREEN SHR 10
;; AUTO [<fromBank 0..111>[,<toBank 0..111>]]
SAVENEX AUTO 21,
SAVENEX AUTO 21, 25,
SAVENEX AUTO -1, 20
SAVENEX AUTO 112, 20
SAVENEX AUTO 21, -1
SAVENEX AUTO 21, 112
SAVENEX AUTO 21, 20
SAVENEX AUTO 5, 1 ; already stored by BANK above
SAVENEX AUTO 0, 1
SAVENEX AUTO 1, 1 ; correct one (but bank is zeroed = no output)
SAVENEX AUTO 1, 1 ; but disabled for second try
SAVENEX AUTO ; correct (but all zeroes = no output)
SAVENEX AUTO ; but all are disabled now
;; CLOSE [<fileToAppend>]
SAVENEX CLOSE "savenexSyntax.asm" ; correct one (there's not much to do wrong
SAVENEX CLOSE ; should be error (no NEX is open)
;; create small NEX for BIN comparison, if the thing at least somewhat works
;; also verify it works twice per source (in sequential order)
SAVENEX OPEN "savenexSyntax.bin", $5000
SAVENEX CORE 2,0,28 : SAVENEX CFG 4,0,0,1 : SAVENEX BAR 0,0,100,0
ORG $4800 : DB $45, $5F, $F5, $44
ORG $5000 : jr $ ; infinite JR loop
SAVENEX AUTO 5, 5 ; should store bank5
; let it close automatically by ending source
END $7170 ; invoke warning about different start address