RTR logo

BBC BASIC for SDL 2.0

BBC BASIC for Windows

Keywords



Introduction to keywords

The BBC BASIC keywords are listed alphabetically for ease of reference. Where appropriate, the abbreviated form is also given (acceptance of abbreviated keywords is controlled by the Customize menu command).

The syntax and any associated keywords are listed at the end of each section.

Syntax

Syntax definitions are given at the end of each keyword section. Rather than use formal Backus-Naur Form (BNF) definitions, which many people find somewhat confusing, we have attempted to use descriptions which, whilst being reasonably precise, are readable by the majority of users. To those who would have preferred 'the real thing' - we apologise.

Symbols

The following symbols have special meaning in the syntax definitions.
{ } The enclosed item may be repeated zero or more times.
[ ] The items enclosed are optional, they may occur zero or one time.
| Indicates alternatives; one of which must be used.
<stmt> Means a BBC BASIC statement.
<var> Means a numeric or string variable.
<exp> Means an expression like PI*radius*height+2 or name$+"FRED"+CHR$(&0D). It can also be a single variable or constant like 23 or "FRED".
<label> Means a label identifying a program line.
<l-num> Means a line number in a BBC BASIC program.
<k-num> Means the number of one of the programmable keys.
<n-const> Means a numeric constant like '26.4' or '256'.
<n-var> Means a numeric variable like 'size' or 'weight'.
<numeric> Means a <n-const> or a <n-var> or an expression combining them. For example: PI*radius+2.66
<s-const> Means a string constant like "FRED".
<s-var> Means a string variable like 'address$'.
<string> Means a <s-const> or a <s-var> or an expression combining them. For example: name$+add$+"Phone".
<array()> Means an entire array. For example: alpha$().
<struct{}> Means an entire structure. For example: my_struct{}.
<t-cond> Means a 'testable condition'. In other words, something which is tested in an IF, UNTIL or WHILE clause. Since BBC BASIC does not have true Boolean variables, a <numeric> can be used anywhere a <t-cond> is specified.
<name> Means a valid variable name.
<member> Means a valid structure member.
<d:> Means a disk drive name (A: to P:).
<dirtry> Means a directory path-name.
<afsp> Means an ambiguous file specifier.
<ufsp> Means an unambiguous file specifier.
<nchr> Means a character valid for use in a name. 0 to 9, A to Z, a to z and underline.

ABS

A function which returns the absolute value of its numeric argument.
X = ABS(deficit)
length = ABS(X1-X2)
This function converts negative numbers into positive ones. It can be used to give the difference between two numbers without regard to the sign of the answer.

It is particularly useful when you want to know the difference between two values, but you don't know which is the larger. For instance, if X=6 and Y=10 then the following examples would give the same result.

difference = ABS(X-Y)
difference = ABS(Y-X)
You can use this function to check that a calculated answer is within certain limits of a specified value. For example, suppose you wanted to check that 'answer' was equal to 'ideal' plus or minus (up to) 0.5. One way would be:
IF answer>ideal-0.5 AND answer<ideal+0.5 THEN....
However, the following example would be a more elegant solution.
IF ABS(answer-ideal)<0.5 THEN....

Syntax

<n-var>=ABS(<numeric>)

Associated Keywords

SGN

ACS

A function which returns, in radians, the arc-cosine of its numeric argument. The permitted range of the argument is −1 to +1.

If you know the cosine of the angle, this function will tell you the angle (in radians). Unfortunately, you cannot do this with complete certainty because two angles within the range +/− PI (+/− 180 degrees) can have the same cosine. This means that one cosine has two associated angles.

The following diagram illustrates the problem:

Arc cosine
Within the four quadrants, there are two angles which have the same cosine, two with the same sine and two with the same tangent. When you are working back from the cosine, sine or tangent you don't know which of the two possible angles is correct.

By convention, ACS gives a result in the top two quadrants (0 to PI; 0 to 180 degrees) and ASN and ATN in the right-hand two quadrants (−PI/2 to +PI/2; −90 to + 90 degrees).

In the example below, 'radian_angle' becomes equal to the angle (in radians) whose cosine is 'y'.

radian_angle=ACS(y)
You can convert the answer to degrees by using the DEG function (or multiplying by 180/PI).
degree_angle=DEG(ACS(y))

Syntax

<n-var>=ACS(<numeric>)

Associated Keywords

ASN, ATN, SIN, COS, TAN, RAD, DEG

ADVAL

A function which returns information about the joystick, if fitted, or the number of free spaces in a buffer. The information returned depends upon the argument passed to ADVAL.

ADVAL positive argument

If the argument is positive (1 to 3), ADVAL returns a value related to the position of the joystick, if any:

ADVAL(1) returns the joystick X-position.
ADVAL(2) returns the joystick Y-position.
ADVAL(3) returns the joystick Z-position.

joyx=ADVAL(1)
level=ADVAL(chnumber)
Depending on the platform and type of joystick/controller, additional axes may be available, corresponding to parameters greater than 3.

ADVAL zero argument

ADVAL(0) returns a value in the range 0 to 15 corresponding to the state of the four joystick buttons. Zero is returned if no buttons are pressed and 15 is returned if all four buttons are pressed.

Depending on the platform and type of joystick/controller, additional buttons may be available, corresponding to values greater than 15.

ADVAL negative argument

ADVAL(−1) returns the number of free spaces in the keyboard buffer. If the keyboard buffer is empty, ADVAL(−1) will return 255. If the keyboard buffer is full, ADVAL(−1) will return 0. Note: this is different from the way ADVAL(−1) works in some other versions of BBC BASIC.

ADVAL(−5) returns the number of free bytes in the channel 0 SOUND queue. If the sound queue is empty, ADVAL(−5) will return 16. If the queue is full, ADVAL(−5) will return 0. Each sound event uses 4 bytes.

ADVAL(−6) returns the number of free bytes in the channel 1 SOUND queue. If the sound queue is empty, ADVAL(−6) will return 16. If the queue is full, ADVAL(−6) will return 0. Each sound event uses 4 bytes.

ADVAL(−7) returns the number of free bytes in the channel 2 SOUND queue. If the sound queue is empty, ADVAL(−7) will return 16. If the queue is full, ADVAL(−7) will return 0. Each sound event uses 4 bytes.

