ZX-V Documentation Español Try it in your browser

BASIC reference

This page describes every statement, function and operator of ZX-V BASIC, plus the error messages, the character set and the limits of the machine. It is a reference: to learn the language step by step, start with the BASIC course; to learn how to type and change programs, read the editor.

How to read this reference

Each entry starts with its syntax, in a box:

PRINT [AT row, column;] [item] [; item]...

Then comes what the keyword does, its parameters and their ranges, a short example you can type, and related entries (See also). When an argument is out of range you get an error report, written as its code and message, for example B Integer out of range (see Error messages).

A statement (also called a command) does something: PRINT, GO TO, BEEP. A function gives back a value and is used inside expressions: SQR 16, LEN a$, INKEY$. Most statements can be typed either in a program line (with a line number, to be run later) or as a direct command (without a number, run as soon as you press Enter).

If you know the Spectrum: ZX-V BASIC runs Sinclair BASIC programs from the 48K, plus PLAY from the 128K, and adds many extensions (structured loops, procedures, labels, error trapping, sprites, files...). Keywords are typed letter by letter, as on the 128K, not with single keys.

Contents

The language

Program lines and statements

A program is a list of lines. Each line starts with a line number from 1 to 9999; the lines are kept in order of their numbers, whatever order you type them in. A line can hold several statements separated by colons (:):

10 PRINT "Hello": PRINT "again"
20 GO TO 10

Line numbers usually go in tens (10, 20, 30...) so there is room to add lines in between later; RENUM tidies them up again. A line typed without a number is a direct command and runs at once.

When something goes wrong, the error report says where: 2 Variable not found, 20:1 means statement 1 of line 20 (see Reports).

Numbers

Numbers can be written as 42, -7, 3.25, .5 or in scientific notation: 1E6 is 1 000 000 and 2.5E-3 is 0.0025. They go from about ±2.9E-39 to ±1.7E38; a result beyond that gives 6 Number too big, and a smaller one becomes 0. BIN writes a number in binary.

PRINT shows up to 8 significant digits, and switches to scientific notation for very large or very small numbers:

PRINT 1/3, 2^31, 1E10, 0.000001

shows 0.33333333, 2.1474836E+9, 1E+10 and 1E-6.

Comparisons (=, <, >...) are done with the same precision as the Spectrum, so 0.1*3=0.3 is true.

Strings

A string is a piece of text between double quotes: "Hello". To put a quote inside a string, write it twice: PRINT "say ""hi""" shows say "hi". The empty string is "". Strings can be as long as memory allows.

+ joins strings: "ZX" + "-V" is "ZX-V".

Slicing takes part of a string. Character positions start at 1:

Expression Result Meaning
"hello"(2 TO 4) "ell" characters 2 to 4
"hello"(3) "l" character 3
"hello"(TO 2) "he" from the start to 2
"hello"(4 TO) "lo" from 4 to the end

A slice where the start is after the end is the empty string; a position outside the string gives 3 Subscript wrong. Slices work on string variables, literals and any expression in brackets: (a$+b$)(2 TO). You can also assign to a slice: LET a$(1)="J" changes the first character (the length of a$ does not change).

Strings are compared character by character using their codes (see Character set), so "B"<"a" is true and "ab"<"abc" is true.

Variables

A variable holds a value under a name.

A variable is created the first time it is given a value (with LET, INPUT, READ or FOR). Reading a variable that does not exist gives 2 Variable not found. RUN and CLEAR delete all the variables.

10 LET my score=10
20 LET a$="Ann"
30 PRINT a$; " has "; MyScore; " points"

Arrays

An array is a numbered list of values (or a table, with several dimensions). It has a single-letter name and is created with DIM:

10 DIM t(5): DIM g(3,3)
20 LET t(1)=100: LET g(2,3)=7
30 PRINT t(1); " "; g(2,3); " "; t(5)

Subscripts start at 1. Numeric arrays start full of zeros. A numeric array and a numeric variable can share a letter (a and a(1) are different). A string array a$ replaces the string variable a$.

String arrays are arrays of characters: the last dimension is the fixed length of each string. DIM n$(3,10) makes 3 strings of 10 characters, filled with spaces. n$(2) is the second string, and n$(2,1) its first character. Assigning a shorter text fills the rest with spaces; a longer one is cut:

10 DIM n$(2,5)
20 LET n$(1)="hello world"
30 PRINT n$(1); "|"; n$(2); "|"

shows hello| |.

Expressions and operators

An expression combines values with operators. When there are several operators, the ones with higher priority are worked out first:

Priority Operators Meaning
highest functions SIN x, LEN a$... take only the value right after them
10 ^ power
9 - (in front) change of sign
8 * / multiplication, division
6 + - addition (and joining strings), subtraction
5 = < > <= >= <> comparisons
4 NOT logical not
3 AND logical and
lowest OR logical or

Operators with the same priority are worked out from left to right, so 2^3^2 is (2^3)^2 = 64. Change of sign goes after the power: -2^2 is -4. Brackets change the order: (1+2)*3 is 9.

Functions take only the value that follows them: SQR 16+9 is (SQR 16)+9 = 13, and SQR (16+9) is 5. When in doubt, use brackets.

Dividing by zero gives 6 Number too big. A power of a negative number gives A Invalid argument.

True and false

Comparisons give 1 when true and 0 when false: PRINT 3>2 shows 1. IF, WHILE and UNTIL take any number, and treat 0 as false and anything else as true.

Expression Value
NOT x 1 if x is 0, otherwise 0
x AND y x if y is not 0, otherwise 0
x OR y 1 if y is not 0, otherwise x
a$ AND y a$ if y is not 0, otherwise ""

So IF a>0 AND a<10 THEN ... works as you expect, and a trick like PRINT ("yes" AND ok); ("no" AND NOT ok) prints one word or the other.

Whole-number arguments

Many statements need whole numbers (a line number, a colour, a coordinate). If you give a number with decimals it is rounded to the nearest whole number (2.5 becomes 3). If the result is out of the allowed range, you get B Integer out of range (or K Invalid colour for colours).

Program flow

GO TO

GO TO line
GO TO @label

Jumps to a line and carries on from there. line can be any expression (GO TO n*100). If that line does not exist, it goes to the next one after it; if there is none, the program ends. With a label it jumps to that exact statement.

10 PRINT "forever"
20 GO TO 10

Press BREAK (Esc) to stop it.

See also: GO SUB, @label, RUN.

GO SUB, RETURN

GO SUB line
GO SUB @label
RETURN

GO SUB jumps to a subroutine, like GO TO, but remembers where it came from; RETURN goes back to the statement after the GO SUB. Subroutines can call other subroutines (up to 512 levels). RETURN without a GO SUB gives 7 RETURN without GOSUB.

10 GO SUB 100: GO SUB 100
20 STOP
100 PRINT "in the subroutine"
110 RETURN

See also: DEF PROC, which is usually clearer.

IF, THEN, ELSE

IF condition THEN statements
IF condition THEN statements ELSE statements

IF condition THEN
  lines
ELSE IF condition THEN
  lines
ELSE
  lines
END IF

If the condition is true (not 0), the statements after THEN run. If it is false, they are skipped: the program carries on at the statements after ELSE, if there is one on the same line, or at the next line. A number after THEN is an error (IF a THEN 100; write IF a THEN GO TO 100).

10 LET n=-5
20 IF n<0 THEN PRINT "negative" ELSE PRINT "zero or positive"
30 IF n<0 THEN PRINT "a": PRINT "b" ELSE PRINT "c": PRINT "d"

Line 30 prints a and b. Everything after THEN up to ELSE belongs to the true part, and everything after ELSE up to the end of the line to the false part. With several IF on one line, each ELSE goes with the nearest IF.

The block IF. If THEN is the last thing on the line, the IF opens a block of several lines, which ends at END IF. Inside it there can be ELSE IF condition THEN parts (also at the end of their line), tried in order if nothing before was true, and an ELSE part for when none is. Only one part runs; then the program carries on after END IF.

10 INPUT "Age? ";a
20 IF a<13 THEN
30 PRINT "Child"
40 ELSE IF a<18 THEN
50 PRINT "Teenager"
60 ELSE
70 PRINT "Adult"
80 IF a>=65 THEN PRINT "Retired"
90 END IF

See also: SELECT CASE, WHILE, Expressions.

SELECT CASE

SELECT CASE value
CASE values
  lines
CASE ELSE
  lines
END SELECT

Chooses a part by value, a number or a string: the part of the first CASE that matches runs (or the CASE ELSE part if none does), and the program carries on after END SELECT. If none matches and there is no CASE ELSE, nothing runs. Each CASE has a list of values separated by commas, which can be:

Value Matches if
5, "yes", a+1 value is equal
1 TO 9, "a" TO "m" value is between the two (both included)
< 0, >= 100, <> 7 value passes the comparison
10 INPUT "A key? ";k$
20 SELECT CASE k$
30 CASE "q", "Q": PRINT "Up"
40 CASE "a", "A": PRINT "Down"
50 CASE "0" TO "9"
60 PRINT "A digit"
70 CASE ELSE: PRINT "Something else"
80 END SELECT

CASE can go on its own line or after :, and the statements of each part on the same line or the following ones; it can all even go on one line (SELECT CASE n: CASE 1: PRINT "one": CASE ELSE: PRINT "other": END SELECT). SELECT CASE can go one inside another. If the value and those of a CASE are not the same type, C Nonsense in BASIC; if END SELECT is missing, Y Structure error.

See also: IF.

FOR, NEXT

FOR var = first TO last [STEP step]
NEXT var

