www.riscos.com Technical Support: |
|
This chapter describes the BBC BASIC keywords. First, there is a short list grouping the keywords by function. Use this list if you are not sure what keywords are available for a particular task.
The remainder of this chapter lists the keywords alphabetically (with the exceptions of *BASIC and *BASIC64, which appear first) for ease of reference. It gives complete definitions of syntax, with examples.
Each keyword is listed in the index.
The command to enter the BASIC V interpreter.
The command *BASIC is not one of the usual BASIC keywords which are described in this chapter. It is an operating system command which is used to activate the interpreter in the first place. It is described here for completeness.
The options control how the interpreter will behave when it starts, and when any program that it executes terminates. If no option is given, BASIC simply starts with a message of the form:
ARM BBC BASIC V version 1.05 (C) Acorn 1989 Starting with 643324 bytes free
The number of bytes free in the above message will depend on the amount of free RAM on your computer. The first line is also used for the default REPORT message, before any errors occur.
One of three options may follow the *BASIC command to cause a program to be loaded, and, optionally, executed automatically. Alternatively, you can use a program that is already loaded into memory by passing its address to the interpreter. Each of these possibilities is described in turn below.
In all cases where a program is specified, this may be a tokenised BASIC program, as created by a SAVE command, or a textual program, which will be tokenised (and possibly renumbered) automatically.
*BASIC -help
This command causes BASIC to print some help information describing the options documented here. Then BASIC starts as usual.
*BASIC [-chain] filename
If you give a filename after the *BASIC command, optionally preceded by the keyword -chain, then the named file is loaded and executed. When the program stops, BASIC enters immediate mode, as usual.
*BASIC -quit filename
This behaves in a similar way to the previous option. However, when the program terminates, BASIC quits automatically, returning to the environment from which the interpreter was originally called. It also performs a CRUNCH %1111 on the program (see the description of the CRUNCH command later in this chapter). This is the default action used by BASIC programs that are executed as * commands. In addition, the function QUIT returns TRUE if BASIC is called in this fashion.
*BASIC -load filename
This option causes the file to be loaded automatically, but not executed. BASIC remains in immediate mode, from where the program can be edited or executed as required.
*BASIC @start,end
This acts in a similar way to the -load form of the command. However, the program that is 'loaded' automatically is not in a file, but already in memory. Following the @ are two addresses. These give, in hexadecimal, the address of the start of the in-core program, and the address of the byte after the last one. The program is copied to PAGE and tokenised if necessary. This form of the command is used by Twin when returning to BASIC.
Note that the in-core address description is fixed format. It should be in the form:
@xxxxxxxx,xxxxxxxx
where x means a hexadecimal digit. Leading zeros must be supplied. The command line terminator character must come immediately after the last digit. No spaces are allowed.
*BASIC -chain @start,end
This behaves like the previous option, but the program is executed as well. When the program terminates, BASIC enters immediate mode.
*BASIC -quit @start,end
This option behaves as the previous one, but when the BASIC program terminates, BASIC automatically quits. The function QUIT will return TRUE during the execution of the program.
*BASIC *BASIC -quit shellProg *BASIC @000ADF0C,000AE345 *BASIC -chain fred
The command to enter the BASIC VI interpreter.
This has exactly the same purpose as the *BASIC command, and takes the same options, the only difference being that it enters the BASIC VI interpreter instead of the BASIC V interpreter.
If no option is given, BASIC VI simply starts with a message of the form:
ARM BBC BASIC VI version 1.05 (C) Acorn 1989
The number of bytes free in the above message will depend on the amount of free RAM on your computer.
*BASIC64
*BASIC64 -quit shellProg
*BASIC64 @000ADF0C,000AE345
*BASIC64 -chain fred
Function giving magnitude of its numeric argument, i.e. changes negative numbers into positive numbers.
ABS factor
Any numeric.
Same as the argument if this is positive, or -(the argument) if it is negative.
Note: The largest negative integer does not have a legal positive value, so that if a%=-2147483648, ABS(a%) yields the same value: -2147483648. However, this does not arise with floating point numbers.
diff=ABS(length1-length2)
Function giving the arc-cosine of its numeric argument.
Real or integer between -1 and 1 inclusive.
Real in the range 0 to radians, being the inverse cosine of the argument.
ang=ACS(normvec1(1)*normvec2(1)+normvec1(2)*normvec2(2))
angle=DEG(ACS(cos1))
PRINT ACS(0.5)
Function reading data from an analogue port if fitted, or giving buffer data.
Negative integer -n, where n is a buffer number between 1 and 10.
The number of spaces or entries in the buffer is given in the table below:
arg | Buffer name | Result | |
---|---|---|---|
-1 | Keyboard | (input) | Number of characters used |
-2 | RS-423 | (input) | Number of characters used |
-3 | RS-423 | (output) | Number of characters free |
-4 | Printer | (output) | Number of characters free |
-5 | Sound 0 | (output) | Number of bytes free |
-6 | Sound 1 | (output) | Number of bytes free |
-7 | Sound 2 | (output) | Number of bytes free |
-8 | Sound 3 | (output) | Number of bytes free |
-9 | Speech | (output) | Number of bytes free |
-10 | Mouse | (input) | Number of bytes used |
The ADVAL function only returns a result for positive arguments if the optional analogue-digital converter podule is fitted. If this is absent, the function ADVAL(1), for example, will result in a Bad command error.
IF ADVAL(-1)=0 THEN PROCinput
relational AND relational
Relational expressions, or bit values to be ANDed.
The bitwise AND of the operands. Corresponding bits in the integer operands are ANDed to produce the result. Hence a bit in the result is one if both of the corresponding bits of the operands are one. Otherwise it is zero.
If used to combine relational values, AND's operands should be either TRUE (-1) or FALSE (0). Otherwise, unexpected results may occur. For example, 2 and 4 are both true (non-zero), but 2 AND 4 yields FALSE (zero).
a = x AND y : REM a is set to binary AND of x and y PRINT var AND 3 : REM print lowest 2 bits of var IF day=4 AND month$="April" THEN PRINT "Happy birthday" IF temp>50 AND NOT windy THEN PROCgo_out ELSE PROCstay_in REPEAT a=a+1 b=b-1 UNTIL a>10 AND b<0 isadog = feet=4 AND tails=1 AND hairy
Command to append a file to a BASIC program.
expression is a string which should evaluate to a filename that is valid for the filing system in use.
The file specified is added to the end of the BASIC program currently in memory. If the file contains a BASIC program, the line numbers and any references to them in the added section are renumbered so that they start after the last line of the current program.
APPEND ":0.lib"
APPEND second_half$
Function giving the ASCII code of the first character in string.
String of length 0 to 255 characters.
ASCII code of the first character of the argument in the range 0 to 255, or -1 if the argument is a null string.
10 x2=ASC(name$)
100 IF code >= ASC("a") AND code <= ASC("z") THEN PRINT "Lower case"
Command initiating automatic line numbering.
start is an integer constant in the range 0 to 65279 and is the first line to be generated automatically. It defaults to 10.
step is an integer constant in the range 1 to 65279 and is the amount by which the line numbers increase when Return is pressed. If omitted, 10 is assumed.
AUTO is used when entering program lines to produce a line number automatically, so that you do not have to type them yourself. To end automatic line numbering use Esc. AUTO will stop if the line number becomes greater than 65279.
AUTO AUTO 1000 AUTO 12,2
Function returning the current beat value.
An integer giving the current beat value. This is the value yielded by the beat counter as it counts from zero to the number set by BEATS at a rate determined by TEMPO. When it reaches its limit it resets to zero. Synchronisation between sound channels is performed with respect to the last reset of the beat counter.
PRINT BEAT
Function returning or statement altering the beat counter.
expression gives the value 1 higher than that which the beat counter increments to, i.e. it counts from 0 to expression-1. This counter is used in conjunction with the SOUND and TEMPO statements to synchronise sound outputs from different sound channels.
An integer giving the current value of the beat limit, as set by a BEATS statement, or 0 if no counting is currently being performed.
BEATS 2000
PRINT BEATS
Function returning the next byte from a file.
A channel number returned by an OPENxx function.
The ASCII code of the character read (at position PTR#) from the file, in the range 0 to 255.
Note: PTR# is updated to point to the next character in the file. If the last character in the file has been read, EOF# for the channel will be TRUE. The next BGET# will return an undefined value and the one after that will produce an End of file on file handle nn error.
char%=BGET# channel char$=CHR$(BGET#fileno) WHILE NOT EOF# channel char% = BGET# channel PROCprocess(char%) ENDWHILE
Statement to write a byte or a string to a file.
(1) BPUT#factor,numeric-expression
(2) BPUT#factor,string-expression[;]
factor is a channel number as returned by an OPENxx function. The numeric-expression is truncated to an integer 0 to 255, and is the ASCII code of the character to be sent to the file.
factor is a channel number as returned by an OPENxx function. string-expression is a string containing 0 to 255 characters. The ASCII codes of all the characters in the string are sent to the file. This is followed by a newline (ASCII value 10), unless the statement is terminated by a ; (semi-colon).
Note: PTR# is updated to point to the next character to be written. If the end of the file is reached, the length (EXT#) increases too. It is only possible to use BPUT# with OPENUP and OPENOUT files, not OPENIN ones.
BPUT#outputfile,byte%
BPUT#channel,ASC(MID$(name$,pos,1))
BPUT#file,"Hello"
BPUT#chan,A$+B$;
Optional part of MOVE, DRAW, POINT and FILL statements.
See the above-mentioned keywords.
The BY keyword changes the effect of certain graphics statements. In particular it indicates that the coordinates given in the statement are relative rather than absolute. For example, POINT BY 100,100 means plot a point at coordinates displaced by (100,100) from the current graphics cursor position, rather than a point which is at (100,100).
In terms of its effect at the VDU driver level, BY makes BASIC use the relative forms of the appropriate OS_Plot calls, instead of the absolute ones.
MOVE BY 4*x%,4*y%
POINT BY 100,0
DRAW BY x%*16, y%=4
FILL BY x%, y%
Statement to execute a machine code or assembly language subroutine.
expression is the address of the routine to be called. The parameter variables, if present, may be of any type, and must exist when the CALL statement is executed. They are accessed through a parameter block which BASIC sets up. The format of this parameter block and of the variables accessed through it is described below.
CALL can be used to enter a machine code program from BASIC. Before the routine is called, the ARM's registers are set up as follows:
R0 | A% |
R1 | B% |
R2 | C% |
R3 | D% |
R4 | E% |
R5 | F% |
R6 | G% |
R7 | H% |
R8 | Pointer to BASIC's workspace (ARGP) |
R9 | Pointer to list of l-values of the parameters |
R10 | Number of parameters |
R11 | Pointer to BASIC's string accumulator (STRACC) |
R12 | BASIC's LINE pointer (points to the current statement) |
R13 | Pointer to BASIC's full, descending stack |
R14 | Link back to BASIC and environment information pointer. |
R9 points to a list giving details of each variable passed as a parameter to CALL. For each variable, two word-aligned words are used. The first one is the l-value of the parameter. This is the address in memory in which the value of the variable is stored.
The second word is the type of variable. This list is in reverse order, so the l-value pointed to by R9 is that of the last parameter in the list. The pointer to the list is always valid, even when if the list is null (i.e. R10 contains 0). The possible types are as follows:
Type | BASIC | l-value points to |
---|---|---|
&00 | ?factor | byte-aligned byte |
&04 | !factor | byte-aligned word |
&04 | name% | word-aligned word |
&04 | name%(n) | word-aligned word |
&05 | |factor | byte-aligned FP value (5 bytes) |
&05 | name | byte-aligned FP value (5 bytes) |
&05 | name(n) | byte-aligned FP value (5 bytes) |
&08 | |factor | word-aligned FP value (8 bytes) |
&08 | name | word-aligned FP value (8 bytes) |
&08 | name(n) | word-aligned FP value (8 bytes) |
&80 | name$ | byte-aligned SIB (5 bytes) |
&80 | name$(n) | byte-aligned SIB (5 bytes) |
&81 | $factor | byte-aligned byte-string (CR-terminated) |
&100+&04 | name%() | word-aligned array pointer |
&100+&05 | name() | word-aligned array pointer |
&100+&08 | name() | word-aligned array pointer |
&100+&80 | name$() | word-aligned array pointer |
For types &00, &04, &05 and &08, the address points to the actual byte, the four-byte integer, the five-byte floating point value or the eight-byte floating point value.
For type &80, the address points to a five-byte 'string information block'. The first four bytes are a byte-aligned word pointing to the first character of the string itself, which is on a word boundary, followed by a byte containing the length of the string.
For types &100+n the value points to a word-aligned word. If the array has not been allocated, or has been made LOCAL but not DIMed, this word contains a value less than 16. Otherwise, the word points to a word-aligned list of integer subscript sizes (the values in the DIM statement plus 1) terminated by a zero word, followed by a word which contains the total number of entries in the array, followed by the zeroth element of the array. For example, consider the following program:
10 DIM a(10,20) 20 a = 12.3 30 a$ = "char" 40 ... 100 CALL code, a, a(), a$
The diagram above shows the resulting parameter block and other data items when code is called. The access method into the arrays is given by the following algorithm:
position = 0 number = 0 REPEAT IF subscript(number) > array(number) THEN fault number = number+1 IF number<>total THEN position = (position+subscript) * array(number) UNTIL no_more_subscripts position = position*size(array)
This means that the last subscript references adjacent elements. For a simple two dimensional array DIM A(LIMI-1,LIMJ-1) the address of A(I,J) is
(I*LIMI+J)*size+base_address
MOVS PC,R14 returns to the BASIC calling program if V set on error is signalled at R0. However, R14 also points to an array of useful values:
Offset | Name | Meaning |
---|---|---|
&00 | RETURN | Return address to BASIC |
The following are words containing a word-aligned offset from ARGP (R8): | ||
&04 | STRACC | String accumulator (256 bytes long) |
&08 | PAGE | Current program PAGE |
&0C | TOP | Current program TOP |
&10 | LOMEM | Current start of variable storage |
&14 | HIMEM | Current stack end (i.e. highest stack location) |
&18 | MEMLIMIT | Limit of available memory |
&1C | FSA | Free space start (end of variables/stack limit) |
&20 | TALLY | Value of COUNT |
&24 | TRACEF | TRACEFILE handle (or 0 if no file being traced to) |
&28 | ESCWORD | Exception flag word (contains escflg, trcflg) |
&2C | WIDTHLOC | Value of WIDTH-1 |
Branches to internal BASIC routines: | ||
&30 | VARIND | Get value of l-value |
&34 | STOREA | Store value into l-value |
&38 | STSTORE | Store string into type 128 strings |
&3C | LVBLNK | Convert variable name string to l-value address and type |
&40 | CREATE | Create new variable |
&44 | EXPR | Use expression analyser on string |
&48 | MATCH | Lexically analyse source string to destination string |
&4C | TOKENADDR | Pointer to string for given token |
&50 | END | End of list, a zero word |
In the following (BASIC V only), R0..R3 contain an expanded floating point value. R9 points to a packed five-byte floating point value accessed through the | operator: | ||
&54 | 9 | number of extra routines |
&58 | FSTA | [R9] = R0..R3 |
&5C | FLDA | R0..R3 = [R9] |
&60 | FADD | R0..R3 = [R9] + (R0..R3) |
&64 | FSUB | R0..R3 = [R9] - (R0..R3) |
&68 | FMUL | R0..R3 = (R0..R3) * [R9] |
&6C | FDIV | R0..R3 = [R9] / (R0..R3) |
&70 | FLOAT | R0..R3 = FLOAT(R0) (R0 contains an integer on entry) |
&74 | FIX | R0 = FIX(R0..R3) (R0 contains an integer on exit) |
&78 | FSQRT | R0..R3 = SQR(R0..R3) |
The word at address [R14] is a branch instruction which returns you to the BASIC interpreter. The words which follow it contain useful addresses which are not absolute, but are offsets from the contents of the ARGP register, R8.
The first offset word, at [R14,#4], gives the location of the string accumulator, STRACC, where string results are kept. Thus if you execute
LDR R0, [R14, #4] ;Get STRACC offset from R8 ADD R0, R8, R0 ;Add offset to ARGP
R0 will give the base address of the string accumulator. (Actually, the address of STRACC is also in R11 on entry, so this isn't a particularly good example.) Similarly, to load the pointer to the end of free space into R0, you would use:
LDR R0, [R14, #&1C] ;Get FSA offset from R8 LDR R0, [R8, R0] ;De-reference it
Although the word referenced through the TRACEF offset is the TRACEFILE handle, the four that follow it are also used. They contain respectively:
[R*, TRACEF+4] | LOCALARLIST | a pointer to the list of local arrays |
[R*, TRACEF+8] | INSTALLLIST | a pointer to the list of installed libraries |
[R*, TRACEF+12] | LIBRARYLIST | a pointer to the list of transient libraries |
[R*, TRACEF+16] | OVERPTR | a pointer to the overlay structure |
The first of these is probably not very useful, but the other three allow routines to access the libraries that have been loaded. For example, a 'find' routine would be able to find a procedure no matter where it was defined (which LIST IF can't do).
Libraries are stored as a word, which is a pointer to the next library (0 denoting the end of the list). The word is followed immediately by the BASIC program which forms the library.
Before an OVERLAY statement has been executed, OVERPTR contains 0. After a statement such as OVERLAY a$(), it contains a pointer to the following structure:
OVERPTR+&00 | Pointer to base of OVERLAY array, i.e. a$(0) |
OVERPTR+&04 | Index of current OVERLAY file (or -1 if none loaded) |
OVERPTR+&08 | Total allowed size of OVERLAY area |
OVERPTR+&0C | Start of current OVERLAY file in memory. |
... |
After the word offsets come the branches useful to BASIC routines. For example, to call STOREA, whose branch is at offset &34 from R14, you might use:
STMFD R13!, {R14} ;Save BASIC return address MOV R10, R14 ;Save pointer to branches ADR R14, myRet ;Set up return address to my code ADD PC, R10, #&34 ;Do the 'branch' .myRet ... LDMFD R13!, {PC}^ ;Return to BASIC
The internal routines are only guaranteed to work in ARM user mode. The following functions are provided:
Entry with R0:
R0 | = | Address of l-value, i.e. where to load the variable from |
R9 | = | Type of l-value, as in CALL parameter block |
R12 | = | LINE |
Returns with R0R3 as the value (or F0 if using BASIC VI), R9 the type of the value as follows:
R9 | Type | Location of value |
---|---|---|
0 | String | STRACC, R2 points to end ([R2]-STRACC is length) |
&40000000 | Integer | R0 |
&80000000 | Float | R0..R3 |
Uses no other registers (including stack). Possible error if asked to take value of an array fred(): will need R12 valid for this error to be reported correctly.
When floating point values are returned/required in R0..R3, the format is as follows:
R0 | = | 32-bit mantissa, normalised (so bit 31 = 1) |
R1 | = | Exponent in excess-128 form |
R2 | = | Undefined |
R3 | = | Sign. 0 POSITIVE_ &80000000 negative |
This is provided for information only. We reserve the right to change this format; you should treat R0..R3 as a single item, without regard to the constituent parts.
Entry with R0..R3 value (stay in STRACC with R2=end) if using BASIC V (F0 if using BASIC VI), as appropriate to type of value in R9.
R4 | = | Address of l-value (where to store the value) |
R5 | = | Type of l-value (as in CALL parameter block) |
R8 | = | ARGP |
R9 | = | Type of value |
R12 | = | LINE (for errors) |
R13 | = | Stack pointer (for free space check) |
Converts between various formats, for example integer and floating point numbers, or produces an error if conversion is impossible.
Returns with R0 to R7 destroyed. Stack is not used.
This stores a string into a string variable. Entry with:
R2 | = | Length (i.e. address of byte beyond the last one) |
R3 | = | Address of start of string |
R4 | = | Address of l-value |
R8 | = | ARGP |
R12 | = | LINE (for error reporting) |
R13 | = | Stack pointer (for free space check) |
The string must start on a word boundary and the length must be 255 or less.
Uses R0, R1, R5, R6, R7. Preserves input registers. Stack not used.
This routine looks up a variable from the name pointed to by R8.
On entry:
R8 | = | ARGP |
R11 | = | Pointer to start of name |
R12 | = | LINE (many errors possible, such as subscript error in array) |
R13 | = | Stack (may call EXPR to evaluate subscripts) |
The string is processed to read one variable name and provide an address and type which can be given to VARIND.
If a valid variable name (or more precisely l-value) was found:
Z flag | = | 0 |
R0 | = | Address of l-value |
R9 | = | Type of l-value |
If a valid variable was not found:
Z flag | = | 1 |
C flag | = | 1 if there is no way the string was a variable name (e.g. %Q) |
C flag | = | 0 Could be a variable but hasn't been created (e.g. A) |
Uses all registers.
This creates a variable. Input is the failure of LVBLNK to find something. Thus we have:
R3 | = | Second character of name or 0 |
R4 | = | Points to start of the rest of the name |
R8 | = | ARGP |
R9 | = | Contains the number of zero bytes on the end |
R10 | = | First character of name |
R11 | = | Points to the end of the name |
R12 | = | LINE |
R13 | = | Stack pointer |
It is recommended that CREATE is only called immediately after a failed LVBLNK.
CREATE uses all registers. Returns result as LVBLNK. The LVBLNK and CREATE routines can be combined together to provide a routine which checks for a variable to assign to, and creates it if necessary:
STMFD R13!,{R14} ;Save return address BL LVBLNK ;Look-up name LDMNEFD R13!,{PC} ;Return if found LDMCSFD R13!,{PC} ;Or illegal name BL CREATE ;Create the new var LDMFD R13!,{PC} ;Return
This evaluates an expression pointed to by R11. On entry:
R8 | = | ARGP |
R11 | = | Pointer to start of string |
R12 | = | LINE |
R13 | = | Stack pointer |
EXPR stops after reading one expression (like those in the PRINT statement).
The value is returned in the same manner as VARIND. On exit:
Z flag | = | 1 the expression was a string |
Z flag | = | 0 the expression was a number |
N flag | = | 1 expression was a floating point number |
N flag | = | 0 expression was an integer |
R9 | = | Type |
R10 | = | First character after the expression |
R11 | = | Pointer to next character after R10 |
The status found in the Z and N flags on exit can be recreated by executing the instruction TEQ R9,#0.
One useful thing about EXPR is that it enables the machine code to call a BASIC routine. You do this by evaluating a string which has a call to a user-defined function in it. For example, the string you evaluate might be "FNinput". The function could perform some task which is tedious to do in machine code, such as input a floating point number.
One slight complication is that the string to be evaluated must have been tokenised already, so you must either call MATCH described below, or store the string with the tokenised form of FN (the byte &A4).
This routine takes a text string and tokenises it to another string. Strings passed to EXPR and LVBLNK must be tokenised first if they contain any BASIC keywords. On entry:
R1 | = | Points to the source string (terminated by ASCII 10 or 13) |
R2 | = | Points to the destination string |
R3 | = | MODE |
R4 | = | CONSTA |
R13 | = | Stack pointer |
Note that MATCH does not need ARGP or LINE.
The MODE value is 0 for left-mode (before an = sign, or at the start of a statement) and 1 for right-mode (in an expression). The difference is in the way that BASIC tokenises the pseudo-variables. Each of these has two tokens, one for when it is used as a statement (e.g. TIME=) and one when it is used as a function (PRINT TIME). As you will generally use MATCH to tokenise an expression string, you will use MODE = 1.
The CONSTA value is 0 if you do not want BASIC to convert integers which could be line numbers (in the range 0 to 65279) into internal format, and 1 if you do. Internal format consists of the token &8D followed by three bytes which contain the encoded line number. A property of these bytes is that they lie in the range 64 to 127, and therefore do not contain control codes or tokens.
Encoded constants are used for line numbers after GOTO, GOSUB, RESTORE, THEN and ELSE keywords. Because they are of fixed length, the program can be renumbered without having to move program lines about. Because they don't contain special characters, certain BASIC search operations (e.g. for the ELSE in a single-line IF) are speeded up.
Both MODE and CONSTA will be updated during the use of the routine. For example, GOTO will set CONSTA to &8D to read the line number, PRINT will change MODE to 1 to read an expression. The table below summarises the setting of MODE and CONSTA:
MODE | CONSTA | Meaning |
---|---|---|
0 | 0 | Tokenise a statement |
0 | &8D | Used to read line number at the start of a line |
1 | 0 | Tokenise an expression |
1 | &8D | Tokenise an expression after GOTO etc. |
The routine uses R0 to R5.
On exit, R1 and R2 are left pointing one byte beyond the terminating CR codes of the strings.
R5 contains status information, it can usually be disregarded: values greater than or equal to &1000 imply mismatched brackets. Bit 8 set implies that a number which was too large to be encoded using &8D (i.e. was greater than 65279) was found. If (R5 AND 255) = 1 then mismatched string quotes were found.
Note: if the first item in the source string is a line number and CONSTA is set on entry, the &8D byte will not be inserted into the destination string, but a space will be left for it. It is safe for the source and destination strings to be the same, as long as the destination never becomes longer than the source (which CONSTA line numbers can do.)
This routine converts a token value into a pointer to the text string representing it. On entry:
R0 | = | The token value |
R12 | = | Pointer to next byte of token string |
The value of R12 is only used when two-byte tokens are required. No other registers are used or required.
Returns R1 as a pointer to the first character of the string, terminated by a byte whose value is &7F or greater. R0 is set to the address of the start of the token table itself. R12 will have been incremented by one if a two-byte token has been used.
Store a four-word FP value into a five-byte variable. On entry:
R0..R3 | = | Source floating pointer value |
R9 | = | Pointer to destination value |
On exit:
R2 | = | Altered (but this doesn't affect the FP value) |
No errors. Stack not used.
Load a five-byte variable into a four-word FP value. On entry:
R9 | = | Pointer to source value |
On exit:
R0..R3 | = | Loaded FP value |
No errors. Stack not used.
Add/multiply the four-word FP value in R0..R3 by the variable at [R9]. On entry:
R0..R3 | = | Source FP value |
R9 | = | Pointer to five-byte variable. |
On exit:
R0..R3 | = | Added/multiplied by [R9] |
R4..R7 | = | Corrupted |
Overflow errors possible. Stack not used.
Subtract R0..R3 from [R9] or divide [R9] by R0..R3, with the result in R0..R3. On entry:
R0..R3 | = | FP value |
R9 | = | Pointer to five-byte variable. |
On exit:
R0..R3 | = | [R9] minus old value or [R9] / old value |
R4..R7 | = | Corrupted |
Overflow errors possible. Divide by zero possible for FDIV. Stack not used.
Convert integer to four-word floating point value. On entry:
R0 | = | Integer |
On exit:
R0..R3 | = | Floated version |
R9 | = | &80000000 (floating type code) |
No overflow possible. Stack not used.
Convert four-word floating point value to an integer. On entry:
R0..R3 = Float ing point value |
On exit:
R0 = Fixed version (rounded towards 0) |
R9 = &40000000 (integer type code) |
Overflow error possible. Stack not used.
Take the square root of the floating point number in R0..R3. On entry:
R0..R3 | = | Floating point value |
On exit:
R0..R3 | = | SQR(old value) |
R0..R7 | = | Corrupt |
Negative root error possible. Stack not used.
If the CALL statement is used with an address which corresponds to a MOS entry point on the BBC Micro/Acorn Electron/Master 128 series machines and there are no other parameters, then BASIC treats the call as if it had been made from one of those machines. The way in which the registers are initialised is then as follows:
R0 | A% |
R1 | X% |
R2 | Y% |
C flag | C% (bit 0) |
This means that programs written to run on earlier machines using legal MOS calls can continue to work. For example, the sequence
10 osbyte=&FFF4 1000 A%=138 1010 X%=0 1020 Y%=65 1030 CALL osbyte
will be interpreted as the equivalent SYS OS_Byte call:
1000 SYS "OS_Byte",138,0,65
This facility is provided for backwards compatibility only. You should not use it in new programs. Also, you must be careful that any machine code you assemble in a program does not lie in the address range &FFCE to &FFF7; otherwise when you call it, it might be mistaken for a call to an old MOS routine.
CALL invertMatrix,a()
CALL sampleWaveform,start%,end%,values%()
Statement marking the start of a CASE OF WHEN OTHERWISE ENDCASE construct. It must be the first statement on the line.
CASE expression OF
WHEN expression [,expression...] [:statements...]
[statements]
[WHEN ...]
OTHERWISE [statements...]
[statements...]
ENDCASE
expression can be any numeric or string expression. The value of expression is compared with the values of each of the expressions in the list following the first WHEN statement. If a match is found, then the block of statements following the WHEN down to either the next WHEN or OTHERWISE or ENDCASE is executed. Then control moves on to the statement following the ENDCASE. If there is no match, then the next WHEN is used, if it exists. OTHERWISE is equivalent to a WHEN but matches any value.
CASE A% OF
CASE Y*2 + X*3 OF
CASE GET$ OF
Statement to load and run a BASIC program.
expression should evaluate to a string which is a valid filename for the filing system in use.
Note: A filing system error may be produced if, for example, the file specified cannot be found. When the program is loaded, all existing variables are lost (except the system integer variables and installed libraries).
CHAIN "partB"
CHAIN a$+"2"
Statement to draw a circle.
The expressions are integers in the range -32767 to +32768. The first two values give the x and y coordinates of the centre of the circle. The third gives the radius. CIRCLE produces a circle outline, whereas CIRCLE FILL plots a solid circle. The current graphics foreground colour and action are used.
Note: In both cases, the position of the graphics cursor is updated to lie at a position on the circumference which has an x coordinate of expression1 + expression3 and a y coordinate of expression2. The 'previous graphics cursor' position (as used by, for example, triangle plotting) will be updated to lie at the centre of the circle plotted.
CIRCLE 640,512,50
CIRCLE FILL RND(1278),RND(1022),RND(200)+50
Statement to remove all program variables.
When this statement is executed, all variables are removed and so become undefined. In addition, any currently active procedures, subroutines, loops, and so on are forgotten, and LIBRARY and OVERLAY libraries are lost. The exceptions to this are the system integer variables and INSTALLed libraries which still remain.
Statement to close an open file.
A channel number as returned by the OPENxx function. If zero is used all open files on the current filing system are closed. Otherwise, only the file with the channel number specified is closed.
Note: you shouldn't use the CLOSE#0 form within programs, as other programs may be relying on files remaining open. You should only use it as an immediate command, and possibly in a program during its development stage.
Closing a file ensures that its contents are updated on whatever medium is being used. This is necessary as a certain amount of buffering is used to make the transfer of data between computer and mass-storage device more efficient. Closing a file, therefore, releases a buffer for use by another file.
CLOSE#indexFile
CLOSE#0
Statement to set the text colours or alter the palette settings.
(1) COLOUR expression [TINT expression]
(2) COLOUR expression,expression
(3) COLOUR expression,expression,expression,expression
expression is an integer in the range 0 to 255. The range 0 to 127 sets the text foreground colour. Adding 128 to this (i.e. 128 to 255) sets the text background colour. The colour is treated MOD the number of colours in the current mode. The argument is the logical colour. For a list of the default logical colours, see the chapter entitled Screen modes.
The optional TINT is only effective in 256-colour modes. It selects the amount of white to be added to the colour. The value can lie in the range 0 to 255, with only the values 0, 64, 128 and 192 currently being used to obtain different whiteness levels. Colours in the 256-colour modes are in the range 0 to 63.
The first expression is an integer in the range 0 to 15 giving the logical colour number. The second expression is an integer in the range 0 to 15 giving the actual colour to be displayed when the logical colour is used. The actual colour numbers correspond to the default colours available in 16-colour modes: eight steady colours and eight flashing colours. The colour list is given in the Screen modes.
This form of the command sets the palette, so any changes are visible immediately.
In WIMP-based programs, you should use the call Wimp_SetPalette to control the palette.
The first expression is an integer in the range 0 to 15 giving the logical colour number. The next three expressions are integers in the range 0 to 255 giving the amount of red, green and blue which are to be assigned to that logical colour. Only the top four bits of each are relevant with the current video display hardware. Thus distinct levels are 0, 16, 32,
Note: The keyword is listed as COLOUR in programs, even if it was typed in using the alternative spelling.
In all modes the default state, before any changes to the palette, dictates that colour 0 is black and colour 63 is white.
Only colours 0 and 1 are unique in two-colour modes. After that the cycle repeats. Similarly, only colours 0, 1, 2 and 3 are distinct in the four-colour modes.
In WIMP-based programs, you should use the call Wimp_SetPalette to control the palette.
COLOUR 128+1 : REM text background colour = 1
COLOUR 1,5 : REM logical colour 1 = colour 5 (magenta)
COLOUR 1,255,255,255 : REM logical colour 1 = white
Function giving the cosine of its numeric argument.
factor is an angle in radians.
Real between -1 and +1 inclusive.
Note: If the argument is outside the range -8388608 to 8388608 radians, it is impossible to determine how many s to subtract. The error Accuracy lost in sine/cosine/tangent is generated.
PRINT COS(RAD(45))
adjacent = hypotenuse*COS(angle)
Function giving the number of characters printed since the last newline.
Positive integer, giving the number of characters output since the last newline was generated by BASIC.
Note: COUNT is reset to zero every time a carriage return is printed (which may happen automatically if a non-zero WIDTH is being used). It is incremented every time a character is output by PRINT, INPUT or REPORT, but not when output by VDU or any of the graphics commands. COUNT is also reset to zero by CLS and MODE.
REPEAT PRINT " ";
UNTIL COUNT=20
chars = COUNT
Command to strip various spaces from a program.
CRUNCH variable
variable is a 5-bit binary word. Each bit in the variable has a special meaning, as follows:
Bit 0 | = | 1 | strips out all spaces before statements. |
Bit 1 | = | 1 | strips out all spaces within statements. Note that CRUNCH %10 may make a program uneditable. |
Bit 2 | = | 1 | strips out all REM statements, except those on the first line. |
Bit 3 | = | 1 | strips out all empty statements. |
Bit 4 | = | 1 | strips out all empty lines. |
The interpreter has been optimised for fully CRUNCHed programs.
Note that, in BASIC VI, programs with -quit set will be CRUNCH %1111, as will LIBRARY subprograms. BASIC V will also do this if the OS variable BASIC$Crunch exists. OVERLAY statements will not be CRUNCHed.
The BASIC 1.04 interpreter cannot read assembler statements that have been CRUNCHed; for example EORR4,R4,R5. Setting bit 4 to 1 may cause problems in constructs that expect an empty line as the target (e.g. GOTO, GOSUB, IF THEN, RESTORE).
CRUNCH %1101
CRUNCH %10011
Passive statement marking the position of data in the program.
The expressions may be of any type and range, and are only evaluated when a READ statement requires them.
Note: The way in which DATA is interpreted depends on the type of variable in the READ statement. A numeric READ evaluates the data as an expression, whereas a string READ treats the data as a literal string. Leading spaces in the data item are ignored, but trailing spaces (except for the last data item on the line) are counted. If it is necessary to have leading spaces, or a comma or quote in the data item, it must be put between quotation marks. For example:
100 DATA " HI","A,B,", """ABCD"
If an attempt is made to execute a DATA statement, BASIC treats it as a REM. In order to be recognised by BASIC, the DATA statement, like other passive statements, should be the first item on a line.
DATA Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec
DATA 3.26,4,4.3,0
Passive statement defining a function or procedure.
(2) DEF PROCproc-part
where proc-part has the form identifier[(parameter-list)]
The optional parameters, which must be enclosed between round brackets and separated by commas, may be of any type. For example: parm, parm%, parm$, !parm, $parm. It may be preceded by RETURN to use value-result passing instead of simple value passing. In addition, whole arrays may be passed as parameters, e.g. a(), a$().
The DEF statement marks the first line of a user-defined function or procedure, and also indicates which parameters are required and their types. The parameters are local to the function or procedure (except for arrays), and are used within it to stand for the values of the actual parameters used when it was called.
Note: Function and procedure definitions should be placed at the end of the program, so that they cannot be executed except when called by the appropriate PROC statement or FN function. The DEF statement should be the first item on the line. If not, it will not be found.
DEF FNmean(a,b)
DEF PROCinit
DEF PROCthrow_dice(d%,tries,RETURN mesg$)
DEF PROCarray_determinant(A())
Command to delete a section of the program.
Integer constants in the range zero to 65279. They give the first and last line to be deleted respectively. If the first line number is greater than the second, no lines are deleted. To delete just a single line the DELETE command is not necessary. Instead type the line number and press Return.
DELETE 5,22
DELETE 110,150
Statement declaring arrays or reserving storage.
Function returning information about an array.
where dim-part is:
(1) identifier[% or $](expression[,expression] etc)
or
(2) numeric-variable space expression
or as a function:
(3) DIM(array)
(4) DIM(array,expression)
The identifier can be any real, integer or string variable name. The expressions are integers which should be greater than or equal to zero. They declare the upper bound of the subscripts; the lower bound is always zero.
This is the way to declare arrays in BASIC. They may be multi-dimensional: the bounds are limited only by the amount of memory in the computer. Numeric arrays are initialised to zeros and string arrays to null strings.
The numeric-variable is any integer or real name. It is always global, even if it is declared locally. The expression gives the number of bytes of storage required minus one, and should be -1 or greater. It is limited only by the amount of free memory.
The use of this form of DIM is to reserve a given number of bytes of memory, in which to put for example, machine code. The address of the first byte reserved, which will be a multiple of four, is placed in the numeric-variable. The byte array is uninitialised.
The array is the name of any previously DIMed array, or an array used as a formal parameter in a procedure or function. The result of the function is the number of dimensions which that array has.
The array is the name of any previously DIMed array or an array used as a formal parameter in a procedure or function. The expression is a number between one and the number of dimensions of the array. The result of the function is the subscript of the highest element in that dimension, i.e. the value used for that subscript in the DIM statement that declared the array in the first place.
Note: It is possible to have local arrays, whose contents are discarded when the procedure or function in which they are created returns. See LOCAL.
DIM name$(num_names%)
DIM sin(90)
DIM matrix%(4,4)
DIM A(64), B%(12,4), C$(2,8,3)
DIM bytes% size*10+overhead
PRINT DIM(name$())
size%=DIM(name$(),1)
Integer division
Integer-range numerics. Reals are converted to integers before the divide operation is carried out. The righthand side must not evaluate to zero.
The (integer) quotient of the operands is always rounded towards zero. If the signs of the operands are the same, the quotient is positive, otherwise it is negative. The remainder can be found using MOD.
PRINT (first-last) DIV 10
a%=space% DIV &100
Statement to draw a line to specified coordinates.
The two expressions give the coordinates of one of the end points of a straight line. The other end point is given by the current graphics cursor position. After the line has been drawn (using the graphics foreground colour and action), the graphics cursor is updated to the coordinates given in the DRAW statement.
If the keyword BY is omitted, the coordinates are absolute. That is, they give the position of the end of the line with respect to the graphics origin. If BY is included, the coordinates are relative. That means they give the position of the end of the line with respect to the current graphics cursor position.
DRAW 640,512 : REM Draw a line to middle of the screen
DRAW BY dx%, dy%
Command to enter the BASIC screen editor.
EDIT enters the BASIC screen editor to allow you to create a new program or amend the current one. Full details of the editor are given in the Editing BASIC programs chapter.
Statement to draw an ellipse.
expr1 to expr5 are integer expressions. The first two give the coordinates of the centre of the ellipse. The third expression gives the length of the semi-major axis. This is the axis parallel with the x axis if the ellipse is not rotated. The fourth expression gives the length of the semi-minor axis. This is the axis parallel with the y axis if the ellipse is not rotated.
The optional fifth expression gives the rotation of the ellipse, in radians, anti-clockwise.
ELLIPSE draws the outline of an ellipse. ELLIPSE FILL plots a solid ellipse.
Note: The ELLIPSE statement has some (minor) restrictions about the size of its operands: if both of the semi-axes are of length zero, then you are not allowed to specify a rotation value. If the semi-minor axis length is zero, then the rotation, if specified, must not be zero. The result of trying to draw any of these 'illegal' ellipses is a Division by zero error.
ELLIPSE 640,512,200,100
ELLIPSE FILL x%,y%,major%,minor%,ang
Part of the ON GOTO/GOSUB/PROC ELSE OR IF THEN ELSE OR IF THEN ELSE ENDIF constructs.
See IF and ON entries, as appropriate.
Note: ELSE may occur anywhere in the program, but is only meaningful after an IF (multi- or single-line) or ON GOSUB/GOTO/PROC statement. When used as part of a multi-line IF statement, it must be the first non-space object on the line.
IF a=b THEN PRINT "hello" ELSE PRINT "good-bye"
IF ok ELSE PRINT "Error"
ON choice GOSUB 100,200,300,400 ELSE PRINT"Bad choice"
IF num>=0 THEN PRINT SQR(num) ELSE PRINT "Negative number" PRINT SQR(-num) ENDIF
Statement terminating the execution of a program or a function returning the top of memory used.
Statement setting the highest address used by BASIC.
Function returning the address of the end of BASIC variables.
as a statement:
as a function:
(3) END
The END statement terminates the execution of a program.
Note: This statement is not always necessary in programs; execution stops when the line at the end of the program is executed. However, END (or STOP) must be included if execution is to end at a point other than at the last program line. This prevents control falling through into a procedure, function or subroutine. END is also useful in error handlers.
When used in a assignment, END sets the highest address used by BASIC when running under the WIMP. This can be used by programs running under the WIMP to claim more memory from the free pool, or alternatively to give up unrequired memory.
The expression should be an integer giving the new value for HIMEM. After the call, memory above the given address will be de-allocated and HIMEM will be set to that location. In addition, local arrays and installed libraries are cleared.
If there is not enough free memory to set HIMEM to the requested value, the error Attempt to allocate insufficient memory is given.
The END function returns the address of the top of memory used by a program and its variables. The expression END-TOP gives the number of bytes used by variables (except LOCAL arrays), and OVERLAY and LIBRARY libraries.
PRINT END
END = &10000 : REM only need 32K to RUN
Statement marking the end of a CASE OF WHEN OTHERWISE ENDCASE construct.
Note: ENDCASE must be the first non-space object on the line. When the statements corresponding to a WHEN or OTHERWISE statement have been executed, control then jumps to the statement following the ENDCASE. If ENDCASE itself is executed, it signals the end of the CASE statement, no matches having been made. Control then continues as normal.
Terminates an IF THEN ELSE ENDIF construct.
Note: ENDIF marks the end of a block-structured IF statement. It must be the first non-space object on a line. When the statements corresponding to the THEN or ELSE statement have been executed, control jumps to the statement following the ENDIF. If ENDIF itself is executed, it signals the end of the IF statement, nothing having been executed as a result of it. Control then continues as normal.
Statement marking the end of a user-defined procedure.
When executed, an ENDPROC statement causes BASIC to terminate the execution of the current procedure and to restore local variables, actual parameters, LOCAL DATA and LOCAL ERROR. Control is passed to the statement after the PROC which called the procedure. ENDPROC should only be used in a procedure. Otherwise, when it is encountered, a Not in a procedure error message is generated.
ENDPROC
IF a<=0 THEN ENDPROC ELSE PROCrecurse(a-1)
Statement to terminate a WHILE ENDWHILE loop.
Note: When an ENDWHILE is executed, control loops back to the corresponding WHILE statement. The statements forming the WHILE ENDWHILE loop are executed until the condition following the matching WHILE evaluates to FALSE, whereupon control jumps to the statement following the ENDWHILE.
MODE 15 INPUT X WHILE X > 0 GCOL X CIRCLE FILL 640,512,X X -= 4 ENDWHILE
Function indicating whether the end of a file has been reached.
A channel number returned by an OPENxx function.
TRUE if the last character in the specified file has been read, FALSE otherwise. EOF for a file may be reset by positioning its pointer using the PTR# statement.
REPEAT VDU BGET#file UNTIL EOF#file IF EOF#invoices PRINT "No more invoices"
Operator giving the bitwise exclusive-OR (EOR).
Relational expressions, or bit values to be EORed
The logical bitwise EOR of the operands. Corresponding bits in the operands are EORed to produce the result. Each bit in the result is zero if the corresponding bits in the operands are equal, and otherwise one.
PRINT height>10 EOR weight<20
bits = mask EOR value1
Function returning the last error line.
Integer between 0 and 65279. This is the line number of the last error to occur. An error line of 0 implies that the error happened in immediate mode or that there has not been an error.
Note: If an error occurs inside a LIBRARY, INSTALL or OVERLAY procedure, ERL is set to the number of the last line of the main program. It does not normally indicate where in the library the error occurred.
REPORT : IF ERL<>0 THEN PRINT " at line "; ERL
IF ERL=3245 PRINT "Bad function, try again"
Function returning the last error number.
A four-byte signed integer. Errors produced by BASIC are in the range 0 to 127.
Note: The error number 0 is classed as a fatal error and cannot be trapped by the ON ERROR statement. An example of a fatal error is that produced when a BASIC STOP statement is executed.
IF ERR=18 THEN PRINT "Can't use zero; try again!!"
IF ERR=17 THEN PRINT"Sure?":A$=GET$:IF INSTR("Yy",A$) THEN STOP
Generates an error, or is part of the ON ERROR statement.
(1) ON ERROR ...
(2) ERROR [EXT] expression1, expression2
Note (1): See ON ERROR for details of the error handling statements.
expression1 evaluates to a four-byte signed integer corresponding to an error number. expression2 evaluates to a string associated with this error number. The error described is generated, in the same way as internal BASIC errors. Thus ERL will be set to expression1 and REPORT$ set to expression2. The current error handler will then be called, unless the error number is zero, in which case a fatal (untrappable) error will be generated.
If the keyword EXT is present, then BASIC terminates and the error number and string are passed to the error handler of the program that invoked BASIC. The default BASIC error handler uses this if the -quit option was given on the command line.
ERROR 6, "Type mismatch: number needed"
ERROR EXT ERR,REPORT$ : REM pass on the error
Function which evaluates its string statement as an expression.
A string which EVAL evaluates as a BASIC expression.
EVAL can return anything that could appear on the righthand side of an assignment statement, including strings. It can also produce the same errors that occur during assignment. For example:
Type mismatch: number needed
and
No such function/procedure.
INPUT hex$
PRINT EVAL("&"+hex$)
f$="LEFT$("
e$=EVAL(f$+"""ABCDE""",2)")
Function returning the exponential of its argument.
Numeric from the largest negative real (about -1E38) to approximately +88.
Positive real in the range zero to the largest positive real (about 1E38). The result could be expressed as the argument where E is the constant 2.718281828.
DEF FNcosh(x)=(EXP(x) + EXP(-x))/2
Pseudo-variable returning or setting the length (extent) of an open file.
factor is a channel number, as allocated by one of the OPENxx functions.
Integer giving the current length of the file from 0 to, in theory 2147483648, although in practice the extent is limited by the file medium in use.
factor is a channel number as allocated by one of the OPENxx functions.
expression is the desired extent of the file, whose upper limit depends on the filing system. The lower limit is 0. The main use of the statement is to shorten a file. For example: EXT#file=EXT#file-&1000. A file may be lengthened by explicitly using PTR#, or implicitly by BPUTing to its end.
Note: As with all the pseudo-variables, the LET keyword and the operators += and -= cannot be used with EXT#.
EXT is also used a part of the ERROR EXT ... statement; see the ERROR keyword for details.
IF EXT#file>90000 THEN PRINT "File full":CLOSE#file
EXT#op=EXT#op+&2000
Flood-fill an area in the current foreground colour.
The two expressions give the coordinates of the point from which the flood-fill is to commence (the 'seed' point). The filled pixels are plotted using the current foreground colour and action over an area bounded by non-background colour pixels and the graphics viewport. If the seed point is in a non-background colour, then no filling takes place at all.
The graphics cursor is updated to the coordinates given,
If the keyword BY is omitted, the coordinates are absolute. That is, they give the position of the seed point with respect to the graphics origin. If BY is included, the coordinates are relative. That means they give the position of the seed point with respect to the current graphics cursor position.
FILL x%,y%
FILL BY dx%,dy%
Word introducing or calling a user-defined function.
(1) DEF FNproc-part
For the format of proc-part, see DEF above. It gives the names and types of the parameters of the function, if any. For example:
1000 DEF FNmin(a%,b%) IF a%<b% THEN =a% ELSE =b%
a% and b% are the formal parameters. They stand for the expressions passed to the function (the actual parameters) when FNmin is called. The result of a user-defined function is given by a statement starting with =. As the example above shows, there may be more than one = in a function. The first one which is encountered during execution terminates the function.
Note: User-defined functions may span several program lines, and contain all the normal BASIC statements, for example, FOR loops, IF statements, and so on. They may also declare local variables using the LOCAL keyword.
proc-part is an identifier followed by a list of expressions (or array or RETURN variables) corresponding to the formal parameters in the DEF statement for the function. The result depends on the assignment that terminated the function, and so can be of any type and range. An example function call is:
PRINT FNmin(2*bananas%, 3*apples%+1)
DEF FNfact(n%) IF n%<1 THEN =1 ELSE =n%*FNfact(n%-1)
DEF FNhex4(n%)=RIGHT$("000"+STR$~(n%),4)
REPEAT PRINT FNhex4(GET): UNTIL FALSE
Part of the FOR NEXT statement.
The variable can be any numeric variable reference. The expressions can be any numeric expressions, though they must lie in the integer range if the variable is an integer one. It is recommended that integer looping variables are used for the following reasons:
If the STEP part is omitted, the step is taken to be +1. The action of the FOR loop is as follows. The looping variable is set to the first expression. The limit expression and step, if present, are remembered for later. The statements up to the matching NEXT are executed. At this stage, the step is added to the looping variable. The termination condition is that, for positive steps, the looping variable has become greater than the limit, and for negative steps it has become less than the limit. If this condition is met, control continues at the statement after the NEXT. Otherwise, control jumps back to the statement after the NEXT.
Note: The statements between a FOR and its corresponding NEXT are executed at least once as the test for loop termination is performed at the NEXT rather than the FOR. Thus a loop started with FOR I=1 TO 0 executes once, with I set to 1 in the body of the loop. The value of the looping variable when the loop has finished should be treated as undefined, and should not be used before being reset by an assignment.
FOR addr%=200 TO 8000 STEP 4
FOR I=1 TO LEN(a$)
Statement to set the graphics colours and actions.
GCOL sets the colour and plot mode that will be used in subsequent graphics operations.
expression1, if present, is an integer between 0 and 255 which determines the plot 'action', i.e. how the graphics colour, expression2, will be combined with what's on the screen when plotting points, lines, etc. Its basic range is 0 to 7, as shown below:
Action | Meaning |
---|---|
0 | Store the colour expression2 on the screen |
1 | OR the colour on the screen with expression2 |
2 | AND the colour on the screen with expression2 |
3 | EOR the colour on the screen with expression2 |
4 | Invert the current colour, disregarding expression2 |
5 | Do not affect the screen at all |
6 | AND the colour on the screen with the NOT expression2 |
7 | OR the colour on the screen with the NOT expression2 |
Although action 5 does not actually alter the screen, each pixel is accessed as though the operation was taking place, so it is no quicker than the other actions.
If you add n*16 to the action number, then colour patterns are used instead of solid colours. n is in the range 1 to 4 for the four basic patterns, or 5 for a large pattern made from the other four placed side by side. VDU 23,2 to VDU 23,5 are used to set the colour fill patterns. If the currently selected pattern is re-defined, it becomes active immediately.
If you further add 8 to the action, then where the colour pattern contains the current graphics background colour, nothing is plotted, i.e. that colour becomes transparent. For example, suppose the display is a four-colour one, and the current background colour is 129 (red).
Now, if pattern 1 was selected as the foreground colour (GCOL 16,0), a solid rectangle would be red-yellow, as pattern 1 consists of alternating red and yellow pixels. However, if the foreground colour was set using GCOL 24,0 (adding 8 to the plot action number), then a solid rectangle would appear yellow, with transparent 'holes' where the red pixels would have been plotted.
Adding 8 to the action also causes sprite plotting to use the transparency mask, if present. See the chapter entitled Sprites for more details.
If expression1 is omitted, 0 is used, which means that the colour given is stored onto the screen.
The colour number, expression2, is in the range 0 to 255. Values below 128 are used to set the graphics foreground colour. Other values set the background colour. For example, colour 129 sets the background colour to 129-128, or 1. The number is treated MOD the number of colours in the current mode, i.e. 2, 4, 16 or 64. Thus in 256-colour modes, the colour range is 0 to 63 (or 128 to 191 for background).
The TINT value, if present, is used to add one of four whiteness levels to the 64 colours available in the 256-colour modes, giving the total 256 possible hues. expression3 is in the range 0 to 255, where currently the only significant levels are 0, 64, 128 and 192.
Note: WIMP-based programs should use Wimp_SetColour or ColourTrans_ReturnGCOL, not GCOL.
GCOL 2
DRAW 100,100 : REM Draw a line in colour 2
GCOL 4,128
CLG : REM Invert the graphics window
GCOL 1,2 : REM OR the screen with colour 2
GCOL 18 TINT 128
Function returning a character code from the input stream (e.g. keyboard, RS423, etc).
An integer between 0 and 255. This is the ASCII code of the next character in the buffer of the currently selected input stream (keyboard or RS423). The function will not return until a character is available, and so it can be used to halt the program temporarily.
Note: The character entered is not echoed onto the screen. To make it appear you must explicitly PRINT it.
PRINT "Press space to continue" :REPEAT UNTIL GET=32
ON GET-127 PROCa, PROCb, PROCc ELSE PRINT "Illegal entry"
Function returning a string from a file.
A channel number returned by an OPENxx function.
A string of characters read until a linefeed (ASCII 10), carriage return (ASCII 13), null character (ASCII 0) or the end of the file is encountered, or else the maximum of 255 characters is reached. The terminating character is not returned as part of the string.
Note: PTR# is updated to point to the next character in the file. If the last character in the file has been read, EOF# for the channel will be TRUE.
string$ = GET$#channel
PRINT GET$#fileno
Function returning a character from the input stream (e.g. keyboard).
A one-character string whose value would be CHR$(GET) if GET had been called instead. This is provided so you can use statements like IF GET$="*"... rather than IF CHR$(GET)="*"
PRINT "Do you want another game?":response$ = GET$
IF response$ = "Y" or response$ = "y" CHAIN "program"
PRINT "Input a digit "; : PRINT GET$
(1) GOSUB expression
(2) ON expression GOSUB expression1 [,expression2...] [ELSE statement]
expression should evaluate to an integer between 0 and 65279, in other words a line number. If the expression is not a simple integer (e.g. 1030) it should be enclosed between round brackets. The line given is jumped to, and control is returned to the statement after the GOSUB by the next RETURN statement.
expression should evaluate to an integer. If this integer is n then the nth subroutine listed after the GOSUB is jumped to. If the integer is less than 1 or greater than the number of line numbers given, the statement following the ELSE, if it is present, is executed.
Note: Procedures should be used in preference to subroutines since they are more flexible and produce a better structured program. The line number after GOSUB should be a constant so that RENUMBER works properly.
10 GOSUB 2000
20 GOSUB (2300+20*opt): REM not nice
30 ON x% GOSUB 100,200,300 ELSE PRINT "Out of range"
(1) GOTO expression
(2) ON expression GOTO expression1 [,expression2...][ELSE statement]
expression should evaluate to an integer between 0 and 65279: a line number. If the expression is not a simple integer, it should be placed between round brackets. This line number is jumped to and execution carries on from this new line.
expression should evaluate to an integer. expression1 should evaluate to integer line numbers between 0 and 65279. If the first integer is n then the nth line after the GOTO is jumped to. If the integer is less than 1 or greater than the number of line numbers given, the statement following the ELSE, if it is present, is executed.
Note: The line number after GOTO should be a constant so that RENUMBER and APPEND work properly.
GOTO 230
IF TIME<1000 THEN GOTO 1000
ON x GOTO 20,50,30,160
Command giving help information.
HELP displays a list of useful information about the status of BASIC. If the keyword is present, help about that particular command, statement or function is printed. To obtain a list of all keywords, type HELP . .
HELP
HELP HIM.
HELP .
Pseudo-variable holding address of the top of the BASIC stack.
An integer giving the address of the location above the end of user memory. The amount of user memory is given by HIMEM - LOMEM and the amount of free memory by HIMEM - END.
expression should be an integer between LOMEM and the top of usable memory. It restricts the amount of memory which the current program can use for workspace stacks etc, hence giving an area where data, or machine code routines can be stored.
Note: If HIMEM is set carelessly, running the program may produce the No room error. There must always be enough for the stack.
The INSTALL statement lowers HIMEM by the size of the library being installed.
When an attempt is made to set HIMEM, LOMEM, or PAGE to an illegal value, a warning message is displayed, and no change is made, but the program nevertheless continues to run. This means that such errors cannot be trapped using ON ERROR.
PRINT "Memory available = ";HIMEM - LOMEM
a%=HIMEM-1000 : HIMEM=a%
Statement to execute statements conditionally.
IF expr [THEN] [statements...] [[ELSE][statements...]]
IF expression THEN [statements...] [ELSE [statements...] statements...] ENDIF
expr is treated as a truth value. If it is non-zero, it is counted as TRUE and any statements in the THEN part are executed. If the expression evaluates to zero (FALSE), then the ELSE part statements are executed.
statements is either a list of zero or more statements separated by colons, or a line number. In the latter case there is an implied GOTO after the THEN (which has to be present) or ELSE.
Note: The THEN is optional before statements except before * commands. For example:
IF a THEN *CAT
not
IF a *CAT
The ELSE part matches any IF, so be wary of nesting IFs on a line. Constructs of the form:
IF a THEN... IF b THEN... ELSE...
should be avoided because the ELSE part might match either the first or second IF depending on the values of a and b. To avoid the ambiguity, use a multi-line IF of the form:
IF a THEN IF b THEN ... ELSE ... ENDIF ENDIF | or |
IF a THEN IF b THEN ... ENDIF ELSE REM part of IF a ... ENDIF |
depending on the effect required.
However, the form:
IF a THEN... ELSE IF b THEN...
is not ambiguous and can be used with no problems.
expression is treated as a truth value. If it is non-zero, it is counted as TRUE and any statements on the line after the THEN down to either an ELSE or an ENDIF are executed. If the expression evaluates to zero (FALSE), any statements following the ELSE (if present) until the ENDIF are executed. Note that in this form, THEN must be the last thing on the line.
IF temp<=10 PROClow_temp IF a%>b% THEN SWAP a%, b% ELSE PRINT "No swap" IF B^2 >= 4*A*C THEN PROCroots(A,B,C) ENDIF IF r$ = "Y" OR r$ = "y" THEN PRINT "YES" ELSE PRINT "NO" STOP ENDIF
Function returning a character code from the current input stream, or interrogating the keyboard.
(1) INKEY positive-factor
(2) INKEY negative-factor
(3) INKEY -256
An integer in the range 0 to 32767, which is a time limit in centi-seconds.
The ASCII code of the next character in the current input buffer if one appears in the time limit set by the argument, or -1 if a time-out occurs.
An integer in the range -255 to -1, which is the negative INKEY code of the key being interrogated (see Appendix D: Inkey values for details).
TRUE if the key is being pressed at the time of the call, FALSE if it is not.
-256
A number indicating which version of the operating system is in the computer.
DEF PROCwait(secs%) IF INKEY(100*secs%): REM throw away result ENDPROC IF INKEY(-99) THEN REPEAT UNTIL NOT INKEY(-99)
Statement obtaining a value or values from the input stream.
INPUT is followed by an optional prompt, which, if present, may be followed by a semi-colon or comma, which causes a ? to be printed out after the prompt. This is followed by a list of variable names of any type, separated by commas. After the last variable, the whole sequence may be repeated, separated from the first by a comma. In addition the position of prompts may be controlled by the SPC, TAB and ' print formatters (see PRINT).
Note: Leading spaces of the input string itself are skipped, and commas are taken as marking the end of input for the current item.
INPUT a$ : REM Print a simple"?" as a prompt
INPUT "How many",num% : REM prompt is "How many?"
INPUT "Address &"hex$ : REM "Address &" no ? because no ,
INPUT TAB(10)"Name ",n$'TAB(10)"Address ",a$
INPUT a,b,c,d,"More ",yn$
INPUT SPC(5)"Letter",char$
Statement obtaining a value or values from the input stream.
This has the same syntax as INPUT
If the input variable is a string, all the user's input is read into the variable, including leading and trailing spaces and commas. If the input variable is numeric, only a single value will be selected from the beginning of the input line.
Note: INPUT LINE is equivalent to LINE INPUT
INPUT LINE ">" basic$
Statement obtaining a value or values from a file.
factor is the channel number of the file from which the information is to be read, as obtained by an OPENxx function. The variables, if present, may be of any type. The separators may be semi-colons instead of commas.
Integer variables are read as &40 followed by the two's complement representation of the integer in four bytes, most significant byte first.
5-byte real variables are read as &80 followed by five bytes. The first four bytes are the mantissa and the fifth is the exponent. The mantissa is read least significant byte (LSB) first. 31 bits represent the magnitude of the mantissa and one bit (bit 7 of the fourth byte) the sign. The exponent byte is in excess-128 form.
8-byte real variables are read as &88 followed by two 4-byte words, in IEEE Double Precision (D) format. The exponent is represented by bits 20 to 30 in the first word. The sign bit is bit 31 in the first word. The mantissa is represented by bits 0 to 19 in the first word and bits 0 to 31 in the second word.
Both BASIC V and BASIC VI can read 5- and 8-byte real formats.
String variables are read as a zero byte followed by a byte containing the string length and then the characters in the string in reverse order.
Note: Files read using INPUT# must adhere to the format described above, which implies they should have been created using PRINT#. BASIC will perform conversion between integers and floating point values where possible.
INPUT#data,name$,addr1$,addr2$,addr3$,age%
INPUT#data,$buffer,len
Statement to load a function or procedure library into memory.
expression is a string which should evaluate to a filename that is valid for the filing system in use.
INSTALL loads the chosen function and procedure library into the top of memory and lowers the BASIC stack and value of HIMEM by an appropriate amount. The library remains in memory until you QUIT from BASIC. Any number of libraries may be installed provided that there is enough memory for them.
When searching for a procedure or function, BASIC looks in the following order: first, the current program is searched, in line-number order; next, any procedure libraries loaded using LIBRARY are searched - the most recently loaded file is searched first; then, any INSTALLed libraries are examined, again in the reverse order of loading. Finally the OVERLAY library list is searched.
The LVAR command lists (the first lines of) libraries in the order in which they are examined.
INSTALL "Printout"
A$ = "Library1"
INSTALL A$
Function to find the position of a substring in a string.
expression1 is any string which is to be searched for a substring.
expression2 is the substring required.
expression3 is a numeric in the range 1 to 255 and determines the position in the main string at which the search for the substring will start. This defaults to 1.
An integer in the range 0 to 255. If 0 is returned, the substring could not be found in the main string. A result of 1 means that the substring was found at the first character of the main string, and so on. The position of the first occurrence only is returned.
Note: If the substring is longer than the main string, 0 is always returned. If the substring is the null string, the result is always equal to expression3, or 1 if this is omitted.
REPEAT a$=GET$:UNTIL INSTR("YyNn",a$) <> 0
pos%=INSTR(com$,"*FX",10)
Function giving the integer part of a number.
Any integer-range numeric.
Nearest integer less than or equal to the argument. Note that this is different from rounding towards zero: whereas INT(1.5) equals 1, INT(-1.5) is equal to -2, not -1.
DEF FNround(n)=INT(n+0.5)
DEF FNTruncateToZero(n)=SGNn*INT(ABS(n))
size=len%*INT((top-bottom)/100)
Function returning, or statement altering, the left part of a string.
(1) LEFT$(expression1 [,expression2])
(2) LEFT$(variable [,expression1]) = expression2
expression1 is a string of length between 0 and 255 characters.
expression2, if present, gives the number of characters from the left of the string that are to be returned. If it is omitted, LEN(expression1)-1 is used, i.e. all but the last character of the string is returned. This is useful for stripping off unwanted trailing characters.
Characters from the left of expression1, where the length of the result is the minimum of the length of expression1 and expression2 (or the implied default for expression2).
variable is the name of the string variable to be altered. The characters in the variable are replaced, starting from the lefthand character (position 1), by the string expression2. If the number expression1expression1 is present, this gives the maximum number of characters that will be overwritten in the variable. Otherwise, it is the smaller of LENvariable and LENexpression2: the string's length can never be altered by this statement.
start$ = LEFT$(a$)
left_half$=LEFT$(input$,LEN(input$) DIV 2 )
LEFT$(A$) = "ABCD"
LEFT$(A$,n%) = B$
Function returning the length of a string.
Any string of 0 to 255 characters.
The number of characters in the argument string, from 0 to 255.
Note: The function SUMLEN returns the total length of the elements in a string array.
REPEAT INPUT a$: UNTIL LEN(a$)<=10
IF LEN(in$) > 12 THEN PRINT "Too long"
Statement assigning a value to a variable.
The variable is any addressable object, such as a, a$, a%, !a, a?10, $a, a(1), a() and so on.
expression is any expression of the range and type allowed by the variable: for reals, any numeric; for integers, any integer-range numeric; for strings, any string of length 0 to 255 characters, and for bytes any integer in the range 0 to 255 (though an integer-range number will be treated AND &FF).
If the variable is a whole array, the righthand side obeys the rules described in the Arrays chapter.
Note: The LET keyword is always optional in a variable assignment, and must not be used in the assignment to a pseudo-variable. For example, LET TIME=100 is illegal.
LET starttime=TIME
LET a$=LEFT$(addr$,10)
LET table?i=127*SIN(RAD(i))
LET a() = 1
LET A%() = B%() + C%()
Statement to load a function or procedure library into memory.
expression is a string which should evaluate to a filename that is valid for the filing system in use.
LIBRARY reserves an area in the BASIC heap (where variables are stored) and loads the chosen function and procedure library into this area. It remains there until the heap is cleared. Whilst the library is in memory, the current program can call any of the procedures and functions it contains. See also INSTALL.
LIBRARY "Printout"
A$ = "Library1"
LIBRARY A$
Draw a line between two points.
The (integer) expressions are two pairs of coordinates between which the line is drawn. The line is drawn using the current graphics foreground colour and action, and the graphics cursor position is updated to the second pair of coordinates. It is equivalent to a MOVE followed by a DRAW.
LINE 100,100,600,700
LINE x1,y1,x2,y2
LINE x1,y1,x1+xoffset,y1+yoffset
Statement obtaining a value or values from the input stream.
This has the same syntax as INPUT
If the input variable is a string, all the user's input is read into the variable, including leading and trailing spaces and commas. If the input variable is numeric, only a single value will be selected from the input line.
Note: LINE INPUT is equivalent to INPUT LINE
LINE INPUT "Your message" mess$
Command to list the program.
line-range gives the start and end lines to be listed. Both values are optional and should be separated by a comma. The first value defaults to zero and the last to 65279.
The IF, when present, is followed by a string of characters (not in quotes). Only lines which contain this string are listed.
Note: In the search string following the IF statement, leading spaces are included as part of the string. So the command
LIST IF PRINT
will list
100 PRINT "Single space between line number and statement."
110 PRINT "Several spaces between line number and statement"
but will ignore
120PRINT "No space between line number and statement."
The command
LIST IFPRINT
will find and list all three lines.
The string given after the IF is tokenised before it is checked against the program. Hence, LIST IF PRINT and LIST IF P. both list lines containing the PRINT keyword. However, LIST IF PR does not.
Because the string after IF is tokenised, only one version of the pseudo-variables (each of which has two tokens) can be found. This is the one acting as a function (as in PRINT TIME), rather than the statement version (as in TIME=expression).
LIST | list the whole program |
LIST 1000, | list from line 1000 to the end |
LIST ,50 | list from the start to line 50 |
LIST 10,40 | list from line 10 to 40 inclusive |
LIST IFDEF | list all lines containing a DEF |
LIST ,100 IFfred%= | list all lines up to line 100 containing fred%= |
Command to set the LIST indentation options.
expression should be in the range zero to 31 and is treated as a five-bit number. The meaning of the bits is as follows:
Bit | Meaning |
---|---|
0 | A space is printed after the line number |
1 | Structures are indented |
2 | Lines are split at the : statement delimiter |
3 | The line number is not listed. An error is displayed at line number references |
4 | Keywords are listed in lower case |
LISTO 0 | Default |
LISTO 2 | All loops and conditionals indented by two characters |
LISTO %10011 | Tokens in lower case, structures indented, line numbers followed by a space. |
Command to load a BASIC program at PAGE.
expression is a string which should evaluate to a filename that is valid for the filing system in use.
Note: Any program which is currently in memory is overwritten and lost with all its variables. The static integers (A% - Z% and @%) and INSTALLed libraries are not affected.
LOAD adfs::GDisc.disasm
where GDisc is the name of a floppy disc.
LOAD FNnextFile
Statement to declare a local variable in a procedure or function.
Statement to make current DATA pointer local.
Statement to make the error control status local.
(1) LOCAL [variable] [,variable...]
(2) LOCAL DATA
(3) LOCAL ERROR
variables following the LOCAL may be of any type, such as a, a%, a$, $buffer, a(), and so on. The statement causes the current value of the variables cited to be stored on BASIC's stack, ready for retrieval at the end of the procedure or function. This means the value inside the procedure may be altered without fear of corrupting a variable of the same name outside the procedure. At the end of the procedure, the old value of the variable is restored.
Note: Local numerics are initialised to zero, and local strings are initialised to the null string. Arrays can be declared as being local and then dimensioned using DIM as normal.
LOCAL DATA stores the current data pointer on the stack for the duration of a loop or function/procedure call. This enables a new data pointer to be set up, using RESTORE, and for the original one to be restored with RESTORE DATA. RESTORE DATA is performed automatically on return from a function/ procedure.
LOCAL ERROR remembers the current error handler so a subsequent use of ON ERROR does not overwrite it. This error handler can later be restored using RESTORE ERROR.
Note: LOCAL ERROR can be used anywhere in a program
If LOCAL ERROR is used within a procedure or function it must be the last item to be made local.
Returning from a procedure or function call which contained a LOCAL ERROR automatically restores any stored error status.
See also ON ERROR LOCAL.
LOCAL a$,len%,price
LOCAL a(), B() : DIM a(2), B(4,5)
10 ON ERROR PROCerror
20 res = FNdivide(opp,adj)
30 END
40 DEFFNdivide(x,y)
50 LOCAL ERROR
60 ON ERROR LOCAL PRINT "attempt to divide by zero" :=0
70 =x/y : REM end of function restores previous error status
Pseudo-variable holding the address of BASIC variables.
(2) LOMEM = expression
The address of the start of the BASIC variables.
expression is the address at which BASIC variables start. The expression should be in the range TOP to HIMEM to avoid corruption of the program and/or the generation of No room errors.
Note: LOMEM should not be changed after any assignments in a program. If it is, variables assigned before the change are lost. LOMEM is reset to TOP by CLEAR (and thus by RUN).
If you attempt to set LOMEM to an illegal value, a warning message is given and LOMEM is not altered.
The value of LOMEM for the BASIC VI (64 bit reals) interpreter is 2Kbytes higher than that for the BASIC V (40 bit reals) interpreter.
LOMEM=TOP+&400 : REM reserve 1K above TOP
PRINT LOMEM
Command displaying the first line of all current libraries, all defined variables and all procedures and functions that have been called.
LVAR lists all the values of BASIC variables, sizes of arrays, known procedures and functions. It also lists the first line of all libraries currently loaded. These are displayed in the same order as that in which the libraries are searched when a library procedure or function is called.
Note: In order for LVAR to be useful, you should ensure that the first line of each library includes the full name of the library and the name of a procedure which can be called to provide details of all the routines which the library contains.
Function returning, or statement assigning to a substring of a string.
(1) MID$(expression1,expression2[,expression3])
(2) MID$(variable,expression1[,expression2]) = expression3
expression1 is a string of length 0 to 255 characters.
expression2 is the position within the string of the first character required.
expression3, if present, gives the number of characters in the substring. The default value is 255 (or to the end of the source string).
The substring of the source string, of a length given in the third argument, and starting from the position specified. The result string can never be of greater length than the source string.
variable is the name of the string variable which is to be altered.
expression3 evaluates to a string which provides the characters to replace those in variable.
expression1 is the position within the string of the first character to be replaced.
expression2, if present, gives the maximum number of characters to be replaced. The replacement stops when the end of the string variable is reached, even if there are characters in expression3 which are unused.
PRINT MID$("ABCDEFG",2,3); : REM should print "BCD"
right_half$=MID$(any$,LEN(any$) DIV 2)
MID$(A$,4,4) = B$
MID$(A$,2,5) = MID$(B$,3,6)
Operator giving the integer remainder of its operands, i.e. gives remainder of the division.
Function giving the modulus of its array argument.
The operands are integer-range numerics. The righthand side must not be zero.
Remainder when the lefthand operand is divided by the righthand one using integer division. The sign of the result is the same as the sign of the lefthand operand.
MOD numeric array
The numeric array can be any integer or floating point array.
The square root of the sum of the squares (the modulus) of all the elements of the array.
INPUT i%: i% = i% MOD max_num%
count%=count% MOD max% + 1
PRINT result% MOD 100
DEF FNrms(a())=MODa()/SQRDIM(a(),1)
Statement changing, or function returning, the display mode.
expression should be an integer in the range 0 to 255.
There are 33 different modes, numbered from 0 to 36 (some numbers are excluded). The appendix VDU commands shows you which modes will work on the different types of monitor available.
If expression is greater than 128, the mode used is expression-128. Sufficient memory, however, for two copies of the screen is reserved if the configured screen size allows. This allows you to have one copy on display whilst you are updating the other, which means that smooth animation can be obtained.
Details of all the modes available are given in the appendix VDU commands.
Changing mode also does the following:
An integer giving the current screen mode. If the screen mode was entered using a number greater than or equal to 128 (i.e. a shadow mode), this is not reflected in the value returned by the MODE function. For example, if you typed MODE 129, the MODE function would return 1.
MODE 0 MODE m%+128 PRINT MODE
Statement interrogating and controlling the mouse position and button status.
MOUSE variable1,variable2,variable3 [,variable4]
The first two variables are assigned the x and y positions of the mouse as values in the range -32768 to 32767. The third variable is assigned a value giving the status of the mouse buttons as follows:
Value | Status |
---|---|
0 | No buttons pressed |
1 | Right button only pressed |
2 | Middle button only pressed |
3 | Middle and right buttons pressed |
4 | Left button only pressed |
5 | Left and right buttons pressed |
6 | Left and middle buttons pressed |
7 | All three buttons pressed |
If present, the last variable is assigned the time of a monotonic (always increasing) centi-second timer, which can act as a time-stamp for making sure that button-press events are processed in order, and for detecting double clicks, etc.
MOUSE ON [expression]
MOUSE ON causes the mouse pointer to be displayed. The optional numeric expression is the pointer shape to be used in the range 1 to 4. If it is omitted, 1 is used.
If bit 7 of the pointer shape number is set, i.e. the expression is in the range &81 to &84, then the mouse pointer will be unlinked from the mouse. That is, movements of the physical mouse will not affect the screen pointer. Instead, you can use POINT TO x,y to position the pointer.
MOUSE OFF
MOUSE OFF disables the mouse pointer, removing it from the screen.
MOUSE COLOUR expression, expression, expression, expression
This sets the colour components of the mouse pointer logical colour given in the first expression to the red, green and blue values given in the second, third and fourth expressions. Pointer logical colours are in the range 1 to 3. Colour 0 is always transparent.
MOUSE TO expression,expression
This moves the mouse (and pointer) to the (x,y) position given by the first and second numeric arguments.
MOUSE STEP expression[,expression]
This controls the speed of movement of the mouse pointer compared to the speed of the movement of the actual mouse device. If there is one argument, it is used as a multiplier for both the x and y movements. If there are two, the first is used for x and the second for y. The arguments can be negative to reverse the usual directions.
MOUSE RECTANGLE expr,expr,expr,expr
This sets a bounding rectangle outside which the mouse cannot move. The arguments are the left, bottom, right and top of the rectangle in graphics units. If the mouse pointer is outside the box when this command is given, it will be moved to the nearest point within it.
MOUSE xpos%,ypos%,button% MOUSE ON 2 MOUSE OFF MOUSE COLOUR Col%,red%,green%,blue% MOUSE TO 100,100 MOUSE STEP 3,2 MOUSE RECTANGLE 640,512,1023,1279
Statement to set the position of the graphics cursor.
The expressions are x and y coordinates of the new position for the graphics cursor.
If the keyword BY is omitted, the coordinates are absolute. That is, they give the position of the cursor with respect to the graphics origin. If BY is included, the coordinates are relative. That means they give the new position of the cursor with respect to the current graphics cursor position.
MOVE is equivalent to PLOT 4; MOVE BY is equivalent to PLOT 0.
MOVE 0,0 : REM Goto the origin MOVE BY 4*dx%,4*dy%
Command to remove the current program, and to initialise the computer so that it is ready to receive a new program.
The NEW command does not destroy the program, but merely sets a few internal variables as if there were no program in the memory. The effect of NEW may be undone using the OLD command, providing no program lines have been typed in, or variables created, between the two commands. BASIC does an automatic NEW whenever it is entered.
Part of the FOR TO NEXT structure.
The variables are of any numeric type, and if present should correspond to the variable used to open the loop. See the FOR entry for a description of the mechanism of the FOR NEXT loop.
Note: The variables after the NEXT should always be specified as this enables BASIC to detect improperly nested loops. If the loop variable given after a NEXT does not correspond to the innermost open loop, BASIC closes the inner loops until a matching looping variable is found. In order for the indentation produced by LISTO 2 to be useful, you should only close one loop per NEXT statement.
NEXT a%
NEXT : REM close one loop
NEXT j%,i% : REM close two loops
NEXT ,,, : REM close four loops
Function returning the bitwise NOT of its argument.
An integer-range numeric.
An integer in which all the bits of the argument have been inverted: ones have changed to zeros and zeros have changed to ones. If the argument is a truth value, NOT can be used in a logical statement to invert the condition. In this case, the truth value should only be one of the values -1 (TRUE) and 0 (FALSE).
IF NOT ok THEN PRINT "Error in input"
inv%=NOT mask%
REPEAT UNTIL NOT INKEY(-99)
Part of the CASE OF WHEN OTHERWISE ENDCASE statement.
expression may yield any type of value: integer, floating point, or string.
Note: The OF keyword must be the last item on the line. See the CASE keyword for more details.
CASE n% OF CASE LEFT$(answer$) OF
Command to retrieve a program after NEW has been typed.
The OLD command retrieves a program lost by NEW or Break providing no new program lines have been entered, or variables defined. When you recover the previous program using OLD, you may notice that the first line number has changed. In particular, it is now its old value MOD 256. So if the first line used to be 1000, it will now be 232. You can remedy this slight problem using the RENUMBER command to reduce the value of the line numbers.
Statement defining or cancelling an error handler
(1) ON ERROR [LOCAL] statements
(2) ON ERROR OFF
The ON ERROR statement introduces an error handler. When an error occurs after an ON ERROR has been executed, control passes to the first statement of the ON ERROR line. The program continues from there. Note that all of the error handler code has to be on the ON ERROR line, so complex error handlers should use a procedure, for example:
10 ON ERROR PROCerr_handler
Usually, before the error handler is called, BASIC will forget about all active procedures, functions and loops, in effect reverting to the 'top-level' of the program. However, if the LOCAL keyword is used on the ON ERROR line, then the nesting level current when the ON ERROR is executed will be re-entered when the error occurs. Thus error handlers which are useful within loops and other constructs may be written.
See also LOCAL ERROR on LOCAL and RESTORE ERROR.
ON ERROR OFF cancels any active error handler, so that this default action is used when an error occurs:
100 TRACE OFF
110 IF QUIT THEN
120 ERROR EXT ERR, REPORT$
130 ELSE
140 RESTORE: (HIMEM-4)=@%:@%=8900
150 REPORT:IF ERL PRINT " at line " ERL ELSE PRINT
160 @%=!(HIMEM-4):END
170 ENDIF
An automatic ON ERROR OFF is performed when fatal errors are generated.
ON ERROR IF ERR=17 STOP : REM trap just Escape
ON ERROR LOCAL PRINT"Bad arguments" : ENDPROC
Function opening an existing file for input only.
A string which evaluates to a valid filename.
An integer acting as a channel number for the file. All subsequent operations on file (e.g. BGET#, PTR#, EOF# etc.) use the channel number, sometimes called a handle, as an argument.
OPENIN opens a file for input only. The file must exist prior to the call. If it doesn't, a channel number of 0 is returned. Only read-type operations are allowed on the file. For example, you can get characters from it, but not put them. You can move PTR# freely within the file, but not outside of it. A file may be opened for reading several times. However, you can't OPENIN and OPENOUT (or OPENUP) the same file.
in_file%=OPENIN "Invoices"
data%=OPENIN(":0"+data$)
Function for opening a new file for input and output.
A string which evaluates to a valid filename.
An integer acting as a channel number for the file. All subsequent operations on file (e.g. BGET#, PTR#, EOF# etc.) use the channel number, sometimes called a handle, as an argument.
OPENOUT creates and opens a file for input and output. Read- and write-type operations are allowed on the file. You can both get characters from, and write characters to, the file. You can move PTR# freely within the file, and extend the file by moving PTR# outside of the file (beyond EXT#). You can also shorten the file by assigning to EXT#. Once you OPENOUT a file, it can't be opened again unless it is closed first. Trying to OPENOUT an open file gives an error.
out_file%=OPENOUT "Customers"
data%=OPENOUT(":datadisc."+data$)
Function for opening an existing file for input and output (update).
A string which evaluates to a valid filename.
An integer acting as a channel number for the file. All subsequent operations on file (e.g. BGET#, PTR#, EOF# etc.) use the channel number, sometimes called a handle, as an argument.
OPENUP opens a file, which must exist already, for input and output. Read- and write-type operations are allowed on the file. You can both get characters from, and write characters to, the file. You can move PTR# freely within the file, and extend the file by moving PTR# outside of the file (beyond EXT#). You can also shorten the file by assigning to EXT#. Once you OPENUP a file, it can't be opened again unless it is closed first. Similarly, trying to OPENUP an open file gives an error.
random_file%=OPENUP("records")
Operator giving the bitwise OR of its operands.
relationals can be any integer-range numerics.
An integer obtained by ORing together the corresponding bits in the operands. The operands may be interpreted as bit-patterns, in which case a bit in the result is set to one if either or both of the corresponding bits in the operands are one. Alternatively, they may be interpreted as logical values, in which case the result is TRUE if either or both of the operands are TRUE.
PRINT a% OR &AA55
IF a<1 OR a>10 THEN PRINT "Bad range"
Statement to move the graphics origin.
The expressions are integer numerics in the range -32768 to +32767. They are the absolute coordinates of the new graphics origin: the position of the point (0,0). These coordinates are always given with respect to the bottom left corner of the screen.
The graphics origin is used by all commands which plot graphics, such as MOVE, LINE, PLOT, CIRCLE, and so on, and also by VDU 24 which sets a graphics viewport.
ORIGIN 640,512 : REM Set origin to the centre of screen
Statement to pass a string to the operating system.
expression should be a string of between 0 and 255 characters. It is passed to the operating system OS_CLI routine to be executed.
Note: The difference between passing a string to the operating system via a * command and via OSCLI is that the former makes no attempt to process the text following it, whereas the latter evaluates the text as a BASIC string expression. Thus you can say:
OSCLI "LOAD file "+STR$~buffer%
but not (usefully)
*"LOAD file "+STR$~buffer%
Many extensions to BBC BASIC on previous machines (e.g. the Master 128) used 'internal' BASIC routines called from OSCLI commands. BBC BASIC provides extra information when using * or OSCLI to allow such software to be ported onto this computer. (Note that this does not happen for SYS "OS_CLI","fred").
Information is passed in registers R0 to R5, because the high user-mode registers are not conveniently readable from other modes. Before using the information passed in these registers, the routine should transfer them to the correct registers, as documented in the section on CALL. It should also ensure it is executing in user mode before calling any BASIC routines.
R0 | contains CLI string pointer |
R1 | contains &BA51Cxxx |
R2 | ARGP |
R3 | LINE |
R4 | current string pointer |
R5 | environment information pointer (as CALL) |
The value in R1 should be inspected by any routine in order to validate that the call is, indeed, from BASIC (it is also a good idea to check R2 to R5 for valid addresses); the value is also at address [R5,#-4]. The current BASIC interpreter provides &BA51C005, the next &BA51C006 and so on.
The value in LINE should not be relied on, except that it is sufficient for BASIC to produce the correct line number in case of an error. When BASIC is eventually returned to at the end of the SWI OS_CLI call, its (user-mode) registers must not have been altered.
OSCLI "CAT"
OSCLI "LOAD "+file$+" "+STR$buff%:REM get file in buffer
See CASE
Note: The OTHERWISE statement is executed only when the previous WHEN statements have failed to match the value of the CASE expression. OTHERWISE matches any values. If it is present, all statements following it will be executed until the matching ENDCASE is encountered.
OTHERWISE PRINT "Bad input"
OTHERWISE PROCdraw(x,y) : PROCwait
Pseudo-variable holding the address of the program.
An address which is an unsigned number. PAGE is the location at which the current BASIC program starts.
expression is an integer in the range &8F00 to HIMEM, where &8F00 is the current limit of BASIC's own workspace (this could change in later versions of BASIC). PAGE should be on a word boundary. By changing PAGE, you can have several BASIC programs residing in the machine at once.
Note: If you attempt to set PAGE to an invalid address, a warning message is given and PAGE is not altered.
PAGE = HIMEM - &4000
Statement performing an operating system PLOT function.
expression1 is the plot number in the range from 0 to 255. For example, 85 is the plot number for an absolute triangle plot in the foreground colour.
The second and third expressions are the x and y coordinates respectively, in the range -32768 to +32767.
See Appendix F: Plot codes for a full list of PLOT codes.
PLOT 85,100,100 : REM Draw a triangle
PLOT 69,x,y : REM Plot a single point
Statement to plot a single point or move the on-screen pointer.
(1) POINT [BY] expression,expression
(2) POINT TO expression,expression
The expressions are integers giving the coordinates at which the point will be plotted. The point is plotted using the current graphics foreground colour and action, and the graphics cursor is updated to these coordinates.
If the keyword BY is omitted, the coordinates are absolute. That is, they give the position of the point with respect to the graphics origin. If BY is included, the coordinates are relative. That means they give the position of the point with respect to the current graphics cursor position.
The expressions are integers giving the coordinates at which the on-screen pointer will be placed if it is not linked to the mouse position. If the pointer is linked to the mouse this command is ignored. See MOUSE for more details about unlinking the pointer from the mouse.
POINT 320,600
POINT X%+4, Y%+4
POINT BY 100,0
POINT TO 640,512
Finds the logical colour of a graphics pixel.
The expressions are the coordinates of the pixel whose colour is required.
This is an integer in the range -1 to n, where n is one less than the number of logical colours in the current mode. For example, n is 15 in a 16-colour mode. If the point specified lies outside the current graphics viewport, -1 is returned. Otherwise, it is the logical colour of the point.
Note that the value returned is in the range 0 to 63 for the 256-colour modes. The function TINT(x,y) will read the tint of the given coordinate, returning a value in the range 0 to 255.
REPEAT Y%+=4:UNTIL POINT(640,Y%)<>0
Function returning the x-coordinate of the text cursor.
An integer between 0 and n, where n is the width of the current text viewport minus one. This is the position of the text cursor which is normally given relative to the lefthand edge of the text viewport. If the cursor direction has been altered using VDU 23,16, then it is given relative to the negative x edge of the screen which may be top, bottom, left or right.
Note: Even in VDU 5 mode, POS returns the position of the text cursor. You should therefore keep track of the horizontal position explicitly in programs which must operate in VDU 5 mode (e.g. WIMP-based programs). COUNT still works as expected in VDU 5 mode.
old_x%=POS
IF POS<>0 THEN PRINT
Print information on the output stream(s) (e.g. screen, printer, etc).
The items following PRINT may be string expressions, numeric expressions, and print formatters. By default, numerics are printed in decimal, right justified in the print field given by @% (see below). Strings are printed left justified in the print field. The print formatters have the following effects when printing numbers:
; | Do not right justify (print leading spaces before) numbers in the print field. Set numeric printing to decimal. Semi-colon stays in effect until a comma is encountered. Do not print a new line at the end if this is the last character of the PRINT statement. |
, (comma) | Right justify numbers in the print field. Set numeric printing to decimal. This is the default print mode. Comma stays in effect until a semi-colon is encountered. If the cursor is not at the start of the print field, print spaces to reach the next one. |
~ (tilde) | Print numbers as hexadecimal integers, using the current left/right-justify mode. Tilde stays in effect until a comma or semi-colon is encountered. |
' (single quote) | Print a new line. Retain current left/right-justify and hexadecimal/decimal modes. |
TAB( | If there is one argument, for example, TAB(n), print (n_COUNT) spaces. If the cursor is initially past position n (i.e. COUNT>n), print a new line first. If there are two arguments, for example, TAB(10,20), move directly to that tab position. Left/right-justify and hexadecimal/decimal modes are retained. |
SPCfactor | Print the given number of spaces. For example SPC5 outputs five spaces. Right-justify and hexadecimal/decimal modes are retained. |
space | Print the next item, retaining left/right-justify and hexadecimal/decimal modes. |
When strings are printed the descriptions above apply, except that hexadecimal mode does not affect the string. Also no trailing spaces are printed after a string unless it is followed by a comma. This prints enough spaces to move to the start of the next print field.
The print formatters TAB, SPC and ' may also be used in INPUT statements.
The format in which numbers are printed, and the width of print fields are determined by the value of the special system integer variable, @%. The way in which you specify @% depends whether you are using the 1.05 BASIC interpreter or the 1.04 BASIC interpreter, as follows:
The value of @% is specified in ANSI printf format, as follows:
@%="expression"
where expression takes the form [+]Ax.y, and must be in quotes.
A defines the format, and can take the following values:
The optional + sign is a switch affecting the STR$ function. If supplied, it forces STR$ to use the format determined by @%. If it is not supplied, STR$ uses a default format equivalent to @%="+G0.10". Note that there must not be any spaces in the definition of @%.
The BASIC 1.05 interpreter supports partial setting of @%, which means you do not have to supply all the arguments. See the examples of @% below.
@%="G10.9" is the default setting. It is a General format, with a field width of 10 and a precision of 9 digits; for example 12.3456789. STR$ uses its default.
@%="+E10.3" is an Exponent format, with a field width of 10, and 3 digits after the decimal point; for example 1.24E1. STR$ uses this format instead of its default.
@%="F7.4" is a Fixed format, with a field width of 7, and 4 digits after the decimal point; for example 12.3457. STR$ uses its default.
@%="+" forces STR$ to use the current format.
@%="G" changes to G format. STR$ uses its default.
@%="10" sets the field width for the current format to 10, and forces STR$ to use its default.
@%=".5" just sets the precision for the current format to 5 digits, and forces STR$ to use its default.
You can set the variable @% to produce the same results as the BASIC 1.05 interpreter. The value of @% is specified using a hexadecimal word four bytes long, as follows:
@%=&wwxxyyzz
@%=&0000090A uses General format with up to nine significant digits in a field width of ten characters. Note that General format reverts to Exponent format when the number is less than 0.1. This is the default setting of @%.
@%=&0101030A uses Exponent format. Three significant digits are printed, in a field of ten characters. These numbers look like 1.23E0, 1.10E-3, etc. In addition, STR$ uses this format instead of its default (which is &00000A00).
@%=&00020407 uses Fixed format with four decimal places in a tab field width of seven. Numbers are printed out in the form 1.23, 923.10, etc.
Note: Setting byte two to 10, e.g. &0A0A, shows the inaccuracies which arise when trying to store certain numbers in binary. For example:
PRINT 7.7
prints 7.699999999 when @%=&0A0A.
PRINT "Hello there";
PRINT a,SIN(RAD(a)),x,y''p,q;
PRINT TAB(10,3)"Profits"SPC(10);profits;
Print information to an open file.
factor is the channel number of a file opened for output or update. The expressions, if present, are any BASIC integer, real or string expressions. They are evaluated and sent to the file specified with the corresponding type information.
Integers are written as &40 followed by the two's complement representation of the integer in four bytes, most significant byte first.
5-byte real variables are written as &80 followed by five bytes. The first four bytes are the mantissa and the fifth is the exponent. The mantissa is written least significant byte (LSB) first. 31 bits represent the magnitude of the mantissa and one bit (bit 7 of the fourth byte) the sign. The exponent byte is in excess-128 form. BASIC V only prints real numbers in 5-byte real format.
8-byte real variables are written as &88 followed by two 4-byte words, in IEEE Double Precision (D) format. The exponent is represented by bits 20 to 30 in the first word. The sign bit is bit 31 in the first word. The mantissa is represented by bits 0 to 19 in the first word and bits 0 to 31 in the second word. BASIC VI only prints real numbers in 8-byte real format. You need 1.05 series (rather than 1.04) to read this information back.
Strings are written as &00 followed by a one byte count of the length of the string, followed by the characters in the string in reverse order.
PRINT#file,name$+":",INT(100*price+.5),qnty%
(1) DEF PROCproc-part
(2) PROCproc-part
(3) ON expression PROCproc1 [,PROCproc2...] [ELSE statement]
proc-part has the form identifier[(parameter-list)]. It gives the name of the procedure (the identifier) and the names and types of the optional parameters, which must be enclosed in brackets and separated by commas.
The second form is used when the procedure is actually invoked, and this time the parameter list comprises expressions of types corresponding to the parameters declared in the DEF PROC statement. The expressions are evaluated and assigned (locally) to the parameter variables. Control returns to the calling program when an ENDPROC is executed.
expression should evaluate to an integer. If this integer is n then the nth procedure listed is called. If the integer is less than 1 or greater than the number of line numbers given, the statement following the ELSE, if it is present, is executed.
DEF PROCdelay(n)
TIME=0:REPEAT UNTIL TIME=n*100:ENDPROC
IF ?flag=0 THEN REPEAT PROCdelay(0.1): UNTIL ?flag
Pseudo-variable accessing the pointer of a file.
(2) PTR#factor = expression
factor is a channel number, as returned from an OPENxx function.
An integer giving the position of the next byte to be read or written relative to the start of the file. The minimum value is 0 and the maximum value depends on the filing system in use.
factor is as (1). The expression is an integer giving the desired position of the sequential pointer in the file. Files opened for input may only have their PTR# value set to between 0 and the EXT# of the file.
PRINT PTR#file;"bytes processed"
PTR#chan%=rec_len%
Statement to leave BASIC.
Function returning -quit status.
QUIT as a statement leaves the BASIC interpreter.
QUIT as a function returns TRUE or FALSE. If the interpreter was invoked using the -quit flag, then it will return TRUE. If -quit was not specified on the command line, then the function returns FALSE.
Statement reading information from a DATA statement.
Any variables should correspond in type to the items in the DATA statement being read. In fact, a string READ item is able to read any type of DATA and interpret it as a string constant after stripping leading spaces. A numeric READ item tries to evaluate its DATA; so in the latter case, the DATA expression should yield a suitable number.
READ n%
READ a$, fred%, float
Statement to draw a rectangle or copy/move a rectangular area of the screen or set the mouse bounding box.
(1) RECTANGLE [FILL] exp1,exp2,exp3[,exp4] (2) RECTANGLE [FILL] exp1,exp2,exp3[,exp4] TO exp5,exp6 (3) MOUSE RECTANGLE exp1,exp2,exp3,exp4
exp1 and exp2 are integer expressions in the range -32768 to +32767. They are the coordinates of one of the corners of the rectangle.
exp3 is the width of the rectangle. It is also the height (giving a square) unless exp4 is given, in which case this is the height.
RECTANGLE draws the outline of a rectangle which is aligned with the x and y axes. RECTANGLE FILL plots a solid axes-aligned rectangle. The rectangles are drawn using the current graphics foreground colour and action.
RECTANGLE leaves the graphics cursor at the starting position. However, with RECTANGLE FILL, the graphics cursor is updated to the position of the opposite corner to the one specified.
The first four arguments define a rectangular area of the screen, as for the first usage described above.
exp5 and exp6 give the position to which the lower left corner of the source rectangle is copied or moved.
RECTANGLE TO copies the original rectangular area defined to the new position, hence making a second copy of a rectangular screen area. Pixels in the source that are outside of the current graphics viewport are drawn in the current graphics background colour.
RECTANGLE FILL TO moves the original rectangular area defined to the new position, replacing the old area with the current graphics background colour. In both cases the new position is allowed to overlap with the rectangular area.
To set a bounding box for the mouse pointer. See MOUSE for details.
RECTANGLE 500,500,-200,-100
RECTANGLE FILL bl%(1),bl%(2),width%,height%
RECTANGLE 400,400,60,60 TO 460,400
RECTANGLE FILL x,y,size,size TO xnew,ynew
Command to renumber the program lines.
See AUTO for a description.
RENUMBER resequences the lines in the program so that the first line is start and the line numbers increase in steps of step. It also changes line numbers within the program, such as after RESTOREs, so that they match the new line numbers. If the line used in a RESTORE cannot be found, the message
Failed with nnnn on line llll
is given, where nnnn is the line number which was referenced but which does not appear in the program, and llll is the line on which the reference was made.
RENUMBER needs some workspace, and if there is not enough room to change the line numbers successfully, a RENUMBER space error is generated.
RENUMBER
RENUMBER 1000,20
Statement marking start of a REPEAT UNTIL loop.
The statements following REPEAT are repeatedly executed until the condition following the matching UNTIL evaluates to FALSE. The statements may occur over several program lines, or may all be on the same line separated by colons. The second approach is useful in immediate statements. The statements are executed at least once.
REPEAT UNTIL INKEY-99 : REM wait for SPACE
REPEAT a%+=1:c%=c% >> 1 UNTIL c%=0
Statement setting the DATA pointer.
Statement restoring DATA pointer from the stack.
expression is a line number. If it is absent, the DATA pointer is reset to the first DATA statement in the program, and the next item READ comes from there. If the line number is present, the DATA pointer is set to the first item of data on or after the line specified, so that subsequent READs access that particular data item (and those which follow).
If the expression is preceded by a + sign, then it is interpreted as an offset from the line containing the RESTORE statement. +0 means the line after the one containing the RESTORE, +1 means the line after that, and so on. The main use of this is in libraries, where references to actual line numbers are not allowed (and RESTORE on its own restores to the start of the main program, not the library).
The second form of RESTORE loads a DATA pointer from the stack that was previously saved using LOCAL DATA. By using these two statements as a pair, you can prevent any RESTOREs in a procedure or function from changing the DATA pointer used by the main program.
RESTORE
RESTORE 1000
RESTORE +10
Statement to restore saved error status.
Note: RESTORE ERROR restores the error status previously saved using LOCAL ERROR. If an error status has not been saved then a fatal error arises.
The error status is restored automatically on return from a procedure or function, and when one of the loop-terminating constructs is encountered (UNTIL, ENDWHILE and NEXT).
10 LOCAL ERROR
20 REPEAT
30 ON ERROR LOCAL PRINT"Negative value"
40 INPUT x
50 PRINT "Square root of x = ";SQR(x)
60 UNTIL x=0
70 RESTORE ERROR
Statement returning control from a subroutine.
Modifier in formal parameter list.
RETURN returns control to the statement following the most recent GOSUB. If there are no GOSUBs currently active, a Not in a subroutine error occurs.
RETURN indicates value-and-result parameter passing (as distinct from value passing, the default) when applied to a parameter in the definition.
DEF PROCSwapIfDisordered(RETURN A, RETURN B) IF A>B SWAP A,B ENDPROC
Function returning or statement altering the right-most character(s) of a string.
(1) RIGHT$(expression1 [,expression2])
(2) RIGHT$(variable [,expression1]) = expression2
expression1 should be a string of length 0 to 255 characters.
If expression2 is present, it should be a numeric giving the number of characters from the right of the string to be returned, also in the range 0 to 255. If it is omitted, a default of 1 is used.
A string consisting of the n right-most character(s) from the source string, where n is expression2 or 1. If n is greater than the length of the source string, the whole source string is returned.
variable is the name of the string variable to be altered. The righthand characters in variable are replaced by the string expression2.
If present, expression1 gives the maximum number of characters which will be replaced: the number of characters altered is the lesser of expression1 and LENexpression2. expression1 defaults to 255.
PRINT RIGHT$(any$,4)
year$=RIGHT$(date$,2)
RIGHT$(birthday$) = "May"
RIGHT$(name$,4) = "Mary"
Function returning a random number.
A four-byte signed random integer between -2147483648 and +2147483647
RND(expression)
expression < 0
expression should be an integer. This reseeds the random number generator, and the function returns its (truncated) argument as a result. Reseeding the generator with a given seed value always produces the same sequence of random numbers.
expression = 0
This uses the same seed as the last RND(1) call and returns the same random number rounded between 0 and 1.
expression = 1
This returns a random real number between 0 and 1.
expression > 1
The expression, n, should be an integer. The result is an integer between 1 and n inclusive.
Note that there should be no space before the opening bracket.
dummy=RND(-TIME) : REM reseed the generator 'randomly'
x%=RND(1280) : y%=RND AND &3ff
prob=RND(1)
lastProb=RND(0)
r%=RND
Command to save a program as a file.
If present, expression should evaluate to a string which is a valid filename under the filing system in use. The current BASIC program is stored (without variables, etc) on the medium under this name.
SAVE can be used without an expression, in which case the name is taken from the first line of the program which should have the format:
10 REM > filename
For example:
10 REM > Game1
SAVE "Version1"
SAVE FNprogName
SAVE
Function returning the sine of its argument.
A numeric representing an angle in radians.
A real in the range -1 to 1, being the sine of the argument.
Note: If the argument is outside the range -8388608 to 8388608 radians, it is impossible to determine how many s to subtract. The error Accuracy lost in sine/cosine/tangent is generated.
PRINT SIN(RAD(135))
opp=hyp*SIN(theta)
Statement generating a sound or suppressing/allowing subsequent sound generation.
(1) SOUND ON
(2) SOUND OFF
(3) SOUND expr1,expr2,expr3,expr4[,expr5]
SOUND ON is the default setting. It allows sounds to be produced by subsequent use of the SOUND (3) statements. SOUND OFF suppresses sounds and means that subsequent SOUND (3) statements have no effect.
expr1 is the channel number
expr2 is the amplitude
expr3 is the pitch
expr4 is the duration
expr5, if present, is the delay.
A two-byte integer giving the channel number to be used. It has the range 1 to 8.
This is an integer in one of two different ranges. The range -15 to 0 is a simple volume (amplitude), -15 being the loudest and zero being the quietest (no sound). The range 256 (&100) to 511 (&1FF) is a logarithmic volume range, a difference of 16 providing a doubling or halving of the volume.
This is treated as an integer. In the range 0 to 255, the note middle C has a pitch value of 53; a difference in the parameter of 48 corresponds to a difference in pitch of one octave. In other words, there are four pitch values per semi-tone. In the range 256 (&100) to 32767 (&7FFF), the note middle C has a pitch value of &4000, and a difference in the value of &1000 corresponds to a difference in pitch of one octave.
The last compulsory SOUND parameter is also treated as a two-byte integer. It gives the duration of the note in twentieths of a second. A value of 255 gives a note with an infinite duration: one that does not stop unless the sound queue is flushed in some way. A value greater than 255 is treated as a duration in 20ths of a second.
This is the number of beat counts from the last beat counter reset before the sound is produced. See BEATS and TEMPO for more details. If this parameter is omitted, the sound is produced immediately. A value of -1 synchronises the new note with the last scheduled sound.
SOUND OFF SOUND 1,-15,255,10 SOUND &102,&140,&2400,200 SOUND 3,300,300,100,200
Function returning the square-root of its argument.
SQR factor
Any non-negative numeric.
A real which is the argument's square-root.
DEF FNlen(x1,y1,x2,y2)=SQR((x2-x1)^2+(y2-y1)^2)
disc=SQR(b*b-4*a*c)
Statement setting the stereo position of a sound channel.
expression1 is the channel number which should be between 1 and the number of active channels (the maximum being 8).
expression2 is a value giving the stereo position. It can take any value between -127 (meaning that the sound is fully to the left) and +127 (meaning that the sound is fully to the right). The default value of each channel is 0, giving central (mono) production.
If the number of physical channels is eight, only the channel specified is programmed. Otherwise, the following occurs, where chan is expression1:
No of channels | Channels programmed |
---|---|
1 | chan to eight |
2 | chan and every alternate channel up to eight |
4 | chan and chan+4 if chan+4 is less than or equal to eight |
STEREO 4,-60
STEREO n%, stereo%
Statement producing the fatal error Stopped to terminate the program.
The STOP statement gives the fatal (untrappable) error message Stopped. It differs from END, as the latter produces no message. It may be used as a debugging aid to halt the program at a given point so that the current values of the program's variables can be determined.
IF NOT ok THEN PRINT"Bad data":STOP
Function producing the string representation of its argument.
Any numeric for decimal conversion, any integer for hexadecimal conversion. Decimal conversion is used when the tilde (~) is absent, hex conversion when it is present.
Decimal or hex string representation of the argument, depending upon the absence or presence of the tilde.
Note: The string returned by STR$ is usually formatted in the same way as the argument would be printed with @% set to &A00. However, if the most significant byte of @% is non-zero, STR$ returns the result in exactly the same format as it would be printed, taking the current value of @% into account. See also PRINT.
DEF FNhex4(a%)=RIGHT$("000"+STR$~(a%),4)
DEF FNdigits(a)=LEN(STR$(a))
dp=INSTR(STR$(any_val),".")
Function returning multiple copies of a string.
expression1 is an integer, n, in the range 0 to 255.
expression2 should be a string of length 0 to (255 DIV n) characters.
A string comprising n concatenated copies of the source string, of a length n*LEN(expression2).
MODE
PRINT STRING$(40,"_"); :REM underline across the screen
pattern$=STRING$(20,"<-->")
Function returning the arithmetic sum or string concatenation of an array.
array is the name of an array.
If the argument is an integer or floating point array, it is an integer or floating point value of the sum of all the elements in the array.
If the argument is a string array, it is the string which contains each of the elements of the array concatenated. This must be less than 256 characters in all.
A() = 1 : PRINT "There are ";SUM(A())" elements."
DEF FNmean(a())=SUMa()/DIM(a(),1)
Function returning the length of the string concatenation of an array.
string-array is the name of a string array.
The sum of the lengths of all the elements in the array. Thus
SUMLENa$()=LENSUMa$()
except that the former is not limited to a maximum of 255 characters.
DEF FNmeanlen(a$())=SUMLENa$()/DIM(a(),1)
Statement exchanging the value of two variables or arrays.
The arguments are variables or array names. Simple variables must be of assignment-compatible types, i.e. both string or numeric. Arrays must be of identical type elements (both integer, floating point or string), but can be of differing sizes.
The SWAP statement exchanges the contents of the two variables or arrays. In the case where arrays are swapped, the number of subscripts and their upper limits are also swapped. For example, if you have
DIM A(10),B(20,20)
SWAP A(),B()
then after the SWAP, it would be as if the arrays had been DIMed:
DIM A(20,20),B(10)
All of the elements of the arrays are also swapped, though no actual movement of data is involved so this is a very quick operation.
SWAP A%, B%
SWAP forename$, surname$
SWAP arr(i%), arr(i%+gap%)
SWAP array1$(), array2$()
SWAP a, B%
SWAP A$, $A%
SWAP matrix(), vector()
A statement for calling operating system routines.
expr1 defines which operating system routine is to be called. It may evaluate to a number giving the routine's SWI number, or to a string which is the name of a routine. BASIC uses the SWI OS_SWINumberFromString to convert from a string to number, so the case of the letters in the string must match exactly that of the SWI name.
The optional list of expressions following this, up to a maximum of eight, is passed to the routine via registers R0 to R7. If the expression evaluates to a numeric, it is converted to an integer and placed directly in a register. If the expression evaluates to a string, the string is placed on BASIC's stack, beginning at a word boundary and terminated with a null character. A pointer to it is put in the register. Any expressions not given (indicated by adjacent commas ,,) default to zero.
The optional TO is followed by a variable list. Each variable is assigned any value returned by the routine in the registers R0 to R7 respectively. If the variable to assign to is numeric, the integer in the register is converted to an appropriate format and stored in it. If the variable to assign to is a string, the register is treated as a pointer to a string terminated by ASCII 0, 10 or 13 and this string is assigned to the variable. The strings given on input can be overwritten, but should not be extended. As with the input expressions, output variables may be omitted using adjacent commas in the list.
flags is an optional variable, to which the processor flag bits are returned. The value stored in the flags value is a binary number of the form %NZCV, where the letters stand for the result flags of the ARM status register.
SYS provides access to the routines supplied by the operating system for entering and outputting characters, error handling, sprite manipulation, and so on. Details of these operating system routines is beyond the scope of this book, but can be found in the Programmer's Reference Manual.
SYS "OS_ReadMonotonicTime" TO time
SYS "OS_SpriteOp",28,,"MYSPRITE",,3
SYS "Font_FindFont",,"Homerton.Medium",12*16,12*16 TO f%
10 SYS 0,0,42 : REM output a *
20 OS_Write% = 0
30 SYS OS_Write%, 42
40 END
Print modifier to position text cursor in PRINT and INPUT statements.
A numeric in the range 0 to 255. It expresses the desired x-coordinate of the cursor. This position is obtained by printing spaces. A new line is generated first if the current position is at or to the right of the required one. COUNT is updated appropriately. This form is useful for tabulating on both the screen (even in VDU 5 mode) or printed output.
expression1 is the desired x coordinate;
expression2 is the desired y coordinate.
The position is reached using the VDU 31 command. Both coordinates must lie within the current text viewport, otherwise, no cursor movement will take place. COUNT is no longer correct. This form is only useful when positioning the cursor on the screen as it uses control codes which will not be sent to a printer.
PRINT TAB(10) "Product";TAB(20) "Price"
INPUT TAB(0,10)"How many eggs",eggs%
Function giving the tangent of its argument.
A real number interpreted as an angle in radians.
A real giving the tangent of the angle, in the range -1E38 to +1E38.
Note: If the argument is outside the range -8388608 to 8388608 radians, it is impossible to determine how many s to subtract. The error Accuracy lost in sine/cosine/tangent is generated.
opp=adj*TAN(RAD(theta))
Function returning or statement altering the beat counter rate.
expression is a scaled fractional number, in which the 12 least-significant bits are the fractional part. Thus a value of &1000 corresponds to a tempo of one tempo beat per centi-second; doubling the value (&2000) causes the tempo to double (two tempo beats per centi-second), halving the value (&800) halves the tempo (one beat every two centi-seconds).
The tempo determines the rate at which the beat counter increases.
A number giving the current tempo.
TEMPO &2000
PRINT TEMPO
DEF FNtempo=TEMPO/&1000
DEF PROCtempo(t) TEMPO t*&1000:ENDPROC
Command to load a BASIC file at PAGE.
TEXTLOAD string expression
string expression is a string which should evaluate to a filename that is valid for the filing system in use. The file can be a BASIC program, or a BASIC program that was saved as a text file (see TEXTSAVE). If a text file is loaded which has lines without line numbers, TEXTLOAD automatically renumbers it.
Note 1: Any program which is currently in memory is overwritten and lost with all its variables. The static integers (A% - Z% and @%) and INSTALLed libraries are not affected.
Note 2: Files loaded with this command must end in a linefeed, or the computer will hang.
TEXTLOAD adfs::GDisc.disasm
where GDisc is the name of a floppy disc.
TEXTLOAD FNnextFile
Command to save a BASIC program to a text file.
(1) TEXTSAVE string expression
(2) TEXTSAVEO expression, string expression
string expression should evaluate to a string which is a valid filename under the filing system in use. The current BASIC program is stored as a text file on the medium under this name.
expression should be in the range zero to 31, and is treated as a 5-bit binary number. TEXTSAVEO is similar to TEXTSAVE, but when it converts the program to text, it uses the LISTO-type option specified by expression to format the output to the file given by string expression.
TEXTSAVE "Version1"
TEXTSAVEO 8, "Version2" : REM strips out line numbers
Optional part of a single line IF THEN ELSE STATEMENT AND COMPULSORY PART OF MULTI-LINE IF THEN ELSE ENDIF statement.
See IF
IF a>3 THEN PRINT "Too large" : REM THEN optional
IF mem THEN HIMEM = HIMEM - &2000
IF A$="Y" THEN 1200 ELSE GOTO 1400
MODE 1 IF colour$ = "red" THEN COLOUR 1 CLS ELSE COLOUR 0 : CLS ENDIF
Pseudo-variable reading or altering the value of the centi-second clock.
An integer giving the number of centi-seconds that have elapsed since the last time the clock was set to zero.
expression is an integer value used to set the clock. TIME is initially set to the lowest four bytes of the five-byte clock value maintained by the operating system. Assigning to the TIME pseudo-variable alters the system centi-second timer (the one which is read and written by OS_Words1 and 2 respectively). There is, however, an additional system clock which is monotonic: it always increases in value with time, and cannot be reset by software. TIME does not affect this timer.
DEF PROCdelay(n) T%=TIME+n*100:REPEAT UNTIL TIME>T%
Pseudo-variable accessing the real-time clock.
TIME$ returns a 24-character string of the format:
Fri,24 May 1984.17:40:59
The date and time part are separated by a full stop '.'.
The expression should be a string specifying the date, the time, or both. Punctuation and spacing are crucial and should be as shown in the examples below.
PRINT TIME$
TIME$="Tue,01 Jan 1972"
TIME$="21:12:06"
TIME$="Tue,01 Jan 1972.21:12:06"
Note that the day of the week is automatically calculated from the date, so that any three characters may be entered at the start of the date, for example
TIME$="xxx,19 Aug 1987"
Part of the COLOUR or GCOL statements for use in 256-colour modes, or a statement on its own, or a function.
(1) COLOUR expr [TINT expression]
(2) GCOL [expr,] expr [TINT expression]
(3) TINT expression, expression
(4) TINT(expression,expression)
For usages (1) and (2), see COLOUR (COLOR) and GCOL respectively.
The TINT statement takes two expressions. The first is a number in the range 0 to 3 which indicates which type of colour's tint value is being set:
Number | Colour affected |
---|---|
0 | Text foreground |
1 | Text background |
2 | Graphics foreground |
3 | Graphics background |
The second expression is a number in the range 0 to 255. This gives the amount of white to add to the basic colour. Currently, only the top two bits of this number are significant, so 0, 64, 128 and 192 give distinct tint values.
The two lines below are equivalent:
GCOL 34 TINT 128
GCOL 34 : TINT 2,128
The two expressions within the brackets give the coordinates of the point whose tint is required. The result is the tint for that pixel, currently one of the values 0, 64, 128 or 192. If the pixel is outside the graphics window, 0 is returned, so POINT() should be used to check that the point is valid first.
COLOUR 1+J% TINT N%
GCOL 128+63 TINT 255 : REM solid white
GCOL 3 TINT TINT(x,y) : REM NB two uses at once!
t=TINT(0,0)
Function returning the address of the end of the program.
TOP gives the address of the first byte after the BASIC program. The length of the program is equal to TOP-PAGE. LOMEM is usually set to TOP (or the first word above if TOP isn't on a word boundary), so this is where the variables start.
PRINT TOP
Statement to initiate or terminate line/procedure tracing.
Function enabling text to be sent to a trace file.
as a statement:
(1) TRACE [STEP] expression
(2) TRACE [STEP] ON
(3) TRACE [STEP] PROC
(4) TRACE OFF
(5) TRACE TO filename
(6) TRACE CLOSE
as a function:
(7) TRACE
expression is a line number. All line numbers below this line number are printed out when they are encountered during the execution of the program.
filename is the name of the file to which TRACE output is directed.
TRACE causes line numbers or procedure and function names to be printed as they are encountered. In cases (1), (2) and (3), if STEP is present, BASIC will wait for a key to be pressed before continuing after each traced item.
(1) TRACE expression traces only those lines with a line number below the value of expression.
(2) TRACE ON is the same as TRACE 65279, i.e. all line numbers are printed as they are met.
(3) TRACE PROC traces procedures and functions only.
(4) TRACE OFF disables tracing, as does the default error handler.
(5) TRACE TO sends the output from TRACE to a specified file (not available on 1.04 interpreter).
(6) TRACE CLOSE stops output to a named file (the interpreter closes the file before exit). Note that errors found when writing to this file will cause it to be closed.
(7) The function TRACE is either zero, or a file handle. It allows output other than line numbers to be sent to the trace file, as in the last example below.
IF debug THEN TRACE 9000 TRACE STEP PROC IF debug THEN TRACE OFF IF TRACE THEN BPUT#TRACE,"X is "+STR$X
Command to enter the Twin text editor.
TWIN converts the program to text, then calls the Twin editor (which should be on a convenient disc known to the system). You can edit the program as required, then return to BASIC using one of Twin's commands. See the Twin User Guide for details.
TWINO is similar, except that when it converts the program to text, it uses the LISTO-type option that follows the command. Most useful is 8, which strips line numbers from the start of the program.
Statement to terminate a REPEAT loop.
expression can be any numeric expression which can be evaluated to give a truth value. If it is zero (FALSE), control passes back to the statement immediately after the corresponding REPEAT. If the expression is non-zero (TRUE), control continues to the statement after the UNTIL.
DEF PROCirritate REPEAT VDU 7:UNTIL FALSE ENDPROC REPEAT PROCmove:UNTIL gameOver
Function returning the value of R0 after executing a machine code routine.
The address of the machine code to be called. Calls to the 6502-based BBC Microcomputer operating systems are handled by USR for compatibility.
USR is similar to CALL except that it returns a result and cannot be passed any parameters. On entry to the routine, R0..R14 are as for CALL.
An integer, being the contents of R0 on return to BASIC.
DEF FNmachinecode =USR(start_of_code)
Function returning the numeric value of a decimal string.
A string of length zero to 255 characters.
The number that would have been read if the string had been typed in response to a numeric INPUT statement. The string is interpreted up to the first character that is not a legal numeric one (0 to 9, E, -, +, and .).
date=VAL(date$)
Statement sending bytes to the VDU drivers.
Any expressions may be followed by a comma, a semi-colon, a vertical bar, or nothing.
Expressions followed by a semi-colon are sent as two bytes (low byte first) to the operating system VDU drivers.
Expressions followed by a comma (or nothing) are sent to the VDU drivers as one byte, taken from the least significant byte of the expression.
The vertical bar means ,0,0,0,0,0,0,0,0,0, and so sends the expression before it as a byte followed by nine zero bytes. Since the maximum number of parameters required by any of the VDU statements is nine, the vertical bar ensures that sufficient parameters have been sent for any particular call. Any surplus ones are irrelevant, since VDU 0 does nothing.
Note: For the meanings of the VDU codes, see the chapter entitled VDU Control.
VDU 24,400;300;1000;740; : REM set up a graphics window
VDU 7 : REM Emit a beep
VDU 23,9,200|23,10,200| : Slow down the flash rate
Statement specifying the number of sound channels to be used.
expression is the number of channels to be used. The maximum number allowed is eight. Any number between 1 and 8 can be specified, but the number which the computer is to handle must be a power of two and so the computer rounds up the number you give to either one, two, four or eight.
Note: The sound system uses up some of the computer's processing power, and so it is good practice to minimise the number of active channels. Otherwise, the computer will take longer to perform other tasks such as drawing to the screen.
VOICES 4 VOICES n%*2
Function returning the y-coordinate of the text cursor.
An integer between 0 and n, where n is the height of the current text viewport minus one. This is the position of the text cursor which is normally given relative to the top edge of the text viewport. If the cursor direction has been altered using VDU 23,16, then it is given relative to the negative y edge of the screen which may be top, bottom, left or right.
Note: Even in VDU 5 mode, VPOS returns the position of the text cursor. You should therefore keep track of the vertical position explicitly in programs which must operate in VDU 5 mode (e.g. WIMP-based programs).
DEF FNmyTab(x%)
PRINT TAB(x%,VPOS);: =""
IF VPOS>10 THEN PRINT TAB(0,10);
Statement to wait for end of the current display frame. Waiting until the end of the frame maximises the amount of time available in which to draw objects while the electron beam is 'blanked'.
To enable a program to synchronise animation effects with the scanning of the display hardware.
MODE 0 a=0 REPEAT POINT 1279,500+200*SINa a+=RAD5 WAIT:RECTANGLE FILL 0,300,1279,400 TO -4,300 UNTIL FALSE
Part of the CASE OF WHEN OTHERWISE ENDCASE statement.
WHEN is followed by a list of expressions separated by commas. These expressions should evaluate to the same type as that of the expression following the corresponding CASE statement. If the value of the expression following the CASE statement matches that of any of the list following the WHEN, statements are executed and control is then passed to the statement following the ENDCASE.
Note: WHEN must be the first non-space object on a line. A CASE statement can contain any number of WHEN statements, but only the statements of the first one which contains a matching value will be executed. To match any value, an OTHERWISE should be used.
WHEN 1 : PROCload
WHEN 2,4,6,8 : PRINT "Even" : remainder= 0
WHEN "Y","y","YES","Yes","yes" : PROCgame
Statement marking the start of a WHILE ENDWHILE loop.
expression can be any numeric which can be evaluated to give a truth value. If it is zero (FALSE), control passes forward to the statement immediately after the corresponding ENDWHILE. If it is non-zero, control continues until the ENDWHILE statement is reached, then loops back to the WHILE statement, and expression is re-evaluated.
Note: The statements making up the body of the WHILE ENDWHILE loop are never executed if the initial value of expression is FALSE.
WHILE TIME < 1000 PROCdraw ENDWHILE
WHILE flag : PROCmainloop : ENDWHILE
Statement setting the line width for BASIC output, and function returning same.
WIDTH returns the current print width, i.e. the last value used in a WIDTH statement described below (or 0 by default).
expression should be a positive integer. Expressions in the range 1 to 2147483627 cause BASIC to print a new line and reset COUNT to zero every time COUNT exceeds that number. If the expression is 0, BASIC stops generating auto-newlines, which is the default.
WIDTH 0: REM 'infinite width'
WIDTH 40: REM newline every 40 characters horizontally
PRINT WIDTH