ADVAL(−8) returns the number of free bytes in the channel 3 SOUND queue. If the sound queue is empty, ADVAL(−8) will return 16. If the queue is full, ADVAL(−8) will return 0. Each sound event uses 4 bytes.

Syntax

<n-var>=ADVAL(<numeric>)

Associated Keywords

SOUND, INPUT, GET

AND

A.

An operator which performs a bitwise or logical AND between two items. The two operands are internally converted to 32-bit integers before the AND operation. For each of the 32 bits AND uses the following truth-table:
Input AInput BOutput
000
010
100
111
You can use AND as a logical operator or as a 'bit-by-bit' (bitwise) operator. The operands can be boolean (logical) or numeric.
answer=num1 AND num2
char=byte AND &7F

IF (num AND &F0)

test=(count=3 AND total=5)
In the following example program segment, AND is used as a bitwise operator to remove the most significant bit of a byte read from a file before writing it to another file. This is useful for converting some word-processor files into standard ASCII format.
byte=BGET#infile AND &7F
BPUT#outfile,byte
BBC BASIC does not have true boolean variables; this can lead to confusion at times (see NOT for more details).

In the example below, the operands are boolean (logical). In other words, the result of the tests (IF) A=2 and (IF) B=3 is either TRUE or FALSE. The result of this example will be TRUE if A=2 and B=3.

answer=(A=2 AND B=3)
The brackets are not necessary, they have been included to make the example easier to follow.

The second example is similar to the first, but in the more familiar surroundings of an IF statement.

IF A=2 AND B=3 THEN 110
or
answer= A=2 AND B=3 (without brackets this time)
IF answer THEN 110
The final example, uses the AND in a similar fashion to the numeric operators (+, −, etc).
A=X AND 11
Suppose X was −20, the AND operation would be:
11111111 11111111 11111111 11101100
00000000 00000000 00000000 00001011
00000000 00000000 00000000 00001000  = 8

Syntax

<n-var>=<numeric> AND <numeric>
<n-var>AND=<numeric>

Associated Keywords

EOR, OR, FALSE, TRUE, NOT

ASC

A function which returns the ASCII value of the first character of the argument string. If the string is empty then −1 will be returned.

A computer only understands numbers. In order to deal with characters, each character is assigned a code number. For example (in the ASCII code table) the character 'A' is given the code number 65 (decimal).

Different types of computer use different numbers for the characters. The codes used for PC Compatible computers are those defined by the American Standard Code for Information Interchange (ASCII). See the Table of ASCII codes section.

You could use this function to convert ASCII codes to some other coding scheme.

ascii_code=ASC("H") Result would be 72
X=ASC("HELLO") Result would be 72
name$="FRED"
ascii_code=ASC(name$) Result would be 70
X=ASC"e" Result would be 101
X=ASC(MID$(A$,position)) Result depends on A$ and position.
ASC is the complement of CHR$.

Syntax

<n-var>=ASC(<string>)

Associated Keywords

CHR$, STR$, VAL

ASN

A function which returns, in radians, the arc sine of its numeric argument. The permitted range of the argument is −1 to +1.

By convention, the result will be in the range −PI/2 to +PI/2 (−90 to +90 degrees).

If you know the sine of the angle, this function will tell you the angle (in radians). Unfortunately, you cannot do this with complete certainty because one sine has two associated angles (see ACS for details).

In the example below, 'radian_angle' becomes equal to the angle (in radians) whose sine is 'y'.

radian_angle=ASN(y)
You can convert the answer to degrees by using the DEG function (the DEG function is equivalent to multiplying by 180/PI). The example below is similar to the first one, but the angle is in degrees.
degree_angle=DEG(ASN(y))

Syntax

<n-var>=ASN(<numeric>)

Associated Keywords

ACS, ATN, SIN, COS, TAN, RAD, DEG

ATN

A function which returns, in radians, the arc tangent of its numeric argument. The permitted range of the argument is from minus infinity to plus infinity.

By convention, the result will be in the range −PI/2 to +PI/2 (−90 to +90 degrees).

If you know the tangent of the angle, this function will tell you the angle (in radians).

As the magnitude of the argument (tangent) becomes very large (approaches + or − infinity) the accuracy diminishes.

In the example below, 'radian_angle' becomes equal to the angle (in radians) whose tangent is 'y'.

radian_angle=ATN(y)
You can convert the answer to degrees by using the DEG function (the DEG function is equivalent to multiplying by 180/PI). The example below is similar to the first one, but the angle is in degrees.
degree_angle=DEG(ATN(y))

Syntax

<n-var>=ATN(<numeric>)

Associated Keywords

ACS, ASN, SIN, COS, TAN, RAD, DEG

BGET#

B.#

A function which reads a byte from the file whose channel number is its argument. The file pointer is incremented after the byte has been read.
E=BGET#n
aux=BGET#3
You must normally have opened a file using OPENOUT, OPENIN or OPENUP before you use this statement. (See these keywords and the Disk files section for details).

You can use BGET# to read single bytes from a disk file. This enables you to read back small integers which have been 'packed' into fewer than 5 bytes (see BPUT#). It is also very useful if you need to perform some conversion operation on a file. Each byte read is numeric, but you can use CHR$(BGET#n) to convert it to a string.

The input file in the example below is a text file produced by a word-processor.

Words to be underlined are 'bracketed' with ^S. The program produces an output file suitable for a printer which expects such words to be bracketed by ^Y. You could, of course, perform several such translations in one program.

REM Open i/p and o/p files. End if error.
infile=OPENIN "WSFILE.DOC"
IF infile=0 THEN END
outfile=OPENOUT "BROTH.DOC"
IF outfile=0 THEN END
:
REM Process file, converting ^S to ^Y
REPEAT
  temp=BGET#infile :REM Read byte
  IF temp=&13 THEN temp=&19 :REM Convert ^S
  BPUT#outfile,temp :REM Write byte
UNTIL temp=&1A OR EOF#infile :REM ^Z
CLOSE#0 :REM Close all files
END
To make the program more useful, it could ask for the names of the input and output files at 'run time':
INPUT "Enter name of INPUT file " infile$
INPUT "Enter name of OUTPUT file " outfile$
REM Open i/p and o/p files. End if error.
infile=OPENIN(infile$)
IF infile=0 THEN END
outfile=OPENOUT(outfile$)
IF outfile=0 THEN END
:
REM Process file, converting ^S to ^Y
REPEAT
  temp=BGET#infile :REM Read byte
  IF temp=&13 THEN temp=&19 :REM Convert ^S
  BPUT#outfile,temp :REM Write byte