Repeats the statements between FOR and NEXT, with the variable going from first to last, adding step each time (1 if there is no STEP). The variable is a single letter. With a negative step it counts down. If the loop should not run at all (FOR i=1 TO 0), the program jumps to after the matching NEXT; if there is none, I FOR without NEXT.

10 FOR i=1 TO 10 STEP 3: PRINT i;" ";: NEXT i
20 PRINT
30 FOR i=3 TO 1 STEP -1: PRINT i: NEXT i

After the loop the variable keeps the first value past the end (here, 0). NEXT with a variable that is not a FOR variable gives 1 NEXT without FOR.

See also: WHILE, REPEAT.

WHILE, WEND

WHILE condition
WEND

Repeats the statements between WHILE and WEND while the condition is true. The condition is checked at the start, so if it is false the first time, the loop is skipped entirely.

10 LET n=1
20 WHILE n<100: LET n=n*2: WEND
30 PRINT n

shows 128. Loops can be nested. WEND without its WHILE, or a WHILE without its WEND, gives Y Structure error.

See also: REPEAT, FOR.

REPEAT, UNTIL

REPEAT
UNTIL condition

Repeats the statements between REPEAT and UNTIL until the condition is true. The condition is checked at the end, so the loop runs at least once.

10 REPEAT
20 LET d=INT (RND*6)+1: PRINT d
30 UNTIL d=6

See also: WHILE.

DEF PROC, PROC, END PROC

DEF PROC name [(param [, param]...)]
END PROC
PROC name [(value [, value]...)]

A procedure is a named piece of program. DEF PROC starts it and END PROC ends it; PROC runs it and then comes back. The parameters receive the values given in PROC; they are local: their old values are restored at END PROC. A numeric parameter is a numeric variable name; a string parameter is a letter with $. Procedures can call themselves.

When the program reaches a DEF PROC while running normally, it skips the whole procedure, so you can put procedures anywhere.

10 PROC greet("Ann", 2)
20 PROC greet("Bob", 1)
30 STOP
100 DEF PROC greet(n$, times)
110 FOR i=1 TO times: PRINT "Hello, "; n$: NEXT i
120 END PROC

Names follow the rules of numeric variables (letters and digits, case and spaces ignored). Up to 16 parameters. Errors: Z PROC not found (no DEF PROC with that name), Q Parameter error (wrong number or type of values), Y Structure error (END PROC outside a procedure, or a DEF PROC without END PROC).

A procedure does not return a value: to give a result back, set a variable.

See also: LOCAL, GO SUB.

LOCAL

LOCAL var [, var]...

Inside a procedure, makes the variables local: they start as 0 (or "") and get their old values back at END PROC. Outside a procedure, Y Structure error.

10 LET i=99: PROC count: PRINT "i is still "; i
20 STOP
100 DEF PROC count
110 LOCAL i
120 FOR i=1 TO 3: PRINT i: NEXT i
130 END PROC

See also: DEF PROC.

@label

@name

A statement made of @ and a name marks a place in the program. GO TO, GO SUB, RUN, RESTORE and ON ERROR GO TO can jump to it by name instead of by line number, to the exact statement (it does not need to be the first one on its line). Labels do not change when you renumber. A label that does not exist gives X Label not found.

10 GO SUB @hello: GO SUB @hello
20 STOP
30 @hello: PRINT "hello": RETURN

See also: GO TO, RENUM.

RUN

RUN [line | @label]

Starts the program from the beginning, or from that line or label. Before starting it clears everything like CLEAR: deletes the variables, clears the screen, closes open files and turns off ON ERROR. To start without losing the variables, use GO TO.

See also: CONTINUE, STOP.

STOP

STOP

Stops the program with the report 9 STOP statement. CONTINUE carries on from the next statement. ON ERROR does not catch STOP.

CONTINUE

CONTINUE

Carries on after a stop: after STOP or BREAK, from the next statement; after an error, it repeats the statement that failed (useful once you have fixed the cause, for example by giving a missing variable a value).

TRACE

TRACE ON
TRACE #stream
TRACE OFF

To follow where a program goes: each time a line starts running (also when it comes back to it with GO TO, NEXT or RETURN), its number is printed in brackets, like [10][20][30]. With TRACE ON it goes to the program screen, mixed with what the program prints; with TRACE #3, to the printer (the file printer.txt), or to the file of a stream opened with OPEN #, so that the screen is not spoilt. TRACE OFF turns it off; it can also go inside the program, to follow only one part. NEW turns it off. With a stream that is not open, O Invalid stream.

TRACE ON: RUN

See also: the BASIC debugger, to stop a program at a line and look at its variables from VS Code.

REM

REM any text

A remark: everything after REM up to the end of the line is ignored, so it is the place for comments.

10 REM Space game, by Ann

PAUSE

PAUSE n

Waits n fiftieths of a second (PAUSE 50 is one second, as on the Spectrum), or until a key is pressed, whichever comes first. PAUSE 0 waits for a key for ever. Only keys pressed after the PAUSE starts count. n goes from 0 to 65535.

10 PRINT "Press a key": PAUSE 0: PRINT "Thanks"

See also: WAIT, INKEY$.

WAIT

WAIT [n]

Waits for the next frame, and until n frames (1 if omitted) have passed since the previous WAIT. There are 60 frames a second. This keeps a game loop at a steady speed even if some turns of the loop take longer than others: WAIT 2 gives 30 turns a second. n goes from 0 to 65535.

10 FOR x=0 TO 200: BOX 0,x,80,8,8: WAIT: NEXT x

See also: PAUSE, TIME.

Variables and data

LET

LET var = value

Gives a value to a variable, creating it if needed. LET is needed (a=1 on its own is an error). The value must match the type: a number for numeric variables, a string for $ variables.

10 LET a=5: LET a=a+1: LET b$="ZX"
20 LET b$(2)="-": PRINT a; b$

See also: Variables, DIM.

DIM

DIM letter(size [, size]...)
DIM letter$(size [, size]...)

Creates an array (see Arrays), replacing any array with the same name. Up to 16 dimensions; each size goes from 1 to 65535. Numeric arrays start full of zeros and string arrays full of spaces. A subscript out of range gives 3 Subscript wrong.

10 DIM s(10): LET s(3)=42: PRINT s(3), s(4)

READ, DATA, RESTORE

DATA value [, value]...
READ var [, var]...
RESTORE [line | @label]

DATA lines hold a list of values inside the program; READ takes them one by one, in order, into variables. The values can be any expression of the right type. RESTORE makes the next READ start again from the first DATA (or from the first DATA at or after that line or label). Reading past the last value gives E Out of DATA.

10 FOR i=1 TO 3
20 READ n$, age: PRINT n$; " is "; age
30 NEXT i
40 DATA "Ann", 12, "Bob", 9, "Eve", 10+1

DATA does nothing when the program reaches it.

CLEAR

CLEAR [address]

Deletes all variables, clears the screen, closes the files opened with OPEN #, forgets the GO SUB and loop returns, turns off ON ERROR and CLIP, and makes READ start from the first DATA. Sprites and other graphics are kept. RUN does a CLEAR first.

With an address, it also moves a memory limit (useful only for advanced programs): below 65536 it sets the "RAMTOP" of the virtual Spectrum memory (at least 23821, otherwise M RAMTOP no good); from 65536 up, it is a real address, and the graphics store is moved just below it, leaving the memory above it free for your own use.

DEF FN, FN

DEF FN letter([param [, param]...]) = expression
DEF FN letter$([param [, param]...]) = string expression
FN letter(values)

Defines your own function with a one-letter name and one-letter parameters (x, or a$ for strings). FN calls it. DEF FN can be anywhere in the program and does nothing when reached. Calling a function that is not defined gives P FN without DEF; the wrong number or type of values gives Q Parameter error.

10 DEF FN h(x,y)=SQR (x*x+y*y)
20 DEF FN u$(a$)=a$+"!"
30 PRINT FN h(3,4); " "; FN u$("hi")

shows 5 hi!.

Maths

SIN, COS, TAN

SIN x     COS x     TAN x

Sine, cosine and tangent of an angle x in radians (a full turn is 2*PI). To use degrees, multiply by PI/180.

PRINT SIN (PI/2); " "; COS (60*PI/180)

ASN, ACS, ATN

ASN x     ACS x     ATN x

Arcsine, arccosine and arctangent: the angle, in radians, whose sine, cosine or tangent is x. ASN and ACS need x from -1 to 1 (otherwise A Invalid argument).

PRINT 4*ATN 1

EXP, LN

EXP x     LN x

EXP x is e (2.7182818...) to the power x. LN x is the natural logarithm; x must be greater than 0 (otherwise A Invalid argument). For a logarithm in base 10 use LN x/LN 10.

SQR

SQR x

Square root. x must not be negative (A Invalid argument).

PRINT SQR 2

ABS, SGN, INT

ABS x     SGN x     INT x

PI

PI

The number π, 3.1415927.

RND, RANDOMIZE

RND
RANDOMIZE [n]

RND gives a random number from 0 up to (not including) 1. For a whole number from 1 to 6, use INT (RND*6)+1.

RANDOMIZE n (0 to 65535) starts the sequence at a fixed point, so the same "random" numbers come out again. RANDOMIZE or RANDOMIZE 0 starts it from the time since the machine was switched on.

10 RANDOMIZE
20 FOR i=1 TO 5: PRINT INT (RND*6)+1;" ";: NEXT i

If you know the Spectrum: RND gives exactly the same sequence as on the 48K.

BIN

BIN digits

Writes a number in binary: BIN 1010 is 10. Handy for designing graphics with POKE USR.