UNTIL temp=&1A OR EOF#infile :REM ^Z
CLOSE#0 :REM Close all files
END

Syntax

<n-var>=BGET#<numeric>

Associated Keywords

OPENIN, OPENUP, OPENOUT, CLOSE#, PRINT#, INPUT#, BGET#, EXT#, PTR#, EOF#, GET$#

BPUT#

BP.#

A statement which writes a byte or string to the data file whose channel number is the first argument. If the second argument is numeric, its least significant byte is written to the file. If the second argument is a string, the contents of the string are written to the file, followed by a line-feed character (CHR$10); adding a terminating semicolon suppresses the line-feed. The file pointer is incremented after the bytes have been written.
BPUT#E,32
BPUT#staff_file,A/256
BPUT#chn,A$
BPUT#N,"a string";
Before you use this statement you must normally have opened a file for output using OPENOUT or OPENUP (see these keywords and the Disk files section for details).

You can use this statement to write single bytes to a disk file. The number that is sent to the file is in the range 0 to 255. Real numbers are converted internally to integers and the top three bytes are 'masked off'. Each byte written is numeric, but you can use ASC(character$) to convert (the first character of) 'character$' to a number.

Alternatively BPUT# can be used to write a character string to a file. The difference between PRINT#file,string$ and BPUT#file,string$ is that PRINT# appends a carriage-return character (CHR$13) whereas BPUT# appends a line-feed character (CHR$10). Adding a terminating semicolon (;) causes the contents of the string to be written to the file with nothing appended.

The example below is a program segment that 'packs' an integer number between 0 and 65535 (&FFFF) into two bytes, least significant byte first. The file must have already been opened for output and the channel number stored in 'fnum'. The integer variable number% contains the value to be written to the file.

BPUT#fnum,number% MOD 256
BPUT#fnum,number% DIV 256

Syntax

BPUT#<numeric>,<numeric>
BPUT#<numeric>,<string>[;]

Associated Keywords

OPENIN, OPENUP, OPENOUT, CLOSE#, PRINT#, INPUT#, BGET#, EXT#, PTR#, EOF#, GET$#

BY

Used in conjunction with DRAW, FILL, MOVE or PLOT, indicates that the supplied X and Y coordinates are relative (offsets from the current point) rather than absolute.

BY is also used with the GET$#channel function to specify the number of bytes to be read from the file.

Syntax

DRAW BY <numeric>,<numeric>
FILL BY <numeric>,<numeric>
MOVE BY <numeric>,<numeric>
PLOT BY <numeric>,<numeric>

Associated Keywords

DRAW, FILL, GET$, MOVE, PLOT

CALL

CA.

A statement to call a machine code (assembly language) subroutine, or to run BBC BASIC code in a separate file.
CALL Muldiv,A,B,C,D
CALL &FFE3
CALL 12340,A$,M,J$

When BBC BASIC is running on a 32-bit x86 CPU the processor's EAX, EBX, ECX and EDX registers are initialised to the contents of A%, B%, C% and D% respectively (see also USR). The processor's flags register is initialised to the contents of F%; however, you cannot disable interrupts nor enter single-step mode by setting F% because this could affect the operation of the Operating System. On other CPUs the first six parameters, as specified by the relevant ABI, are initialised to A%, B%, C%, D%, E% and F% respectively.

Your machine-code routine should return to BBC BASIC with a return instruction (RET).

Operating system interface

CALL and USR operate differently when addresses in the range &FF00 to &FFFF are used. See the Operating System Interface section for more details and an example of the use of CALL.

Parameter table

CALL sets up a table in RAM containing details of the parameters. On a 32-bit x86 CPU the base pointer (EBP register) is set to the memory address of this parameter table; on other CPUs the seventh parameter, as specified by the relevant ABI, is set to the memory address of the parameter table.

Variables included in the parameter list need not have been declared before the CALL statement.

The parameter types are:

CodeParameter typeExample
0:byte (unsigned 8 bits)?ptr
1:byte (unsigned 8 bits)A&
4:32-bit signed integerA% or !ptr
40:64-bit signed integerA%% or ]ptr
5:40-bit variantA1
8:64-bit variantA2 or A#
10:80-bit variantA3
24:structureA{}
36:function or procedureFNa or PROCa
65:byte arrayA&()
68:32-bit integer arrayA%()
104:64-bit integer arrayA%%()
69:40-bit variant arrayA()1
72:64-bit variant arrayA()2 or A#()
74:80-bit variant arrayA()3
88:structure arrayA{()}
100:function or procedureFNa() or PROCa()
128:fixed string (CR terminated)$ptr
129:movable string, 6-byte descriptorA$1,2
136:movable string, 8-byte descriptorA$3
130:fixed string (NUL terminated)$$ptr
193:string array, 6-byte descriptorsA$()1,2
200:string array, 8-byte descriptorsA$()3
1.  BBC BASIC for Windows version 5.95a or earlier in *FLOAT 40 mode.
2.  BBC BASIC for Windows version 5.95a or earlier in *FLOAT 64 mode.
3.  BBC BASIC for Windows version 6.00a or later, or BBC BASIC for SDL 2.0.

On entry to the subroutine the parameter table contains the following values:

Number of parameters1 byte
Parameter type1 byte
Parameter address4 bytes or 8 bytes
Parameter type) repeated as often
Parameter address) as necessary.

Parameter formats

The parameter address given is the absolute address at which the item is stored, in the following formats:

Byte variables are stored as a single unsigned byte.

Integer variables are stored in twos complement format with their least significant byte first.

Real variables are stored in 5-byte, 8-byte or 10-byte binary floating point format with their least significant byte first.

Fixed strings are stored as the characters of the string followed by a carriage return (&0D) or NUL (&00).

In the case of a movable string (normal string variable), the parameter address points to the 'string descriptor'.

In the case of an array, the parameter address points to an indirect pointer to the 'array descriptor'.

In the case of a structure, the parameter address points to the 'structure descriptor'.

See the Format of data in memory section for details.

Running BASIC code in a separate file