Text functions

LEN

LEN a$

The number of characters in a string. LEN "" is 0.

PRINT LEN "ZX-V"

CHR$, CODE

CHR$ n     CODE a$

CHR$ n is the character with code n (0 to 255), and CODE a$ the code of the first character of a$ (0 if it is empty). See the Character set.

PRINT CHR$ 65; " "; CODE "a"

shows A 97.

STR$, VAL, VAL$

STR$ x     VAL a$     VAL$ a$
10 LET a$="12": LET b$="30"
20 PRINT a$+b$; " "; VAL a$+VAL b$

shows 1230 42.

The screen and printing

The program screen has an upper part, where PRINT and the drawing commands work, and a lower part of two lines at the bottom, used by INPUT and by the reports. In the normal mode 0 the screen has 24 rows of 32 characters (256 × 192 pixels), and PRINT can use rows 0 to 21; in mode 1 it has 48 rows of 64 characters (see MODE).

When printing goes past the last row, the screen scrolls up. Each time a screenful has scrolled, it stops and asks scroll?: press N, Space or BREAK to stop the program (D BREAK - CONT repeats), or any other key to go on.

PRINT

PRINT [item] [separator] [item]...

Shows numbers and text on the screen. The items can be:

Item Effect
a number or string expression prints its value
AT row, column moves the print position (row 0 is at the top)
TAB column moves right to that column, filling with spaces
INK n, PAPER n, FLASH n, BRIGHT n, INVERSE n, OVER n changes the colours for the rest of this PRINT only (see Colours)
#stream prints through that stream (see Streams)

And between them, the separators:

Separator Effect
; nothing: the next item goes right after
, moves to the next half of the line (to the next column 0 or 16; in mode 1, every 16 columns)
' starts a new line

If the PRINT does not end with a separator, it moves to a new line at the end. PRINT on its own prints an empty line.

10 PRINT "Name", "Score"
20 PRINT "Ann", 120
30 PRINT AT 10,5; "at row 10"; TAB 25; "tab"
40 PRINT "one"'"two"; " and three"
50 PRINT INK 2; "red"; INK 0; " black"

AT outside the screen gives 5 Out of screen. TAB wraps round the line width.

See also: LPRINT, INPUT, Colours.

CLS

CLS

Clears the screen with the current PAPER colour and puts the print position back at the top left corner.

SCREEN$, ATTR

SCREEN$ (row, column)
ATTR (row, column)

SCREEN$ gives the character printed at that position ("" if it does not recognise it, for example a drawing). ATTR gives the colours of that character cell as one number: FLASH×128 + BRIGHT×64 + PAPER×8 + INK. Positions outside the screen give B Integer out of range.

10 PRINT AT 0,0; INK 2; PAPER 6; "A"
20 PRINT SCREEN$ (0,0); " "; ATTR (0,0)

shows A 50 (6×8 + 2).

See also: POINT, PIXEL.

LPRINT, LLIST

LPRINT [items]
LLIST [line]

Like PRINT and LIST, but to the printer. ZX-V has no paper printer: the printer is the text file printer.txt at the root of the SD card, and everything printed is added to its end. Colours and AT (except its column) are ignored. Lines are up to 64 characters long (32 in mode 0).

LPRINT "Shopping list": LPRINT "- milk"

See also: COPY, Streams.

Colours

Each character cell of the screen has an ink (the colour of the character) and a paper (the background). Colours are numbered from 0 to 7, and BRIGHT 1 makes them brighter:

Number Colour With BRIGHT 1
0 black black
1 blue bright blue
2 red bright red
3 magenta bright magenta
4 green bright green
5 cyan bright cyan
6 yellow bright yellow
7 white (light grey) bright white

The sprite and fast graphics commands, RASTER BORDER and REMAP use the 16 colours directly, from 0 to 15: 0–7 are the colours above and 8–15 their bright versions (10 is bright red). Colour 8 is black too, and is used as "transparent" in sprites. With PALETTE, each of the 16 can be any colour you like.

On ZX-V, each pixel has its own colour: drawing a pixel only changes the colour of that pixel, never its neighbours.

If you know the Spectrum: there is no colour clash. PLOT, DRAW and CIRCLE paint with the ink only, pixel by pixel; ATTR still reports the last colours written in each cell.

INK, PAPER, FLASH, BRIGHT, INVERSE and OVER can be used in two ways:

10 PAPER 1: INK 6: CLS
20 PRINT "yellow on blue"
30 PRINT PAPER 2; INK 7; "white on red, only here"
40 PRINT "yellow on blue again"

INK, PAPER

INK n     PAPER n

Ink and paper colour, from 0 to 7 (see the table), or:

Other values give K Invalid colour. PAPER takes effect on the whole screen with the next CLS.

BORDER

BORDER n

Colour of the border around the screen, 0 to 7. The lower part of the screen (the two lines of INPUT and the reports) uses the border colour as its paper.

BORDER 0: PAPER 0: INK 4: CLS

See also: RASTER BORDER, for stripes of colour.

BRIGHT, FLASH

BRIGHT n     FLASH n

BRIGHT 1 uses the bright version of the ink and paper; BRIGHT 0 the normal one. FLASH 1 makes the cell swap its ink and paper about every third of a second. 8 is transparent (keeps what the cell had). Other values give K Invalid colour.

PRINT FLASH 1; "GAME OVER"

INVERSE, OVER

INVERSE n     OVER n

INVERSE 1 prints with ink and paper swapped. OVER 1 prints over what is already there, changing each pixel of the character between ink and paper (printing the same thing twice with OVER 1 rubs it out). 0 turns them off; other values give K Invalid colour.

10 PRINT AT 5,5; "X": PRINT AT 5,5; OVER 1; "O"

Drawing with PLOT and DRAW

These commands draw on the program screen with the ink colour. Their coordinates are in pixels, with (0, 0) at the bottom left corner: x goes from 0 to 255 to the right and y from 0 to 175 upwards (the two bottom rows belong to the lower part of the screen). In mode 1, x goes to 511 and y to 367. A point outside the screen gives B Integer out of range.

You can put colour items at the start, as in PLOT INK 2; 10,10.

The fast graphics commands (BOX, SPRITE...) count y from the top instead, like PRINT AT.

PLOT

PLOT [colour items;] x, y

Draws a point and makes it the start for the next DRAW.

10 FOR x=0 TO 255 STEP 4: PLOT x, 88+40*SIN (x/20): NEXT x

DRAW

DRAW [colour items;] dx, dy [, angle]

Draws a line from the last point to the point dx pixels to the right and dy pixels up (negative values go left and down). With angle (in radians) it draws an arc instead, turning that much on the way: PI draws half a circle, and a positive angle curves anticlockwise.

10 PLOT 50,50: DRAW 100,0: DRAW 0,100: DRAW -100,-100
20 PLOT 150,60: DRAW 60,0,PI

CIRCLE

CIRCLE [colour items;] x, y, radius

Draws a circle with its centre at x, y.

10 FOR r=10 TO 80 STEP 10: CIRCLE INK r/10; 128,88,r: NEXT r

POINT

POINT (x, y)

1 if the pixel at x, y was drawn with ink, 0 if it is paper. It sees what PRINT, PLOT, DRAW and CIRCLE draw, but not the fast graphics commands (use PIXEL for those).

10 PLOT 10,10: PRINT POINT (10,10); POINT (11,10)

Video modes and screen effects

MODE

MODE n
MODE 0, width, height

Chooses the screen mode and clears the screen:

Mode Pixels Text
0 256 × 192 32 columns × 24 rows (the one at start)
1 512 × 384 64 columns × 48 rows

MODE clears both pages, shows page 0 and removes scrolling, REMAP, PALETTE, RASTER and CLIP. In mode 0, the page can also be larger than the screen, so that the screen is a window that you move over it with SCROLL: MODE 0, 512, 384, MODE 0, 1024, 192 or MODE 0, 256, 768. Then PRINT AT, PLOT and the rest cover the whole page (PRINT AT reaches column 127 on a 1024-pixel-wide page). Other sizes give A Invalid argument.

10 MODE 1: CIRCLE 256,184,150: PRINT AT 24,26; "Mode 1"

PAGE, SCREEN

PAGE n
SCREEN n

ZX-V has two screen pages, 0 and 1. PAGE chooses the one that is shown; SCREEN chooses the one where PRINT, CLS, PLOT, sprites and so on draw. Drawing on the hidden page and then showing it gives smooth animation without flicker (double buffering). Values other than 0 and 1 give A Invalid argument.

10 LET s=1
20 SCREEN s: CLS: CIRCLE 128,88,RND*80
30 PAGE s: LET s=1-s: WAIT 10: GO TO 20

Error reports and INPUT always appear on the page being shown. The editor also uses page 1: when a program uses page 1 again, the text and the PLOT and DRAW drawings are restored, but the fast graphics (sprites, maps...) drawn there are lost.

SCROLL

SCROLL x, y
SCROLL

Moves the picture without redrawing it: pixel (x, y) of the page appears at the top left corner of the screen, and the page wraps round at the edges. SCROLL alone puts it back. This is how a game scrolls a large MODE 0 page.

10 MODE 0,1024,192: CIRCLE 600,100,50
20 FOR x=0 TO 1023 STEP 2: SCROLL x,0: WAIT: NEXT x

REMAP

REMAP colour, newcolour [; colour, newcolour]...
REMAP #table; colour, newcolour [; colour, newcolour]...
REMAP #table
REMAP

Shows one colour as another everywhere on the screen, instantly and without redrawing: after REMAP 1,10, everything blue is shown bright red. Colours go from 0 to 15 (otherwise K Invalid colour). This is useful for fades, flashing and colour cycling.