You can execute BBC BASIC code in an external file using the following syntax:
CALL filename$
The contents of the file are loaded into memory, executed, and then discarded. As with the INSTALL statement the file must be in BBC BASIC internal (tokenised) format, and line numbers and labels are not recognised. Whereas INSTALLed modules should only contain procedure and function definitions, CALLed modules should normally not contain any procedure or function definitions (nor should they INSTALL modules which do). Attempting to execute such a procedure or function after the CALLed module has returned could easily crash BASIC.

One use for this facility is to keep 'constant' and structure definitions (such as might be used, for example, by calls to OS API functions) in separate files rather than including them in every program that uses them. In this way it is easier to maintain and update the definitions, and your program size is reduced. This is similar to the use of library files for packaging functions which you might want to call from many programs.

You should normally prefix the filename with either @lib$ (for standard definitions) or @dir$ (for definitions specific to your program) so that the file will be loaded from the correct location irrespective of the current directory setting:

CALL @lib$+"windefs"
CALL @dir$+"mydefs"
This also makes it easier to embed the files within a compiled executable. If you crunch your compiled program, using the abbreviate names option, it is important that any CALLed files are also crunched in such a way that any variable and structure names declared in the files agree with those used in your main program. You can achieve that using the crunch embedded files option of the Compile command.

The CALLed program will return control to the calling program when execution 'drops off the end' of the code, or if a RETURN statement is executed. CALL may be nested, that is program files executed using CALL may themselves include CALL statements.

Syntax

CALL <numeric>{,<n-var>|<s-var>|<array()>|<struct{}>}
CALL <string>

Associated Keywords

INSTALL, RETURN, USR

CASE

A statement which results in different actions depending on the value of a numeric or string variable. The value is compared with each of the alternatives given; if it matches then the appropriate statements are executed. If the value does not match any of the alternatives, the statements following the OTHERWISE statement (if any) are executed. CASE ... ENDCASE clauses can be nested.

WHEN and ENDCASE must be the first thing on the program line and OF must be the last thing on the line (it cannot even be followed by a REMark).

CASE toss% OF
  WHEN 0 : coin$ = "tails"
  WHEN 1 : coin$ = "heads"
  OTHERWISE coin$ = "cheat"
ENDCASE

CASE direction$ OF
  WHEN "left","LEFT" :
  PRINT "turn left"
  WHEN "right","RIGHT" :
  PRINT "Turn right"
  OTHERWISE
  PRINT "Straight on"
ENDCASE

Syntax

CASE <numeric>|<string> OF
  WHEN <numeric>|<string>{,<numeric>|<string>} : {<stmt>}
  {<stmt>}
  WHEN <numeric>|<string>{,<numeric>|<string>} : {<stmt>}
  {<stmt>}
  OTHERWISE {<stmt>}
  {<stmt>}
ENDCASE

Associated Keywords

ENDCASE, IF, OF, ON, OTHERWISE, WHEN

CHAIN

CH.

A statement which loads and runs the program whose name is specified in the argument.
CHAIN "GAME1"
CHAIN A$
The program file must be in BBC BASIC internal (tokenised) format.

All but the static variables @% to Z% are CLEARed.

CHAIN sets ON ERROR OFF before chaining the specified program.

RUN may be used as an alternative to CHAIN.

You can use CHAIN (or RUN) to link program modules together. This allows you to write modular programs which would, if written in one piece, be too large for the memory available or too unwieldy.

Passing data between CHAINed programs can be a bit of a problem because all but the static variables are cleared by CHAIN.

If you wish to pass large amounts of data between CHAINed programs, you should use a data file. However, if the amount of data to be passed is small and you do not wish to suffer the time penalty of using a data file, you can pass data to the CHAINed program by using the indirection operators to store them at known addresses. The safest way to do this is to move HIMEM down and store common data at the top of memory.

The following sample program segment moves HIMEM down 1000 bytes and stores the input and output file names in the memory above HIMEM. There is, of course, still plenty of room for other data in this area.

HIMEM=HIMEM-1000
$HIMEM=in_file$
$(HIMEM+256)=out_file$
CHAIN "NEXTPROG"

Syntax

CHAIN <string>

Associated Keywords

CALL, INSTALL, RUN

CHR$

A function which returns a string of length 1 containing the ASCII character specified by the least significant byte of the numeric argument.
A$=CHR$(72)
B$=CHR$(12)
C$=CHR$(A/200)
CHR$ generates an ASCII character (symbol, letter, number character, control character, etc) from the number given. The number specifies the position of the generated character in the ASCII table. For example:
char$=CHR$(65)
will set char$ equal to the character 'A'. You can use CHR$ to send a special character to the terminal or printer (generally, VDU is better for sending characters to the screen). For example,
CHR$(7)
will generate the ASCII character ^G. So,
PRINT "ERROR"+CHR$(7)
will print the message 'ERROR' and sound the PC's 'bell'.

CHR$ is the complement of ASC.

Syntax

<s-var>=CHR$(<numeric>)

Associated Keywords

ASC, STR$, VAL, VDU

CIRCLE

A statement which draws a circle or disc (filled circle) in all screen modes except MODE 7. CIRCLE is followed by the X and Y coordinates of the centre of the circle and the radius. To draw a filled (solid) circle rather than an outline circle, use CIRCLE FILL.