There are three remap tables, 0 to 2. Without #, REMAP changes table 0, which is the one normally in use. REMAP #t; ... changes table t without showing it; REMAP #t makes the whole screen use table t (so all its changes appear at once); RASTER REMAP uses a table for some lines only. REMAP alone resets the three tables and goes back to table 0.

10 PRINT INK 1; "blinking"
20 REMAP 1,10: PAUSE 25: REMAP 1,1: PAUSE 25: GO TO 20

REMAP swaps one of the 16 colours for another; what each colour looks like is set by PALETTE.

PALETTE

PALETTE colour, r, g, b [; colour, r, g, b]...
PALETTE #table; colour, r, g, b [; colour, r, g, b]...
PALETTE #table
PALETTE

Changes how one of the 16 colours looks: r, g and b are its red, green and blue, from 0 to 255. Everything drawn in that colour changes instantly. After PALETTE 1, 255, 128, 0, blue is shown orange. The colour goes from 0 to 15 (otherwise K Invalid colour), and r, g and b from 0 to 255 (otherwise B Integer out of range).

The usual colours have 215 in each component (255 the bright ones): red is PALETTE 2, 215, 0, 0. The screen has 65,536 possible colours, and the nearest one is used.

Each REMAP table has its own palette. Without #, PALETTE changes table 0's, the one normally in use; PALETTE #t; ... changes table t's (0 to 2). So, with RASTER REMAP, each band of the screen can have its own 16 colours. PALETTE #t alone gives table t back its usual colours, and PALETTE alone does it for all three. MODE also resets them.

Colour 8 is still transparent in sprites and tiles (it is not drawn), even if the palette gives it another colour.

10 FOR i=0 TO 15: BOX i, i*16, 0, 16, 176: NEXT i
20 FOR v=0 TO 255 STEP 5: PALETTE 7, v, v, 255-v: WAIT: NEXT v

RASTER

RASTER BORDER y1, y2, colour
RASTER REMAP y1, y2, table
RASTER SCROLL y1, y2, x [, y]
RASTER

Changes things line by line on the screen, without using any processor time while the program runs:

Lines are pixel rows counted from the top of the screen (0). The border lines above the picture are negative (down to -24 in mode 0, -48 in mode 1) and those below go past the height (up to 215 in mode 0, 431 in mode 1). MODE turns this off.

10 FOR y=-24 TO 215 STEP 4: RASTER BORDER y,y+1,2: RASTER BORDER y+2,y+3,6: NEXT y

Sprites, tile maps and fast graphics

These commands use the ROM's graphics engine to draw games quickly: sprites with transparency, scrolling tile maps, a perspective floor ("mode 7") and filled shapes. They differ from PLOT and DRAW in a few ways:

Sprites, tiles, maps and textures are kept by number in a graphics store in memory. They survive RUN, CLEAR and LOAD (so a loader can prepare the graphics and then load the game), and NEW deletes them. Defining a number again replaces it. SAVE "name" GRAPHICS saves the whole store in a .gfx file, and LOAD "name" GRAPHICS loads one (see SAVE and LOAD). You can also draw them on the PC with the graphics editor zxv-gfx, which comes with the emulator, or on the machine itself with LOAD "ROM:gfxedit", or make .gfx files from PNG images with the SDK tool png2gfx (see the SDK graphics guide).

A sprite, tile set, map or texture that does not exist gives A Invalid argument; numbers out of range give B Integer out of range; and if the graphics do not fit in memory, 4 Out of memory.

GRAB

GRAB n, x, y, width, height [, t]
GRAB n, width, a$

Defines sprite n (0 to 255).

10 GRAB 0,8,"..2222..22222222.222222...2222..."
20 FOR x=0 TO 240 STEP 16: SPRITE 0,x,80: NEXT x

SPRITE

SPRITE n, x, y [, flip [, c$ [, width, height]]]

Draws sprite n with its top left corner at x, y. Its transparent pixels let the background show through.

10 GRAB 0,4,"1111122112211111"
20 SPRITE 0,10,10: SPRITE 0,30,10,0,"0a": SPRITE 0,50,10,0,"",32,32

See also: HIT, GRAB.

HIT

HIT(a, ax, ay, b, bx, by)

Collision test: 1 if any solid (not transparent) pixel of sprite a drawn at ax, ay would land on a solid pixel of sprite b drawn at bx, by; otherwise 0. Nothing is drawn.

10 GRAB 0,4,"1111111111111111"
20 PRINT HIT(0,0,0,0,3,3); HIT(0,0,0,0,4,0)

shows 10.

TILE

TILE size, n, x, y [, width, height [, t]]
TILE size, n, a$

Defines tiles for tile maps. There are two tile sets, one of 8 × 8 pixel tiles and one of 16 × 16 (size is 8 or 16, otherwise A Invalid argument), each with tiles numbered 0 to 4095.

A tile set grows when you define a higher tile; the new tiles start black.

10 BOX 2,0,0,8,8: POLY 7,0,3,7,3: TILE 8,1,0,0

MAP DIM, MAP POKE

MAP DIM m, width, height [, size [, wrap]]
MAP POKE m, x, y, value
MAP POKE m, x, y, a$

MAP DIM creates tile map m (0 to 15) with width × height cells, all set to tile 0. size is the tile size, 8 (the default) or 16. With wrap = 1 the map repeats endlessly in both directions.

MAP POKE sets the cell at column x, row y (counting from 0). The value is the tile number plus any of these:

Add Effect
4096 tile mirrored left to right
8192 tile upside down
16384 colour 8 of the tile is transparent (lets what is behind show)
32768 priority (see the filter of MAP)

With a string, it fills the cells from x to the right, using the code of each character as the tile number: " ##.." uses tiles 32, 35 and 46. This makes it easy to draw levels with text.

See also: MAP, CELL.

MAP

MAP m [, mx, my [, x, y, width, height [, filter]]]

Draws tile map m, starting at pixel mx, my of the map (0, 0 if omitted), on the whole page or in the rectangle x, y, width, height. Changing mx and my scrolls the map. filter: 0 draws all cells, 1 only those without priority and 2 only those with priority (so you can draw the background, then the sprites, then the parts of the scenery in front). All the tiles the map uses must exist (otherwise A Invalid argument).

10 BOX 5,0,0,8,8: TILE 8,32,0,0
20 BOX 2,0,0,8,8: POLY 7,0,3,7,3: TILE 8,35,0,0
30 MAP DIM 0,40,1: MAP POKE 0,0,0,"####  ####   ######  #########   ####"
40 FOR x=0 TO 64: MAP 0,x,0,0,100,256,8: WAIT: NEXT x

CELL

CELL(m, x, y)

The value of the cell at column x, row y of map m, including the mirror, transparency and priority bits. Outside a map that does not wrap, 0. Useful to check what the scenery has at some place: the cell under a sprite at pixel px, py is CELL(m, INT (px/8), INT (py/8)) for 8-pixel tiles.

TEXTURE

TEXTURE n, x, y, size [, c]

Defines texture n (0 to 3) for FLOOR: the square of size × size pixels (a power of 2 from 2 to 256: 2, 4, 8... 256; any other size gives A Invalid argument) of the drawing page with its top left corner at x, y. The texture repeats for ever; if colour c is given, everything outside it is that colour instead.

FLOOR

FLOOR n, x, y, height, angle, horizon [, focal]

Draws a floor in perspective with texture n, as seen from point x, y of the texture at that height, looking in direction angle (in radians; 0 looks towards growing x). The horizon is at line horizon of the page, and the floor fills from the line below it to the bottom of the page. focal is the focal distance (half the page width if omitted): smaller values give a wider view. This is the "mode 7" effect of racing and flying games.

10 FOR i=0 TO 7: BOX i,i*8,0,8,64: NEXT i: TEXTURE 0,0,0,64
20 FOR a=0 TO 2*PI STEP .05: FLOOR 0,32,32,20,a,80: WAIT: NEXT a

POLY

POLY colour, x1, y1 [, x2, y2]...

With one point, draws a pixel; with two, a line; with three or more (up to 64), a filled polygon.

POLY 4, 128,20, 200,150, 56,150

BOX

BOX colour, x, y, width, height

A filled rectangle with its top left corner at x, y.

BOX 2, 10,10, 100,50

DISC

DISC colour, x, y, radius

A filled circle with its centre at x, y.

DISC 6, 128,96, 40

CLIP

CLIP x, y, width, height
CLIP

From now on, the commands of this section only draw inside that rectangle. CLIP alone removes the limit (as do MODE, RUN and CLEAR).

10 CLIP 50,50,100,50: DISC 2,100,75,60: CLIP

PIXEL

PIXEL(x, y)

The colour (0 to 15) of the pixel at x, y of the drawing page, counting from the top left, whatever drew it; -1 outside the page. It ignores REMAP. Useful for collisions with anything drawn on the screen.

10 BOX 4,10,10,20,20: PRINT PIXEL(15,15); " "; PIXEL(5,5); " "; PIXEL(-1,0)

Sound and music

ZX-V has a beeper (a simple speaker, used by BEEP) and two AY sound chips with three channels each (used by PLAY, SOUND, MUSIC and SFX).

BEEP

BEEP duration, pitch

Plays a note on the beeper. duration is in seconds (0 to 10); pitch is in semitones above middle C (0 is middle C, 12 the C above, -12 the C below), from -60 to 69, and can have decimals. The program waits until the note ends.

10 FOR n=0 TO 12: BEEP 0.1,n: NEXT n

PLAY