The graphics origin (X=0, Y=0) is normally the bottom left of the 'screen' (BASIC's output window). The origin can be changed using the VDU29 command or the ORIGIN statement. See the Graphics and colours section for more details.

The circle or disc is drawn in the current graphics foreground colour. This colour can be changed using the GCOL statement.

CIRCLE x,y,r is equivalent to MOVE x,y : PLOT 145,r,0
CIRCLE FILL x,y,r is equivalent to MOVE x,y : PLOT 153,r,0

CIRCLE 200,300,40
CIRCLE FILL 300,400,100

Syntax

CIRCLE [FILL] <numeric>,<numeric>,<numeric>

Associated Keywords

ELLIPSE, FILL, GCOL, MOVE, PLOT

CLEAR

CL.

A statement which clears all the dynamically declared variables, including strings. CLEAR does not affect the static variables.

The CLEAR command tells BBC BASIC to 'forget' about ALL the dynamic variables used so far. This includes strings, arrays and structures, but the static variables (@% to Z%) are not altered.

You can use the indirection operators to store integers and strings at known addresses and these will not be affected by CLEAR. However, you will need to 'protect' the area of memory used. One way to do this is to move HIMEM down. See CHAIN for an example.

CLEAR sets LOMEM equal to TOP.

Syntax

CLEAR

Associated Keywords

None

CLOSE#

CLO.#

A statement used to close a data file. CLOSE #0 will close all data files.
CLOSE#file_num
CLOSE#0
You use CLOSE# to tell BBC BASIC that you have completely finished with a data file for this phase of the program. Any data still in the file buffer is written to the file before the file is closed.

You can open and close a file several times within one program, but it is generally considered 'better form' not to close a file until you have finally finished with it. However, if you wish to CLEAR the variables, it is simpler if you close the data files first.

You should also close data files before chaining another program. CHAIN does not automatically close data files, but it does clear the variables in which the channel numbers were stored. You can still access the open file if you have used one of the static variables (A% to Z%) to store the channel number. Alternatively, you could reserve an area of memory (by moving HIMEM down for example) and use the byte indirection operator to store the channel number. See the keyword CHAIN for more details.

END or 'dropping off' the end of a program will also close all open data files. However, QUIT and STOP do not close data files.

CLOSE is also used in the ON CLOSE statement.

Syntax

CLOSE#<numeric>

Associated Keywords

OPENIN, OPENUP, OPENOUT, PRINT#, INPUT#, BPUT#, BGET#, EXT#, PTR#, EOF#, ON CLOSE

CLG

A statement which clears the graphics viewport and sets it to the currently selected graphics background colour using the current background plotting action (set by GCOL). The position of the graphics cursor is unchanged.

See the Graphics and colours section or GCOL for more information on graphics colours.

Syntax

CLG

Associated Keywords

CLS, GCOL

CLS

A statement which clears the text viewport and sets it to the currently selected text background colour. The text cursor is moved to the 'home' position (0,0) at the top left-hand corner of the text viewport.

See the Graphics and colours section or COLOUR for more information on text colours.

Syntax

CLS

Associated Keywords

CLG, COLOUR

COLOUR (COLOR)

C.

A statement which sets the text foreground and background colour or modifies the colour palette.

When COLOUR is followed by one value the text foreground or background colour is set. If the value is less than 128, the text foreground colour is set to that value. If the number is 128 or greater, the text background colour is set to value−128.

There are up to 128 logical colours (numbered 0 to 127), but the number available varies with the mode; see the section on text colours for details.

COLOUR 1 : REM sets the text foreground colour to 1
COLOUR 130 : REM sets the text background colour to 2
COLOUR n is equivalent to VDU 17,n.

When COLOUR is followed by two values the palette is modified using a physical colour number. The first value specifies the logical colour to be changed (0-127) and the second value specifies the physical colour to which it should be mapped (0-15).

COLOUR 1,4 : REM set logical colour 1 to blue
COLOUR l,p is equivalent to VDU 19,l,p,0,0,0

When COLOUR is followed by four values the palette is modified using an RGB (Red, Green, Blue) colour. The first value specifies the logical colour to be changed (0-127) and the second, third and fourth values specify the red, green and blue components of the colour to which it should be mapped. In each case the value should be in the range 0 (none) to 255 (maximum).

COLOUR 1,128,0,128 : REM set logical colour 1 to dark purple
COLOUR l,r,g,b is equivalent to VDU 19,l,16,r,g,b

Syntax

COLOUR <numeric>
COLOUR <numeric>,<numeric>
COLOUR <numeric>,<numeric>,<numeric>,<numeric>

Associated Keywords

VDU, GCOL, MODE

COS

A function giving the cosine of its radian argument.
X=COS(angle)
This function returns the cosine of an angle. The angle must be expressed in radians, not degrees.

Whilst the computer is quite happy dealing with angles expressed in radians, you may prefer to express angles in degrees. You can use the RAD function to convert an angle from degrees to radians.

The example below sets Y to the cosine of the angle 'degree_angle' expressed in degrees.

Y=COS(RAD(degree_angle))

Syntax

<n-var>=COS(<numeric>)

Associated Keywords

SIN, TAN, ACS, ASN, ATN, DEG, RAD

COUNT

COU.

A function returning the number of text characters written to the screen since the last new line.
char_count=COUNT
Characters with an ASCII value of less than 13 (carriage return/new-line/enter) have no effect on COUNT.

Because control characters above 13 are included in COUNT, you cannot reliably use it to find the position of the cursor on the screen. If you need to know the cursor's horizontal position use the POS function.

The example below prints strings from the string array 'words$'. The strings are printed on the same line until the line length exceeds 65. When the line length is in excess of 65, a new-line is printed.

PRINT
FOR i=1 TO 1000
  PRINT words$(i);
  IF COUNT>65 THEN PRINT
NEXT
Note that COUNT may not return the expected value when UTF-8 mode is enabled (it counts bytes rather than characters).

Syntax

<n-var>=COUNT

Associated Keywords

POS

DATA

D.

A program object which must precede all lists of data for use by the READ statement. DATA must be used at the start of a program line.

As for INPUT, string values may be quoted or unquoted. However, quotes need to be used if the string contains commas or leading spaces.

Numeric values may include calculation so long as there are no keywords.

Data items in the list should be separated by a comma.

DATA 10.7,2,HELLO," THIS IS A COMMA,",1/3,PRINT
DATA " This is a string with leading spaces."
You can use DATA in conjunction with READ to include data in your program which you may need to change from time to time, but which does not need to be different every time you run the program.

The following example program segment reads through a list of names looking for the name in 'name$'. If the name is found, the name and age are printed. If not, an error message is printed.

DATA FRED,17,BILL,21,ALLISON,21,NOEL,32
DATA JOAN,26,JOHN,19,WENDY,35,ZZZZ,0
REPEAT
READ list$,age
IF list$=name$ THEN PRINT name$,age
UNTIL list$=name$ OR list$="ZZZZ"
IF list$="ZZZZ" PRINT "Name not in list"

Syntax

DATA <s-const>|<n-const>{,<s-const>|<n-const>}

Associated Keywords

READ, RESTORE, LOCAL

DEF

A program object which must precede declaration of a user defined function (FN) or procedure (PROC). DEF must be used at the start of a program line.

If DEF is encountered during execution, the rest of the line is ignored. As a consequence, single line definitions can be put anywhere in the program.

Multi-line definitions must not be executed. The safest place to put multi-line definitions is at the end of the main program after the END statement.

There is no speed advantage to be gained by placing function or procedure definitions at the start of the program.

DEF FNMEAN ....
DEF PROCJIM ....
The function or procedure name may start with an underline:
DEF FN_mean ....
DEF PROC_Jim$ ....
Function and procedure names may end with a '$'. This is not compulsory for functions which return strings.

A procedure definition is terminated by the statement ENDPROC.

A function definition is terminated by a statement which starts with an equals (=) sign. The function returns the value of the expression to the right of the equals sign.

For examples of function and procedure declarations, see FN and PROC. For a general explanation refer to the Procedures and functions section.

Syntax

DEF PROC<name>[([RETURN]<s-var>|<n-var>{,[RETURN]<s-var>|<n-var>})]
DEF FN<name>[([RETURN]<s-var>|<n-var>{,[RETURN]<s-var>|<n-var>})]

Associated Keywords

ENDPROC, FN, PROC, RETURN

DEG

A function which converts radians to degrees.
degree_angle=DEG(PI/2)
X=DEG(ATN(1))
You can use this function to convert an angle expressed in radians to degrees. One radian is approximately 57 degrees (actually 180/PI). PI/2 radians is 90 degrees and PI radians is 180 degrees.

Using DEG is equivalent to multiplying the radian value by 180/PI, but the result is calculated internally to a greater accuracy.

See ACS, ASN and ATN for further examples of the use of DEG.

Syntax

<n-var>=DEG(<numeric>)

Associated Keywords

RAD, SIN, COS, TAN, ACS, ASN, ATN, PI

DIM

DIM can be used as a statement or as a function. When used as a statement, DIM has three different forms: the first declares an array, the second declares a structure and the third reserves an area of memory for special applications. When used as a function, DIM returns the number of dimensions in an array, the size of a particular dimension or the size of a structure.

Dimensioning arrays

The DIM statement is used to declare arrays. Arrays must be pre-declared before use and once declared their dimensions cannot be changed (with the exception of LOCAL and PRIVATE arrays). Arrays may be integer numeric, byte numeric, real numeric or string and they may be multi-dimensional. However, you cannot mix integers, bytes, reals and/or strings in the same array.
DIM A(2),Ab(2,3),A$(2,3,4),A%(3,4,5,6)
All elements in the array are initialised to zero (for numeric arrays) or to empty strings (for string arrays). Note that you can repeat an array declaration so long as the dimensions are identical to those specified when it was first declared. In this case the contents of the array remain unchanged: they are not initialised.

The subscript base is 0, so DIM X(12) defines an array of 13 elements whose subscript value can be from 0 to 12 inclusive.

Arrays are like lists or tables. A list of names is a single dimension array. In other words, there is only one column - the names. Its single dimension in a DIM statement would be the maximum number of names you expected in the table less 1.

If you wanted to describe the position of the pieces on a chess board you could use a two dimensional array. The two dimensions would represent the row (numbered 0 to 7) and the column (also numbered 0 to 7). The contents of each 'cell' of the array would indicate the presence (if any) of a piece and its value.

DIM chess_board(7,7)
Such an array would only represent the chess board at one moment of play. If you wanted to represent a series of board positions you would need to use a three dimensional array. The third dimension would represent the 'move number'. Each move would use about 320 bytes of memory, so you could record 40 moves in about 12.5k bytes.
DIM chess_game(7,7,40)
The 'DIM space' error will occur if you attempt to declare an array for which there is insufficient memory. In this case you can (usually) increase the value of HIMEM to make more memory available.

Declaring structures

The DIM statement is used to declare structures and arrays of structures. Structures must be pre-declared before use and once declared their format cannot be changed (with the exception of LOCAL and PRIVATE structures). Structures may contain integer numeric, byte numeric, real numeric, string, array or sub-structure members, and arrays of structures can be one-dimensional or multi-dimensional. For more details see the Structures section.
DIM mystruct{one,two%,three$,four(3),five%(1,2),six$(9),seven{a,b%}}
DIM structarray{(10)one,two%,three$}
DIM newstruct{}=protostruct{}
DIM multistruct{(3,2)}=protostruct{}
All members of the structure are initialised to zero (for numeric members) or to empty strings (for string members). Note that you can repeat a structure declaration so long as the format is identical to that specified when it was first declared. In this case the contents of the structure remain unchanged: they are not initialised.

The 'DIM space' error will occur if you attempt to declare a structure or structure array for which there is insufficient memory. In this case you can (usually) increase the value of HIMEM to make more memory available.

Reserving an area of memory

The DIM statement can be used to reserve an area of memory which the interpreter will not then use. The variable specified in the DIM statement is set to the start address of this memory area. This reserved area can then be used by the indirection operators, assembly language code, etc.

The example below reserves 68 bytes of memory from the heap and sets a%% equal to the address of the first byte. Thus a%%?0 to a%%?67 are free for use by the program (68 bytes in all):

DIM a%% 67
The amount of memory reserved is one byte greater than the value specified. DIM p%% −1 is a special case; it reserves zero bytes of memory. This is of more use than you might think, since it tells you the limit of the dynamic variable allocation (the heap) so far. Thus,
DIM p%% -1
PRINT HIMEM-p%%
is the equivalent of PRINT HIMEM-END (or PRINT FREE(0) in some other dialects of BASIC).

Memory reserved in this way causes irreversible loss of heap space, therefore you must be very careful not to reserve the memory multiple times when once will suffice. This is a particular danger when DIM is used within a function or procedure.

See the Assembler section for a more detailed description of the use of DIM for reserving memory for machine code programs.

Reserving a temporary area of memory

If you want to reserve a temporary block of memory for use within a function or procedure you can use use the following construct:
DIM a%% LOCAL 67
This reserves 68 bytes from the stack rather than from the heap, and the memory is automatically freed on exit from the function or procedure.

Note that the variable (a%% in this case) is not automatically made LOCAL to the function or procedure. In most cases you will want to do that as well:

LOCAL a%%
DIM a%% LOCAL 67

The amount of memory reserved is one byte greater than the value specified. DIM p%% LOCAL −1 is a special case; it reserves zero bytes of memory. This is of more use than you might think, since it tells you the current size of the stack:

DIM p%% LOCAL -1
PRINT HIMEM-p%%

DIM as a function

You can use DIM as a function to discover the number of dimensions in an array, the size of an array dimension or the size of a structure. The function DIM(array()) returns the number of dimensions in the array (note the use of opening and closing brackets with nothing in between). The function DIM (array(),n) returns the size of dimension 'n', where n is in the range 1 to the number of dimensions. The function DIM(structure{}) returns the size of the structure in bytes.

If an array is declared as follows:

DIM cuboid(4,5,7)
the function DIM(cuboid()) will return the value 3, the function DIM(cuboid(),1) will return the value 4, the function DIM(cuboid(),2) will return the value 5 and the function DIM(cuboid(),3) will return the value 7.

Discovering the size of an array is of particular interest when a whole array is passed as a parameter to a function or procedure. For example, if you write a general-purpose function to calculate the geometric mean of the values in a numeric array, the function must know the total number of elements in the array. See the section on passing arrays to functions/procedures for an example.

If a structure is declared as follows:

DIM mystruct{alpha%, beta$, gamma{l&,h&}}
the function DIM(mystruct{}) would return the value 12 (4 + 6 + 2).

Syntax

DIM <n-var>|<s-var>(<numeric>{,<numeric>})
DIM <name>{<member>{,<member>}}
DIM <struct{}>=<struct{}>
DIM <n-var> [LOCAL] <numeric>
<n-var> = DIM(<array()>[,<numeric>])
<n-var> = DIM(<struct{}>)

Associated Keywords

CLEAR, HIMEM, LOCAL, LOMEM

DIV

An operator returning the integer quotient of two items. The result is always an integer.
X=A DIV B
y=(top+bottom+1) DIV 2
You can use this function to give the 'whole number' part of the answer to a division. For example,
21 DIV 4
would give 5 (with a 'remainder' of 1).

Whilst it is possible to use DIV with real numbers, it is really intended for use with integers. If you do use real numbers, BBC BASIC converts them to integers by truncation before DIViding them.

Syntax

<n-var>=<numeric> DIV <numeric>
<n-var>DIV=<numeric>

Associated Keywords

MOD

DRAW

A statement which draws a line on the screen (in all modes except MODE 7). DRAW is followed by the X and Y coordinates of the end of the line; the optional qualifier BY indicates that the coordinates are relative (offsets from the start of the line) rather than absolute. The coordinates must be in the range −32768 to +32767.

The start of the line is the current graphics cursor position, i.e. either the last point 'visited' (for example the end of the last line drawn) or a point explicitly specified by a MOVE statement.

The graphics origin (X=0, Y=0) is normally the bottom left of the 'screen' (BASIC's output window). The origin can be changed using the ORIGIN statement or the VDU 29 command.

The line is drawn in the current graphics foreground colour. This colour can be changed using the GCOL statement. DRAW only draws solid lines; you can draw dotted or dashed lines by using the PLOT statement.

DRAW x,y

MOVE 200,300
DRAW 640,800
DRAW x,y is equivalent to PLOT 5,x,y.
DRAW BY x,y is equivalent to PLOT 1,x,y.

Syntax

DRAW <numeric>,<numeric>
DRAW BY <numeric>,<numeric>

Associated Keywords

BY, MODE, PLOT, MOVE, CLG, VDU, GCOL

ELLIPSE

A statement which draws an outline ellipse or filled ellipse, in all screen modes except MODE 7. ELLIPSE is followed by the X and Y coordinates of the centre of the ellipse, the horizontal radius and the vertical radius, in that order. To draw a filled ellipse use ELLIPSE FILL.

BBC BASIC for Windows and BBC BASIC for SDL 2.0 can draw only axis-aligned ellipses. To draw an angled ellipse use the ELLIPSE library routines.

The graphics origin (X=0, Y=0) is normally the bottom left of the 'screen' (BASIC's output window). The origin can be changed using the VDU29 command or the ORIGIN statement. See the Graphics and colours section for more details.

The ellipse is drawn in the current graphics foreground colour. This colour can be changed using the GCOL statement.

ELLIPSE x,y,a,b is equivalent to MOVE x,y : PLOT 0,a,0 : PLOT 193,0,b
ELLIPSE FILL x,y,a,b is equivalent to MOVE x,y : PLOT 0,a,0 : PLOT 201,0,b

ELLIPSE 200,300,40,50
ELLIPSE FILL 300,400,100,80

Syntax

ELLIPSE [FILL] <numeric>,<numeric>,<numeric>,<numeric>

Associated Keywords

CIRCLE, FILL, GCOL, MOVE, PLOT

ELSE

EL.

A statement delimiter which provides an alternative course of action in IF...THEN, ON...GOSUB, ON...GOTO and ON...PROC statements.

In an IF statement, if the conditional expression evaluates to zero, the statements after ELSE will be executed. This makes the following work:

IF A=B THEN B=C ELSE B=D
IF A=B THEN B=C:PRINT"WWW" ELSE B=D:PRINT"QQQ"
IF A=B THEN B=C ELSE IF A=C THEN...............
In a multi statement line containing more than one IF, the statement(s) after the ELSE delimiter will be actioned if ANY of the tests fail. For instance, the example below would print the error message 'er$' if 'x' did not equal 3 OR if 'a' did not equal 'b'.
IF x=3 THEN IF a=b THEN PRINT a$ ELSE PRINT er$
If you want to 'nest' the tests, you should use a multi-line IF ... ENDIF statement. The following example would print "Bad" ONLY if x was equal to 3 AND 'a' was not equal to 'b'.
IF x=3 THEN
  IF a=b THEN PRINT a$ ELSE PRINT "Bad"
ENDIF
ELSE can be used to indicate an alternative course of action in a multi-line IF ... THEN ... ENDIF statement:
IF x=3 THEN
  PRINT "x is 3"
ELSE
  PRINT "x is not 3"
ENDIF
In this case ELSE must be the first thing on the line. You can cascade multiple IF ... ENDIF statements to test a number of different alternatives:
IF x=3 THEN
  PRINT "x is 3"
ELSE IF x=4 THEN
    PRINT "x is 4"
  ELSE
    PRINT "x is neither 3 nor 4"
  ENDIF
ENDIF
but in this situation a CASE statement would be a better choice.

You can use ELSE with ON...GOSUB, ON...GOTO and ON...PROC statements to prevent an out of range control variable causing an 'ON range' error.

ON action GOTO 100, 200, 300 ELSE PRINT "Error"
ON number GOSUB 100,200,300 ELSE PRINT "Error"
ON value PROCa,PROCb,PROCc ELSE PRINT "Error"

Syntax

IF <t-cond> [THEN <stmt>{:<stmt>}] [ELSE <stmt>{:<stmt>}]
ELSE [<stmt>]
ON <n-var> GOTO <l-num>{,<l-num>} ELSE <stmt>
ON <n-var> GOSUB <l-num>{,<l-num>} ELSE <stmt>
ON <n-var> PROC<name>{,PROC<name>} ELSE <stmt>

Associated Keywords:

IF, THEN, ON, ENDIF

END

A statement causing the interpreter to return to immediate mode. There can be any number (>=0) of END statements anywhere in a program. END closes all open data files.

END tells BBC BASIC that it has reached the end of the program. You don't have to use END, just 'running out of program' will have the same effect, but it's a bit messy.

You can use END within, for instance, an IF...THEN...ELSE statement to stop your program if certain conditions are satisfied. You should also use END to stop BBC BASIC 'falling into' any procedure or function definitions at the end of your program.

END can also be used as a function. It returns the address of the first byte above BASIC's dynamic variable area (the heap). These two statements are equivalent:

e%% = END
DIM e%% -1

Syntax

END
<n-var> = END

Associated Keywords

QUIT, STOP, CLOSE#

ENDCASE

A keyword which terminates a CASE...ENDCASE clause. ENDCASE must be the first item on the program line.
CASE die% OF
  WHEN 1,2,3 : bet$ = "lose"
  WHEN 4,5,6 : bet$ = "win"
  OTHERWISE bet$ = "cheat"
ENDCASE

Syntax

ENDCASE

Associated Keywords

CASE, OF, OTHERWISE, WHEN

ENDIF

A keyword which terminates a multi-line IF clause. ENDIF must be the first thing on the program line.

Syntax

ENDIF

Associated Keywords

ELSE, IF, THEN

ENDPROC

A statement denoting the end of a procedure.

All LOCAL or PRIVATE variables and the dummy arguments are restored at ENDPROC and the program returns to the statement after the calling statement.

Syntax

ENDPROC

Associated Keywords

DEF, FN, LOCAL, PRIVATE, PROC

ENDWHILE

A keyword which terminates a WHILE... ENDWHILE clause. If the ENDWHILE statement is executed, BBC BASIC jumps to the matching WHILE statement. If the WHILE condition is not met, control is transferred to the statement after the matching ENDWHILE statement.
 WHILE LEFT$(A$,1) = " " A$ = MID$(A$,2) : ENDWHILE

Syntax

ENDWHILE

Associated Keywords

REPEAT, UNTIL, WHILE

ENVELOPE

A statement which is used, in conjunction with the SOUND statement, to control the pitch and/or amplitude of a sound whilst it is playing.

During its 'life' the pitch and amplitude (volume) of a sound may change. The variation of pitch with time is called the pitch envelope and the variation of amplitude with time is called the amplitude envelope. In BBC BASIC there are four phases of amplitude (the attack phase, the decay phase, the sustain phase and the release phase) and three phases of pitch. The four amplitude phases and the three pitch phases are defined separately based on a common 'step' duration.

You may use the ENVELOPE statement to define up to 16 different envelopes. The envelopes are referred to by number in the SOUND statement.

The ENVELOPE statement has 14 parameters. The syntax of the ENVELOPE statement is:

ENVELOPE <parameter list>
The parameter list has the format shown below; all the parameters must be supplied.
N,T,PI1,PI2,PI3,PN1,PN2,PN3,AA,AD,AS,AR,ALA,ALD
ParamRangeFunction
N1 to 16Envelope number.
T (bits 0-6) 0 to 127Length of each step in hundredths of a second.
T (bit 7)0 or 10=Auto repeat the pitch envelope.
1=Don't auto repeat.
PI1−128 to 127 Change of pitch per step in section 1.
PI2−128 to 127Change of pitch per step in section 2.
PI3−128 to 127Change of pitch per step in section 3.
PN10 to 255Number of steps in section 1.
PN20 to 255Number of steps in section 2.
PN30 to 255Number of steps in section 3.
AA−127 to 127Change of amplitude per step during the attack phase.
AD−127 to 127Change of amplitude per step during the decay phase.
AS−127 to 0Change of amplitude per step during the sustain phase.
AR−127 to 0Change of amplitude per step during the release phase.
ALA0 to 126Target of level at the end of the attack phase.
ALD0 to 126Target of level at the end of the decay phase.

The durations of the three phases of the pitch envelope are explicitly specified (PN1, PN2 and PN3 respectively) but the durations of the phases of the amplitude envelope are determined indirectly. See *TEMPO for more information about the pitch envelope.

The duration of the 'attack' phase is determined by the target level (ALA) and the rate of attack (AA), i.e. the duration is equal to ALA/AA or the total duration specified in the SOUND statement, whichever is less.

The duration of the 'decay' phase is determined by the target level (ALD) and the rate of decay (AD), i.e. the duration is equal to (ALD-ALA)/AD or what remains of the total duration specified in the SOUND statement, whichever is less.

The duration of the 'sustain' phase is determined by what remains of the total duration specified in the SOUND statement. For example if the total duration is two seconds, and the attack and decay phases lasted a total of one second, the sustain phase will last one second.

The 'release' phase is terminated as soon as another note is ready to play on that channel, otherwise it continues indefinitely or until the amplitude has reduced to zero. A SOUND statement with the 'hold' bit set can be used to force some or all of the release phase to sound even if there are more notes ready to be played.

When the pitch envelope is set to auto-repeat, there are two different interpretations of what this means. The first is that the pitch-changes repeat, the second (default) is that the actual pitches repeat. This is determined by the *TEMPO command.

Syntax

ENVELOPE <numeric>, <numeric>, <numeric>, <numeric>, <numeric>, <numeric>, <numeric>, <numeric>, <numeric>, <numeric>, <numeric>, <numeric>, <numeric>, <numeric>

Associated Keywords

SOUND

Left CONTENTS

CONTINUE Right


Best viewed with Any Browser Valid HTML 3.2!
© Richard Russell 2024