PLAY a$ [, b$]...

Plays music written as text, with up to six voices at once: the first three strings play on the three channels of the first AY chip, and the next three on the second. The program waits until all the strings have finished; BREAK stops them. A badly written string gives A Invalid argument, and a number out of range B Integer out of range; all strings are checked before any sound starts.

Inside each string:

Text Meaning
c d e f g a b a note; upper case C...B is one octave higher
#, $ sharp or flat (before the note): #f, $b
& a rest (silence)
1 to 9 length of the following notes: 1 semiquaver (sixteenth note), 2 dotted semiquaver, 3 quaver (eighth note), 4 dotted quaver, 5 crotchet (quarter note, the default), 6 dotted crotchet, 7 minim (half note), 8 dotted minim, 9 semibreve (whole note)
10 11 12 triplets of semiquavers, quavers and crotchets: they apply to the next three notes
n_m tied lengths: the next note lasts both
O n octave, 0 to 8 (default 5, where c is middle C)
T n tempo in crotchets per minute, 60 to 240 (default 120); only in the first string
V n volume, 0 to 15 (default 15)
U use the volume envelope
W n envelope shape, 0 to 7
X n envelope period, 0 to 65535
M n mixer: bits 0–2 turn on the tone of channels A, B and C, bits 3–5 their noise
N separator (does nothing)
( ) repeat what is inside once (up to 4 levels); a ) without its ( repeats the whole string for ever (until BREAK)
!...! a comment
H stop all voices
Y n, Z n MIDI on the 128K: ignored

Spaces are ignored. The envelope and mixer belong to each chip, so they are shared by its three voices.

10 PLAY "T140 O4 5cdec 5cdec 5efg&"
20 PLAY "O4 3cegC", "O3 9c", "O5 V10 3(gfed)"

SOUND

SOUND register, value [; register, value]...

Writes directly to the registers of the AY chips, for sound effects. Registers 0 to 15 belong to the first chip and 16 to 31 to the second (same meaning, 16 higher); values are 0 to 255. A register above 31 gives B Integer out of range.

Register Use
0–1, 2–3, 4–5 tone period of channels A, B and C (low byte, high byte 0–15); the frequency is 110 840 / period Hz
6 noise period, 0–31
7 mixer: a bit at 0 turns on: bits 0–2 tone A, B, C; bits 3–5 noise A, B, C
8, 9, 10 volume of A, B and C, 0–15; 16 uses the envelope
11–12 envelope period (low, high)
13 envelope shape (writing it restarts the envelope)
10 SOUND 7,62; 8,15; 0,200; 1,0
20 PAUSE 25: SOUND 8,0

plays a tone on channel A for half a second.

See also: IN and OUT for the 128K ports.

MUSIC

LOAD name$ MUSIC
MUSIC PLAY
MUSIC STOP
MUSIC PAUSE
MUSIC CONTINUE
MUSIC                          (function)

Plays music made with a tracker, in the background: the program carries on while it plays, as in games. LOAD name$ MUSIC loads a module (without an extension, name.pt3): Pro Tracker 3 or Vortex Tracker II (.pt3, the one the ZX-V tracker, zxv-tracker, saves), a TurboSound (two modules, one on each AY chip: six voices), Pro Tracker 2, Sound Tracker, ASC Sound Master or a PSG dump. A file that is none of those gives R Tape loading error.

It plays on the first AY chip (a TurboSound, on both), with the same code as the tracker and C programs. It stops with MUSIC STOP, BREAK, RUN, NEW, PLAY (which uses the chips its own way) and when a native program is loaded; if the program ends or gives an error, it keeps playing. What SOUND writes on the music's chip lasts until the music writes that register again.

The module takes the size of its file (2 to 15 KB for a normal one) and goes with the graphics: RUN and CLEAR keep it and NEW deletes it.

10 LOAD "tune" MUSIC: MUSIC PLAY
20 PRINT "Playing..."
30 IF INKEY$="" THEN GO TO 30
40 MUSIC STOP

SFX

LOAD name$ SFX
SFX n [, channel]
SFX STOP
SFX                            (function)

Sound effects as in games: an AYFX effect bank (.afb, the one the effects tab of zxv-tracker or the AY Sound FX Editor saves; without an extension, name.afb) or a single effect (.afx). A file that is not a bank gives R Tape loading error.

They play at the same time as the music, BEEP and everything else. BREAK, RUN and NEW stop them; the bank is kept like the module.

10 LOAD "effects" SFX
20 IF INKEY$=" " THEN SFX 0
30 GO TO 20

Keyboard, joystick and mouse

INPUT

INPUT [prompt items] var [, var]...
INPUT ... LINE a$

Stops the program and lets the user type values into variables, in the lower part of the screen. The items are as in PRINT: string literals and expressions in brackets are shown as a prompt, AT, TAB and colours work, and each variable waits for a value.

The cursor shows L, or C when Caps Lock is on.

10 INPUT "Your name? "; LINE n$
20 INPUT "Your age? "; a
30 PRINT "Hello, "; n$; ". Next year you will be "; a+1

What the user types follows the rules of the editor: accented letters lose their accent, so Peña arrives as Pena (see Character set).

INPUT #n reads from a file (see Streams).

INKEY$

INKEY$

The key being pressed at this moment, as a one-character string, or "" if none. It does not wait. Letters come out in lower case (upper case with Shift or Caps Lock), digits as digits, Enter as CHR$ 13, and the cursor keys as CHR$ 8 (left), CHR$ 9 (right), CHR$ 10 (down) and CHR$ 11 (up). Shift works as the Spectrum's CAPS SHIFT and Ctrl as its SYMBOL SHIFT. A joystick set up as keys with JOY also counts.

Whatever is pressed while a program reads the keyboard this way (with INKEY$, IN or KEY) is not kept for later: when the program ends it does not appear typed in the editor, and an INPUT starts empty.

10 LET k$=INKEY$: IF k$="" THEN GO TO 10
20 PRINT "You pressed "; k$: IF k$<>"q" THEN GO TO 10

See also: KEY, which is better for games, and PAUSE.

KEY

KEY n

1 if key n is held down right now, 0 if not. Several keys can be held at once, so this is the way to read the keyboard in games. n is:

n Key
CODE "a" to CODE "z" (or upper case) a letter
CODE "0" to CODE "9" a digit
8, 9, 10, 11 the cursor keys left, right, down, up
12 Backspace
13 Enter
32 Space
256 + code any other key, by its USB key code: 298 Backspace, 299 Tab, 314 to 325 F1 to F12, 480 left Ctrl, 481 left Shift, 482 left Alt

Other values give A Invalid argument.

10 LET x=128
20 LET x=x+KEY 9-KEY 8: PLOT x,88: WAIT: GO TO 20

JOY

JOY n
JOY n, mode

The function JOY n gives the state of joystick or gamepad n (0 for the first one connected, 1 for the second) as a number made of these bits; 0 if it is not connected:

Bit Value Button
0 1 right
1 2 left
2 4 down
3 8 up
4 16 fire 1
5 32 fire 2
6 64 fire 3
7 128 start
8 256 select

To test a button, divide and look at the remainder, for example INT (JOY 0/16)-2*INT (JOY 0/32) is 1 while fire 1 is held.

The statement JOY n, mode makes joystick n also act as keys, for programs that read the keyboard with INKEY$ or IN (any fire button counts as fire):

Mode Left Right Down Up Fire
0 (not as keys)
1 Sinclair 1 6 7 8 9 0
2 Sinclair 2 1 2 3 4 5
3 Cursor 5 8 6 7 0

At start, joystick 0 is Sinclair 1 and joystick 1 is Sinclair 2. KEY does not see these keys. A joystick other than 0 or 1, or a mode other than 0 to 3, gives B Integer out of range, as in the function.

10 PRINT AT 0,0; JOY 0; "   ": GO TO 10

MOUSE

MOUSE n
MOUSE x, y

The function MOUSE n reads the mouse:

n Value
0 x of the pointer, in pixels from the left of the screen
1 y of the pointer, in pixels from the top
2 buttons: 1 left, 2 right, 4 middle (added together)
3 wheel: grows when turned up, shrinks when turned down

The pointer starts at the centre of the screen and stays inside it (0–255 and 0–191 in mode 0). The statement MOUSE x, y moves the pointer. ZX-V does not draw the pointer: your program draws it, for example with a sprite.

10 GRAB 0,3,"ff.f.f..f"
20 CLS: SPRITE 0,MOUSE 0,MOUSE 1: IF MOUSE 2 THEN PRINT "click"
30 WAIT: GO TO 20

Files and the SD card

Programs and data are kept on the SD card. There is also a read-only drive, ROM:, with the examples that come with the machine.

File names and drives

Common file errors are F Invalid file name, T File not found, U No SD card and V Disk error, which adds the reason when it is known: (already exists), (folder not empty), (it is a folder), (not a folder), (card full) or (not allowed).

SAVE

SAVE name$ [LINE line [SCREEN$] [PROTECT]]
SAVE name$ CODE start, length
SAVE name$ SCREEN$
SAVE name$ DATA letter()
SAVE name$ DATA letter$()
SAVE name$ GRAPHICS

Saves to the SD card:

If the name has no extension, each kind gets its own: .zvb, .bin, .zvd or .gfx (GRAPHICS and SCREEN$). With another extension, CODE is saved the same way, as plain bytes, and a program, an array or a screen in its format. An existing file is replaced.

With the extension .tap, it is saved as a Spectrum tape, to take it to a Spectrum emulator: the program and its variables, the CODE block (with its address, so that LOAD puts it back), the screen (the Spectrum's, as with .scr) or the array, in the Spectrum's format. The loading screen only goes in a .zvb. ZX-V's own keywords show there as odd characters, and a block cannot be over 64 KB, nor a string of 65535 characters (B Integer out of range). A .tzx is not saved.

With the extension .bas, the program is saved as a listing in plain text (see Listings in text): SAVE "game.bas". A listing has neither the variables nor the start line: SAVE "game.bas" LINE 10 gives C Nonsense in BASIC.

10 PRINT "I was saved"
SAVE "hello" LINE 10

LOAD

LOAD name$
LOAD name$ CODE [start [, length]]
LOAD name$ SCREEN$
LOAD name$ DATA letter()
LOAD name$ DATA letter$()
LOAD name$ GRAPHICS
LOAD name$ MUSIC
LOAD name$ SFX

Loads from the SD card (or the ROM: drive):

LOAD "" (an empty name) loads the next block from the inserted tape (see Tape files).

The program's folder. ZX-V remembers the folder the program was loaded from. A name with no drive and no leading / is looked for in the current folder first and, if it is not there, in the program's folder. So a game loaded with LOAD "ROM:game" finds its graphics and music with LOAD "game" GRAPHICS, without writing ROM:; and a file with the same name in the card's current folder comes first, so you can replace them without touching the game. It also works for VERIFY, MERGE and OPEN # for reading (not for writing: SAVE always goes to the current folder). NEW forgets it.

LOAD "hello"
LOAD "ROM:graphics"

VERIFY

VERIFY name$ [CODE ... | SCREEN$ | DATA ... | GRAPHICS]

Checks that a file is the same as what is in memory, with the same forms as LOAD, without changing anything. If it differs, R Tape loading error.

MERGE

MERGE name$

Adds the lines of a saved program to the one in memory; lines with the same number are replaced. The same goes for the variables, as on the Spectrum: those in the file replace the ones with the same name, and the others stay. It also works with a listing in text (.bas), which has no variables. A protected program cannot be merged (R Tape loading error).

Protected programs

SAVE name$ LINE line [SCREEN$] PROTECT

If you do not want the people who play your program to see how it is made, save it with PROTECT. The program in memory does not change: you can go on working on it and also save it unprotected, for yourself.

It is a protection like the Spectrum's: it stops the curious, but the file format is open, and someone who knows can read it on a PC. ZX-V's tools do not show its listing either.

Listings in text

A program can also live in a plain text file with the extension .bas, one line of the program per line, each with its number, as LIST shows it. You can write it in any text editor on your computer, copy it to the card and load it with LOAD "game.bas" (or MERGE); SAVE "game.bas" writes the one in memory.

10 REM Written outside ZX-V
20 for i = 1 to 10: print i: next i

CAT

CAT [name$]

Lists a folder: first the folder name, then each file with its size in bytes, and each folder with / and <DIR>. Without a name, the current folder. With wildcards or a file name, only what matches.

CAT "ROM:"
CAT "*.zvb"

CD, DIR$

CD folder$
DIR$

CD changes the current folder: CD "games", CD ".." (the folder above), CD "/" (the root of the drive), CD "ROM:" (the built-in examples drive) and CD "SD:" (back to the card). The function DIR$ gives the current folder, such as "/games" or "ROM:/".

CD "ROM:": PRINT DIR$: CAT

A program that loads more files (like the platform game) looks for them in the current folder and, if they are not there, in its own folder (see LOAD): with LOAD "ROM:platformer" it finds its graphics without changing folder.

MKDIR, RMDIR

MKDIR folder$
RMDIR folder$

MKDIR creates a folder; RMDIR deletes an empty folder (otherwise V Disk error (folder not empty)).

ERASE

ERASE name$

Deletes a file, or with wildcards every file that matches (ERASE "*.bak"). Folders are not deleted (use RMDIR). There is no undo.

MOVE

MOVE from$ TO to$

Renames a file or folder, or moves it to another folder: if to$ is a folder, it goes inside it with the same name. With wildcards, to$ must be a folder and every file that matches is moved.

MOVE "game.zvb" TO "old game.zvb"
MOVE "*.zvb" TO "games"

COPY

COPY from$ TO to$
COPY

With two names, copies a file (replacing to$ if it exists; if to$ is a folder, the copy goes inside). With wildcards, to$ must be a folder. Copying a file onto itself gives V Disk error (already exists). To copy an example to the card: COPY "ROM:hello.zxv" TO "hello.zxv".

COPY alone sends the text on the screen to the printer (the file printer.txt, see LPRINT).

Native programs

Programs written in C with the SDK are .zxv files. LOAD "name" runs them (the extension is optional). A native program uses the memory of BASIC: when it ends, the BASIC program and its variables are gone, so save your BASIC program first.

LOAD "ROM:hello"

When the program ends, BASIC shows a report, as after a command:

The report is the program's: it says nothing about your BASIC program, which is gone in every case.

Tape files

ZX-V reads the tape files of Spectrum emulators, .tap and .tzx (the standard-speed blocks: programs, CODE, screens and arrays), to use BASIC code made for the Spectrum. Spectrum machine code inside them cannot run. ZX-V programs are saved in their own format, .zvb (see SAVE); a .tap is only saved when asked for, to take a program to a Spectrum emulator.

A tape file that has been loaded stays inserted, like a cassette in a tape recorder, so programs in several parts work:

So LOAD "game" loads the loader from game.tap, which can then bring its title screen and the main program with LOAD "" SCREEN$: LOAD "".

Streams and channels

Text goes in and out through numbered streams, 0 to 15. Streams 0 to 3 are ready from the start:

Stream Goes to
0, 1 the lower part of the screen (channel "k")
2 the upper part of the screen (channel "s"), used by PRINT
3 the printer, the file printer.txt (channel "p"), used by LPRINT

PRINT, LIST and INPUT take a stream with #: PRINT #1; "bottom" prints in the lower part, LIST #3 lists to the printer. Streams 4 to 15 can be connected to text files on the SD card. A stream that is not open gives O Invalid stream.

OPEN, CLOSE

OPEN #stream, name$ IN
OPEN #stream, name$ OUT
OPEN #stream, channel$
CLOSE #stream

OPEN # ... OUT creates a text file (emptying it if it exists) to write to; OPEN # ... IN opens one to read. Files can only use streams 4 to 15, and up to 8 files can be open at once (otherwise O Invalid stream). Opening a stream that already has a file closes it first.

OPEN #stream, "k", "s" or "p" connects a stream to the lower screen, the upper screen or the printer; another channel gives J Invalid I/O device.

CLOSE #stream closes the file (writing whatever is pending) and frees the stream; streams 0 to 3 go back to their original channels. RUN, CLEAR and NEW close all files.

Reading and writing text files

PRINT #stream; items
LIST #stream
INPUT #stream; var [, var]... [LINE a$]
INKEY$ #stream

Writing to a file opened with IN, or reading from one opened with OUT, gives J Invalid I/O device.

10 OPEN #4, "scores.txt" OUT: PRINT #4; "Ann", 120: CLOSE #4
20 OPEN #4, "scores.txt" IN: INPUT #4; n$, p: CLOSE #4
30 PRINT n$; " scored "; p

To read a file whose length you do not know, catch the end of file with ON ERROR:

10 ON ERROR GO TO 50: OPEN #5, "scores.txt" IN
20 INPUT #5; LINE l$: PRINT l$: GO TO 20
50 CLOSE #5: IF ERR<>8 THEN PRINT "Error "; ERR

FORMAT

FORMAT exists only for compatibility with old Spectrum programs and gives O Invalid stream.

Memory and system

PEEK, POKE

PEEK address
POKE address, value

PEEK reads a byte (0 to 255) from memory and POKE writes one (a negative value from -255 to -1 is written as 256 plus that value).

PRINT PEEK 536872704

prints the low byte of the ZX-V frame counter (60 per second; the Spectrum's, FRAMES, is at 23672).

The virtual Spectrum memory

Addresses Contents
0–16383 Spectrum ROM: reads as 0, except the character set at 15616
16384–22527 the screen pixels, laid out as on the Spectrum (POKE draws, using the colours of each cell)
22528–23295 the colours of each cell (POKE changes them)
23552–23733 system variables (see below)
23296–65535 normal memory: what you POKE you can PEEK
65368–65535 the user-defined graphics A to U

Only the first 256 × 192 pixels of the screen are visible at these addresses.

System variables that work: LAST K (23560, the last key), CHARS (23606, where the character set is; you can point it to your own font in virtual memory), BORDCR (23624), PROG (23635), FLAGS2 (23658, bit 3 is Caps Lock), DF SZ (23659), SEED (23670, the RND seed), FRAMES (23672, three bytes counting fiftieths of a second, like the Spectrum's frames), UDG (23675), COORDS (23677, the last point of PLOT), S POSN (23688), SCR CT (23692), ATTR P, MASK P, ATTR T, MASK T and P FLAG (23693 to 23697) and RAMTOP (23730).

User-defined graphics (UDG)

The character codes 144 to 164 are 21 characters, A to U, that you can draw yourself. USR "a" gives the address of the first byte of character A (and so on to USR "u"); each character is 8 bytes, one per row from the top, and each bit is a pixel (1 = ink). At start they look like the letters A to U.

10 FOR i=0 TO 7: READ b: POKE USR "a"+i, b: NEXT i
20 PRINT CHR$ 144; CHR$ 144; CHR$ 144
30 DATA BIN 00111100, BIN 01111110, BIN 11011011, BIN 11111111
40 DATA BIN 11111111, BIN 10111101, BIN 11000011, BIN 01111110

The editor cannot type these characters: use CHR$.

USR

USR address
USR "letter"

With an address of 65536 or more, calls native RISC-V machine code at that address and gives back the value it returns (in register a0). If the code fails, W Native code error. Spectrum Z80 machine code cannot run: an address below 65536 gives S Z80 code not supported. To call code without using the result: RANDOMIZE USR address.

USR "a" to USR "u" give the address of a user-defined graphic; another letter gives A Invalid argument.

IN, OUT

IN port
OUT port, value

Read and write the ports of the Spectrum, as emulated by ZX-V:

Port IN OUT
254 (and any even port) the keyboard half-rows selected by the high byte, as on the Spectrum (bits at 0 = pressed) bits 0–2 border colour, bit 4 beeper
31 Kempston joystick (joystick 0)
64479, 65503 Kempston mouse: x and y counters
64223 Kempston mouse buttons (0 = pressed)
65533 read the selected AY register select an AY register; 255 selects the first chip and 254 the second
49149 write the selected AY register

Other ports read 255 and ignore writes. Programs written for ZX-V are better off with KEY, JOY, MOUSE, BORDER and SOUND.

TIME

TIME

The number of frames since the machine was switched on, 60 per second. To time something, subtract two readings:

10 LET t=TIME: PAUSE 100: PRINT (TIME-t)/60; " seconds"

CLOCK

CLOCK n
CLOCK year, month, day, hour, minutes [, seconds]

The function CLOCK n reads the date and time: 0 year, 1 month, 2 day, 3 hour, 4 minutes, 5 seconds, 6 day of the week (1 Monday to 7 Sunday). It gives 0 if the clock has not been set. The statement sets the clock (years 2000 to 2099); a date that does not exist gives A Invalid argument. Files saved on the card are stamped with this date.

PRINT CLOCK 2; "/"; CLOCK 1; "/"; CLOCK 0; " "; CLOCK 3; ":"; CLOCK 4

SPEED

SPEED n

SPEED 1 (the default) runs BASIC at full speed, about 200 times faster than a Spectrum. SPEED 0 makes each statement take about as long as on a 48K Spectrum, for old programs that use loops as delays or would be unplayable at full speed. Other values give A Invalid argument. The new commands (sprites, maps...) are not slowed down.

LANGUAGE

LANGUAGE code$

Sets the language of the machine with a two-letter code: "en" English or "es" Spanish. Error reports and the editor's bar and menu use it from then on, and the machine remembers it (on the real hardware, in its battery-backed clock; in the emulator, in its settings). Any other two-letter code is accepted and shows English (a program can read it to choose its own texts: PEEK 536872736 and PEEK 536872737 are the codes of the two letters). Something that is not two letters gives A Invalid argument.

LANGUAGE "es"

MONITOR

MONITOR

Opens the test monitor, a screen for checking the hardware (keyboard, joystick, video modes, sound). To leave it, reset the machine (Ctrl+Alt+Del).

Editing commands

These commands are mostly typed as direct commands while you write a program. See the editor for the full picture.

LIST

LIST [line]
LIST #stream [, line]

As a direct command, LIST takes you to the editor with the cursor on that line (or the next one that exists), ready to change it. Inside a program, or with a stream, it prints the listing from that line: LIST #2 on the program screen, LIST #3 to the printer, LIST #4 to a file. The listing is indented: whatever is inside a loop, a procedure or a block shows two spaces further right for each level (the spaces are not stored).

See also: LLIST, EDIT.

EDIT

EDIT [line]

Puts the editor's cursor on that line (without a number, on the current line). Not to be confused with the EDIT key (Tab), which opens the editor's options menu.

AUTO

AUTO [first [, step]]

Automatic line numbers: each new line in the editor starts with the next number. Without values, it starts at the last line plus 10, and goes up in tens. It ends when you press Enter on a line with only the number, press Esc, or move to another line. Only as a direct command (in a program, C Nonsense in BASIC).

AUTO 100, 5

RENUM

RENUM [first [, step]]

Renumbers the program (from 10 in tens by default), and corrects the line numbers after GO TO, GO SUB, RESTORE, RUN, LIST, LLIST and LINE. Only numbers written directly are corrected: in GO TO n*10 the expression is not changed. Labels do not need correcting. If the numbers would go past 9999, B Integer out of range. Only as a direct command. The editor's options menu has the same thing.

RENUM 100, 10

DELETE

DELETE first [, last]

Deletes the lines from first to last (or just line first). Only as a direct command.

DELETE 100, 190

FIND

FIND [text]

Moves the editor's cursor to the next program line where text appears, starting with the line after the cursor and going round at the end, with the cursor on the text. Upper and lower case are the same, and it searches the listing as you see it (not the line numbers). Without text, it searches for the same as last time, like the F3 key. If it is not there, the status line says Not found. Only as a direct command.

FIND "score"

See also: REPLACE.

REPLACE

REPLACE old, new

Changes the text old to new in the whole program, with upper and lower case the same. Each changed line is checked as if it were typed, and lines that would have a mistake are left alone. The status line says how many changes were made and how many lines were left unchanged. With an empty old, A Invalid argument. Only as a direct command.

REPLACE "lives", "energy"

See also: FIND.

NEW

NEW

Deletes the program, the variables and the graphics store, and starts afresh (the inserted tape stays). There is no undo: save first.

Error handling

Reports

When a program stops, a report appears at the bottom of the program screen:

2 Variable not found, 20:1

It gives a code (a digit or a letter), the message, and where it happened: the line number and the statement within the line (20:1 is the first statement of line 20; line 0 means a direct command). 0 OK means the program ended normally. Press a key to go back to the editor.

The reports appear in the language of the machine (see LANGUAGE).

ON ERROR

ON ERROR GO TO line | @label
ON ERROR GO TO 0

From now on, if an error stops the program, it jumps to that line or label instead. There, ERR and ERL say what happened. ON ERROR GO TO 0 turns it off, as do RUN and CLEAR.

10 ON ERROR GO TO @oops
20 PRINT 1/0
30 PRINT "carrying on"
40 STOP
50 @oops: PRINT "Error "; ERR; " at line "; ERL
60 ON ERROR GO TO @oops: GO TO 30

ERR, ERL

ERR
ERL

After an error caught by ON ERROR, ERR is the error code as a number (the digits are themselves, and the letters count on from 10: A is 10, B 11... Z 35; the table below gives them all) and ERL is the line where it happened.

Error messages

The reports in English and Spanish, with the number that ERR gives:

Code ERR English Spanish What usually causes it
0 0 OK OK Not an error: the program or command ended normally.
1 1 NEXT without FOR NEXT sin FOR NEXT with a variable that is not the control variable of a FOR.
2 2 Variable not found Variable no encontrada Using a variable before giving it a value, or an array before its DIM.
3 3 Subscript wrong Subíndice incorrecto An array subscript out of its size, the wrong number of subscripts, or a slice outside a string.
4 4 Out of memory Sin memoria Not enough memory, too many nested GO SUB (512) or loops and procedures (64), or an expression nested too deep.
5 5 Out of screen Fuera de la pantalla PRINT AT or INPUT outside the screen.
6 6 Number too big Número demasiado grande A result above 1.7E38, often a division by zero.
7 7 RETURN without GOSUB RETURN sin GO SUB RETURN with no GO SUB to go back to.
8 8 End of file Fin del fichero INPUT # after the last line of a file.
9 9 STOP statement Sentencia STOP The program reached STOP. CONTINUE carries on.
A 10 Invalid argument Argumento no válido A value a function cannot take (SQR -1, LN 0), a sprite or map that does not exist, a bad PLAY string, an impossible date.
B 11 Integer out of range Entero fuera de rango A whole number out of its range: a coordinate off the screen, CHR$ 300, POKE with 256...
C 12 Nonsense in BASIC Sintaxis incorrecta The line is not valid BASIC (a typing mistake, a missing bracket), or a value of the wrong type.
D 13 BREAK - CONT repeats BREAK - CONT repite You answered N, Space or BREAK to scroll?. CONTINUE repeats.
E 14 Out of DATA No quedan DATA READ with no DATA left.
F 15 Invalid file name Nombre de fichero no válido An empty name, a name too long, or with characters not allowed.
G 16 No room for line No cabe la línea The line is too long, or memory is full.
H 17 STOP in INPUT STOP en INPUT STOP typed, or BREAK pressed, in an INPUT.
I 18 FOR without NEXT FOR sin NEXT A FOR loop that runs no times and has no NEXT to jump to.
J 19 Invalid I/O device Dispositivo no válido Writing to a file opened for reading (or the reverse), or an unknown channel in OPEN #.
K 20 Invalid colour Color no válido A colour out of range (INK 10, BORDER 8, BOX 16,...).
L 21 BREAK into program BREAK en el programa You pressed BREAK (Esc). CONTINUE carries on with the next statement.
M 22 RAMTOP no good RAMTOP no válido A CLEAR address that is too low or too high.
N 23 Statement lost Sentencia perdida A jump back to a statement that no longer exists (for example after changing the line).
O 24 Invalid stream Canal no válido A stream not open, a file on streams 0–3, more than 8 open files, or FORMAT.
P 25 FN without DEF FN sin DEF FN FN of a function with no DEF FN in the program.
Q 26 Parameter error Error en los parámetros The wrong number or type of values for FN or PROC, or too many.
R 27 Tape loading error Error al cargar A file that is not valid or not the right kind, LOAD "" with no tape inserted, or VERIFY found differences.
S 28 Z80 code not supported Código Z80 no admitido USR with an address below 65536: Spectrum machine code.
T 29 File not found Fichero no encontrado No file or folder with that name, or nothing matches the wildcards.
U 30 No SD card No hay tarjeta SD There is no card in the slot.
V 31 Disk error Error de disco The card failed or the operation is not possible; the reason follows in brackets.
W 32 Native code error Error en el código nativo Native code called with USR crashed, or a native program (.zxv) ended with an error. The program's code or its own message may appear instead (see Native programs).
X 33 Label not found Etiqueta no encontrada GO TO @name (or similar) with no @name in the program.
Y 34 Structure error Error de estructura WEND, UNTIL, END PROC or LOCAL without their opening, or a block (WHILE, IF, SELECT CASE...) without its end.
Z 35 PROC not found PROC no encontrado PROC of a procedure with no DEF PROC.

The reasons of V Disk error: already exists / ya existe, folder not empty / la carpeta no está vacía, it is a folder / es una carpeta, not a folder / no es una carpeta, card full / la tarjeta está llena, not allowed / no se puede.

Character set

Each character has a code from 0 to 255 (CODE and CHR$ convert between them):

Codes Characters
0–31 control codes (see below); others print as ?
32–126 letters, digits and symbols, as in ASCII, except 96, which is £
127 ©
128–143 block graphics: the 16 combinations of the four quarters of a character cell
144–164 the user-defined graphics A to U
165–255 the keywords: PRINT CHR$ 245 prints PRINT

Control codes that have an effect when printed:

Code Effect
6 as a comma in PRINT
8 back one column
13 new line
16 to 21 INK, PAPER, FLASH, BRIGHT, INVERSE, OVER: the next character is the value
22 AT: the next two characters are the row and the column
23 TAB: the next two characters are the column (low and high byte)

For example, PRINT CHR$ 22; CHR$ 5; CHR$ 10; "X" is the same as PRINT AT 5,10; "X".

Block graphics. Codes 128 to 143 divide the character cell into four quarters. To find the code of a pattern, add to 128 the values of the quarters filled with ink: 1 top right, 2 top left, 4 bottom right, 8 bottom left. For example, 128 + 2 + 8 = 138 is the left half.

Code Character Code Character Code Character Code Character
128 (empty) 132 ▗ 136 ▖ 140 ▄
129 ▝ 133 ▐ 137 ▞ 141 ▟
130 ▘ 134 ▚ 138 ▌ 142 ▙
131 ▀ 135 ▜ 139 ▛ 143 █

The quarters are in ink and the rest of the cell in paper, as with any other character. The codes are the same as on the Spectrum.

In the editor you can type the codes 32 to 127 (£ and © too, if your keyboard has them). Block graphics and user-defined graphics are written with CHR$. Other characters, such as accented letters, are not part of the set, so BASIC strings cannot hold them. When you type them, in the editor or in an INPUT, a letter with an accent, a diaeresis, a tilde or a cedilla comes out without it (á as a, Ñ as N, ç as c), ¿ and ¡ come out as ? and !, and any other character does nothing. The ROM can show the Spanish letters (á, ñ, ¿...) in its own messages, such as the error reports in Spanish, but your programs cannot.

Limits

What Limit
Line numbers 1 to 9999
Length of a line in the editor 1024 characters
Numbers about ±2.9E-39 to ±1.7E38, 8 digits shown
Numeric variable names up to 63 letters and digits
String variables, arrays, FOR variables, DEF FN one letter (26 of each)
Strings as long as memory allows
Array dimensions up to 16, each up to 65535
Nested GO SUB 512
Nested WHILE, REPEAT and PROC 64
Nested block IFs and SELECT CASE no limit
Parameters of a procedure 16
Nested brackets in an expression about 150 (about 25 nested FN)
Memory for program and variables about 94 KB (shown in the editor's bar)
Open files 8, on streams 4 to 15
Sprites 256 (0–255), each up to 1024 × 1024 pixels
Tiles 4096 of 8 × 8 and 4096 of 16 × 16
Tile maps 16 (0–15), up to 32767 × 32767 cells
Textures 4 (0–3)
Polygon corners 64
PLAY 8 strings (6 play), 4 levels of brackets
File names 63 characters; paths 255

Keyword index

Keyword Kind Entry
@ statement @label
ABS function ABS, SGN, INT
ACS function ASN, ACS, ATN
AND operator True and false
ASN function ASN, ACS, ATN
AT in PRINT, INPUT PRINT
ATN function ASN, ACS, ATN
ATTR function SCREEN$, ATTR
AUTO statement AUTO
BEEP statement BEEP
BIN number BIN
BORDER statement BORDER
BOX statement BOX
BRIGHT statement, item BRIGHT, FLASH
CAT statement CAT
CASE in SELECT CASE SELECT CASE
CD statement CD, DIR$
CELL function CELL
CHR$ function CHR$, CODE
CIRCLE statement CIRCLE
CLEAR statement CLEAR
CLIP statement CLIP
CLOCK function, statement CLOCK
CLOSE # statement OPEN, CLOSE
CLS statement CLS
CODE function; in SAVE, LOAD CHR$, CODE, SAVE
CONTINUE statement CONTINUE
COPY statement COPY
COS function SIN, COS, TAN
DATA statement; in SAVE, LOAD READ, DATA, RESTORE, SAVE
DEF FN statement DEF FN, FN
DEF PROC statement DEF PROC, PROC, END PROC
DELETE statement DELETE
DIM statement DIM
DIR$ function CD, DIR$
DISC statement DISC
DRAW statement DRAW
EDIT statement EDIT
ELSE in IF IF, THEN, ELSE
END IF statement IF, THEN, ELSE
END PROC statement DEF PROC, PROC, END PROC
END SELECT statement SELECT CASE
ERASE statement ERASE
ERL function ERR, ERL
ERR function ERR, ERL
EXP function EXP, LN
FIND statement FIND
FLASH statement, item BRIGHT, FLASH
FLOOR statement FLOOR
FN function DEF FN, FN
FOR statement FOR, NEXT
FORMAT statement FORMAT
GO SUB statement GO SUB, RETURN
GO TO statement GO TO
GRAB statement GRAB
GRAPHICS in SAVE, LOAD, VERIFY SAVE, LOAD
HIT function HIT
IF statement IF, THEN, ELSE
IN function; in OPEN # IN, OUT, OPEN, CLOSE
INK statement, item INK, PAPER
INKEY$ function INKEY$
INPUT statement INPUT
INT function ABS, SGN, INT
INVERSE statement, item INVERSE, OVER
JOY function, statement JOY
KEY function KEY
LANGUAGE statement LANGUAGE
LEN function LEN
LET statement LET
LINE in INPUT, SAVE INPUT, SAVE
LIST statement LIST
LLIST statement LPRINT, LLIST
LN function EXP, LN
LOAD statement LOAD
LOCAL statement LOCAL
LPRINT statement LPRINT, LLIST
MAP statement MAP, MAP DIM, MAP POKE
MERGE statement MERGE
MKDIR statement MKDIR, RMDIR
MODE statement MODE
MONITOR statement MONITOR
MOUSE function, statement MOUSE
MOVE statement MOVE
MUSIC function, statement; in LOAD MUSIC, LOAD
NEW statement NEW
NEXT statement FOR, NEXT
NOT operator True and false
ON ERROR statement ON ERROR
OPEN # statement OPEN, CLOSE
OR operator True and false
OUT statement; in OPEN # IN, OUT, OPEN, CLOSE
OVER statement, item INVERSE, OVER
PAGE statement PAGE, SCREEN
PALETTE statement PALETTE
PAPER statement, item INK, PAPER
PAUSE statement PAUSE
PEEK function PEEK, POKE
PI function PI
PIXEL function PIXEL
PLAY statement PLAY
PLOT statement PLOT
POINT function POINT
POKE statement; in MAP PEEK, POKE, MAP DIM, MAP POKE
POLY statement POLY
PRINT statement PRINT
PROC statement DEF PROC, PROC, END PROC
PROTECT in SAVE Protected programs
RANDOMIZE statement RND, RANDOMIZE
RASTER statement RASTER
READ statement READ, DATA, RESTORE
REM statement REM
REMAP statement REMAP
RENUM statement RENUM
REPEAT statement REPEAT, UNTIL
REPLACE statement REPLACE
RESTORE statement READ, DATA, RESTORE
RETURN statement GO SUB, RETURN
RMDIR statement MKDIR, RMDIR
RND function RND, RANDOMIZE
RUN statement RUN
SAVE statement SAVE
SCREEN statement PAGE, SCREEN
SCREEN$ function; in SAVE, LOAD SCREEN$, ATTR, SAVE
SCROLL statement SCROLL
SELECT CASE statement SELECT CASE
SFX function, statement; in LOAD SFX, LOAD
SGN function ABS, SGN, INT
SIN function SIN, COS, TAN
SOUND statement SOUND
SPEED statement SPEED
SPRITE statement SPRITE
SQR function SQR
STEP in FOR FOR, NEXT
STOP statement STOP
STR$ function STR$, VAL, VAL$
TAB in PRINT, INPUT PRINT
TAN function SIN, COS, TAN
TEXTURE statement TEXTURE
THEN in IF IF, THEN, ELSE
TILE statement TILE
TIME function TIME
TO in FOR, slices, MOVE, COPY FOR, NEXT, Strings
TRACE statement TRACE
UNTIL statement REPEAT, UNTIL
USR function USR
VAL function STR$, VAL, VAL$
VAL$ function STR$, VAL, VAL$
VERIFY statement VERIFY
WAIT statement WAIT
WEND statement WHILE, WEND
WHILE statement WHILE, WEND