Introduction

Before You Start

This is a reference manual, it is not intended to teach you BASIC. It gives a summary of the commands and functions plus some hints and tips on their use. It also describes the minor differences between this and other versions of BBC BASIC. A general knowledge of BASIC has been assumed.

Installation

BBC BASIC (Z80) for the TI-83+ and TI-84+ is a Flash application. To install it you will need a transfer cable and supporting software (such as TI Connect™). Transfer the BBC BASIC.8xk file to your calculator. Once installed BBCBasic should appear on the Applications menu.

Consult your calculator documentation and file transfer software documentation for further information.

Getting Started

Here follows a quick guide to get you up and running in the BBC BASIC environment. For more detailed information, look up keywords in the dedicated reference or documentation in the overview section. For help on entering text, see the page on Editing.

The BBC BASIC Environment

When you run BBC BASIC from the applications menu, you will be presented with the following screen:

BBC BASIC (Z80) v3.00
(C) R.T.Russell 1987
>_

BBC BASIC takes the form of a command-line interface. BASIC commands or OS ("star") commands are typed into this interface for immediate execution or as part of a program. For example, type in

*BYE

at BASIC's prompt and press the Enter key. This will exit BBC BASIC and return you to the TI-OS.

Return to BBC BASIC and enter the following line at the prompt:

PRINT RAD(180)

When you press the Enter key, BBC BASIC evaluates the BASIC program code and displays

3.14159265

which is the value of PI. The PRINT statement outputs the value following it to the display; in this case the value is the result of RAD(180). RAD converts a value in degrees into an value in radians; 180 degrees is, indeed, pi radians.

If you wish to store BASIC code as part of a program, for later execution, you need to prefix it by a line number. If you repeat the previous example, and type in the following,

10 PRINT RAD(180)

BBC BASIC will accept the line as part of a program. It is conventional to give BASIC programs line numbers that are multiples of 10, starting at 10 (10, 20, 30, etc). You can now run the program by entering the RUN command.

You can display the current program's listing with the LIST statement, or search through it using the LIST IF statement. If you type in a new line that starts with a line number that already exists, the existing line is overwritten. If you just type a line number, the corresponding line number is deleted.

One reason for entering line numbers in increments of 10 is that it gives you the ability to insert new lines between two existing ones. For example, if you wanted to insert a line between 10 and 20 you could give it a number of 15. This will ultimately lead to erratic and messy line numbers, which can be tidied up with the RENUMBER command.

Saving and Loading Programs

Start by entering the following program to calculate the area of a circle from its radius:

10 INPUT"Radius=",R
20 PRINT"Area=",PI*R^2

Once you have typed it in, you can verify it works by running it with the RUN command. You will usually want to save programs you have worked on so they can be run again at a later date. To do this you will need to use the SAVE command. Try saving the program you just typed in above by typing in the following command:

SAVE "CIRCAREA"

This will save the program in memory to a program variable named CIRCAREA. (See the Files section for information about filenames and how files are stored). Now type NEW to remove the loaded program from memory followed by the LIST keyword to verify that it has, in fact, been unloaded. Use the LOAD command to reload the CIRCAREA program into memory:

LOAD "CIRCAREA"

You can now use the LIST command you can see that the file has been reloaded, or simply RUN run it. You can load and run a program from storage directly by using the CHAIN keyword or RUN followed by a filename.

© Richard Russell with modifications by Ben Ryves.


Credits

BBC BASIC (Z80) is Copyright © R. T. Russell, 1982-2009.

This documentation has been adapted from the BBC BASIC (86) Manual, also Copyright © R. T. Russell.

The TI-83+/TI-84+ version host interface and documentation is by Ben Ryves for MaxCoderz 2008-2009.

Contributors

BBC BASIC

R. T. Russell, author of BBC BASIC (Z80), provided the binaries and documentation required to create the TI-83+/TI-84+ version, as well as help via email for specific implementation problems.

J. G. Harston, author of the ZX Spectrum interface for BBC BASIC (Z80), provided much help via email and helped develop a preliminary version of the TI-83+/TI-84+ based around the Tube interface version of BBC BASIC (Z80).

TI-83+/TI-84+

Darren Cubitt provided several routines for the graphics system, including the line clipping code, circle and ellipse plotting and drawing code and the horizontal line filling code.

References

  • BBC BASIC (86) Manual by Richard Russell.
  • BASIC ROM User Guide by Mark Plumbley.
  • The Advanced User Guide for the BBC Micro by Andrew Bray, Adrian Dickens and Mark Holmes.

Links

  • http://www.bbcbasic.co.uk/ - R. T. Russell's BBC BASIC website provides comprehensive documentation on several different implementations of BBC BASIC, including the Windows, DOS (86) and Z80 versions.
  • http://mdfs.net/bbcbasic/ - J. G. Harston's website covers a wide range of topics including a directory of every known version of BBC BASIC.


Editing

Keypad Layout

BBC BASIC uses a different keypad layout to the TI-OS to try and make typing BBC BASIC easier. The following diagram illustrates the function of each key.

When using the TI-OS you would use the 2nd and Alpha keys as dead keys; press either of them once followed by the key that you wish to modify. Within BBC BASIC they are replaced by Shift and Alpha modifiers; you need to hold them down when pressing the key you wish to modify.

By default, each key types the uppercase letter that is printed above it. To type the lowercase equivalent, hold down the 2nd key whilst pressing the key. Holding Alpha will type a number of symbol of some description - in the diagram above it's the number or symbol above the key, to the left. Finally, holding 2nd and Alpha down can be used to type some extended symbols, which appear above the key and to the right.

Copy Key Editing

Using copy key editing to correct a mistake in a program.

This version of BBC BASIC (Z80) supports a text editing feature known as copy key editing. It allows you to split the text editing cursor into two components, a write cursor and a read cursor. The read cursor, which takes the form of a blinking underscore, may be moved anywhere on the screen, and by pressing the Copy key the text characters underneath it are copied and written to the write cursor's position (which takes the form of a solid block). Both cursors then advance together.

You enter the copy key editing mode by pressing any of the four cursor keys (up, down, left or right). Position the read cursor with the cursor keys to the start of the text you wish to copy, then press the Copy key - marked X,T,Θ,n on the calculator keypad - to copy text to the write cursor. Copy key editing mode is exited when you press Enter to confirm the line.


Files

Introduction

BBC BASIC (Z80) has a number of file-related functions that are accessible in this version. As the calculator OS does not have a traditional file system, there are some important rules to bear in mind.

Naming Files

The extension of the file is used to determine the type of file. If no extension is specified a default of .PRG is assumed. Filenames are case sensitive. If an invalid filename is specified, a 'Bad name' error is triggered.

Extension | File Type
PRG | Program variable.
VAR | Application variable.
PIC | Picture variable.
DEV | Hardware device.

Program Variables

Program variables are variable-length, random-access, general-purpose files that are listed on the PRGM menu on the TI-OS. They can have any filename up to 8 characters in length, which means that you can use BBC BASIC to create program variables that are not accessible via the TI-OS. For this reason it is strongly recommended that you only create program variables with UPPERCASE names and only use alphanumeric characters, with the exception of the first character which cannot be a number.

Here are some examples of good names:

  • TETRIS
  • CUBE3D.PRG
  • FINANCE.PRG
  • QUADRATC

Here are some examples of bad names:

  • snake (lowercase characters)
  • 3DCUBE.PRG (first character is a number)
  • MY_MAZE.PRG (non-alphanumeric)

Here are some examples of invalid names:

  • BATTLESHIPS.PRG (too long)
  • Pong.prg (lowercase extension)

Application Variables

Application variables, or AppVars, follow the same rules as program variables. The main difference between the two types is that the TI-OS only allows access to application variables via the memory management menu; consider using application variables for resources or related data files for your program.

Picture Variables

BBC BASIC allows you to work with the TI-OS picture variables Pic1 to Pic9 and Pic0. They have a fixed size (756 bytes) and support random access. You must specify their filename in the form PICn.PIC, where n is the number of the variable to access.

The following example program copies the top 63 rows of data from the graph buffer to Pic1.

10 S%=OPENOUT"PIC1.PIC"
20 GBUF%=&9340
30 FOR P%=0 TO 755
40   D%=GBUF%?P%
50   BPUT#S%,D%
60 NEXT
70 CLOSE#S%

Hardware Devices

BBC BASIC (Z80) lets you access certain hardware devices using the standard file manipulation routines. In these cases the supplied filename has .DEV as its extension.

The block copy routines do not work with hardware devices; you are only able to access them byte-by-byte.

Sony Serial Infrared Remote Control System (SIRCS.DEV)

By attaching a suitable adapter to the calculator's data port you can send and receive commands to and from SIRCS-compatible devices.

Most of the hard work is done in software so the adapter is very easy to build. No responsibility is accepted for any damage to your calculator as a result of using an adapter built from the above diagram.

Receiving command codes from a remote control is straightforwards. Each command code is 7 bits and can be read using BGET#:

sircs%=OPENIN"SIRCS.DEV"
command%=BGET#sircs%

Program execution will pause at BGET# until a command has been received.

A SIRCS remote control will transmit a device code along with the command code to tie the remote control to the device it is meant to be controlling. You can get or set the device code via PTR#.

The SIRCS protocol exists in 12-, 15- and 20-bit variations. Most common devices use the 12-bit variant. The PlayStation 2 console, however, uses the 20-bit variation. You can get or set the number of bits using EXT#.

The following program will wait for a command to be received from a remote control then display information on the screen about the data received.

sircs%=OPENIN"SIRCS.DEV"
REPEAT
  C%=BGET#sircs%
  CLS
  PRINT "Command",~C%
  PRINT "Device ",~PTR#sircs%
  PRINT "Size   ",EXT#sircs%
UNTIL FALSE

To send a "cross" command (&5E) to a PlayStation 2 console (a 20-bit device with the code &1B5A) you could do the following:

sircs%=OPENOUT"SIRCS.DEV"
EXT#sircs%=20    : REM Sending 20-bit commands.
PTR#sircs%=&1B5A : REM PS/2 console has a device code of &1BFA
BPUT#sircs%,&5E  : REM &5E is the command code for "X".

Each command is transmitted six times in rapid succession for reliability.

See the SIRCS Command and Device Codes appendix for more information.


Variables

Variable names may be of unlimited length and all characters are significant. Variable names must start with a letter. They can only contain the characters A..Z, a..z, 0..9 and underscore. Embedded keywords are allowed. Upper and lower case variables of the same name are different.

The following types of variable are allowed:

A | Real numeric
A% | Integer numeric
A$ | String

Numeric Variables

Real Variables

Real variables have a range of ±5.9E-39 to ±3.4E+38 and numeric functions evaluate to 9 significant figure accuracy. Internally every real number is stored in 40 bits (5 bytes). The number is composed of a 4 byte mantissa and a single byte exponent. An explanation of how variables are stored is given in the appendix Format of Program and Variables in Memory.

Integer Variables

Integer variables are stored in 32 bits and have a range of +2147483647 to -2147483648. It is not necessary to declare a variable as an integer for advantage to be taken of fast integer arithmetic. For example, FOR...NEXT loops execute at integer speed whether or not the control variable is an 'integer variable' (% type), so long as it has an integer value.

Static Variables

The variables A%..Z% are a special type of integer variable in that they are not cleared by the statements RUN, CHAIN and CLEAR. In addition A%, B%, C%, D%, E%, F%, H% and L% have special uses in CALL and USR routines and P% and O% have a special meaning in the Assembler (P% is the program counter and O% points to the code origin). The special variable @% controls numeric print formatting. The variables @%..Z% are called 'static', all other variables are called 'dynamic'.

Boolean Variables

Boolean variables can only take one of the two values TRUE or FALSE. Unfortunately, BBC BASIC does not have true boolean variables. However, it does allow numeric variables to be used for logical operations. The operands are converted to 4 byte integers (by truncation) before the logical operation is performed. For example:

PRINT NOT 1.5
      -2

The argument, 1.5, is truncated to 1 and the logical inversion of this gives -2.

PRINT NOT -1.5
       0

The argument is truncated to -1 and the logical inversion of this gives 0.

Two numeric functions, TRUE and FALSE, are provided. TRUE returns the value -1 and FALSE the value 0. These values allow the logical operators (NOT, AND, EOR and OR) to work properly. However, anything which is non-zero is considered to be TRUE. This can give rise to confusion, since +1 is considered to be TRUE and NOT(+1) is -2, which is also considered to be TRUE.

Numeric Accuracy

Numbers are stored in binary format. Integers and the mantissa of real numbers are stored in 32 bits. This gives a maximum accuracy of just over 9 decimal digits. It is possible to display up to 10 digits before switching to exponential (scientific) notation (PRINT and STR$). This is of little use when displaying real numbers because the accuracy of the last digit is suspect, but it does allow the full range of integers to be displayed. Numbers up to the maximum integer value may be entered as a decimal constant without any loss of accuracy. For instance, A%=2147483647 is equivalent to A%=&7FFFFFFF.

String Variables and Garbage

Strings

String variables may contain up to 255 characters. An explanation of how variables are stored is given at the appendix entitled Format of Program and Variables in Memory.

Garbage Generation

Unlike numeric variables, string variables do not have a fixed length. When you create a string variable, the memory used is sufficient for the initial value of the string. If you subsequently assign a longer string to the variable there will be insufficient room for it and the string will have to occupy a different area in memory. The initial area will then become 'dead'. These areas of 'dead' memory are called garbage. As more and more re-assignments take place, the area of memory used for the variables grows and eventually there is no more room. Several versions of BASIC have automatic 'garbage collection' routines which tidy up the variable memory space when this occurs. Unfortunately, this can take several seconds and can be embarrassing if your program is time conscious. BBC BASIC (Z80) does not incorporate 'garbage collection' routines and it is possible to run out of room for variables even though there should be enough space.

Memory Allocation

You can overcome the problem of 'garbage' by reserving enough memory for the longest string you will ever put into a variable before you use it. You do this simply by assigning a string of spaces to the variable. If your program needs to find an empty string the first time it is used, you can subsequently assign a null string to it. The same technique can be used for string arrays. The example below sets up a single dimensional string array with room for 20 characters in each entry, and then empties it ready for use.

10 DIM names$(10)
20 FOR i=0 TO 10
30   name$(i)=STRING$(20," ")
40 NEXT
50 stop$="";
60 FOR i=0 TO 10
70   name$(i)="";
80 NEXT

Assigning a null string to stop$ prevents the space for the last entry in the array being recovered when it is emptied.

Arrays

Arrays of integer, real and string variables are allowed. All arrays must be dimensioned before use. Integers, reals and strings cannot be mixed in a multi-dimensional array; you have to use one array for each type of variable you need.


Flow Control

Whenever BBC BASIC (Z80) comes across a FOR, REPEAT, WHILE, GOSUB, FN or PROC statement, it needs to remember where it is in the program so that it can loop back or return there when it encounters a line with NEXT, UNTIL, ENDWHILE or RETURN statement or when it reaches the end of a function or procedure. These 'return addresses' tell BBC BASIC (Z80) where it is in the structure of your program.

Every time BBC BASIC (Z80) encounters a FOR, REPEAT, WHILE, GOSUB, FN or PROC statement it 'pushes' the return address on to a 'stack' and every time it encounters a NEXT, UNTIL, ENDWHILE, RETURN statement or the end of a function or procedure it 'pops' the latest return address of the stack and goes back there.

BBC BASIC (Z80) uses a single control stack (the processor's hardware stack) for all looping and nesting operations. The main effects of this are discussed below.

Loop Operation Errors

Apart from memory size, there is no limit to the level of nesting of FOR…NEXT, REPEAT…UNTIL, WHILE…ENDWHILE and GOSUB…RETURN operations. The untrappable error message No room will be issued if all the stack space is used up.

Program Structure Limitations

The use of a common stack has one disadvantage (if it is a disadvantage) in that it forces stricter adherence to proper program structure. It is not good practice to exit from a FOR…NEXT loop without passing through the NEXT statement. It makes the program more difficult to understand and the FOR address is left on the stack. Similarly, the loop or return address is left on the stack if a REPEAT…UNTIL loop, WHILE…ENDWHILE loop or a GOSUB…RETURN structure is incorrectly exited. This means that if you leave a FOR…NEXT loop without executing the NEXT statement, and then subsequently encounter, for example, a RETURN statement, BBC BASIC (Z80) will report an error. (In this case, a No GOSUB error.) The example below would result in the error message 'No PROC at line 500'.

400 - - -
410 INPUT "What number should I stop at", num
420 PROC_error_demo
430 END
440 :
450 DEF PROC_error_demo
460 FOR i=1 TO 100
470   PRINT i;
480   IF i=num THEN 500
490 NEXT i
500 ENDPROC

BBC BASIC (Z80) is a little unusual in detecting this error, but it is always risky. It usually results in an inconsistent program structure.

Leaving Program Loops

There are a number of ways to leave a program loop which do not conflict with the need to write tidy program structures. These are discussed below.

EXIT

The easiest and safest way to simply leave a loop (or several nested loops of different types) is to use a suitable EXIT statement.

10 i=1
20 REPEAT
30   PRINT i
40   i=i+1
50   IF i=6 THEN EXIT REPEAT
60 UNTIL FALSE
70 PRINT "Done"

EXIT is not a standard feature of BBC BASIC (Z80) and so may not be available in other implementations. Even though the other methods for leaving a loop prematurely may not seem as practical as EXIT they have the advantage of increased compatibility as well as smaller code size and higher performance by being supported directly by the interpreter with dedicated tokens.

REPEAT…UNTIL Loops

The simplest way to overcome the problem of exiting a FOR…NEXT loop is to restructure it as a REPEAT…UNTIL loop. The example below performs the same function as the previous example, but exits the structure properly. It has the additional advantage of more clearly showing the conditions which will cause the loop to be terminated.

400 - - -
410 INPUT "What number should I stop at", num
420 PROC_error_demo
430 END
440 :
450 DEF PROC_error_demo
460 i=0
470 REPEAT
480   i=i+1
490   PRINT i;
500 UNTIL i=100 OR i=num
510 ENDPROC

Changing the Loop Variable

A simple way of forcing an exit from a FOR…NEXT loop is to set the loop variable to a value equal to the limit value and then GOTO to the NEXT statement. alternatively, you could set the loop variable to a value greater than the limit (assuming a positive step), but in this case the value on exit would be different depending on why the loop was terminated. (In some circumstances, this may be an advantage). The example below uses this method to exit from the loop. Notice, however, that the conditions which cause the loop to terminate are less clear since they do not appear together.

400 - - -
410 INPUT "What number should I stop at", num
420 PROC_error_demo
430 END
440 :
450 DEF PROC_error_demo
460 FOR i=1 TO 100
470   PRINT i;
480   IF i=num THEN i=500: GOTO 510
490   …
500   (More program here if necessary)
510 NEXT
520 ENDPROC

Popping the Inner Variable

A less satisfactory way of exiting a FOR…NEXT loop is to enclose the loop in a dummy outer loop and rely on BBC BASIC (Z80)'s ability to 'pop' inner control variables off the stack until they match. If you use this method you MUST include the variable name in the NEXT statement. This method, which is demonstrated below, is very artificial and the conditions which cause the loop to terminate are unclear.

400 - - -
410 INPUT "What number should I stop at", num
420 PROC_error_demo
430 END
440 :
450 DEF PROC_error_demo
460 FOR dummy=1 TO 1 :REM Loop once only
470 FOR i=1 TO 100
480   PRINT i;
490   IF i=num THEN 530 :REM Jump to outer NEXT
500   - - -
510   (More program here if necessary)
520 NEXT i
530 NEXT dummy
540 ENDPROC

Local Variables

Since local variables are also stored on the processor's stack, you cannot use a FOR…NEXT loop to make an array LOCAL. For example, the following program will give the the error message 'Not LOCAL at line 400'.

380 DEF PROC_error_demo
390 FOR i=1 TO 10
400   LOCAL data(i)
410 NEXT
420 ENDPROC

You can overcome this by fabricating the loop using an IF…THEN statement as shown below. This is probably the only occasion when the use of a single stack promotes poor program structure.

380 DEF PROC_error_demo
390 i=1
400 LOCAL data(i)
410 i=i+1
420 IF i<11 THEN 400
430 ENDPROC

Stack Pointer

The program stack is initialised to begin at HIMEM and, because of this, you cannot change the value of HIMEM when there is anything on the stack. As a result, you cannot change HIMEM from within a procedure, function, subroutine, FOR…NEXT loop, REPEAT…UNTIL loop or WHILE…ENDWHILE loop.


Indirection

Introduction

Most versions of BASIC allow access to the computer's memory with the PEEK function and the POKE command. Such access, which is limited to one byte at a time, is sufficient for setting and reading screen locations or 'flags', but it is difficult to use for building more complicated data structures. The indirection operators provided in BBC BASIC (Z80) enable you to read and write to memory in a far more flexible way. They provide a simple equivalent of PEEK and POKE, but they come into their own when used to pass data between CHAINed programs, build complicated data structures or for use with machine code programs.

BBC BASIC (Z80) can 'see' all the computer's memory and the indirection operators will accept 16-bit addresses in the range &0000 to &FFFF.

There are three indirection operators:

Name | Symbol | Purpose | No. of Bytes Affected
Query | ? | Byte Indirection Operator | 1
Exclamation | ! | Word Indirection Operator | 4
Dollar | $ | String Indirection Operator | 1 to 256

Query

Byte Access

The query (?) operator accesses individual bytes of memory. ?M means 'the contents of' memory location 'M'. The first two examples below write &23 to memory location &4FA2, the second two examples set 'number' to the contents of that memory location and the third two examples print the contents of that memory location.

?&4FA2=&23

or

memory=&4FA2
?memory=&23
number=?&4FA2

or

memory=&4FA2
number=?memory
PRINT ?&4FA2

or

memory=&4FA2
PRINT ?memory

Thus, '?' provides a direct replacement for PEEK and POKE.

  • ?A=B is equivalent to POKE A,B
  • B=?A is equivalent to B=PEEK(A)

Query as a Byte Variable

A byte variable, '?count' for instance, may be used as the control variable in a FOR...NEXT loop and only one byte of memory will be used.

DIM count% 0
FOR ?count%=0 TO 20
  - - -

  - - -
NEXT

Exclamation

The query (?) indirection operator works on one byte of memory. The word indirection operator (!) works on 4 bytes (an integer word) of memory. Thus,

!M=&12345678

would load

  • &78 into address M
  • &56 into address M+1
  • &34 into address M+2
  • &12 into address M+3.

and

PRINT ~!M : REM (print !M in hex format)

would give

12345678

Dollar

The string indirection operator ($) writes a string followed by a carriage-return (&0D) into memory starting at the specified address. Do not confuse M$ with $M. The former is the familiar string variable whilst the latter means 'the string starting at memory location M'. For example,

$M="ABCDEF"

would load the ASCII characters A to F into addresses M to M+5 and &0D into address M+6, and

PRINT $M

would print

ABCDEF

Use as Binary Operators

All the examples so far have used only one operand with the byte and word indirection operators. Provided the left-hand operand is a variable (such as 'memory') and not a constant, '?' and '!' can also be used as binary operators. (In other words, they can be used with two operands.) For instance, M?3 means 'the contents of memory location M plus 3' and M!3 means 'the contents of the 4 bytes starting at M plus 3'. In the following example, the contents of memory location &4000 plus 5 (&4005) is first set to &50 and then printed.

memory=&4000
memory?5=&50
PRINT memory?5

Thus,

  • A?I=B is equivalent to POKE A+I,B
  • B=A?I is equivalent to B=PEEK(A+I)

The two examples below show how two operands can be used with the byte indirection operator (?) to examine the contents of memory. The first example displays the contents of 12 bytes of memory from location &4000. The second example displays the memory contents for a real numeric variable. (See the appendix entitled Format of Program and Variables in Memory).

10 memory=&4000
20 FOR offset=0 TO 12
30   PRINT ~memory+offset, ~memory?offset
40 NEXT

Line 30 prints the memory address and the contents in hexadecimal format.

 10 NUMBER=0
 20 DIM A% -1
 30 REPEAT
 40   INPUT"NUMBER PLEASE "NUMBER
 50   PRINT "& ";
 60   FOR I%=2 TO 5
 70     NUM$=STR$~(A%?-I%)
 80     IF LEN(NUM$)=1 NUM$="0"+NUM$
 90     PRINT NUM$;" ";
100   NEXT
110   N%=A%?-1
120   NUM$=STR$~(N%)
130   IF LEN(NUM$)=1 NUM$="0"+NUM$
140   PRINT " & "+NUM$''
150 UNTIL NUMBER=0

See the appendix entitled Format of Program and Variables in Memory for an explanation of this program.

Power of Indirection Operators

Indirection operators can be used to create special data structures, and as such they are an extremely powerful feature. For example, a structure consisting of a 10 character string, an 8 bit number and a reference to a similar structure can be constructed.

If M is the address of the start of the structure then:

  • $M is the string
  • M?11 is the 8 bit number
  • M!12 is the address of the related structure

Linked lists and tree structures can easily be created and manipulated in memory using this facility.


Evaluation Order

The various mathematical and logical operators have a priority order. The computer will evaluate an expression taking this priority order into account. Operators with the same priority will be evaluated from left to right. For example, in a line containing multiplication and subtraction, ALL the multiplications would be performed before any of the subtractions were carried out. The various operators are listed below in priority order.

  • variables functions () ! ? & unary+- NOT
  • ^
  • * / MOD DIV
  • + -
  • = <> <= >= > <
  • AND
  • EOR OR

Examples

The following are some examples of the way expression priority can be used. It often makes things easier for us humans to understand if you include the brackets whether the computer needs them or not.

IF A=2 AND B=3 THEN...
IF ((A=2)AND(B=3))THEN...
IF A=1 OR C=2 AND B=3 THEN...
IF((A=1)OR((C=2)AND(B=3)))THEN...
IF NOT(A=1 AND B=2) THEN...
IF(NOT((A=1)AND(B=2)))THEN...
N=A+B/C-D N=A+(B/C)-D
N=A/B+C/D N=(A/B)+(C/D)


Error Handling

The ON ERROR command directs BBC BASIC (Z80) to execute the statement(s) following ON ERROR when a trappable error occurs:

ON ERROR PRINT '"Oh No!":END

If an error was detected in a program after this line had been encountered, the message 'Oh No!' would be printed and the program terminated. If, as in this example, the ON ERROR line contains the END statement or transfers control elsewhere (e.g. using GOTO) then the position of the line within the program is unimportant so long as it is encountered before the error occurs. If there is no transfer of control, execution following the error continues as usual on the succeeding line, so in this case the position of the ON ERROR line can matter.

As explained in the Flow Control sub-section, every time BBC BASIC (Z80) encounters a FOR, REPEAT, GOSUB, FN or PROC statement it 'pushes' the return address on to a 'stack' and every time it encounters a NEXT, UNTIL, RETURN statement or the end of a function or procedure it 'pops' the latest return address of the stack and goes back there. The program stack is where BBC BASIC (Z80) records where it is within the structure of your program.

When an error is detected by BBC BASIC (Z80), the stack is cleared. Thus, you cannot just take any necessary action depending on the error and return to where you were because BBC BASIC (Z80) no longer knows where you were.

If an error occurs within a procedure or function, the value of any private variables will be the last value they were set to within the procedure or function which gave rise to the error.


Procedures and Functions

Introduction

Procedures and functions are similar to subroutines in that they are 'bits' of program which perform a discrete function. Like subroutines, they can be performed (called) from several places in the program. However, they have two great advantages over subroutines: you can refer to them by name and the variables used within them can be made private to the procedure or function.

Arguably, the major advantage of procedures and functions is that they can be referred to by name. Consider the two similar program lines below.

100 IF name$="ZZ" THEN GOSUB 500 ELSE GOSUB 800
100 IF name$="ZZ" THEN PROC_end ELSE PROC_print

The first statement gives no indication of what the subroutines at 500 and 800 actually do. The second, however, tells you what to expect from the two procedures. This enhanced readability stems from the choice of meaningful names for the two procedures.

A function often carries out a number of actions, but it always produces a single result. For instance, the 'built in' function INT returns the integer part of its argument.

age=INT(months/12)

A procedure on the other hand, is specifically intended to carry out a number of actions, some of which may affect program variables, but it does not directly return a result.

Whilst BBC BASIC (Z80) has a large number of pre-defined functions (INT and LEN for example) it is very useful to be able to define your own to do something special. Suppose you had written a function called FN_discount to calculate the discount price from the normal retail price. You could write something similar to the following example anywhere in your program where you wished this calculation to be carried out.

discount_price=FN_discount(retail_price)

It may seem hardly worth while defining a function to do something this simple. However, functions and procedures are not confined to single line definitions and they are very useful for improving the structure and readability of your program.

Names

The names of procedures and functions must start with PROC or FN and, like variable names, they cannot contain spaces. (A space tells BBC BASIC (Z80) that it has reached the end of the word). This restriction can give rise to some pretty unreadable names. However, the underline character can be used to advantage. Consider the procedure and function names below and decide which is the easier to read.

  • PROCPRINTDETAILS
  • FNDISCOUNT
  • PROC_print_details
  • FN_discount

Function and procedure names may end with a '$'. However, this is not compulsory for functions which return strings.

Functions and Procedure Definitions

Starting a Definition

Functions and procedure definitions are 'signalled' to BBC BASIC (Z80) by preceding the function or procedure name with the keyword DEF. DEF must be at the beginning of the line. If the computer encounters DEF during execution of the program, the rest of the line is ignored. Consequently, you can put single line definitions anywhere in your program.

The Function/Procedure Body

The 'body' of a procedure or function must not be executed directly - it must be performed (called) by another part of the program. Since BBC BASIC (Z80) only skips the rest of the line when it encounters DEF, there is a danger that the remaining lines of a multi-line definition might be executed directly. You can avoid this by putting multi-line definitions at the end of the main program text after the END statement. Procedures and functions do not need to be declared before they are used and there is no speed advantage to be gained by placing them at the start of the program.

Ending a Definition

The end of a procedure definition is indicated by the keyword ENDPROC. The end of a function definition is signalled by using a statement which starts with an equals (=) sign. The function returns the value of the expression to the right of the equals sign.

Single Line Functions/Procedures

For single line definitions, the start and end are signalled on the same line. The first example below defines a function which returns the average of two numbers. The second defines a procedure which clears from the current cursor position to the end of line on a 40 column screen.

110 DEF FN_avg(a,b)=(a+b)/2
120 DEF PROC_clear:PRINT SPC(40-POS);:ENDPROC

Extending the Language

You can define a whole library of procedures and functions and include them in your programs. By doing this you can effectively extend the scope of the language. For instance, BBC BASIC (Z80) does not have a 'clear to end of screen' command. Some computers will perform this function on receipt of a sequence of control characters and in this case you can use VDU or CHR$ to send the appropriate codes. However, many computers do not have this facility and a procedure to clear to the end of the screen would be useful. The example below is a procedure to clear to the end of screen on a computer with a 24 by 10 display. The three variables used (i, x, and y) are declared as LOCAL to the procedure (see later).

100 DEF PROC_clear_to_end
110 LOCAL i,x,y
120 x=POS:y=VPOS
130 REM If not last line, print lines of spaces which
140 REM will wrap around and end up on last line
150 IF y<9 FOR i=y TO 8:PRINT SPC(24);:NEXT
160 REM Print spaces to end-1 of last line.
170 PRINT SPC(23-x);
180 PRINT TAB(x,y);
190 ENDPROC

Passing Parameters

When you define a procedure or a function, you list the parameters to be passed to it in brackets. For instance, the discount example expected one parameter (the retail price) to be passed to it. You can write the definition to accept any number of parameters. For example, we may wish to pass both the retail price and the discount percentage. The function definition would then look something like this:

DEF FN_discnt(price,pcent)=price*(1-pcent/100)

In this case, to use the function we would need to pass two parameters.

 90 ...
100 retail_price=26.55
110 discount_price=FN_discount(retail_price,25)
120 ...

or

 90 ...
100 price=26.55
110 discount=25
120 price=FN_discount(price,discount)
130 ...

or

 90 ....
100 price=FN_discount(26.55,25)
110 ....

Formal and Actual Parameters

The value of the first parameter in the line using the procedure or function is passed to the first variable named in the parameter list in the definition, the second to the second, and so on. This is termed 'passing by value'. The parameters declared in the definition are called 'formal parameters' and the values passed in the lines which perform (call) the procedure or function are called 'actual parameters'. There must be as many actual parameters passed as there are formal parameters declared in the definition. You can pass a mix of string and numeric parameters to the same procedure or function and a function can return either a string or numeric value, irrespective of the type of parameters passed to it. However, you must make sure that the parameter types match up. The first example below is correct; the second would give rise to an 'Arguments at line 10' error message and the third would cause a 'Type mismatch at line 10' error to be reported.

Correct

10 PROC_printit(1,"FRED",2)
20 END
30 :
40 DEF PROC_printit(num1,name$,num2)
50 PRINT num1,name$,num2
60 ENDPROC

Arguments Error

10 PROC_printit(1,"FRED",2,4)
20 END
30 :
40 DEF PROC_printit(num1,name$,num2)
50 PRINT num1,name$,num2
60 ENDPROC

Type Mismatch

10 PROC_printit(1,"FRED","JIM")
20 END
30 :
40 DEF PROC_printit(num1,name$,num2)
50 PRINT num1,name$,num2
60 ENDPROC

Local Variables

You can use the statement LOCAL to define variables which are only known locally to individual procedures and functions. In addition, formal parameters are local to the procedure or function declaring them. These variables are only known locally to the defining procedure or function. They are not known to the rest of the program and they can only be changed from within the procedure or function where they are defined. Consequently, you can have two variables of the same name, say FLAG, in various parts of your program, and change the value of one without changing the other.

Declaring variables as local, creates them locally and initialises them to zero/null.

Variables which are not formal variables or declared as LOCAL are known to the whole program, including all the procedures and functions. Such variables are called global.

Re-entrant Functions/Procedures

Because the formal parameters which receive the passed parameters are local, all procedures and functions can be re-entrant. That is, they can call themselves. But for this feature, the short example program below would be very difficult to code. It is the often used example of a factorial number routine. (The factorial of a number n is n * n-1 * n-2 *....* 1. Factorial 6, for instance, is 6*5*4*3*2*1).

 10 REPEAT
 20   INPUT "Enter an INTEGER less than 35 "num
 30 UNTIL INT(num)=num AND num<35
 40 fact=FN_fact_num(num)
 50 PRINT num,fact
 60 END
 70:
 80 DEF FN_fact_num(n)
 90 IF n=1 OR n=0 THEN =1
100 REM Return with 1 if n= 0 or 1
110 =n*FN_fact_num(n-1)
120 REM Else go round again

Since n is the input variable to the function FN_fact_num, it is local to each and every use of the function. The function keeps calling itself until it returns the answer 1. It then works its way back through all the calls until it has completed the final multiplication, when it returns the answer. The limit of 35 on the input number prevents the answer being too big for the computer to handle.


Graphics

Introduction

Whilst the commands for positioning and printing text on the screen are similar to other versions of BASIC (TAB and PRINT), BBC BASIC (Z80) has an extensive range of graphics commands. These commands are similar to those available on a BBC Micro, but different from many other versions of BASIC.

Colours

Dither patterns from colour 0 (black) to 15 (white).

As this version of BBC BASIC only works with a monochrome display, there are only two colours - black and white. However, certain graphics operations that fill regions (such as the rectangle or circle filling operations) can fill using a dithered pattern.

Colours values are in the range 0 to 15. 0 is black and 15 is white; values in-between depend on the drawing operation.

  • For text and traced shapes (eg lines and unfilled circles) colours 0 to 7 are black and colours 8 to 15 are white.
  • For filled shapes (eg filled circles and filled rectangles) the colour specifies a dither pattern.

The text colour can be set with the COLOUR statement and the graphics colour can be set with the GCOL statement.

Colours can be reset to their default values with the VDU 20 command.

The following snippet can be used to set a greyscale palette in BBC BASIC for Windows that mimics the dithered palette in the calculator version.

FOR C%=0 TO 15
  COLOUR C%,C%*16+C%,C%*16+C%,C%*16+C%
NEXT C%

Patterns

You can instruct BBC BASIC to fill shapes using an 8×8 pixel pattern of your own design with the GCOLPAT keyword. This pattern will replace the foreground and background colour in plotting operations that fill shapes - outlined shapes are not affected.

Drawing on the Screen

The Graphics Area

BBC BASIC (Z80) has a logical graphics area (or 'internal' screen) with a size of +32767 to -32768 in both the X and Y axis. The graphics window, the graphics origin and the current graphics cursor position may be anywhere within this graphics area.

The physical screen is a window on the graphics area. Its 'logical' size depends upon the window mode selected and it is much smaller then the graphics area.

By default the graphics origin is in the bottom-left corner of the display with the X axis pointing right and the Y axis pointing up. Coordinates are expressed in logical units rather than physical units. For example, in the default MODE 0 the display has a logical resolution of 384×320, putting the point (192,160) in the centre of the display. The graphics origin can be moved with the VDU 29 command, the scaling of logical units to physical units can be set with the *GSCALE command and the orientation of the Y axis can be changed with the *YAXIS command.

Graphical operations act on a user-definable window. By default this window is the full size of the screen. You may change the size of the graphics window with the VDU 24 command.

More information may be found in the Windows section.

You can move or draw to any point which is within the graphics area whether or not this point is outside the current graphics window. If you draw a line to a point outside the graphics window, the line is not displayed beyond the boundary of the window.

DRAW

You can use the DRAW statement to draw a straight line on the screen. The statement is followed by the X and Y coordinates of the end of the line.

The start of the line is the current graphics cursor position. This is either the end of the last line drawn or a point specified by a MOVE statement.

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

DRAW x,y
MOVE 20,30
DRAW 64,80

The DRAW statement is identical to PLOT 5.

MOVE

You can move the graphics cursor to an absolute position without drawing a line with the MOVE statement.

MOVE X,Y
MOVE 12,32

The MOVE statement is identical to PLOT 4.

PLOT

PLOT is a multi-purpose drawing statement. Typically, three numbers follow the PLOT statement: the first specifies the type of point, line or shape to be drawn; the second and third give the X and Y coordinates to be used.

PLOT mode,X,Y

The available PLOT modes are listed in its keyword reference.

POINT

The POINT function returns a number giving the logical colour of the screen at the coordinates specified. If the point is outside the display, then -1 is returned.

There must not be a space between POINT and the opening bracket.

colour=POINT(X,Y)

See the POINT keyword reference for more information.


Windows

Introduction

BBC BASIC (Z80) writes text to the text window and graphics to the graphics window, rectangular regions that form part (or all) of the screen. An alternative name for a window is a viewport. The text and graphics windows can overlap. By default, the text and graphics windows are as close to the full size of the screen as possible, but the size and position of the windows may be changed.

The text and graphics windows may be restored to their default state with the VDU 26 command.

The CLS command clears the text window to the current text background colour. The CLG command clears the graphics window to the current graphics background colour with the current graphics background plotting action (set by GCOL). If the text and graphics windows overlap, the background colour of the overlapping area will be set by the last clear command issued.

Text Window

The text origin is the top left-hand corner of the current text window. The reference point for defining a text window is also the top left-hand corner of the screen.

Define Text Window

The VDU 28 command defines a text window. The four bytes following the command define the X & Y coordinates of the top-left corner of the window and the X & Y coordinates of the bottom-right corner of the window, in that order. The coordinates are with respect to the screen text origin and are measured in 'character positions'.

If the text cursor is outside the new window, it is moved to the new home position (top left of the window). If it is inside the new window, it is not moved.

If any of the edges of the new text window would be off the screen, they are clipped.

The following example defines a text window with the top-left corner at (0,3) (X across, Y down) and the bottom-right corner at (20,6) (X across, Y down).

VDU 28,0,3,20,6

Clear Text Window

The CLS (or VDU 12) command clears the text window to the current text background colour. If you subsequently change the text background colour, the background of each character cell will be set to the new background colour as the character is printed on the screen. When the screen scrolls, the 'empty' line scrolled onto the screen will have the new background colour.

Graphics Window

The graphics origin is initially the top-left hand corner of the screen. A graphics window is defined with reference to the current graphics origin. The graphics origin may be set with the VDU 29 command as described later.

Define Graphics Window

In the graphics modes, the VDU 24 command defines a graphics window. The four words (pairs of bytes) following the command are the X & Y coordinates of the top-left corner of the window and the X & Y coordinates of the bottom-right corner of the window, in that order. The coordinates are with respect to the current graphics origin.

If any of the edges of the new graphics window would be off the screen, they are clipped. It is particularly easy to select invalid window limits if the graphics origin has been moved. It is advisable, therefore, to precede a VDU 24 command with a VDU 26 command to reset the windows and the graphics origin.

The following example defines a graphics window with the top-left corner at (20,10) (X,Y) and the bottom-right corner at (80,60) (X,Y).

VDU 24,20;10;80;60;

Note the use of semicolons in this VDU command. Their significance is explained under the VDU keyword.

Clear Graphics Window

The CLG (or VDU 16) command clears the graphics window to the current graphics background colour using the current background plotting action (set by GCOL). If you change the graphics background colour, you will probably not notice a change in the graphics background colour until you next clear the graphics window. However, some of the PLOT modes use the current background colour.

Changing the Graphics Origin

In the graphics modes, VDU 29 moves the graphics origin to the coordinates specified by the following two words (pairs of bytes). The first word specifies the X coordinate of the new origin and the second specifies the Y coordinate. Subsequent graphics commands operate with respect to this origin.

The following example sets the graphics origin to the centre of the screen, assuming a width of 96 pixels and a height of 64 pixels:

VDU 29,48;32;

Note the use of semicolons in this VDU command. Their significance is explained under the VDU keyword.

Resetting Text and Graphics Windows

VDU 26 resets the text and graphics windows to their default positions (filling the whole screen), homes the text cursor to the top left of the screen (0,0), resets the graphics origin to the bottom left of the screen (0,0) and homes the graphics cursor to the graphics origin.

Positioning The Cursor

Text Cursor

The text cursor may be positioned within the text window with the TAB(X,Y) command. For example;

PRINT TAB(2,3)"Fred"

will print the word 'Fred' starting at column 2 of row 3. The top left hand corner of the text window is (0,0).

Graphics Cursor

Within the graphics window, the graphics cursor is positioned by the MOVE, DRAW or PLOT commands.

When printing characters at the graphics cursor position, the top left-hand corner of the character cell is positioned at the graphics cursor position.

Homing The Cursor

In VDU 4 mode, VDU 30 homes the text cursor to the top left corner of the text window. In VDU 5 mode, VDU 30 homes the graphics cursor to the top left corner of the graphics window.


Assembler

Introduction

BBC BASIC includes a powerful inline assembler allowing you to include Z80 machine code directly in you BBC BASIC programs. '[' enters assembler mode and ']' exits assembler mode. You can then call assembled Z80 code from BASIC with the CALL or USR keywords.

Statements

An assembly language statement consists of three elements; an optional label, an instruction and an operand. A comment may follow the operand field. The instruction following a label must be separated from it by at least one space. Similarly, the operand must also be separated from the instruction by a space.

Statements are terminated by a colon (:) or end of line.

Labels

Any BBC BASIC (Z80) numeric variable may be used as a label. These (external) labels are defined by an assignment (count=23 for instance). Internal labels are defined by preceding them with a full stop. When the assembler encounters such a label, a BASIC variable is created containing the current value of the Program Counter (P%). (See The Program Counter for more information).

In the example shown later under the heading The Assembly Process, two internal labels are defined and used. Labels have the same rules as standard BBC BASIC (Z80) variable names; they should start with a letter and not start with a keyword.

Comments

You can insert comments into assembly language programs by preceding them with a semi-colon (;) or a back-slash (\). In assembly language, a comment ends at the end of the statement. Thus, the following example will work (but it's a bit untidy).

[;start assembly language program
etc
LD A,C ;In-line comment:POP BC ;start add
JR NZ,loop ;Go back if not finished:RET ;Return
etc
;end assembly language program:]

Language Syntax

All standard Zilog mnemonics are accepted: ADD, ADC and SBC must be followed by A or HL. For example, ADD A,C is accepted but ADD C is not. However, the brackets around the port number in IN and OUT are optional. Thus both OUT (5),A and OUT 5,A are accepted. The instruction IN F,(C) is not accepted, but the equivalent code is produced from IN (HL),C.

Constants

You can store constants within your assembly language program using the define byte (DEFB), define word (DEFW) and define string (DEFM) pseudo-operation commands. These will create 1 byte, 2 byte or string items respectively.

Define Byte - DEFB

DEFB can be used to set one byte of memory to a particular value. For example,

.data DEFB 15
      DEFB 9

will set two consecutive bytes of memory to 15 and 9 (decimal). The address of the first byte will be stored in the variable 'data'.

Define Word - DEFW

DEFW can be used to set two bytes of memory to a particular value. The first byte is set to the least significant byte of the number and the second to the most significant byte. For example,

.data DW &90F

will have the same result as the Define Byte - DEFB example.

Define String - DEFM

DEFM can be used to load a string of ASCII characters into memory. For example,

JP continue; jump round the data
.string DEFM "This is a test message"
DEFB &D
.continue; and continue the process

will load the string 'This is a test message' followed by a carriage-return into memory. The address of the start of the message is loaded into the variable 'string'. This is equivalent to the following program segment:

JP continue;	jump round the data
.string;	leave assembly and load the string
]
$P%="This is a test message" REM starting at P%
P%=P%+LEN($P%)+1 REM adjust P% to next free byte
[
OPT opt; reset OPT
.continue;	and continue the program

Reserving Memory

The Program Counter

Machine code instructions are assembled as if they were going to be placed in memory at the addresses specified by the program counter, P%. Their actual location in memory may be determined by O% depending on the OPTion specified. You must make sure that P% (or O%) is pointing to a free area of memory before your program begins assembly. In addition, you need to reserve the area of memory that your machine code program will use so that it is not overwritten at run time. You can reserve memory by using a special version of the DIM statement or by changing HIMEM or LOMEM.

Using DIM to Reserve Memory

Using the special version of the DIM statement to reserve an area of memory is the simplest way for short programs which do not have to be located at a particular memory address. (See the keyword DIM for more details.) For example,

DIM code 20: REM Note the absence of brackets

will reserve 21 bytes of code (byte 0 to byte 20) and load the variable 'code' with the start address of the reserved area. You can then set P% (or O%) to the start of that area. The example below reserves an area of memory 100 bytes long and sets P% to the first byte of the reserved area.

DIM sort% 99
P%=sort%

Moving HIMEM to Reserve Memory

If you are going to use a machine code program in a number of your BBC BASIC (Z80) programs, the simplest way is to assemble it once, save it using *SAVE and load it from each of your programs using *LOAD. In order for this to work, the machine code program must be loaded into the same address each time. The most convenient way to arrange this is to move HIMEM down by the length of the program and load the machine code program in to this protected area. Theoretically, you could raise LOMEM to provide a similar protected area below your BBC BASIC (Z80) program. However, altering LOMEM destroys all your dynamic variables and is more risky.

Length of Reserved Memory

You must reserve an area of memory which is sufficiently large for your machine code program before you assemble it, but you may have no real idea how long the program will be until after it is assembled. How then can you know how much memory to reserve? Unfortunately, the answer is that you can't. However, you can add to your program to find the length used and then change the memory reserved by the DIM statement to the correct amount.

In the example below, a large amount of memory is initially reserved. To begin with, a single pass is made through the assembly code and the length needed for the code is calculated (lines 100 to 120). After a CLEAR, the correct amount of memory is reserved (line 140) and a further two passes of the assembly code are performed as usual. Your program should not, of course, subsequently try to use variables set before the clear statement. If you use a similar structure to the example and place the program lines which initiate the assembly function at the start of your program, you can place your assembly code anywhere you like and still avoid this problem.

  100 DIM free -1, code HIMEM-free-1000
  110 PROC_ass(0)
  120 L%=P%-code
  130 CLEAR
  140 DIM code L%
  150 PROC_ass(0)
  160 PROC_ass(2)

      - - -
      Put the rest of your program here.
      - - -

 1000 DEF PROC_ass(opt)
10010 P%=code
10020 [OPT opt

      - - -
      Assembler code program.
      - - -

11000 ]
11010 ENDPROC

Initial Setting of the Program Counter

The program counters, P%, and O% are initialised to zero. Using the assembler without first setting P% (and O%) is liable to corrupt BBC BASIC (Z80)'s workspace and possibly result in a crash (see the appendix entitled Format of Program and Variables in Memory).

The Assembly Process

OPT

The only assembly directive is OPT. It controls the way the assembler works, whether a listing is displayed and whether errors are reported. OPT should be followed by a number in the range 0 to 7. The way the assembler functions is controlled by the three bits of this number in the following manner.

Bit 0 - LSB

Bit 0 controls the listing. If it is set, a listing is displayed.

Bit 1

Bit 1 controls the error reporting. If it is set, errors are reported.

Bit 2

Bit 2 controls where the assembled code is placed. If bit 2 is set, code is placed in memory starting at the address specified by O%. However, the program counter (P%) is still used by the assembler for calculating the instruction addresses.

Assembly at a Different Address

In general, machine code will only run properly if it is in memory at the addresses for which it was assembled. Thus, at first glance, the option of assembling it in a different area of memory is of little use. However, using this facility, it is possible to build up a library of machine code utilities for use by a number of programs. The machine code can be assembled for a particular address by one program without any constraints as to its actual location in memory and saved using *SAVE. This code can then be loaded into its working location from a number of different programs using *LOAD.

OPT Summary

Code Assembled Starting at P%

The code is assembled using the program counter (P%) to calculate the instruction addresses and the code is also placed in memory at the address specified by the program counter.

  • OPT 0 reports no errors and gives no listing.
  • OPT 1 reports no errors, but gives a listing.
  • OPT 2 reports errors, but gives no listing.
  • OPT 3 reports errors and gives a listing.

Code Assembled Starting at O%

The code is assembled using the program counter (P%) to calculate the instruction addresses. However, the assembled code is placed in memory at the address specified by O%.

  • OPT 4 reports no errors and gives no listing.
  • OPT 5 reports no errors, but gives a listing.
  • OPT 6 reports errors, but gives no listing.
  • OPT 7 reports errors and gives a listing.

How the Assembler Works

The assembler works line by line through the machine code. When it finds a label declared it generates a BBC BASIC variable with that name and loads it with the current value of the program counter (P%). This is fine all the while labels are declared before they are used. However, labels are often used for forward jumps and no variable with that name would exist when it was first encountered. When this happens, a 'No such variable' error occurs. If error reporting has not been disabled, this error is reported and BBC BASIC (Z80) returns to the direct mode in the normal way. If error reporting has been disabled (OPT 0, 1, 4 or 5), the current value of the program counter is used in place of the address which would have been found in the variable, and assembly continues. By the end of the assembly process the variable will exist (assuming the code is correct), but this is of little use since the assembler cannot 'back track' and correct the errors. However, if a second pass is made through the assembly code, all the labels will exist as variables and errors will not occur.

The example below shows the result of two passes through a (completely futile) demonstration program. Ten bytes of memory are reserved for the program. (If the program was run, it would 'doom-loop' from line 50 to 70 and back again). The program disables error reporting by using OPT 1.

10 DIM code 9
20 FOR opt=1 TO 3 STEP 2
30 P%=code
40 [OPT opt
50 .jim JP fred
60 DEFW &2345
70 .fred JP jim
80 ]
90 NEXT

This is the first pass through the assembly process (note that the 'JP fred' instruction jumps to itself):

C07A              OPT opt
C07A C3 7A C0     .jim JP fred
C07D 45 23        DEFW &2345
C07F C3 7A C0     .fred JP jim

This is the second pass through the assembly process (note that the 'JP fred' instruction now jumps to the correct address):

C07A              OPT opt
C07A C3 7F C0     .jim JP fred
C07D 45 23        DEFW &2345
C07F C3 7A C0     .fred JP jim

Generally, if labels have been used, you must make two passes through the assembly language code to resolve forward references. This can be done using a FOR...NEXT loop. Normally, the first pass should be with OPT 0 (or OPT 4) and the second pass with OPT 2 (OPT 6). If you want a listing, use OPT 3 (OPT 7) for the second pass. During the first pass, a table of variables giving the address of the labels is built. Labels which have not yet been included in the table (forward references) will generate the address of the current op-code. The correct address will be generated during the second pass.

Conditional Assembly and Macros

Introduction

Most machine code assemblers provide conditional assembly and macro facilities. The assembler does not directly offer these facilities, but it is possible to implement them by using other features of BBC BASIC (Z80).

Conditional Assembly

You may wish to write a program which makes use of special facilities and which will be run on different types of computer. The majority of the assembly code will be the same, but some of it will be different. In the example below, different output routines are assembled depending on the value of 'flag'.

DIM code 200
FOR pass=0 TO 3 STEP 3
  [OPT pass
  .start     - - -
             - - - code - - -
                        - - - :]
  :
  IF flag  [OPT  pass: - code for routine 1 -:]
  IF NOT flag [OPT pass: - code for routine 2 - :]
  :
  [OPT pass
  .more_code - - -
             - - - code - - -
                        - - -:]
NEXT

Macros

Within any machine code program it is often necessary to repeat a section of code a number of times and this can become quite tedious. You can avoid this repetition by defining a macro which you use every time you want to include the code. The example below uses a macro to expand a value from 8 bits to 16. Conditional assembly is used within the macro to select a different register depending on the value of op_flag.

It is possible to suppress the listing of the code in a macro by forcing bit 0 of OPT to zero for the duration of the macro code. This can most easily be done by ANDing the value passed to OPT with 6. This is illustrated in PROC_extend_hl and PROC_extend_de in the example below.

DIM code 200
op_flag=TRUE
FOR pass=0 TO 3 STEP 3
  [OPT pass
  .start   - - -
           - - - code - - -
                      - - -
:
  OPT FN_select(op_flag); Include code depending on op_flag
:
           - - -
           - - - code - - -
                      - - -:]
NEXT
END
:
:
REM Include code depending on value of op_flag
:
DEF FN_select(op_flag)
IF op_flag PROC_extend_hl ELSE PROC_extend_de
=pass
REM Return original value of OPT.  This is a
REM bit artificial, but necessary to insert
REM some BBC BASIC (Z80) code in the assembly code.
:
DEF PROC_extend_hl
[OPT pass AND 6
LD L,A
ADD A,A
SBC A,A
LD H,A:]
ENDPROC
:
DEF PROC_extend_de
[OPT pass AND 6
LD E,A
ADD A,A
SBC A,A
LD D,A:]
ENDPROC

The use of a function call to incorporate the code provides a neat way of incorporating the macro within the program and allows parameters to be passed to it. The function should return the original value of OPT.


VDU Emulator

Introduction

On the BBC Microcomputer and Acorn Archimedes the VDU commands perform a number of important actions, primarily involving the screen display and graphics. Although not strictly part of BASIC, most of these commands have been emulated in the TI-83+ port of BBC BASIC (Z80).

The VDU statement takes a list of numeric arguments (constants or variables) and sends their least significant bytes as characters to the currently selected output stream.

A 16 bit value (word) can be sent if the value is followed by a semi-colon. It is sent as a pair of characters, the least significant byte first.

VDU Commands

VDU 0

VDU 0 does absolutely nothing. In other words, it is ignored.

VDU 4

VDU 4 causes text to be written at the text cursor position in the normal way. This is the default mode.

Characters can be positioned only at text coordinates within the text viewport; the text viewport scrolls as necessary. Characters are written using the current text foreground colour on an opaque background of the current text background colour (see COLOUR).

VDU 5

VDU 5 causes text to be written at the graphics cursor position.

Characters may be positioned at any graphics coordinate within the graphics viewport. The top left corner of the character cell is the reference point. Characters are clipped to the limits of the graphics viewport if necessary. No scrolling takes place.

Characters are plotted using the current graphics foreground colour and in the current graphics foreground plotting mode (see GCOL).

The character background is 'transparent', i.e. it does not change what was previously displayed underneath. VDU 127 (DEL) is an exception; it backspaces and deletes just as it does in the normal text mode, using the current background GCOL rules and colour.

VDU 8

VDU 8 moves the text cursor left one character. If the cursor moves outside the text viewport it is moved back to the rightmost column and up a line.

VDU 9

VDU 9 moves the text cursor right one character. If the cursor moves outside the text viewport it is moved back to the leftmost column and down a line.

VDU 10

VDU 10 moves the text cursor down one line. By default, if the cursor was on the bottom line of the text viewport, the viewport scrolls up (except in VDU 5 mode). The cursor is constrained to remain within the text viewport.

VDU 11

VDU 11 moves the text cursor up one line. If the cursor was on the top line of the text viewport, the viewport scrolls down (except in VDU 5 mode). The cursor is constrained to remain within the text viewport.

VDU 12

VDU 12 clears the text viewport to the current text background colour and moves the text cursor the top-left corner of the text viewport; it is identical to CLS.

VDU 13

VDU 13 moves the text cursor to the the left edge of the text viewport.

VDU 14

VDU 14 enables auto-paging mode. In this mode outputting to the console is paused once the text viewport has been filled until the 2nd key is pressed.

VDU 15

VDU 15 disables auto-paging mode. This is the default condition.

VDU 16

VDU 16 clears the graphics viewport using the current background GCOL colour. It does not move the graphics cursor. VDU 16 is identical to CLG.

VDU 17

VDU 17 is identical to COLOUR. The next byte determines the text foreground or background colour.

VDU 18

VDU 18 is identical to GCOL. It takes the next two characters as the plotting mode and graphics colour respectively.

VDU 20

VDU 20 sets the text and graphics foreground and background to their default logical colours and plotting modes. This action is the same as issuing the commands:

COLOUR 0
COLOUR 255
GCOL 0,0
GCOL 0,255

VDU 22

VDU 22 is identical to MODE, except that MODE zeros the value of COUNT whereas VDU 22 does not. The mode is set according to the value of the byte following the VDU 22 command. The example below sets mode 3.

VDU 22,3

VDU 22 also resets all the screen driver variables (colour, palette, viewports, cursor position, graphics origin, etc). In particular, VDU 22 performs the actions of VDU 4, VDU 12, VDU 20 and VDU 26.

See the MODE keyword for further details.

VDU 23

Changing the appearance of the letter 'O'.

VDU 23 can be used to create user-defined characters, show or hide the text cursor or scroll the display.

User-defined characters

Characters from &20 to &FF (32 to 255) may be programmed using the VDU 23 command. User-defined characters can only be used in modes using 8×8 pixel characters - see the MODE statement for more information.

The format of the VDU 23 command is;

VDU 23,char_no,r1,r2,r3,r4,r5,r6,r7,r8

Char_no is the character number to be programmed and r1 to r8 are the values of the bytes which define the character, top to bottom.

You can calculate the eight bytes of data that define the character using a grid similar to the one shown above. For each row in the character, take any pixel that is "on" (black), and add up the corresponding values taken from the column headers. For example, the first, fifth, sixth, seventh and eigth pixel are set in the third row of the ball image above. Adding up the column headers &80+&08+&04+&02+&01 yields a value of &8F for that row.

VDU 23,ASC"O",&3C,&5E,&8F,&DF,&FF,&FF,&7E,&3C

You can reset characters to their original value with the *RESETCHR command.

Text cursor control

The text cursor (caret) may be disabled and enabled using the VDU 23 command as shown below.

VDU 23,1,0;0;0;0; : REM Disable cursor
VDU 23,1,1;0;0;0; : REM Enable cursor

The text cursor is disabled in VDU 5 and is automatically re-enabled when changing MODE.

Scrolling the window

The contents of BASIC's output window (or just the current text viewport) can be scrolled, by one character width or height, using VDU 23,7:

VDU 23,7,m,d,0;0;0;

where m and d are as follows:

  • m = 0 - scroll just the text viewport.
  • m = 1 - scroll BASIC's entire output window.
  • d = 2 - scroll down one row.
  • d = 3 - scroll up one row.

The cursor is not repositioned after the screen has been scrolled.

VDU 24

VDU 24 defines a graphics viewport. The following four words (pairs of bytes) are the X & Y coordinates of the bottom-left corner of the viewport and the X & Y coordinates of the top-right corner of the viewport, in that order. The coordinates are with respect to the current graphics origin.

It is particularly easy to select invalid viewport limits if the graphics origin has been moved. It is advisable, therefore, to precede a VDU 24 command with a VDU 29,0;0; command to reset the graphics origin.

The following example defines a graphics viewport with the bottom left corner at 100,50 and the top right corner at 250,150.

VDU 24,100;50;250;150;
VDU 24,left;bottom;right;top;

Be very careful not to omit the final semicolon.

VDU 25

VDU 25 is identical to the PLOT statement. See the Graphics section or the keyword PLOT for more details.

VDU 25,mode,x_coord;y_coord;

The following example draws a line in the current foreground colour to the point 35,52:

VDU 25,5,35;52;

VDU 26

VDU 26 resets the text and graphics viewports to their default positions (filling the whole screen), homes the text cursor to the top left of the screen (0,0), resets the graphics origin to the top-left of the screen (0,0) and moves the 'current point' to the graphics origin.

VDU 27

VDU 27 sends the next byte to the screen without interpreting it as a control character. It allows graphics characters corresponding to VDU 0 to VDU 31 and VDU 127 to be displayed.

VDU 28

VDU 28 defines a text viewport. The following four bytes are the X & Y coordinates of the bottom-left corner of the viewport and the X & Y coordinates of the top-right corner of the viewport, in that order. The coordinates are with respect to the text origin (top left) and are measured in 'character positions'.

If the text cursor is outside the new viewport, it is moved to the new home position (top-left of the viewport). If it is inside the new viewport, it is not moved.

The following example defines a text viewport with the bottom-left corner at X=0, Y=5 and the top-right corner at X=20, Y=3.

VDU 28,0,5,20,3
VDU 28,left,bottom,right,top

VDU 29

VDU 29 moves the graphics origin to the coordinates specified by the following two words (pairs of bytes). The first word specifies the X coordinate of the new origin and the second specifies the Y coordinate. Subsequent graphics commands operate with respect to this origin.

The following example sets the graphics origin to (48,32):

VDU 29,48;32;

VDU 30

In VDU 4 mode, VDU 30 homes the text cursor to column 0, row 0 (the top-left corner of the text viewport). In VDU 5 mode, VDU 30 homes the graphics cursor to the top-left corner of the graphics viewport.

VDU 31

VDU 31 is identical to PRINT TAB (x,y). It positions the text cursor according to the following two bytes, the first determining the column number and the second the row number. The example below positions the text cursor in column 5 and row 3.

VDU 31,5,3

See the keyword TAB for further details.

VDU 31,col,row

VDU 127

VDU 127 deletes the character to the left of the cursor and backspaces the cursor to this position.


Escape

Escape

Escape is a key pressed to break program execution or cancel text input (for example, when entering program lines with AUTO. It triggers error 17, Escape.

On the TI-83+ or TI-84+ series calculators, the On button is used as the Escape key.

Break

There are some instances where BBC BASIC can appear to go into an infinite loop and this is the only way to remedy it. Take, for example, the following code:

10 ON ERROR PRINT "Whoops"
20 X=1/0

Line 20 triggers an error, so BBC BASIC executes the error handler in line 10. Once it has printed Whoops it carries on to line 20, triggers the error again, then jumps back to 10. You cannot break out of this loop as pressing Escape itself triggers an error!

Holding down the Escape key for roughly five seconds forces BBC BASIC to restart. As it will have started with a NEW program you will need to use the OLD keyword to retrieve the program you were working on.


ABS

A function giving the absolute value of its 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 giving the arc cosine of its argument in radians. 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:

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 mouse, if present. The information returned depends upon the argument passed to ADVAL.

ADVAL positive argument

If the argument is positive, ADVAL returns a value related to the distance that the mouse has been moved.

  • ADVAL(1) returns the distance travelled in the X-direction.
  • ADVAL(2) returns the distance travelled in the Y-direction.
  • ADVAL(3) returns the amount that the scroll-wheel has been rotated.

The value returned corresponds to the total distance travelled in a particular axis since the last time that axis was checked using ADVAL.

The X value increases as the mouse is moved right on a surface; the Y value increases as the mouse is moved up on a surface.

You should poll the mouse using a routine like the following:

mouseX%= 0
mouseY%= 0
REPEAT
  mouseX%= mouseX% + ADVAL(1)
  mouseY%= mouseY% + ADVAL(2)
UNTIL FALSE

ADVAL zero argument

ADVAL(0) returns a value in the range 0 to 7 corresponding to the state of the three mouse buttons. You can check the state of individual buttons using the AND operator.

buttons%= ADVAL(0)
leftPressed%= buttons% AND 1
rightPressed%= buttons% AND 2
middlePressed%= buttons% AND 4

Syntax

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

Associated Keywords

  • INPUT
  • GET/GET$


AND

ANDA.

The operation of integer bitwise logical AND between two items. The 2 operands are internally converted to four byte integers before the AND operation.

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.

210 byte=BGET#infile AND &7F
220 BPUT#outfile,byte

Unfortunately, BBC BASIC does not have true Boolean variables; it uses numeric variables and assigns the value 0 for FALSE and -1 for TRUE. 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>

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.

ASC is the complement of CHR$.

Syntax

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

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 giving the arc tangent of its argument in radians. The permitted range of the argument is from - to + 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


AUTO

A command allowing the user to enter lines without first typing in the number of the line. The line numbers are preceded by the usual prompt (>).

You can use this command to tell the computer to type the line numbers automatically for you when you are entering a program (or part of a program).

If AUTO is used on its own, the line numbers will start at 10 and go up by 10 for each line. However, you can specify the start number and the value by which the line numbers will increment. The step size can be in the range 1 to 255.

You cannot use the AUTO command within a program or a multi-statement command line.

You can leave the AUTO mode by pressing the Escape key.

AUTO | Offers line numbers 10, 20, 30, …
AUTO 100 | Starts at 100 with step 10
AUTO 100,1 | Starts at 100 with step 1
AUTO ,2 | Starts at 10 with step 2

A hyphen is an acceptable alternative to a comma.

Syntax

AUTO [<n-const> [,<n-const>]]


BGET#

BGET#B.#

A function which gets a byte from the file whose file handle 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.

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.

 10 REM Open i/p and o/p files. End if error.
 20 infile=OPENIN "WSFILE.DOC"
 30 IF infile=0 THEN END
 40 outfile=OPENOUT "BROTH.DOC"
 50 IF outfile=0 THEN END
 60 :
 70 REM Process file, converting ^S to ^Y
 80 REPEAT
 90   temp=BGET#infile :REM Read byte
100    IF temp=&13 THEN temp=&19 :REM Convert ^S
110    BPUT#outfile,temp :REM Write byte
120 UNTIL temp=&1A :REM ^Z
130 CLOSE#0 :REM Close all files
140 END

To make the program more useful, it could ask for the names of the input and output files at 'run time':

 10 INPUT "Enter name of INPUT file " infile$
 20 INPUT "Enter name of OUTPUT file " outfile$
 30 REM Open i/p and o/p files. End if error.
 40 infile=OPENIN(infile$)
 50 IF infile=0 THEN END
 60 outfile=OPENOUT(outfile$)
 70 IF outfile=0 THEN END
 80 :
 90 REM Process file, converting ^S to ^Y
100 REPEAT
110    temp=BGET#infile :REM Read byte
120    IF temp=&13 THEN temp=&19 :REM Convert ^S
130    BPUT#outfile,temp :REM Write byte
140 UNTIL temp=&1A :REM ^Z
150 CLOSE#0 :REM Close all files
160 END

Syntax

<n-var>=BGET#<numeric>

Associated Keywords

  • OPENIN
  • OPENUP
  • OPENOUT
  • CLOSE#
  • PRINT#
  • INPUT#
  • BPUT#
  • EXT#
  • PTR#
  • EOF#


BPUT#

BPUT#BP.#

A statement which puts a byte to the data file whose file handle is the first argument. The second argument's least significant byte is written to the file. The file pointer is incremented after the byte has been written.

BPUT#E,32
BPUT#staff_file,A/256
BPUT#4,prn

Before you use this statement you must normally have opened a file for output using OPENOUT or OPENUP.

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.

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 file handle stored in 'fnum'. The integer variable number% contains the value to be written to the file.

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

Syntax

BPUT#<numeric>,<numeric>

Associated Keywords

  • OPENIN
  • OPENUP
  • OPENOUT
  • CLOSE#
  • PRINT#
  • INPUT#
  • BGET#
  • EXT#
  • PTR#
  • EOF#


BY

This is an experimental feature that may change in future versions.
It is provided for compatibility with the Windows version of BBC BASIC and to enhance the code readibility of the Z80 version.

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.

Syntax

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

Associated Keywords

  • DRAW
  • FILL
  • MOVE
  • PLOT


CALL

CALLCA.

A statement to call a machine code subroutine.

CALL Muldiv,A,B,C,D
CALL &FFE3
CALL 12340,A$,M,J$

CALL sets up a table in RAM containing details of the parameters; the processor's IX register is set to the address of this parameter table. The other processor registers are initialised as follows:

  • A is initialised to the least significant byte of A%
  • B is initialised to the least significant byte of B%
  • C is initialised to the least significant byte of C%
  • D is initialised to the least significant byte of D%
  • E is initialised to the least significant byte of E%
  • F is initialised to the least significant byte of F%
  • H is initialised to the least significant byte of H%
  • L is initialised to the least significant byte of L%

The parameter types are:

Code No. | Parameter Type | Example
0 | Byte (8 bits) | ?A%
4 | Word (32 bits) | !A% or A%
5 | Real (40 bits) | A
128 | Fixed string | $A%
129 | Movable string | A$

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

  • Number of parameters 1 byte (at IX+0).
  • Parameter type 1 byte (at IX+1).
  • Parameter address 2 bytes (at IX+2, IX+3, LSB first).
  • Parameter type 1 byte (repeated as often as necessary).
  • Parameter address 2 bytes (repeated often as necessary).

Except in the case of a movable string (normal string variable), the parameter address given is the absolute address at which the item is stored. In the case of movable strings (type 129) it is the address of a 4-byte parameter block containing the current length, the maximum length and the start address of the string (LSB first) in that order.

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

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

Floating point variables are stored in binary floating point format with their least significant byte first; the fifth byte is the exponent. The mantissa is stored as a binary fraction in sign and magnitude format. Bit 7 of the most significant byte is the sign bit and, for the purposes of calculating the magnitude of the number, this bit is assumed to be set to one. The exponent is stored as an integer in excess 127 format (to find the exponent subtract 127 from the value in the fifth byte).

If the exponent byte of a floating point number is zero, the number is an integer stored in integer format in the mantissa bytes. Thus an integer can be represented in two different ways in a real variable. For example the value +5 can be stored as:

05 00 00 00 00 Integer 5
00 00 00 20 82 (0.5 + 0.125) * 2^3

Here is an example assembly program routine that allows you to find the upper bound of an array.

 10 DIM UBOUND 40
 20 P%=UBOUND
 30 [
 40 OPT 0
 50 LD A,(IX+0)
 60 CP 2:RET NZ
 70 LD A,(IX+4)
 80 CP 4:RET NZ
 90 LD L,(IX+2):LD H,(IX+3)
100 DEC HL:LD D,(HL)
110 DEC HL:LD E,(HL)
120 DEC DE
130 LD L,(IX+5):LD H,(IX+6)
140 LD (HL),E:INC HL
150 LD (HL),D:INC HL
160 LD (HL),0:INC HL
170 LD (HL),0
180 RET
190 ]

It expects there to be two arguments - an array element (input) and an integer to receive the upper bound (size). You could then invoke it like this:

DIM array$(12)
CALL UBOUND,array$(0),ub%
PRINT ub%

which would output '12'.

See the Format of Program and Variables in Memory or Assembler sections for more information.

Syntax

CALL <numeric>{,<n-var>|<s-var>}

Associated Keywords

  • USR


CHAIN

CHAINCH.

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 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.

Passing data between CHAINed programs can be a bit of a problem because COMMON variables cannot be declared and 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 100 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.

100 HIMEM=HIMEM-100
110 $HIMEM=in_file$
120 $(HIMEM+13)=out_file$
130 CHAIN "NEXTPROG"

Syntax

CHAIN <str>

Associated Keywords

  • LOAD
  • RUN
  • SAVE


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.

CHR$ is the complement of ASC.

Syntax

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

Associated Keywords

  • ASC
  • STR$
  • VAL
  • VDU


CIRCLE

This is an experimental feature that may change in future versions.
It is provided for compatibility with the Windows version of BBC BASIC and to enhance the code readibility of the Z80 version.

A statement which draws a circle or disc (filled circle). 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. The origin can be changed using the VDU 29 command. See the Graphics 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 100,80,40
CIRCLE FILL 150,60,100

Syntax

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

Associated Keywords

  • ELLIPSE
  • FILL
  • GCOL
  • MOVE
  • PLOT


CLEAR

CLEARCL.

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 and arrays, 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. The easiest way to do this is to move HIMEM down. See CHAIN for an example.

Syntax

CLEAR


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.

GCOL 128 : Set background colour to 0 (white).
CLG      : Clears viewport to white.
GCOL 4,0 : Sets plot mode to invert, foreground colour to white.
CLG      : Inverts the viewport.

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

Syntax

CLG

Associated Keywords

  • CLS
  • GCOL


CLOSE#

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 (Z80) 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 file handles were stored. You can still access the open file if you have used one of the static variables (A% to Z%) to store the file handle. Alternatively, you could reserve an area of memory (by moving HIMEM down for example) and use the byte indirection operator to store the file handle. (See the keyword CHAIN for more details).

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

Syntax

CLOSE#<numeric>

Associated Keywords

  • OPENIN
  • OPENUP
  • OPENOUT
  • PRINT#
  • INPUT#
  • BPUT#
  • BGET#
  • EXT#
  • PTR#
  • EOF#


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 section or COLOUR for more information on text colours.

Syntax

CLS

Associated Keywords

  • CLG
  • COLOUR


COLOUR

COLOURC.

A statement which sets the text foreground and background colour.

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.

See the Graphics section for more information about colours.

Both UK and US English spellings are accepted, but only the UK spelling is LISTed.

Syntax

  • COLOUR <numeric>
  • COLOR <numeric>

Associated Keywords

  • VDU
  • GCOL
  • GCOLPAT
  • 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

COUNTCOU.

A function returning the number of characters sent to the output stream (VDU or printer) 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 20. When the line length is in excess of 20, a new-line is printed.

 90 ...
100 PRINT
110 FOR i=1 TO 1000
120 PRINT words$(i);
130 IF COUNT>20 THEN PRINT
140 NEXT
150 ...

Syntax

<n-var>=COUNT

Associated Keywords

  • POS


DATA

DATAD.

A program object which must precede all lists of data for use by the READ statement.

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


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 ...

In order to make the text more readable (always a good thing) 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 of functions and procedures, refer to the Procedures and Functions sub-section.

Syntax

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

Associated Keywords

  • ENDPROC
  • FN
  • PROC


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

There are two quite different uses for the DIM statement: the first dimensions an array and the second reserves an area of memory for special applications.

Dimensioning Arrays

The DIM statement is used to declare arrays. Arrays must be pre-declared before use and they must not be re-dimensioned. Both numeric and string arrays may be multi dimensional.

DIM A(2),Ab(2,3),A$(2,3,4),A%(3,4,5,6)

After DIM, all elements in the array are 0/null.

The subscript base is 0, so DIM X(12) defines an array of 13 elements.

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)

Reserving an Area of Memory

A DIM statement is used to reserve an area of memory which the interpreter will not then use. The variable in the DIM statement is set by BBC BASIC (Z80) to the start address of this memory area. This reserved area can be used by the indirection operators, machine code, etc.

The example below reserves 68 bytes of memory 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

A 'DIM space' error will occur if a size of less than -1 is used (DIM P% -2). 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. Thus,

DIM P% -1
PRINT HIMEM-P%

is the equivalent of PRINT FREE(0) in some other versions of BASIC. See the Assembler section for a more detailed description of the use of DIM for reserving memory for machine code programs.

Syntax

  • DIM <n-var>|<s-var>(<numeric>{,<numeric>})
  • DIM <n-var> <numeric>

Associated Keywords

  • CLEAR


DIV

A binary operation giving 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 (Z80) converts them to integers by truncation before DIViding them.

Syntax

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

Associated Keywords

  • MOD


DRAW

A statement which draws a line on the screen. 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 start of the line is either the end of the last line drawn or a point specified by a MOVE statement.

The graphics origin (X=0, Y=0) is normally the bottom-left of the screen. The origin can be changed using the VDU 29 command. See the Graphics section for more details.

The line is drawn in the current graphics foreground colour. This colour can be changed using the GCOL 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 [BY] <numeric>,<numeric>

Associated Keywords

  • MODE
  • PLOT
  • MOVE
  • CLG
  • VDU
  • GCOL


ELLIPSE

This is an experimental feature that may change in future versions.
It is provided for compatibility with the Windows version of BBC BASIC and to enhance the code readibility of the Z80 version.

A statement which draws an outline ellipse or filled ellipse. 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.

The graphics origin (X=0, Y=0) is normally the bottom-left of the screen. The origin can be changed using the VDU 29 command. See the Graphics 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,w,h is equivalent to MOVE x,y : PLOT 0,w,0 : PLOT 193,0,h.

ELLIPSE FILL x,y,w,h is equivalent to MOVE x,y : PLOT 0,w,0 : PLOT 201,0,h.

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

ELSEEL.

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 test is FALSE, 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 procedure call. The following example, would print 'Bad' ONLY if x was equal to 3 AND 'a' was not equal to 'b'.

IF x=3 THEN PROC_ab_test
...

...
DEF PROC_ab_test
IF a=b THEN PRINT a$ ELSE PRINT er$
ENDPROC

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> 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


END

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

END tells BBC BASIC (Z80) 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 (Z80) 'running into' any procedure or function definitions at the end of your program.

Syntax

END

Associated Keywords

  • STOP


ENDPROC

A statement denoting the end of a procedure.

All local 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
  • PROC
  • LOCAL


ENDWHILE

This is an experimental feature that may change in future versions.
It is provided for compatibility with the Windows version of BBC BASIC and to enhance the code readibility of the Z80 version.

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


EOF#

A function which will return -1 (TRUE) if the data file whose file handle is the argument is at, or beyond, its end. In other words, when PTR# points beyond the current end of the file. When reading a serial file, EOF# would go true when the last byte of the file had been read.

Writing to a byte beyond the current end of file updates the file length immediately, whether the record is physically written to storage at that time or not. However, the file must be closed in order to ensure that all the data written to it is physically written to storage.

Syntax

<n-var>=EOF#(<numeric>)

Associated Keywords

  • OPENIN
  • OPENUP
  • OPENOUT
  • CLOSE#
  • PRINT#
  • INPUT#
  • BGET#
  • BPUT#
  • EXT#
  • PTR#


EOR

The operation of bitwise integer logical exclusive-or between two items. The two operands are internally converted to 4 byte integers before the EOR operation. EOR will return a non-zero result if the two items are different.

X=B EOR 4
IF A=2 EOR B=3 THEN 110

You can use EOR as a logical operator or as a 'bit-by-bit' (bitwise) operator. The operands can be boolean (logical) or numeric.

Unfortunately, BBC BASIC does not have true Boolean variables; it uses numeric variables and assigns the value 0 for FALSE and -1 for TRUE. This can lead to confusion at times. (See NOT for more details).

In the example below, the operands are Boolean (logical) and the result of the tests (IF) A=2 and (IF) B=3 is either TRUE or FALSE.

The result of this example will be FALSE if A=2 and B=3 or A<>2 and B<>3. In other words, the answer will only be TRUE if the results of the two tests are different.

answer=(A=2 EOR B=3)

The brackets are not necessary, they have been included to make the example easier to follow.

The last example uses EOR in a similar fashion to the numeric operators (+, -, etc).

A=X EOR 11

Suppose X was -20, the EOR operation would be:

11111111 11111111 11111111 11101100
00000000 00000000 00000000 00001011
11111111 11111111 11111111 11100111  = -25

Syntax

<n-var>=<numeric> EOR <numeric>

Associated Keywords

  • NOT
  • AND
  • OR


ERL

A function returning the line number of the line where the last error occurred.

X=ERL

If there was an error in a procedure call, the line number of the calling line would be returned, not the line number of the definition.

The number returned by ERL is the line number printed out when BBC BASIC (Z80) reports an error.

See the Error Handling sub-section for more information on error handling and correction.

Syntax

<n-var>=ERL

Associated Keywords

  • ON ERROR
  • REPORT
  • ERR


ERR

A function returning the error code number of the last error which occurred.

X=ERR

Once you have assumed responsibility for error handling using the ON ERROR statement, you can use this function to discover which error occurred.

See the Error Handling sub-section for more information on error handling and correction.

Syntax

<n-var>=ERR

Associated Keywords

  • ON ERROR
  • ERL
  • REPORT


EVAL

EVALEV.

A function which applies the interpreter's expression evaluation program to the characters held in the argument string.

X=EVAL("X^Q+Y^P")
X=EVAL"A$+B$"
X$=EVAL(A$)

In effect, you pass the string to BBC BASIC (Z80)'s evaluation program and say 'work this out'.

You can use this function to accept and evaluate an expression, such as a mathematical equation, whilst the program is running. You could, for instance, use it in a 'calculator' program to accept and evaluate the calculation you wished to perform. Another use would be in a graph plotting program to accept the mathematical equation you wished to plot.

The example below is a 'bare bones' calculator program which evaluates the expression typed in by the user.

10 PRINT "This program evaluates the expression"
20 PRINT "you type in and prints the answer"
30 REPEAT
40   INPUT "Enter an expression" exp$
50   IF exp$<>"END" PRINT EVAL exp$
60 UNTIL exp$="END"
70 END

You can only use EVAL to work out functions (like SIN, COS, etc). It won't execute statements like MODE 0, PRINT, etc.

Syntax

  • <n-var>=EVAL(<str>)
  • <s-var>=EVAL(<str>)

Associated Keywords

  • STR$
  • VAL


EXIT

This is an experimental feature that may change in future versions.
It is provided for compatibility with the Windows version of BBC BASIC and to enhance the code readibility of the Z80 version.

EXIT FOR causes execution to continue after the matching NEXT statement, EXIT REPEAT causes execution to continue after the matching UNTIL statement and EXIT WHILE causes execution to continue after the matching ENDWHILE statement. Typically you would use EXIT when a situation occurs which necessitates leaving the loop 'part way through':

FOR I% = start% TO finish%
  ...
  IF bool% THEN EXIT FOR
  ...
NEXT I%
REPEAT
  ...
  IF bool% THEN EXIT REPEAT
  ...
UNTIL condition%
WHILE condition%
  ...
  IF bool% THEN EXIT WHILE
  ...
ENDWHILE

You can EXIT from a loop even when inside a nested loop of a different kind:

REPEAT
  FOR J% = first% TO last%
    ...
    IF bool% THEN EXIT REPEAT
    ...
  NEXT
UNTIL FALSE
REM Execution continues here

EXIT is not compatible with the use of non-standard FOR…NEXT constructs such as 'popping' an inner loop or listing multiple loop variables after NEXT. When EXIT is used, every FOR must have a matching NEXT. The following is permitted:

FOR I%=1 TO 3
  FOR J%=4 TO 5
    IF bool% THEN EXIT FOR I%
  NEXT J%
NEXT I%

However, the following are not.

FOR I%=1 TO 3
  FOR J%=4 TO 5
    IF bool% THEN EXIT FOR I%
  NEXT J%,I%
FOR I%=1 TO 3
  FOR J%=4 TO 5
    IF bool% THEN EXIT FOR I%
  NEXT I%

Syntax

  • EXIT FOR [<n-var>]
  • EXIT REPEAT
  • EXIT WHILE

Associated Keywords

  • FOR
  • REPEAT
  • WHILE


EXP

A function returning 'e' to the power of the argument. The argument must be < 88.7228392. The 'natural' number, 'e', is approximately 2.71828183.

Y=EXP(Z)

This function can be used as the 'anti-log' of a natural logarithm. Logarithms are 'traditionally' used for multiplication (by adding the logarithms) and division (by subtracting the logarithms). For example,

10 log1=LN(2.5)
20 log2=LN(2)
30 log3=log1+log2
40 answer=EXP(log3)
50 PRINT answer

will calculate 2.5*2 by adding their natural logarithms and print the answer.

Syntax

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

Associated Keywords

  • LN
  • LOG


EXT#

A function or statement which either get or sets the total length of the file whose file handle is its argument or the total amount of unused RAM.

File Length

In its normal usage, EXT# can be used to get or set the length of a file.

length=EXT#f_num
EXT#f_name=length

The file must have been opened before EXT# can be used to get or set its length.

If you want to write extra data at the end of an existing file, you should open the file with OPENUP and then set the file pointer to the end of the existing data:

PTR#f_num=EXT#f_num

When a file is resized the file pointer is moved to the end of the file if it would have otherwise pointed past the end of the file.

Unused RAM

You can retrieve the amount of unused RAM in bytes by passing -1 to the EXT# function. Unused RAM is RAM outside BBC BASIC's memory map that is not currently being used by the TI-OS.

Syntax

<n-var>=EXT#(<numeric>)

EXT#(<numeric>)=<numeric>

Associated Keywords

  • OPENIN
  • OPENUP
  • OPENOUT
  • CLOSE#
  • PRINT#
  • INPUT#
  • BPUT#
  • BGET#
  • PTR#
  • EOF#


FALSE

FALSEFA.

A function returning the value zero.

 10 flag=FALSE
 20 ...
150 IF flag ...

BBC BASIC (Z80) does not have true Boolean variables. Instead, numeric variables are used and their value is interpreted in a 'logical' manner.

A value of zero is interpreted as FALSE and NOT FALSE (in other words, NOT 0) is interpreted as TRUE. In practice, any value other than zero is considered TRUE.

You can use FALSE in a REPEAT...UNTIL loop to make the loop repeat for ever. Consider the following example.

10 terminator=10
20 REPEAT
30 PRINT "An endless loop"
40 UNTIL terminator=0

Since 'terminator' will never be zero, the result of the test 'terminator=0' will always be FALSE. Thus, the following example has the same effect as the previous one.

10 REPEAT
20 PRINT "An endless loop"
30 UNTIL FALSE

Similarly, since FALSE=0, the following example will also have the same effect, but its meaning is less clear.

10 REPEAT
20 PRINT "An endless loop"
30 UNTIL 0

See the keyword AND for logical tests and their results.

Syntax

<n-var>=FALSE

Associated Keywords

  • TRUE
  • EOR
  • OR
  • AND
  • NOT


FILL

This is an experimental feature that may change in future versions.
It is provided for compatibility with the Windows version of BBC BASIC and to enhance the code readibility of the Z80 version.

A statement which performs a 'flood fill' in the current graphics foreground colour, starting at the specified point and continuing until non-background-colour pixels are found. FILL is followed by the X and Y coordinates of the starting point; the optional qualifier BY indicates that the coordinates are relative (offsets from the current graphics cursor position) rather than absolute.

FILL x,y is equivalent to PLOT 133,x,y. FILL BY x,y is equivalent to PLOT 129,x,y.

FILL is also used with the CIRCLE, ELLIPSE and RECTANGLE statements to indicate that a filled (solid) shape should be drawn.

FILL 400,400

Syntax

  • FILL <numeric>,<numeric>
  • FILL BY <numeric>,<numeric>
  • CIRCLE FILL <numeric>,<numeric>,<numeric>
  • ELLIPSE FILL <numeric>,<numeric>,<numeric>,<numeric>
  • RECTANGLE FILL <numeric>,<numeric>,<numeric>,<numeric>

Associated Keywords

  • BY
  • CIRCLE
  • ELLIPSE
  • GCOL
  • RECTANGLE


FN

A keyword used at the start of all user declared functions. The first character of the function name can be an underline (or a number).

If there are spaces between the function name and the opening bracket of the parameter list (if any) they must be present both in the definition and the call. It's safer not to have spaces between the function name and the opening bracket.

A function may be defined with any number of parameters of any type, and may return (using =) a string or numeric result. It does not have to be defined before it is used.

A function definition is terminated by '=' used in the statement position.

The following examples show the '=' as part of a program line and at the start of a line. The first two examples are single line function definitions.

DEF FN_mean(Q1,Q2,Q3,Q4)=(Q1+Q2+Q3+Q4)/4
DEF FN_fact(N) IF N<2 =1 ELSE =N*FN_fact(N-1)
DEF FN_reverse(A$)
LOCAL B$,Z%
FOR Z%=1 TO LEN(A$)
  B$=MID$(A$,Z%,1)+B$
NEXT
=B$

Functions are re-entrant and the parameters (arguments) are passed by value.

You can write single line, multi statement functions so long as you have a colon after the definition statement.

The following function sets the print control variable to the parameter passed and returns a null string. It may be used in a PRINT command to change the print control variable (@%) within a print list.

DEF FN_pformat(N):@%=N:=""

Functions have to return an answer, but the value returned by this function is a null string. Consequently, its only effect is to change the print control variable. Thus the PRINT statement

PRINT FN_pformat(&90A) X FN_pformat(&2020A) Y

will print X in G9z10 format and Y in F2z10 format. See the keyword PRINT for print format details.

Syntax

  • <n-var>|<s-var>=FN<name>[(<exp>{,<exp>})]
  • DEF FN<name>[(<n-var>|<s-var>{,<n-var>|<s-var>})]

Associated Keywords

  • DEF
  • ENDPROC
  • PROC
  • LOCAL


FOR

FORF.

A statement initialising a FOR…NEXT loop. The loop is executed at least once.

FOR temperature%=0 TO 9
FOR A(2,3,1)=9 TO 1 STEP -0.3

The FOR…NEXT loop is a way of repeating a section of program a set number of times. For example, the two programs below perform identically, but the second is easier to understand.

10 start=4: end=20: step=2
20 counter=start
30 PRINT counter," ",counter^2
40 counter=counter+step
50 IF counter<=end THEN 30
60 ...
10 start=4: end=20: step=2
20 FOR counter=start TO end STEP step
30   PRINT counter," ",counter^2
40 NEXT
50 ...

You can GOTO anywhere within one FOR…NEXT loop, but not outside it. This means you can't exit the loop with a GOTO. You can force a premature end to the loop with EXIT FOR or by setting the control variable to a value equal to or greater than the end value (assuming a positive STEP).

110 FOR I=1 TO 20
120   X=A^I
130   IF X>1000 THEN I=20: GOTO 150
140   PRINT I,X
150 NEXT

It is not necessary to declare the loop variable as an integer type in order to take advantage of fast integer arithmetic. If it is an integer, then fast integer arithmetic is used automatically.

Because a single stack is used, you cannot use a FOR…NEXT loop to set array elements to LOCAL in a procedure or function.

Syntax

FOR <n-var>=<numeric> TO <numeric> [STEP <numeric>]

Associated Keywords

  • TO
  • STEP
  • NEXT
  • EXIT


GCOL

Dither patterns from colour 0 (black) to 15 (white).

GCOL sets the graphics foreground or background colour, as well as specifying how the colour is to be plotted on the screen. It can be plotted directly, ANDed, ORed or Exclusive-ORed with the colour already there, or the existing colour can be inverted.

The first value passed to GCOL determines the plotting mode and the second the graphics foreground or background colour. The plotting modes are as follows:

Code | Operation
0 | Plot the colour specified.
1 | OR the specified colour with the colour that is already there.
2 | AND the specified colour with the colour that is already there.
3 | Exclusive-OR the specified colour with the colour that is already there.
4 | Invert the colour that is already there.

The second value determines the colour. If the value is less than 128, the graphics foreground colour is set to that value. If the number is 128 or greater, the graphics background colour is set to value-128.

If GCOL is only followed by a single value then the foreground or background colour is set and the plot mode is reset to 0, plot.

GCOL 1,64 : REM Set plot mode to OR, foreground colour to 64.
GCOL 255  : REM Set plot mode to plot, background colour to 127.

Generally, you will not notice a change in the graphics background colour until you clear the graphics screen with a CLG command.

GCOL disables any fill pattern set by the GCOLPAT statement.

Syntax

GCOL [<numeric>,]<numeric>

Associated Keywords

  • CLS
  • CLG
  • MODE
  • COLOUR
  • GCOLPAT
  • PLOT


GCOLPAT

Using GCOLPAT to define custom fill patterns.

This statement allows you to define a custom 8×8 pixel pattern that is used in place of the standard dither patterns when a shape is filled. You must use DIM to allocate 8 bytes of memory to store the pattern then pass the address of the memory to the GCOLPAT statement.

The pattern is anchored to the top-left hand corner of the screen, not the graphics viewport.

Graphics operations that are affected include:

  • Clearing the screen (CLG).
  • Filled rectangles (PLOT modes 96-103).
  • Flood-filled regions (PLOT modes 128-143).
  • Filled circles (PLOT modes 152-159).
  • Filled ellipses (PLOT modes 200-207).

The specified pattern replaces the foreground and background colour in fill operations. However, certain plotting operations that rely on a background or foreground colour (such as the flood-filling boundaries) will continue to use the colour values previously set with GCOL.

GCOLPAT does not copy the pattern data, it merely keeps track of the address you passed it. This means that you can modify the pattern memory between plotting operations without invoking GCOLPAT again.

The image above was created with the following code:

 10 DIM pattern 7
 20 GCOLPAT pattern
 30 pattern?0=&F8
 40 pattern?1=&74
 50 pattern?2=&22
 60 pattern?3=&47
 70 pattern?4=&8F
 80 pattern?5=&17
 90 pattern?6=&22
100 pattern?7=&71
110 CLG
120 pattern?0=&77
130 pattern?1=&89
140 pattern?2=&8F
150 pattern?3=&8F
160 pattern?4=&77
170 pattern?5=&98
180 pattern?6=&F8
190 pattern?7=&F8
200 MOVE 48,32
210 PLOT 153,24,0
220 MOVE 48,32
230 PLOT 145,24,0
240 REPEAT:UNTIL INKEY(0)<>-1

Passing FALSE or 0 to GCOLPAT reverts to using the dither pattern set by GCOL. Setting a new foreground or background colour with GCOL will also disable your custom fill pattern.

Syntax

  • GCOLPAT <numeric>
  • GCOLPAT FALSE

Associated Keywords

  • GCOL
  • COLOUR
  • PLOT


GET

Keyboard Input

A function and compatible string function that reads the next character from the keyboard buffer (it waits for the character).

N=GET
N$=GET$

GET and GET$ wait for a 'key' (character) to be present in the keyboard buffer and then return the ASCII number of the key or a string containing the character of the key. If there are any characters in the keyboard buffer when a GET is issued, then a character will be returned immediately. See the keyword INKEY for a way of emptying the keyboard buffer before issuing a GET.

GET and GET$ do not echo the pressed key to the screen. If you want to display the character for the pressed key, you must PRINT it.

You can use GET and GET$ whenever you want your program to wait for a reply before continuing. For example, you may wish to display several screens of instructions and allow the user to decide when he has read each screen.

REM First screen of instructions
CLS
PRINT ...
PRINT ...
PRINT "Press any key to continue ";
temp=GET
REM Second screen of instructions
CLS
PRINT ... etc

I/O Port Input

GET can also be used to input data from an I/O port.

N=GET(X) : REM input from port X

Syntax

  • <n-var>=GET
  • <n-var>=GET(<numeric>)
  • <s-var>=GET$

Associated Keywords

  • INKEY/INKEY$
  • PUT


GOSUB

A statement which calls a section of a program (which is a subroutine) at a specified line number. One subroutine may call another subroutine (or itself).

GOSUB 400
GOSUB (4*answer+6)

The only limit placed on the depth of nesting is the room available for the stack.

You may calculate the line number. However, if you do, the program should not be RENUMBERed. A calculated value must be placed in parentheses.

Very often you need to use the same group of program instructions at several different places within your program. It is tedious and wasteful to repeat this group of instructions every time you wish to use them. You can separate this group of instructions into a small sub-program. This sub-program is called a subroutine. The subroutine can be 'called' by the main program every time it is needed by using the GOSUB statement. At the end of the subroutine, the RETURN statement causes the program to return to the statement after the GOSUB statement.

Subroutines are similar to PROCedures, but they are called by line number not by name. This can make the program difficult to read because you have no idea what the subroutine does until you have followed it through. You will probably find that PROCedures offer you all the facilities of subroutines and, by choosing their names carefully, you can make your programs much more readable.

Syntax

  • GOSUB <l-num>
  • GOSUB (<numeric>)

Associated Keywords

  • RETURN
  • ON
  • PROC


GOTO

GOTOG.

A statement which transfers program control to a line with a specified or calculated line number.

GOTO 100
GOTO (X*10)

You may not GOTO a line which is outside the current FOR...NEXT, REPEAT...UNTIL or GOSUB loop.

If a calculated value is used, the program should not be RENUMBERed. A calculated value must be placed in parentheses.

The GOTO statement makes BBC BASIC (Z80) jump to a specified line number rather than continuing with the next statement in the program.

You should use GOTO with care. Uninhibited use will make your programs almost impossible to understand (and hence, debug). If you use REPEAT...UNTIL and FOR...NEXT loops you will not need to use many GOTO statements.

Syntax

  • GOTO <l-num>
  • GOTO (<numeric>)

Associated Keywords

  • GOSUB
  • ON


HIMEM

A pseudo-variable which contains the address of the first byte that BBC BASIC (Z80) will not use.

HIMEM must not be changed within a subroutine, procedure, function, FOR...NEXT, REPEAT...UNTIL or GOSUB loop.

HIMEM=HIMEM-40

BBC BASIC (Z80) uses the calculator's memory to store your program and the variables that your program uses. When BBC BASIC is first loaded and run it checks to find the highest memory address it can use.

If you want to use a machine code subroutine or store some data for use by a CHAINed program, you can move HIMEM down. This protects the area above HIMEM from being overwritten by BBC BASIC (Z80). See the Assembler section and the keyword CHAIN for details.

If you want to change HIMEM, you should do so early in your program. Once it has been changed it will stay at its new value until set to another value. Thus, if you wish to load a machine code subroutine for use by several programs, you only have to change HIMEM and load the subroutine once.

HIMEM must not be raised above its initial value. Memory above HIMEM is used to store TI-OS user variables and moving HIMEM into this region will cause BBC BASIC to corrupt them.

If you wish to increase HIMEM to give more memory to BBC BASIC or decrease HIMEM to give memory to the TI-OS for the creation of new variables use the *HIMEM star command instead.

USE WITH CARE.

Syntax

  • HIMEM=<numeric>
  • <n-var>=HIMEM

Associated Keywords

  • *HIMEM
  • LOMEM
  • PAGE
  • TOP


IF

A statement which sets up a test condition which can be used to control the subsequent flow of the program. It is part of the IF...THEN....ELSE structure.

IF length=5 THEN 110
IF A<C OR A>D GOTO 110
IF A>C AND C>=D THEN GOTO 110 ELSE PRINT "BBC"
IF A>Q PRINT"IT IS GREATER":A=1:GOTO 120

The word THEN is optional under most circumstances.

The IF statement is the primary decision making statement. The testable condition (A=B, etc) is evaluated and the answer is either TRUE or FALSE. If the answer is TRUE, the rest of the line (up to the ELSE clause if there is one) is executed.

The '=' sign has two meanings. It can be used to assign a value to a variable or as part of a test. The example shows the two uses in one program line.

A=B=C

In English this reads "A becomes equal to the result of the test B=C". Thus if B does equal C, A will be set to TRUE (-1). However, if B does not equal C, A will be set to FALSE (0). The example below is similar, but A will be set to TRUE (-1) if 'age' is less than 21.

A=age<21

Since the IF statement evaluates the testable condition and acts on the result, you can use a previously set variable name in place of the test.

The two examples below will print 'Under 21' if the value of 'age' is less than 21.

IF age<21 THEN PRINT "Under 21"
flag=age<21
IF flag THEN PRINT "Under 21"

Syntax

  • IF <t-cond> THEN <stmt>{:<stmt>} [ELSE <stmt>{:<stmt>}]
  • IF <exp> THEN <stmt>{:<stmt>} [ELSE <stmt>{:<stmt>}]
  • IF <t-cond> GOTO <l-num> [ELSE <l-num>]
  • IF <exp> GOTO <l-num> [ELSE <l-num>]
  • IF <t-cond> THEN <l-num> [ELSE <l-num>]
  • IF <exp> THEN <l-num> [ELSE <l-num>]

Associated Keywords

  • THEN
  • ELSE


INKEY

A function and compatible string function which does a GET/GET$, but waits for a specified maximum time rather than indefinitely. INKEY can also be used to test the current state of a specific key (pressed or not pressed).

INKEY or INKEY$ is followed by a numeric argument. If this is zero or positive it indicates the maximum time to wait for a keypress (in units of 10ms). If it is negative it indicates which key should be tested.

INKEY positive or zero argument

INKEY/INKEY$ waits for the specified maximum number of clock ticks of 10ms each. If no key is pressed in the time limit, INKEY will return -1 and INKEY$ will return a null (empty) string. If there is one or more characters waiting in the keyboard buffer, INKEY/INKEY$ will behave exactly the same as GET/GET$. If the specified time limit is zero, INKEY/INKEY$ will return immediately.

The INKEY function returns the ASCII value of the key pressed. The INKEY$ function returns a string (length=1) containing the character corresponding to the key pressed.

key=INKEY(num)
N=INKEY(0)
N$=INKEY$(100)

INKEY can be used to 'empty' the keyboard buffer. You can do this with the following program line:

REPEAT UNTIL INKEY(0)=-1

INKEY negative argument

If INKEY is followed by a negative argument, the state of a particular key is tested. If the key is currently pressed INKEY will return the value -1 (TRUE); if the key is not pressed INKEY will return the value 0 (FALSE).

The numeric values corresponding to the different keys are as follows (note that these values are as compatible as possible with the BBC Micro and the Acorn Archimedes, allowing for the differences between their keyboards and the PC's keyboard).

IF INKEY(-74) PRINT "Enter pressed"

INKEY(-256)

INKEY(-256) is a special case that can be used to identify the hardware. It will return &83 for a TI-83+(SE) and &84 for a TI-84+(SE).

Syntax

  • <n-var>=INKEY(<numeric>)
  • <s-var>=INKEY$(<numeric>)

Associated Keywords

  • GET
  • GET$


INPUT

A statement to input values from the console input channel (usually keyboard).

INPUT A,B,C,D$,"WHO ARE YOU",W$,"NAME"R$

If items are not immediately preceded by a printable prompt string (even if null) then a '?' will be printed as a prompt. If the variable is not separated from the prompt string by a comma, the '?' is not printed. In other words: no comma - no question mark.

Items A, B, C, D$ in the above example can have their answers returned on one to four lines, separate items being separated by commas. Extra items will be ignored.

Then WHO ARE YOU? is printed (the question mark comes from the comma) and W$ is input, then NAME is printed and R$ is input (no comma - no '? ').

When the Enter key is pressed to complete an entry, a new-line is generated. BBC BASIC has no facility for suppressing this new-line, but the TAB function can be used to reposition the cursor. For example,

INPUT TAB(0,5) "Name ? " N$,TAB(20,5) "Age ? " A

will position the cursor at column 0 of line 5 and print the prompt Name ?. After the name has been entered the cursor will be positioned at column 20 on the same line and Age ? will be printed. When the age has been entered the cursor will move to the next line.

The statement

INPUT A

is exactly equivalent to

INPUT A$: A=VAL(A$)

Leading spaces will be removed from the input line, but not trailing spaces. If the input string is not completely numeric, it will make the best it can of what it is given. If the first character is not numeric, 0 will be returned. Neither of these two cases will produce an error indication. Consequently, your program will not abort back to the command mode if a bad number is input. You may use the EVAL function to convert a string input to a numeric and report an error if the string is not a proper number or you can include your own validation checks.

INPUT A$
A=EVAL(A$)

Strings in quoted form are taken as they are, with a possible error occurring for a missing closing quote.

A semicolon following a prompt string is an acceptable alternative to a comma.

Syntax

INPUT [TAB(X[,Y])][SPC(<numeric>)]['][<s-const>[,|;]]<n-var>|<s-var>{,<n-var>|<s-var>}

Associated Keywords

  • INPUT LINE
  • INPUT#
  • GET
  • INKEY


INPUT#

A statement which reads data in internal format from a file and puts them in the specified variables. INPUT# is normally used with a file or device opened with OPENIN, OPENUP or OPENOUT.

INPUT #E,A,B,C,D$,E$,F$

It is possible to read past the end-of-file without an error being reported. You should always include some form of check for the end of the file.

READ# can be used as an alternative to INPUT#.

See the Files section for more details and numerous examples of the use of INPUT#.

Syntax

INPUT #<numeric>,<n-var>|<s-var>{,<n-var>|<s-var>}

Associated Keywords

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


INPUT LINE

A statement of identical syntax to INPUT which uses a new line for each item to be input. The item input is taken as is, including commas, quotes and leading spaces.

INPUT LINE A$

Syntax

INPUT LINE[TAB(X[,Y])][SPC(<numeric>)]['][<s-const>[,|;]]<s-var>{,<s-var>}

Associated Keywords

  • INPUT


INSTR

A function which returns the position of a sub-string within a string, optionally starting the search at a specified place in the string. The leftmost character position is 1. If the sub-string is not found, 0 is returned.

The first string is searched for any occurrence of the second string.

There must not be any spaces between INSTR and the opening bracket.

X=INSTR(A$,B$)
position=INSTR(word$,guess$)
Y=INSTR(A$,B$,Z%) :REM START AT POSITION Z%

You can use this function for validation purposes. If you wished to test A$ to see if was one of the set FRED BERT JIM JOHN, you could use the following:

set$="FRED BERT JIM JOHN"
IF INSTR(set$,A$) PROC_valid ELSE PROC_invalid

The character used to separate the items in the set must be excluded from the characters possible in A$. One way to do this is to make the separator an unusual character, say CHR$(127).

z$=CHR$(127)
set$="FRED"+z$+"BERT"+z$+"JIM"+z$+"JOHN"

Syntax

<n-var>=INSTR(<str>,<str>[,<numeric>])

Associated Keywords

  • LEFT$
  • MID$
  • RIGHT$
  • LEN


INT

Introduction

A function truncating a real number to the lower integer.

X=INT(Y)
Example | Result
INT(99.8) | 99
INT(-12) | -12
INT(-12.1) | -13

This function converts a real number (one with a decimal part) to the nearest integer (whole number) less than the number supplied. Thus,

INT(14.56)

gives 14, whereas

INT(-14.5)

gives -15.

Alternative Rounding Methods

This type of rounding (or truncation) is known as rounding towards negative infinity and is often implemented by the floor function.

DEF FN_floor(n)=INT(n)

Rounding in the opposite direction, towards positive infinity, is often implemented by the ceiling function and can be implemented in BBC BASIC using the following function:

DEF FN_ceiling(n)=-INT(-n)

Another common type of truncation is rounding towards zero. This has the effect of removing the fractional part of the number and leaving the whole part intact, so +3.14 and -6.28 would end up as 3 and -6 respectively. A BBC BASIC function implementation could be implemented as follows:

DEF FN_truncate(n)=SGN(n)*INT(ABS(n))

You may also wish to round to the nearest whole integer.

DEF FN_round(n) LOCAL m : m=ABS(n) : IF m-INT(m)<0.5 =SGN(n)*INT(m) ELSE =SGN(n)*-INT(-m)

FN_round(2.3) returns 2, FN_round(5.8) returns 6, FN_round(-12.1) returns -12 and FN_round(-3.6) returns -4.

Syntax

<n-var>=INT<numeric>


LEFT$

A string function which returns the left 'num' characters of the string. If there are insufficient characters in the source string, all the characters are returned.

There must not be any spaces between LEFT$ and the opening bracket.

newstring$=LEFT$(A$,num)
A$=LEFT$(A$,2)
A$=LEFT$(RIGHT$(A$,3),2)

For example,

10 name$="BBCBASIC(Z80)"
20 FOR i=3 TO 14
30   PRINT LEFT$(name$,i)
40 NEXT
50 END

would print

BBC
BBCB
BBCBA
BBCBAS
BBCBASI
BBCBASIC
BBCBASIC(
BBCBASIC(Z
BBCBASIC(Z8
BBCBASIC(Z80
BBCBASIC(Z80)
BBCBASIC(Z80)

Syntax

<s-var>=LEFT$(<str>,<numeric>)

Associated Keywords

  • RIGHT$
  • MID$
  • LEN
  • INSTR


LEN

A function which returns the length of the argument string.

X=LEN"fred"
X=LENA$
X=LEN(A$+B$)

This function 'counts' the number of characters in a string. For example,

length=LEN("BBCBASIC(Z80)   ")

would set 'length' to 16 since the string consists of the 13 characters of BBCBASIC(Z80) followed by three spaces.

LEN is often used with a FOR...NEXT loop to 'work down' a string doing something with each letter in the string. For example, the following program looks at each character in a string and checks that it is a valid hexadecimal numeric character.

 10 valid$="0123456789ABCDEF"
 20 REPEAT
 30   INPUT "Type in a HEX number" hex$
 40   flag=TRUE
 50   FOR i=1 TO LEN(hex$)
 60     IF INSTR(valid$,MID$(hex$,i,1))=0 flag=FALSE
 80   NEXT
 90   IF NOT flag THEN PRINT "Bad HEX"
100 UNTIL flag

Syntax

<n-var>=LEN(<str>)

Associated Keywords

  • LEFT$
  • MID$
  • RIGHT$
  • INSTR


LET

A statement indicating an assignment to a string or numeric variable (or an array element or structure member). LET can normally be omitted, and must be omitted in the case of assignment to the pseudo-variables LOMEM, HIMEM, PAGE, PTR# and TIME.

LET was mandatory in early versions of BASIC. Its use emphasised that when we write

X=X+4

we don't mean to state that X equals X+4 - it can't be, but rather 'let X become equal to what it was plus 4':

LET X=X+4

Most modern versions of BASIC allow you to drop the LET statement. However, if you are writing a program for a novice, the use of LET makes it more understandable.

Syntax

[LET] <var>=<exp>


LIST

LISTL.

A command which causes lines of the current program to be listed out to the console with the automatic formatting options specified by LISTO.

LIST | Lists the entire program.
LIST ,111 | Lists up to line 111.
LIST 111, | Lists from line 111 to the end.
LIST 111,222 | Lists lines 111 to 222 inclusive.
LIST 100 | Lists line 100 only.

A hyphen is an acceptable alternative to a comma.

Escape will abort the listing.

LIST may be included within a program, but it will exit to the command mode on completion of the listing.

Syntax

  • LIST
  • LIST <n-const>
  • LIST <n-const>,
  • LIST ,<n-const>
  • LIST <n-const>,<n-const>

Associated Keywords

  • LIST IF
  • LISTO
  • OLD
  • NEW


LIST IF

Introduction

A command which causes lines of the current program which contain the specified string to be listed to the console.

LIST IF *FX
LIST IF Please press <ENTER> to continue

You can specify the range of line numbers to be listed in a similar manner to LIST. For example,

LIST 100,2500 IF DEF

Will list all the lines between 100 and 2500 which contain the keyword DEF.

Keywords are tokenised before the search begins. Consequently, you can use LIST IF to find lines with particular commands in them.

LIST IF PROC
LIST IF DEF

LIST IF is very useful for locating the lines in a program which define or use functions or procedures.

Limitations

Because keywords are tokenised wherever they occur in the command line, you cannot use LIST IF to search for a string (including a star command) which contains a keyword. For example, the following will not work:

LIST IF *LOAD
LIST IF DO YOU WANT TO PRINT THE RESULTS?

You cannot search for the 'left' form of those pseudo-variables which have two forms (PTR#=, PAGE=, TIME=, TIME=, LOMEM=, HIMEM=) because the 'right' form is assumed when the name is tokenised. Consequently,

LIST IF TIME

will find line 20 but not line 10 in the following program segment

10 TIME=20
20 now=TIME

You cannot search for 'keywords' which are not tokenised in the context of the program. For example,

LIST IF LOAD

will not list lines containing

ZLOAD=1
PROCLOAD
FNLOAD
"LOAD"
REM LOAD

because LOAD is not tokenised in any of these lines.

The internal format of line numbers (GOTO 1000, for example) may spuriously match a search string of three characters or less.

Syntax

  • LIST IF <string>
  • LIST <n-const> IF <string>
  • LIST <n-const>, IF <string>
  • LIST ,<n-const> IF <string>
  • LIST <n-const>,<n-const> IF <string>

Associated Keywords

  • LIST
  • OLD
  • NEW


LISTO

Introduction

A command which controls the appearance of a LISTed program. The command controls the setting of the three least significant bits of the format control byte which can, therefore, be set to an integer 0 to 7 (0 for all three bits 0, 7 for all three bits 1).

Bit Settings

Bit | Function
0 | If Bit 0 is set, a space will be printed between the line number and the remainder of the line. (All leading spaces are stripped when the line is originally entered).
1 | If Bit 1 is set, two extra spaces will be printed out on lines between FOR and NEXT. Two extra spaces will be printed for each depth of nesting.
2 | If Bit 2 is set two extra spaces will be printed out on lines between REPEAT and UNTIL. Two extra spaces will be printed for each depth of nesting.

The default setting of LISTO is 7. This will give a properly formatted listing. The indentation of the FOR...NEXT and REPEAT...UNTIL lines is done in the correct manner, in that the NEXT is aligned with the FOR and the REPEAT with the UNTIL.

LISTO 7

will give

 10 A=20
 20 TEST$="FRED"
 30 FOR I=1 TO A
 40   Z=2^I
 50   PRINT I,Z
 60   REPEAT
 70     PRINT TEST$
 80     TEST$=LEFT$(TEST$,LEN(TEST$)-1)
 90   UNTIL LEN(TEST$)=0
100 NEXT
110 END

at the other extreme

LISTO 0

will give

 10A=20
 20TEST$="FRED"
 30FOR I=1 TO A
 40Z=2^I
 50PRINT I,Z
 60REPEAT
 70PRINT TEST$
 80TEST$=LEFT$(TEST$,LEN(TEST$)-1)
 90UNTIL LEN(TEST$)=0
100NEXT
110END

and

LISTO 2

will give

 10A=20
 20TEST$="FRED"
 30FOR I=1 TO A
 40  Z=2^Z
 50  PRINT I,Z
 60  REPEAT
 70  PRINT TEST$
 80  TEST$=LEFT$(TEST$,LEN(TEST$)-1)
 90  UNTIL LEN(TEST$)=0
100NEXT
110END

Syntax

LISTO <n-const>

Associated Keywords

  • LIST


LN

A function giving the natural logarithm of its argument.

X=LN(Y)

This function gives the logarithm to the base 'e' of its argument. The 'natural' number, 'e', is approximately 2.71828183.

Logarithms are 'traditionally' used for multiplication (by adding the logarithms) and division (by subtracting the logarithms). For example,

10 log1=LN(2.5)
20 log2=LN(2)
30 log3=log1+log2
40 answer=EXP(log3)
50 PRINT answer

will calculate 2.5*2 by adding their natural logarithms and print the answer.

Syntax

<n-var>=LN<numeric>

Associated Keywords

  • LOG
  • EXP


LOAD

LOADLO.

A command which loads a new program from a file and CLEARs the variables of the old program. The program file must be in 'internal' (tokenised) format.

LOAD "PROG1"
LOAD A$

You use LOAD to bring a program in a disk file into memory. The keyword LOAD should be followed by the name of the program file.

Syntax

LOAD <str>

Associated Keywords

  • SAVE
  • CHAIN


LOCAL

A statement to declare variables for local use inside a function (FN) or procedure (PROC). A null list of variables is not permitted.

LOCAL A$,X,Y%

LOCAL saves the values of its arguments in such a way that they will be restored at '=' or ENDPROC.

If a function or a procedure is used recursively, the LOCAL variables will be preserved at each level.

The LOCAL variables are initialised to zero/null.

Syntax

LOCAL <n-var>|<s-var>{,<n-var>|<s-var>}

Associated Keywords

  • DEF
  • ENDPROC
  • FN
  • PROC


LOG

A function giving the base-10 logarithm of its argument.

X = LOG(Y)

This function calculates the common (base 10) logarithm of its argument. Inverse logarithms (anti-logs) can be calculated by raising 10 to the power of the logarithm. For example, if x=LOG(y) then y=10<sup>x</sup>.

Logarithms are 'traditionally' used for multiplication (by adding the logarithms) and division (by subtracting the logarithms). For example,

10 log1=LOG(2.5)
20 log2=LOG(2)
30 log3=log1+log2
40 answer=10^log3
50 PRINT answer

Syntax

<n-var>=LOG<numeric>

Associated Keywords

  • LN
  • EXP


LOMEM

A pseudo-variable which controls where in memory the dynamic data structures are to be placed. The default is TOP, the first free address after the end of the program.

LOMEM=LOMEM+100
PRINT ~LOMEM :REM The ~ makes it print in HEX.

Normally, dynamic variables are stored in memory immediately after your program. (See the appendix entitled Format of Program and Variables in Memory). You can change the address where BBC BASIC (Z80) starts to store these variables by changing LOMEM.

USE WITH CARE. Changing LOMEM in the middle of a program causes BBC BASIC (Z80) to lose track of all the variables you are using.

Syntax

  • LOMEM=<numeric>
  • <n-var>=LOMEM

Associated Keywords

  • HIMEM
  • TOP
  • PAGE


MAT

This is an experimental feature that may change in future versions.
It is provided for compatibility with other dialects of BASIC and to enhance the code readibility of the Z80 version.

Introduction

The MAT statement can be used to perform a number of matrix operations. Matrices are represented by arrays. Individual matrices can have any number of dimensions and be any size, but several operations rely on the matrices they are working on being a particular size, shape or type.

Matrix operations follow the general form:

MAT <array-var>() = <operation>

The array used to store the result of the matrix operation must have been dimensioned beforehand using the DIM statement. For example, to set a three-by-three array a to the identity matrix, one could use the IDN constant:

DIM a(2,2)
MAT a() = IDN

Assignment

You can copy one numeric matrix to another by assigning one to the other:

MAT b() = a()

Both arrays must have the same number of dimensions and be the same size, but do not have to be the same type. If you assign an array of real numbers to an array of integers then each element will be truncated appropriately.

Constant Operations

ZER

The ZER constant sets all array elements to zero (in the case of numeric arrays) or the empty string (in the case of string arrays). The array can have any number of dimensions, be any shape and be any size.

MAT a() = ZER

CON

The CON constant sets all numeric array elements to one. This operation may not be used with string arrays. The array can have any number of dimensions, be any shape and be any size.

MAT a() = CON

CON(expr)

The CON(expr) constant sets all numeric array elements to the result of the expression expr. This operation may not be used with string arrays. The array can have any number of dimensions, be any shape and be any size.

MAT a() = CON(SQR(PI))

IDN

The IDN constant sets the array to an identity matrix. The array must be numeric, be two-dimensional and be square, but can be any size.

DIM a(3,3)
MAT a() = IDN

The elements that lie on the diagonal between the top-left corner and bottom-right corner of the array are set to one; every other element is set to zero. The above sample code would produce the following matrix:

1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

Arithmetic

You can perform matrix arithmetic using the following syntax:

MAT <result>() = <op1> <operator> <op2>

The available operators are listed below. You may only perform a single operation in each MAT statement. Scalar values must be surrounded with parentheses.

Addition

You can add two numeric matrices together with the + operator. Both matrices must have the same number of dimensions and be the same size.

MAT c() = a()+b()

Each element in a() is added to each element in b() and stored in c() in turn.

Subtraction

You can subtract two numeric matrices together with the - operator. Both matrices must have the same number of dimensions and be the same size.

MAT c() = a()-b()

Each element in b() is subtracted from each element in a() and stored in c() in turn.

Multiplication

You can multiply two numeric matrices together with the * operator. Both matrices must be two dimensional.

MAT c() = a()*b()

The result must have the same number of rows as the first operand and the same number of columns as the second operand. The second operand must have the same number of rows as the number of columns in the first operand.

10 DIM a(1,2),b(2,3),product(1,3)
20 FOR i=0 TO 1:FOR j=0 TO 2:a(i,j)=j+i*3+1:NEXT j:NEXT i
30 FOR i=0 TO 2:FOR j=0 TO 3:b(i,j)=j+i*4+1:NEXT j:NEXT i
40 MAT product()=a()*b()
50 @%=&904
60 MAT PRINT a(),b(),product()

The above sample program produces the following output:

   1   2   3
   4   5   6

   1   2   3   4
   5   6   7   8
   9  10  11  12

  38  44  50  56
  83  98 113 128

Functions

TRN

The TRN function transposes a numeric matrix - in effect, it swaps the rows and columns.

MAT b() = TRN(b())

Both matrices must have two dimensions, and the number of rows in one must equal the number of columns in the other and vice-versa. You may not transpose a matrix to itself.

 10 REM Dimension and populate a sample 2x3 matrix:
 20 DIM a%(1,2)
 30 a%(0,0)=1:a%(0,1)=2:a%(0,2)=3
 40 a%(1,0)=4:a%(1,1)=5:a%(1,2)=6
 50 REM Create a transposed version of the above matrix:
 60 DIM b%(2,1)
 70 MAT b%()=TRN(a%())
 80 REM Print both matrices:
 90 @%=&902
100 MAT PRINT a%(),b%()

The above sample program produces the following output:

 1 2 3
 4 5 6

 1 4
 2 5
 3 6

Syntax

MAT <array-var>[()] = <operation>

Associated Keywords

  • MAT PRINT


MAT PRINT

This is an experimental feature that may change in future versions.
It is provided for compatibility with other dialects of BASIC and to enhance the code readibility of the Z80 version.

The MAT PRINT statement PRINTs the contents of an array. You can PRINT arrays of any number of dimensions, size or shape. Numeric and string arrays are supported. Array elements are formatted according to the value of the print formatting variable @%.

 10 REM Dimension and populate a sample 2x3 matrix:
 20 DIM a%(1,2)
 30 a%(0,0)=1:a%(0,1)=2:a%(0,2)=3
 40 a%(1,0)=4:a%(1,1)=5:a%(1,2)=6
 50 REM Create a transposed version of the above matrix:
 60 DIM b%(2,1)
 70 MAT b%()=TRN(a%())
 80 REM Print both matrices:
 90 @%=&902
100 MAT PRINT a%(),b%()

Produces the following output:

 1 2 3
 4 5 6

 1 4
 2 5
 3 6

Single-dimensional arrays are printed on a single line. Two-dimensional arrays are printed in a grid. Arrays with more than two dimensions are printed as a sequence of two-dimensional arrays.

Syntax

MAT PRINT <array-var>[()] [, <array-var>[()] [, ...]]

Associated Keywords

  • MAT


MID$

A string function which returns 'num' characters of the string starting from character 'start_posn'. If 'num' is not present or if there are insufficient characters in the string, then all the characters from 'start_posn' onwards are returned.

C$=MID$(A$,start_posn,num)
C$=MID$(A$,Z)

You can use this function to select any part of a string. For instance, if

name$="BBCBASIC(Z80)"

then

part$=MID$(name$,4,5)

would assign BASIC to 'part$'. If the last number is omitted or there are insufficient characters to the right of the specified position, MID$ returns with the right hand part of the string starting at the specified position. Thus,

part$=MID$(name$,9)

would assign (Z80) to 'part$'.

For example,

10 name$="BBCBASIC(Z80)"
20 FOR i=1 TO LEN(name$)
30   PRINT MID$(name$,i,10)
40 NEXT

would print

BBCBASIC(Z
BCBASIC(Z8
CBASIC(Z80
BASIC(Z80)
ASIC(Z80)
SIC(Z80)
IC(Z80)
C(Z80)
(Z80)
Z80)
80)
0)
)

Syntax

<s-var>=MID$(<str>,<numeric>[,<numeric>])

Associated Keywords

  • LEFT$
  • RIGHT$
  • LEN
  • INSTR


MOD

A binary operation giving the signed remainder of the integer division.

X=A MOD B

MOD is defined such that,

A MOD B = A - ( A DIV B ) * B.

If you are doing integer division (DIV) of whole numbers it is often desirable to know the remainder. (A 'teach children to divide' program for instance). For example, 23 divided by 3 is 7, remainder 2. Thus,

10 PRINT 23 DIV 3
20 PRINT 23 MOD 3

would print

         7
         2

You can use real numbers in these calculations, but they are truncated to their integer part before BBC BASIC (Z80) calculates the result. Thus,

10 PRINT 23.1 DIV 3.9
20 PRINT 23.1 MOD 3.9

would give exactly the same results as the previous example.

Syntax

<n-var>=<numeric> MOD <numeric>

Associated Keywords

  • DIV


MODE

Introduction

The MODE (or VDU 22) command sets the screen display mode. The screen is cleared and all the graphics and text parameters (colours, origin, etc) are reset to their default values.

MODE 4

The default display mode is MODE 0.

Available Modes

The modes listed below change the way text is displayed and graphics commands are handled. It is possible to specify a different mode number to the ones listed below, but for future compatibility it is recommended that you only use the modes below.

Mode | Logical pixels per device pixel |  | Logical resolution | Text resolution (characters) | Character resolution (pixels) | User-definable characters
 | Horizontal | Vertical
MODE 0 | 4 | 5 | 384×320 | 24×10 | 4×6 | No
MODE 3 | 4 | 4 | 384×256 | 24×10 | 4×6 | No
MODE 4 | 4 | 4 | 384×256 | 12×8 | 8×8 | Yes

Syntax

MODE <numeric>

Associated Keywords

  • CLS
  • CLG


MOVE

A statement which moves the graphics cursor to an absolute position without drawing a line. MOVE is followed by the X and Y coordinates to which the cursor should be moved; the optional qualifier BY indicates that the coordinates are relative (offsets from the current graphics cursor position) rather than absolute.

MOVE X,Y
MOVE 124,327

MOVE x,y is equivalent to PLOT 4,x,y. MOVE BY x,y is equivalent to PLOT 0,x,y.

Syntax

MOVE [BY] <numeric>,<numeric>

Associated Keywords

  • DRAW
  • MODE
  • GCOL
  • PLOT


NEW

A command which initialises the interpreter for a new program to be typed in. The old program may be recovered with the OLD command provided no new program lines have been typed in or deleted and no variables have been created.

NEW

This command effectively 'removes' a program from the computer's memory. In reality, the program is still there, but BBC BASIC (Z80) has been told to forget about it.

If you have made a mistake, you can recover your old program by typing OLD. However, this won't work if you have begun to enter a new program.

Syntax

NEW

Associated Keywords

  • OLD


NEXT

NEXTN.

The statement delimiting FOR...NEXT loops. NEXT takes an optional control variable.

NEXT
NEXT J

If the control variable is present then FOR...NEXT loops may be 'popped' automatically in an attempt to match the correct FOR statement (this should not be necessary). If a matching FOR statement cannot be found, a 'Can't match FOR' error will be reported.

Leaving out the control variable will make the program run quicker, but this is not to be encouraged.

See the keyword FOR for more details about the structure of FOR...NEXT loops.

Syntax

NEXT [<n-var>{,<n-var>}]

Associated Keywords

  • FOR
  • TO
  • STEP


NOT

This is a high priority unary operator (the same priority as unary -). It causes a bit-by-bit binary inversion of the numeric to its right. The numeric may be a constant, a variable, or a mathematical or boolean expression. Expressions must be enclosed in brackets.

A=NOT 3
flag=NOT flag
flag=NOT(A=B)

NOT is most commonly used in an IF...THEN...ELSE statement to reverse the effect of the test.

IF NOT(rate>5 AND TIME<100) THEN ...
IF NOT flag THEN ...

BBC BASIC (Z80) does not have true Boolean variables; it makes do with numeric variables. This can lead to confusion because the testable condition in an IF...THEN...ELSE statement is evaluated mathematically and can result in something other than -1 (TRUE) or 0 (FALSE).

When the test in an IF...THEN...ELSE is evaluated, FALSE=0 and anything else is considered to be TRUE. If you wish to use NOT to reverse the action of an IF statement it is important to ensure that the testable condition does actually evaluate to -1 for TRUE.

If the testable condition evaluates to 1, for example, the result of the test would be considered to be TRUE and the THEN part of the IF....THEN....ELSE statement would be carried out. However, using NOT in front of the testable condition would not reverse the action. NOT 1 evaluates to -2, which would also be considered to be TRUE.

Syntax

<n-var>=NOT<numeric>


OLD

A command which undoes the effect of NEW provided no lines have been typed in or deleted, and no variables have been created.

OLD

OLD works even if BBC BASIC (Z80) has been re-started if the memory it used previously is still intact. Running other programs or extended loss of power may prevent OLD from working.

Syntax

OLD

Associated Keywords

  • NEW


ON

A statement controlling a multi-way switch. The line numbers in the list may be constants or calculated and the 'unwanted' ones are skipped without calculation. The ON statement is used in conjunction with four other key-words: GOTO, GOSUB, PROC and ERROR. (ON ERROR is explained separately).

ON option GOTO 1000,2000,3000,4000
ON action GOSUB 100,3000,200,5000,30
ON choice PROC_add,PROC_find,PROC_delete

The ON statement alters the path through your program by transferring control to one of a selection of line numbers depending on the value of a variable. For example,

200 ON number GOTO 1000,2000,500,100

would send your program to line 1000 if 'number' was 1, to line 2000 if 'number' was 2, to line 500 if 'number' was 3 and to line 100 if 'number' was 4.

Exceptions may be trapped using the ELSE statement delimiter.

ON action GOTO 100,300,120 ELSE PRINT"Illegal"

If there is no statement after the ELSE, the program will 'drop through' to the following line if an exception occurs. In the two following examples, the program would drop through to the error handling part of the program if 'choice' or 'B-46' was less than one or more than 3.

ON choice PROC_add,PROC_find(a$),PROC_delete ELSE
PRINT "Illegal Choice - Try again"
ON B-46 GOSUB 100,200,(C/200) ELSE PRINT "ERROR"

You can use ON…GOTO, ON…GOSUB, and ON…PROC to execute the appropriate part of your program as the result of a menu selection. The following skeleton example offers a menu with three choices.

 20 CLS
 30 PRINT "SELECT THE ACTION YOU WISH TO TAKE"
 40 PRINT "1 OPEN A NEW DATA FILE"
 50 PRINT "2 ADD DATA TO THE FILE"
 60 PRINT "3 CLOSE THE FILE AND END"''
 70 REPEAT
 80   INPUT TAB(10,20)"WHAT DO YOU WANT ? "choice
 90 UNTIL choice>0 AND choice<4
100 ON choice PROC_open,PROC_add,PROC_close ELSE
110 ...

Limitations

If a statement terminator (: or the token for ELSE) appears within the line, the interpreter assumes that the ON… statement is terminated. For example, you cannot pass a colon as a literal string parameter in an ON…PROC command. The program line

ON entry PROC_start,PROC_add(":"),PROC_end

would be interpreted as

ON entry PROC_start,PROC_add("
:"),PROC_end

and give rise to an interesting crop of error messages.

Syntax

  • ON <numeric> GOTO <l-num>{,<l-num>} [ELSE <stmt>{:<stmt>}]
  • ON <numeric> GOSUB <l-num>{,<l-num>} [ELSE <stmt>{:<stmt>}]
  • ON <numeric> PROC<name>[(<exp>{,<exp>})] {,PROC<name>[(<exp>{,<exp>})]} [ELSE <stmt>{:<stmt>}]

Associated Keywords

  • ON ERROR
  • GOTO
  • GOSUB
  • PROC


ON ERROR

A statement controlling error trapping. If an ON ERROR statement has been encountered, BBC BASIC (Z80) will transfer control to it (without taking any reporting action) when an error is detected. This allows error reporting/recovery to be controlled by the program. However, the program control stack is still cleared when the error is detected and it is not possible to RETURN to the point where the error occurred.

ON ERROR OFF returns the control of error handling to BBC BASIC (Z80).

ON ERROR PRINT"Suicide":END
ON ERROR GOTO 100
ON ERROR OFF

For example, the ON ERROR statement can be used to trap out the Escape key to prevent a program being terminated at the wrong time by its accidental use.

50 ON ERROR IF ERR=17 THEN 70
60 PRINT:REPORT:PRINT " at line ";ERL:END
70 ...

Error Handling is explained more fully in the overview section.

Syntax

  • ON ERROR <stmt>{:<stmt>}
  • ON ERROR OFF

Associated Keywords

  • ON
  • GOTO
  • GOSUB
  • PROC


OPENIN

OPENINOP.

A function which opens a file for reading and returns the handle of the file. This number must be used in subsequent references to the file with BGET#, INPUT#, EXT#, PTR#, EOF# or CLOSE#.

A returned value of zero signifies that the specified file was not found.

X=OPENIN "jim"
X=OPENIN A$
X=OPENIN (A$)
X=OPENIN ("FILE1")
X=OPENIN ("COM2")

The example below reads data from disk into an array. If the data file does not exist, an error message is printed and the program ends.

10 DIM posn(10),name$(10)
20 fnum=OPENIN "TOPTEN"
30 IF fnum=0 THEN PRINT "No TOPTEN data": END
40 FOR i=1 TO 10
50   INPUT#fnum,posn(i),name$(i)
60 NEXT
70 CLOSE#fnum

Syntax

<n-var>=OPENIN(<str>)

Associated Keywords

  • OPENOUT
  • OPENUP
  • CLOSE#
  • PTR#
  • PRINT#
  • INPUT#
  • BGET#
  • BPUT#
  • EOF#


OPENOUT

A function which opens a file for writing and returns the handle of the file. This number must be used in subsequent references to the file with BPUT#, PRINT#, EXT#, PTR# or CLOSE#. If the specified file does not exist it is created. If the specified file already exists it is truncated to zero length.

A returned value of zero indicates that the specified file could not be created.

X=OPENOUT(A$)
X=OPENOUT("DATAFILE")
X=OPENOUT("LPT1")

You can also read from a file which has been opened using OPENOUT. This is of little use until you have written some data to it. However, once you have done so, you can move around the file using PTR# and read back previously written data.

Data is not written to the file at the time it is opened. Consequently, it is possible to successfully open a file on a full disk. Under these circumstances, a 'Disk full' error would be reported when you tried to write data to the file for the first time.

The example below writes the contents of two arrays (tables) to a file called 'TOPTEN.BBC'.

10 A=OPENOUT "TOPTEN"
20 FOR Z=1 TO 10
30   PRINT#A,N(Z),N$(Z)
40 NEXT
50 CLOSE#A
60 END

Syntax

<n-var>=OPENOUT(<str>)

Associated Keywords

  • OPENIN
  • OPENUP
  • CLOSE#
  • PTR#
  • PRINT#
  • INPUT#
  • BGET#
  • BPUT#
  • EOF#


OPENUP

A function which opens a disk data file for update (reading and writing) and returns the handle of the file. This number must be used in subsequent references to the file with BGET#, BPUT#, INPUT#, PRINT#, EXT#, PTR#, EOF# or CLOSE#.

A returned value of zero signifies that the specified file was not found.

X=OPENUP "jim"
X=OPENUP A$
X=OPENUP (A$)
X=OPENUP ("FILE1")

Syntax

<n-var>=OPENUP(<str>)

Associated Keywords

  • OPENIN
  • OPENOUT
  • CLOSE#
  • PTR#
  • PRINT#
  • INPUT#
  • BGET#
  • BPUT#
  • EOF#


OPT

An assembler pseudo operation controlling the method of assembly. (See the assembler section for more details). OPT should be followed by a number in the range 0 to 7. The way the assembler functions is controlled by the three bits of this number in the following manner.

Bit 0 - LSB

Bit 0 controls the listing. If it is set, a listing is displayed.

Bit 1

Bit 1 controls the error reporting. If it is set, errors are reported.

Bit 2

Bit 2 controls where the assembled code is placed. If bit 2 is set, code is placed in memory starting at the address specified by O%. However, the program counter (P%) is still used by the assembler for calculating the instruction addresses.

Syntax

  • OPT <numeric>


OR

The operation of bitwise integer logical OR between two items. The two operands are internally converted to 4 byte integers before the OR operation.

IF A=2 OR B=3 THEN 110
X=B OR 4

You can leave out the space between OR and a preceding constant, but it makes your programs difficult to read.

You can use OR as a logical operator or as a 'bit-by-bit' (bitwise) operator. The operands can be boolean (logical) or numeric.

Unfortunately, BBC BASIC does not have true Boolean variables; it uses numeric variables and assigns the value 0 for FALSE and -1 for TRUE. 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 or B=3.

answer=(A=2 OR B=3)

The brackets are not necessary, they have been included to make the example easier to follow.

The last example, uses the OR in a similar fashion to the numeric operators (+, -, etc).

Suppose X was -20 in the following example,

A=X OR 11

the OR operation would be:

11111111 11111111 11111111 11101100
00000000 00000000 00000000 00001011
11111111 11111111 11111111 11101111  = -17

Syntax

<n-var>=<numeric> OR <numeric>

Associated Keywords

  • AND
  • EOR
  • NOT


OSCLI

This command allows a string expression to be passed to the command-line interpreter. It overcomes the problems caused by the exclusion of variables in the star (*) commands. Using this statement, you can, for instance, erase and rename files whose names you only know at run-time.

filename$="SOMEFILE"
command$="DEL "+filename$
OSCLI command$
source$="OLDNAME"
dest$="NEWNAME"
command$="REN "+source$+"="+dest$
OSCLI command$

Syntax

OSCLI <str>


PAGE

PAGEPA.

A pseudo-variable controlling the starting address of the current user program area. It addresses the area where a program is (or will be) stored.

PAGE=&3100
PRINT ~PAGE
PAGE=TOP+&100: REM Move to start of next page.

PAGE is automatically initialised by BBC BASIC (Z80) to the address of the lowest available page (256-byte aligned region) in RAM, but you may change it.

  • If you make PAGE less than its original value or greater than the original value of HIMEM, you will get a 'Bad program' error when you try to enter a program line and you may well crash BBC BASIC (Z80).
  • If you make PAGE greater than HIMEM, a 'No room' error will occur if the program exits to command level.

With care, several programs can be left around in RAM without the need for saving them.

USE WITH CARE.

Syntax

  • PAGE=<numeric>
  • <n-var>=PAGE

Associated Keywords

  • TOP
  • LOMEM
  • HIMEM


PI

A function returning 3.14159265.

X=PI

You can use PI to calculate the circumference and area of a circle. The example below calculates the circumference and area of a circle of a given radius.

10 CLS
20 INPUT "What is the radius of the circle ",rad
30 PRINT "The circumference is: ";2*PI*rad
40 PRINT "The area is: ";PI*rad*rad
50 END

PI can also be used to convert degrees to radians and radians to degrees.

radians=PI/180*degrees
degrees=180/PI*radians

However, BBC BASIC (Z80) has two functions (RAD and DEG) which perform these conversions to a higher accuracy.

Syntax

<n-var>=PI

Associated Keywords

  • RAD
  • DEG


PLOT

PLOTPL.

Introduction

PLOT is a multi-purpose drawing statement. Typically three numbers follow the PLOT statement: the first specifies the type of point, line, triangle or circle to be drawn; the second and third give the X and Y coordinates to be used.

PLOT Mode,X,Y

Lines are drawn from the current graphics cursor position (the last point 'visited') to the specified (X,Y) coordinates. The graphics origin is usually the bottom-left corner of the screen, but it can be changed using the VDU 29 statement.

The two most commonly used statements, PLOT 4 and PLOT 5, have the duplicate keywords MOVE and DRAW.

Plot Modes

Each drawing operation is assigned a numeric code. There are eight different numeric codes for each plotting mode, controlling the use of colour and whether the specified coordinates are absolute or relative to the last visited point.

Mode Offset | Colour | Coordinate
0 | None | Relative
1 | Foreground
2 | Inverse
3 | Background
4 | None | Absolute
5 | Foreground
6 | Inverse
7 | Background

Lines

BBC BASIC will draw a line between the two most recently visited points. For example,

PLOT 4,10,20
PLOT 5,30,40

draws a line in the current foreground colour between (10,20) and (30,40) inclusive. There are four different line patterns; solid, dotted, short dashes and long dashes.

Additionally, the last pixel of each line can be optionally drawn twice. This is most useful when drawing inverse-coloured lines, as it has the effect of not plotting the last pixel.

Mode Range | Line Style | Last Pixel Drawn Twice
0-7 | Solid | No
8-15 |  | Yes
16-23 | Dotted | No
24-31 |  | Yes
32-39 | Short Dashes | No
40-47 |  | Yes
48-55 | Long Dashes | No
56-63 |  | Yes

Points

Modes 64-71 will plot a single point, or pixel. You can retrieve the state of a point using the POINT function.

PLOT x,y is equivalent to PLOT 69,x,y. PLOT BY x,y is equivalent to PLOT 65,x,y.

Triangles

Modes 80-87 will plot and fill a triangle. The triangle is formed from the given X,Y coordinates and the previous two points 'visited', however they were specified.

The following example plots and fills the triangle shown with vertices at (30,0), (90,30) and (10,60) in the current graphics foreground colour.

MOVE 30,0
MOVE 90,30
PLOT 85,10,60

If the PLOT number is 81 or 85, the triangle is drawn and filled in the current foreground colour.

Rectangles

Modes 96-103 will plot and fill an axis-aligned rectangle. The two most recently visited points are used for the two opposite corners of the rectangle.

Parallelograms

Modes 112-119 plot and fill a parallelogram whose vertices are defined by the previous two points visited and the point specified. For reference purposes, call the previous two points visited point1 and point2 in order, and the point specified in the PLOT command, point3. The x and y coordinates of the fourth point are calculated by point3-point2+point1.

The order in which the points are visited is important.

The following example plots and fills the parallelogram illustrated in the current graphics foreground colour.

MOVE 10,40
MOVE 30,10
PLOT 117,90,25

If the PLOT number is 113 or 117, the parallelogram will be drawn and filled in the current foreground colour.

Flood Filling

Modes 128-135 and 136-143 can be used to flood fill a region of the screen starting from a given point, similar to the paint bucket tool found in image manipulation software.

  • Modes 128-135 will start filling at the given point and continue until non-background pixels are found.
  • Modes 136-142 will start filling at the given point and continue until foreground pixels are found.

For example, if you had a white region with a black border that you wished to fill you could either set the background colour to white and use one of modes 128-135 or set the foreground colour to black and use one of modes 136-142.

The following procedure acts like the paint bucket tool in an image manipulation program; it will allow you to fill regions of any colour with any other colour. It uses the POINT function to find the starting colour under the given point to set the correct background colour.

DEF PROC_fill(x,y,c)
GCOL c
GCOL 128+POINT(x,y)
PLOT 133,x,y
ENDPROC

Flood-filling is a memory-intensive operation, and if BBC BASIC is running low on memory it is possible for this plotting operation to trigger the untrappable 'No room' error.

Circles

Modes 144-151 and 152-159 can be used to draw and fill circles respectively with the origin at the current graphics cursor position.

Point on Circumference

If the 'absolute' plot codes (148-151 or 156-159) are used the point specified will be on the circumference of the circle. For example,

MOVE x1,y1
PLOT 149,x2,y2

will draw a circle centred on (x1,y1) with the point (x2,y2) in its circumference.

Radius

If the 'relative' plot codes (144-147 or 152-155) are used either of the parameters may be used to specify the radius. For example, either

MOVE x,y
PLOT 145,R,0

or

MOVE x,y
PLOT 145,0,R

will draw a circle of radius R centred about the point (x,y).

Ellipses

Modes 192-199 and 200-207 can be used to draw and fill ellipses respectively. Three points are required to draw an ellipse:

  1. The origin (centre) of the ellipse.
  2. A point on the vertical tangent of the ellipse.
  3. A point on the horizontal tangent of the ellipse.

For example, to fill an ellipse centred around (x,y) with a horizontal radius hr and a vertical radius vr, you could use this code:

MOVE x,y
PLOT 0,hr,0
PLOT 201,0,vr

Syntax

  • PLOT <numeric>,<numeric>,<numeric>
  • PLOT [BY] <numeric>,<numeric>

Associated Keywords

  • BY
  • CIRCLE
  • CLG
  • DRAW
  • ELLIPSE
  • FILL
  • GCOL
  • MODE
  • MOVE
  • POINT
  • RECTANGLE
  • VDU


POINT

A function which returns a number giving the colour of the screen at the coordinates specified. There must not be a space between POINT and the opening bracket.

colour=POINT(X,Y)
IF POINT(X,Y)>7 THEN 300

You can use POINT to find out the colour of the screen at the specified point and take action accordingly. It will return one of the following values:

Value | Meaning
0 | The pixel is black.
15 | The pixel is white.
-1 | The specified point was outside the screen.

The coordinates passed are absolute and can read anywhere on the screen (including outside the graphics viewport).

Syntax

<n-var>=POINT(<numeric>,<numeric>)

Associated Keywords

  • PLOT
  • DRAW
  • MOVE
  • GCOL


POS

A function returning the horizontal position of the cursor on the screen. The left hand column is 0 and the right hand column is one less than the width of the display.

X=POS

COUNT will tell you the number of characters that have been output since the last new line. It is an uncertain indicator of the horizontal position of the cursor on the screen. (See the keyword COUNT for details.)

See VPOS for an example of the use of POS and VPOS.

Syntax

<n-var>=POS

Associated Keywords

  • COUNT
  • TAB
  • VPOS


PRINT

PRINTP.

A statement which prints characters to the current output device.

General Information

The items following PRINT are called the print list. The print list may contain a sequence of string or numeric literals or variables. The spacing between the items printed will vary depending on the punctuation used. If the print list does not end with a semi-colon, a new-line will be printed after all the items in the print list.

In the examples which follow, commas have been printed instead of spaces to help you count.

The screen is divided into zones (initially) 10 characters wide. By default, numeric quantities are printed right justified in the print zone and strings are printed just as they are (with no leading spaces). Numeric quantities can be printed left justified by preceding them with a semi-colon. In the examples the zone width is indicated as z10, z4 etc.

                    z10
                    012345678901234567890123456789
PRINT 23.162        ,,,,23.162
PRINT "HELLO"       HELLO
PRINT ;23.162       23.162

Initially numeric items are printed in decimal. If a tilde (~) is encountered in the print list, the numeric items which follow it are printed in hexadecimal. If a comma or a semi-colon is encountered further down the print list, the format reverts to decimal.

                    z10
                    012345678901234567890123456789
PRINT ~10 58,58     ,,,,,,,,,A,,,,,,,,3A,,,,,,,,58

A comma (,) causes the cursor to TAB to the beginning of the next print zone unless the cursor is already at the start of a print zone. A semi-colon causes the next and following items to be printed on the same line immediately after the previous item. This 'no-gap' printing continues until a comma (or the end of the print list) is encountered. An apostrophe (') will force a new line. TAB(X) and TAB(Y,Z) can also be used at any position in the print line to position the cursor.

                    z10
                    012345678901234567890123456789
PRINT "HELLO",24.2  HELLO     ,,,,,,24.2
PRINT "HELLO";24.2  HELLO24.2
PRINT ;2 5 4.3,2    254.3     ,,,,,,,,,2
PRINT "HELLO"'2.45  HELLO
                    ,,,,,,2.45

Unlike most other versions of BASIC, a comma at the end of the print list will not suppress the new line and advance the cursor to the next zone. If you wish to split a line over two or more PRINT statements, end the previous print list with a semicolon and start the following list with a comma or end the line with a comma followed by a semicolon.

                    z10
                    012345678901234567890123456789
PRINT "HELLO" 12;   HELLO,,,,,,,,12,,,,,,,,,,23.67
PRINT ,23.67

or

PRINT "HELLO" 12,;
PRINT 23.67

Printing a string followed by a numeric effectively moves the start of the print zones towards the right by the length of the string. This displacement continues until a comma is encountered.

                    z10
                    012345678901234567890123456789
PRINT "HELLO"12 34  HELLO,,,,,,,,12,,,,,,,,34
PRINT "HELLO"12,34  HELLO,,,,,,,,12     ,,,,,,,,34

Print Format Control

Although PRINT USING is not implemented in BBC BASIC, similar control over the print format can be obtained. The overall width of the print zones and print field, the number of figures or decimal places and the print format may be controlled by setting the print variable, @%, to the appropriate value. The print variable (@%) comprises 4 bytes and each byte controls one aspect of the print format. @% can be set equal to a decimal integer, but it is easier to use hexadecimal, since each byte can then be considered separately.

@%=&SSNNPPWW
Byte | Range | Default | Purpose
SS | 00-01 | 00 | STR$ Format Control
NN | 00-02 | 00 | Format Selection
PP | ??-?? | 09 | Number of Digits Printed
WW | 00-0F | 0A(10) | Zone and Print Field Width

STR$ Format Control - SS

Byte 3 effects the format of the string generated by the STR$ function. If Byte 3 is 1 the string will be generated according to the format set by @%, otherwise the G9 format will be used.

Format Selection - NN

Byte 2 selects the general format as follows:

  • 00 - General Format (G).
  • 01 - Exponential Format (E).
  • 02 - Fixed Format (F).

G Format

Numbers that are integers are printed as such. Numbers in the range 0.1 to 1 will be printed as such. Numbers less than 0.1 will be printed in E format. Numbers greater than the range set by Byte 1 will be printed in E format. In which case, the number of digits printed will still be controlled by Byte 1, but according to the E format rules.

The earlier examples were all printed in G9 format.

E Format

Numbers are printed in the scientific (engineering) notation.

F Format

Numbers are printed with a fixed number of decimal places.

Number of Digits - PP

Byte 1 controls the number of digits printed in the selected format. The number is rounded (not truncated) to this size before it is printed. If Byte 1 is set outside the range allowed for by the selected format, it is taken as 9. The effect of Byte 1 differs slightly with the various formats.

Format Range Control Function
G 01-0A The maximum number of digits which can be printed, excluding the decimal point, before changing to the E format.
                    01234567890123456789
&030A - G3z10
(00'00'03'0A)
PRINT 1000.31       ,,,,,,,1E3
PRINT 1016.31       ,,,,1.02E3
PRINT 10.56         ,,,,,,10.6
E 01-FF The total number of digits to be printed excluding the decimal point and the digits after the E. Three characters or spaces are always printed after the E.

If the number of significant figures called for is greater than 10, then trailing zeros will be printed.

01030A - E3z10
(00'01'03'0A)
                    01234567890123456789
PRINT 10.56         ,,1.06E1

&010F0A - E15z10
(00'01'0F'0A)
                    01234567890123456789
PRINT 10.56         1.05600000000000E1
F 00-0A The number of digits to be printed after the decimal point.
&02020A - F2z10
(00'02'02'0A)
                    01234567890123456789
PRINT 10.56         ,,,,,10.56
PRINT 100.5864      ,,,,100.59
PRINT .64862        ,,,,,,0.65

Zone Width - WW

Byte 0 sets the width of the print zones and field.

&020208 - F2z8
(00'00'02'08)

followed by

&020206 - F2z6
(00'02'02'06)
                    01234567890123456789
PRINT 10.2,3.8      ,,,10.20,,,,3.80
PRINT 10.2,3.8      ,10.20,,3.80

Changing the Print Control Variable

It is possible to change the print control variable (@%) within a print list by using the function:

DEF FN_pformat(N):@%=N:=""

Functions have to return an answer, but the value returned by this function is a null string. Consequently, its only effect is to change the print control variable. Thus the PRINT statement

PRINT FN_pformat(&90A) x FN_pformat(&2020A) y

will print x in G9z10 format and y in F2z10 format.

Examples

G9z10
&00090A
012345678901234
1111.11111
13.7174211
,1.5241579
1.88167642E-2
2.09975158E-3
G2z10
&00020A
012345678901234
,,,,,1.1E3
,,,,,,,,14
,,,,,,,1.5
,,,,1.9E-2
,,,,2.1E-3
F2z10
&02020A
012345678901234
,,,1111.11
,,,,,13.72
,,,,,,1.52
,,,,,,0.02
,,,,,,0.00
E2z10
&0102A
012345678901234
,,,1.1E3
,,,1.4E1
,,,1.5E0
,,,1.9E-2
,,,2.1E-3

The results obtained by running the following example program show the effect of changing the zone width. The results for zone widths of 5 and 10 (&0A) illustrate what happens when the zone width is too small for the number to be printed properly. The example also illustrates what happens when the number is too large for the chosen precision.

 10 test=7.8123
 20 FOR i=5 TO 25 STEP 5
 30   PRINT
 40   @%=&020200+i
 50   PRINT "@%=&000";~@%
 60   PRINT STRING$(3,"0123456789")
 70   FOR j=1 TO 10
 80     PRINT test^j
 90   NEXT
100   PRINT '
110 NEXT
120 @%=&90A
&00020205
012345678901234567890123456789
 7.81
61.03
476.80
3724.91
29100.11
227338.75
1776038.54
13874945.89
1.083952398E8
8.46816132E8

&0002020A
012345678901234567890123456789
      7.81
     61.03
    476.80
   3724.91
  29100.11
 227338.75
1776038.54
13874945.89
1.083952398E8
8.46816132E8

&0002020F
012345678901234567890123456789
           7.81
          61.03
         476.80
        3724.91
       29100.11
      227338.75
     1776038.54
    13874945.89
   1.083952398E8
    8.46816132E8

&00020214
012345678901234567890123456789
                7.81
               61.03
              476.80
             3724.91
            29100.11
           227338.75
          1776038.54
         13874945.89
       1.083952398E8
        8.46816132E8

&00020219
012345678901234567890123456789
                     7.81
                    61.03
                   476.80
                  3724.91
                 29100.11
                227338.75
               1776038.54
              13874945.89
            1.083952398E8
             8.46816132E8

Syntax

PRINT {[TAB(<numeric>[,<numeric>])][SPC(<numeric>)]['][,][;][~][<str>|<numeric>]}

Associated Keywords

  • PRINT#
  • TAB
  • POS
  • STR$
  • WIDTH
  • INPUT
  • VDU


PRINT#

PRINT#P.#

A statement which writes the internal form of a value out to a data file.

PRINT#E,A,B,C,D$,E$,F$
PRINT#4,prn$

The format of the variables as written to the file differs from the format used on the BBC Micro. All numeric values are written as five bytes of binary real data (see the section entitled Format of Program and Variables in Memory). Strings are written as the bytes in the string (in the correct order) plus a carriage return.

Before you use this statement, you must normally have opened a file using OPENOUT or OPENUP.

You can use PRINT# to write data (numbers and strings) to a data file in the 'standard' manner. If you wish to 'pack' your data in a different way, you should use BPUT#. You can use PRINT# and BPUT# together to mix or modify the data format. For example, if you wish to write a 'compatible' text file, you could PRINT# the string and BPUT# a line-feed. This would write the string followed by a carriage-return and a line-feed to the file.

Remember, with BBC BASIC (Z80) the format of the file is completely under your control.

Syntax

PRINT#<numeric>{,<numeric>|<str>}

Associated Keywords

  • PRINT
  • OPENUP
  • OPENOUT
  • CLOSE#
  • INPUT#
  • BPUT#
  • BGET#
  • EXT#
  • PTR#
  • EOF#


PROC

A keyword used at the start of all user declared procedures. The first character of a procedure name can be an underline (or a number).

If there are spaces between the procedure name and the opening bracket of the parameter list (if any) they must be present both in the definition and the call. It's safer not to have spaces between the procedure name and the opening bracket.

A procedure may be defined with any number of parameters of any type.

A procedure definition is terminated by ENDPROC.

A procedure does not have to be declared before it is called.

Procedures are re-entrant and the parameters (arguments) are passed by value.

 10 INPUT"Number of discs "F
 20 PROC_hanoi(F,1,2,3)
 30 END
 40 :
 50 DEF PROC_hanoi(A,B,C,D)
 60 IF A=0 THEN ENDPROC
 70 PROC_hanoi(A-1,B,D,C)
 80 PRINT"Move disk ";A" from ";B" to ";C
 90 PROC_hanoi(A-1,D,C,B)
100 ENDPROC

See the Procedures and Functions sub-section for more details.

Syntax

PROC<name>[(<exp>{,<exp>})]

Associated Keywords

  • DEF
  • ENDPROC
  • FN
  • LOCAL


PTR#

A pseudo-variable allowing the random-access pointer of the file whose file handle is its argument to be read and changed.

PTR#F=PTR#F+5 :REM Move pointer to next number
PTR#F=recordnumber*recordlength

Reading or writing (using BGET#, BPUT#, INPUT# or PRINT#) takes place at the current position of the pointer. The pointer is automatically updated following a read or write operation.

You can use PTR# to select which item in a file is to be read or written to next. In a random file you use PTR# to select the record you wish to read or write.

If you wish to move about in a file using PTR# you will need to know the precise format of the data in the file.

A file opened with OPENUP may be extended by setting its pointer to its end (PTR#fnum = EXT#fnum) and then writing to it.

By using PTR# you have complete control over where you read and write data in a file. This is simple concept, but it may initially be difficult to grasp its many ramifications.

Syntax

  • PTR#<numeric>=<numeric>
  • <n-var>=PTR#<numeric>

Associated Keywords

  • OPENIN
  • OPENUP
  • OPENOUT
  • CLOSE#
  • PRINT#
  • INPUT#
  • BPUT#
  • BGET#
  • EXT#
  • EOF#


PUT

A statement to output data to an output port.

PUT A,N :REM output N to port A.

This instruction gives direct access from BBC BASIC (Z80) to the computer's I/O hardware. Typically, you can use it to directly access I/O ports.

Syntax

PUT <numeric>,<numeric>

Associated Keywords

  • GET


RAD

A function which converts degrees to radians.

X=RAD(Y)
X=SIN RAD(90)

Unlike humans, BBC BASIC (Z80) wants angles expressed in radians. You can use this function to convert an angle expressed in degrees to radians before using one of the angle functions (SIN, COS, etc).

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

See COS, SIN and TAN for further examples of the use of RAD.

Syntax

<n-var>=RAD<numeric>

Associated Keywords

  • DEG


READ

A statement which will assign to variables values read from the DATA statements in the program. Strings must be enclosed in double quotes if they have leading spaces or contain commas.

READ C,D,A$

In many of your programs, you will want to use data values which do not change frequently. Because these values are subject to some degree of change, you won't want to use constants. On the other hand, you won't want to input them every time you run the program either. You can get the best of both worlds by declaring these values in DATA statements at the beginning or end of your program and READing them into variables in your program.

A typical use for DATA and READ is a name and address list. The addresses won't change very often, but when they do you can easily amend the appropriate DATA statement.

See DATA for more details and an example of the use of DATA and READ.

Syntax

READ <n-var>|<s-var>{<n-var>|<s-var>}

Associated Keywords

  • DATA
  • RESTORE


READ#

READ# is a synonym for INPUT#.

Syntax

READ #<numeric>,<n-var>|<s-var>{,<n-var>|<s-var>}


RECTANGLE

This is an experimental feature that may change in future versions.
It is provided for compatibility with the Windows version of BBC BASIC and to enhance the code readibility of the Z80 version.

A statement which draws an outline rectangle or a filled rectangle. RECTANGLE is followed by the X and Y coordinates of the bottom left-hand corner of the rectangle then the width and height of the rectangle. To draw a square you can omit the fourth parameter; the height is then assumed to be the same as the width. To draw a filled (solid) rectangle or square use RECTANGLE FILL.

The graphics origin (X=0, Y=0) is normally the bottom-left of the screen. The origin can be changed using the VDU 29 command. See the Graphics section for more details.

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

RECTANGLE xpos,ypos,width,height
RECTANGLE FILL 100,90,50

Syntax

  • RECTANGLE [FILL] <numeric>,<numeric>,<numeric>[,<numeric>]

Associated Keywords

  • FILL


REM

A statement that causes the rest of the line to be ignored thereby allowing comments to be included in a program.

You can use the REM statement to put remarks and comments in to your program to help you remember what the various bits of your program do. BBC BASIC (Z80) completely ignores anything on the line following a REM statement.

You will be able to get away without including any REMarks in simple programs. However, if you go back to a lengthy program after a couple of months you will find it very difficult to understand if you have not included any REMs.

If you include nothing else, include the name of the program, the date you last revised it and a revision number at the start of your program.

10 REM WSCONVERT REV 2.30
20 REM 5 AUG 84
30 REM Converts 'hard' carriage-returns to 'soft'
40 REM ones in preparation for use with WS.

Syntax

REM any text


RENUMBER

RENUMBERREN.

A command which will renumber the lines and correct the cross references inside a program.

The options are as for AUTO, but increments of greater than 255 are allowed.

You can specify both the new first number (n1) and/or the step size (s). The default for both the first number and the step size is 10. The two parameters should be separated by a comma or a hyphen.

RENUMBER
RENUMBER n1
RENUMBER n1,s
RENUMBER ,s

For example,

RENUMBER | First number 10, step 10
RENUMBER 1000 | First number 1000, step 10
RENUMBER 1000-5 | First number 1000, step 5
RENUMBER ,5 | First number 10, step 5
RENUMBER -5 | First number 10, step 5

RENUMBER produces error messages when a cross reference fails. The line number containing the failed cross-reference is renumbered and the line number in the error report is the new line number.

If you renumber a line containing an ON GOTO/GOSUB statement which has a calculated line number, RENUMBER will correctly cope with line numbers before the calculated line number. However, line numbers after the calculated line number will not be changed.

In the following example, the first two line numbers would be renumbered correctly, but the last two would be left unchanged.

ON action GOSUB 100,200,(type*10+300),400,500

RENUMBER may be used in a program, but it will exit to the command mode on completion.

Syntax

RENUMBER [<n-const>[,<n-const>]]

Associated Keywords

  • LIST


REPEAT

REPEATREP.

A statement which is the starting point of a REPEAT…UNTIL loop. A single REPEAT may have more than one UNTIL, but this is bad practice.

The purpose of a REPEAT…UNTIL loop is to make BBC BASIC (Z80) repeat a set number of instructions until some condition is satisfied.

You can force a premature end to the loop with the EXIT REPEAT statement. REPEAT…UNTIL loops may be nested.

REPEAT UNTIL GET=13 :REM wait for CR
X=0
REPEAT
  X=X+10
  PRINT "What do you think of it so far?"
UNTIL X>45

You must not exit a REPEAT…UNTIL loop with a GOTO. If you jump out of a loop with a GOTO (How could you!) you should jump back in. If you must jump out of the loop, you should use UNTIL TRUE to 'pop' the stack. For (a ghastly) example:

 10 i=1
 20 REPEAT: REM Print 1 to 100 unless
 30   I=I+1: REM interrupted by the
 40   PRINT i: REM space bar being pressed
 50   x=INKEY(0): REM Get a key
 60   IF x=32 THEN 110:REM exit if <SPACE>
 70 UNTIL i=100
 80 PRINT "****"
 90 END
100 :
110 UNTIL TRUE: REM Pop the stack
120 PRINT "Forced exit":REM Carry on with program
130 FOR j=1000 TO 1005
140   PRINT j
150 NEXT
160 END

See the keyword UNTIL for ways of using REPEAT…UNTIL loops to replace unconditional GOTOs for program looping.

See Flow Control for more details on the working of the program stack.

Syntax

REPEAT

Associated Keywords

  • EXIT
  • UNTIL
  • WHILE


REPORT

A statement which prints out the error string associated with the last error which occurred.

You can use this statement within your own error handling routines to print out an error message for those errors you are not able to cope with.

The example below is an error handling routine designed to cope only with the Escape key being pressed. All other errors are reported and the program terminated.

  10 ON ERROR GOTO 1000
  20 ...
 970 ...
 980 END
 990 :
1000 PRINT
1010 IF ERR=17 THEN PRINT "<ESCAPE> ignored":GOTO 20
1020 REPORT:PRINT " at line ";ERL

See the sub-section on Error Handling and the keywords ERR, ERL and ON ERROR for more details.

Syntax

REPORT

Associated Keywords

  • ERR
  • ERL
  • ON ERROR


RESTORE

RESTORERES.

RESTORE can be used at any time in a program to set the line where DATA is read from.

RESTORE on its own resets the data pointer to the first data item in the program.

RESTORE followed by a parameter sets the data pointer to the first item of data in the specified line (or the next line containing a DATA statement if the specified line does not contain data). This optional parameter for RESTORE can specify a calculated line number.

RESTORE
RESTORE 100
RESTORE (10*A+20)

You can use RESTORE to reset the data pointer to the start of your data in order to re-use it. alternatively, you can have several DATA lists in your program and use RESTORE to set the data pointer to the appropriate list.

Syntax

  • RESTORE [<l-num>]
  • RESTORE [(<numeric>)]

Associated Keywords

  • READ
  • DATA


RETURN

RETURNR.

A statement causing a RETURN to the statement after the most recent GOSUB statement.

You use RETURN at the end of a subroutine to make BBC BASIC (Z80) return to the place in your program which originally 'called' the subroutine.

You may have more than one return statement in a subroutine, but it is preferable to have only one entry point and one exit point (RETURN).

Try to structure your program so you don't leave a subroutine with a GOTO. If you do, you should always return to the subroutine and exit via the RETURN statement. If you insist on using GOTO all over the place, you will end up confusing yourself and maybe confusing BBC BASIC (Z80) as well. The sub-section on Flow Control explains why.

Syntax

RETURN

Associated Keywords

  • GOSUB
  • ON


RIGHT$

A string function which returns the right 'num' characters of the string. If there are insufficient characters in the string then all are returned.

There must not be any spaces between the RIGHT$ and the opening bracket.

A$=RIGHT$(A$,num)
A$=RIGHT$(A$,2)
A$=RIGHT$(LEFT$(A$,3),2)

For example,

10 name$="BBCBASIC(Z80)"
20 FOR i=3 TO 14
30   PRINT RIGHT$(name$,i)
40 NEXT
50 END

would print

80)
Z80)
(Z80)
C(Z80)
IC(Z80)
SIC(Z80)
ASIC(Z80)
BASIC(Z80)
CBASIC(Z80)
BCBASIC(Z80)
BBCBASIC(Z80)
BBCBASIC(Z80)

Syntax

<s-var>=RIGHT$(<str>,<numeric>)

Associated Keywords

  • LEFT$
  • MID$
  • LEN
  • INSTR


RND

A function which returns a random number. The type and range of the number returned depends upon the optional parameter.

Argument | Result
RND | Returns a random integer 1 - &FFFFFFFF.
RND(1) | Returns a real number in the range 0.0 to .99999999.
RND(0) | Returns the previous random number in RND(1) format.
RND(n>1) | Returns an integer in the range 1 to n (n>1).
RND(n<0) | Seeds the pseudo-random sequence generator and returns the seed value.

The random number generator is initialised by RUN (or CHAIN). Consequently, RND will return zero until the RUN (or CHAIN) command is first issued.

X=RND(1)
X%=RND
N=RND(6)

Syntax

<n-var>=RND[(<numeric>)]


RUN

Start execution of the program.

RUN

RUN is a statement and so programs can re-execute themselves.

All variables except @% to Z% are CLEARed by RUN.

If you want to start a program without clearing all the variables, you can use the statement

GOTO nnnn

where nnnn is number of the line at which you wish execution of the program to start.

RUN "filename" can be used as an alternative to CHAIN "filename".

Syntax

RUN

Associated Keywords

  • NEW
  • OLD
  • LIST
  • CHAIN


SAVE

SAVESA.

A statement which saves the current program area to a file, in internal (tokenised) format.

SAVE "FRED.BBC"
SAVE A$

You use SAVE to save your program for use at a later time. The program must be given a name (file-specifier) and this name becomes the name of the file in which your program is saved.

Syntax

SAVE <str>

Associated Keywords

  • LOAD
  • CHAIN


SGN

A function returning -1 for negative argument, 0 for zero argument and +1 for positive argument.

X=SGN(Y)
result=SGN(answer)

You can use this function to determine whether a number is positive, negative or zero.

Syntax

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

Associated Keywords

ABS


SIN

A function giving the sine of its radian argument.

X=SIN(Y)

This function returns the sine 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 sine of the angle 'degree_angle' expressed in degrees.

Y=SIN(RAD(degree_angle))

Syntax

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

Associated Keywords

  • COS
  • TAN
  • ACS
  • ASN
  • ATN
  • DEG
  • RAD


SPC

A statement which prints a number of spaces to the screen. The argument specifies the number of spaces (up to 255) to be printed.

SPC can only be used within a PRINT or INPUT statement.

PRINT DATE;SPC(6);SALARY
INPUT SPC(5) "What is your name ",name$

Syntax

  • PRINT SPC(<numeric>)
  • INPUT SPC(<numeric>)

Associated Keywords

  • TAB
  • PRINT
  • INPUT


SQR

A function returning the square root of its argument.

X=SQR(Y)

If you attempt to calculate the square root of a negative number, a '-ve root' error will occur. You could use error trapping to recover from this error, but it is better to check that the argument is not negative before using the SQR function.

Syntax

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


STEP

STEPS.

Part of the FOR statement, this optional section specifies step sizes other than 1.

FOR i=1 TO 20 STEP 5

The step may be positive or negative. STEP is optional; if it is omitted, a step size of +1 is assumed.

You can use this optional part of the FOR...TO...STEP...NEXT structure to specify the amount by which the FOR...NEXT loop control variable is changed each time round the loop. In the example below, the loop control variable, 'cost' starts as 20, ends at 5 and is changed by -5 each time round the loop.

10 FOR cost=20 TO 5 STEP -5
20   PRINT cost,cost*1.15
30 NEXT

Syntax

FOR <n-var>=<numeric> TO <numeric> [STEP <numeric>]

Associated Keywords

  • FOR
  • TO
  • NEXT


STOP

Syntactically identical to END, STOP also prints a message to the effect that the program has stopped.

You can use STOP at various places in your program to aid debugging. If your program is going wrong, you can place STOP commands at various points to see the path taken by your program. (TRACE is generally a more useful aid to tracing a program's flow unless you are using formatted screen displays).

Once your program has STOPped you can investigate the values of the variables to find out why things happened the way they did.

Stop does not close data files. If you use STOP to exit a program for debugging, CLOSE all the data files before RUNning the program again. If you don't you will get some most peculiar error messages.

Syntax

STOP

Associated Keywords

  • END


STR$

A string function which returns the string form of the numeric argument as it would have been printed.

If the most significant byte of @% is not zero, STR$ uses the current @% description when generating the string. If it is zero (the initial value) then the G9 format (see PRINT) is used.

If STR$ is followed by ~ (tilde) then a hexadecimal conversion is carried out.

A$=STR$(PI)
B$=STR$~(100) :REM B$ will be "64"

The opposite function to STR$ is performed by the VAL function.

Syntax

<s-var>=STR$[~](<numeric>)

Associated Keywords

  • VAL
  • PRINT


STRING$

A function returning N concatenations of a string.

A$=STRING$(N,"hello")
B$=STRING$(10,"-*-")
C$=STRING$(Z%,S$)

You can use this function to print repeated copies of a string. It is useful for printing headings or underlinings. The last example for PRINT uses the STRING$ function to print the column numbers across the page. For example,

PRINT STRING$(4,"-=*=-")

would print

-=*=--=*=--=*=--=*=-

and

PRINT STRING$(3,"0123456789")

would print

012345678901234567890123456789

Syntax

  • <s-var>=STRING$(<numeric>,<str>)


SWAP

This is an experimental feature that may change in future versions.
It is provided for compatibility with the Windows version of BBC BASIC and to enhance the code readibility of the Z80 version.

A statement which swaps (exchanges) the contents of two variables. The variables must be of the same type, for example two integer numeric variables or two strings. If the types differ, a Type mismatch error will result.

SWAP a,b
SWAP Coat$,Hat$
SWAP array%(3),array%(4)
SWAP buffer!0,buffer!4

Be very careful when swapping fixed strings that there is sufficient storage for both strings. For example, the following code

DIM tiny 4 : $tiny="Tiny"
DIM gigantic 8 : $gigantic="Gigantic"
SWAP $tiny,$gigantic

will try and swap the string 'Gigantic' (9 bytes including its CR terminator) into a memory location where only five bytes were allocated.

Syntax

  • SWAP <n-var>,<n-var>
  • SWAP <s-var>,<s-var>


TAB

A keyword available in PRINT or INPUT.

There are two versions of TAB: TAB(X) and TAB(X,Y) and they are effectively two different keywords.

  • TAB(X) is a printer orientated statement. The number of printable characters since the last new-line (COUNT) is compared with X. If X is equal or greater than COUNT, sufficient spaces to make them equal are printed. These spaces will overwrite any characters which may already be on the screen. If X is less than COUNT, a new-line will be printed first.
  • TAB(X,Y) is a screen orientated statement. It will move the cursor on the screen to character cell X,Y (column X, row Y) if possible. No characters are overwritten and COUNT is not updated. Consequently, a TAB(X,Y) followed by a TAB(X) will give unpredictable (at first glance) results.

The leftmost column is column 0 and the top of the screen is row 0.

PRINT TAB(10);A$
PRINT TAB(X,Y);B$

Syntax

  • PRINT TAB(<numeric>[,<numeric>])
  • INPUT TAB(<numeric>[,<numeric>])

Associated Keywords

  • POS
  • VPOS
  • PRINT
  • INPUT


TAN

TANT.

A function giving the tangent of its radian argument.

X = TAN(Y)

This function returns the tangent 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 tangent of the angle 'degree_angle' expressed in degrees.

Y=TAN(RAD(degree_angle))

Syntax

<n-var>=TAN<numeric>

Associated Keywords

  • COS
  • SIN
  • ACS
  • ATN
  • ASN
  • DEG
  • RAD


THEN

THENTH.

An optional part of the IF...THEN...ELSE statement. It introduces the action to be taken if the testable condition evaluates to TRUE.

IF A=B THEN 3000
IF A=B THEN PRINT "Equal" ELSE PRINT "Help"

You need to use THEN if it is followed by:

  • A line number.
IF a=b THEN 320
  • A 'star' (*) command.
IF a=b THEN *BYE
  • An assignment of a pseudo-variable.
IF a=b THEN TIME=0

or you wish to exit from a function as a result of the test. This is because BBC BASIC (Z80) can't work out what you mean in these circumstances if you leave the THEN out.

IF A=B PRINT "Equal" ELSE PRINT "Help"
DEF FN_test(num)
IF a=b THEN =num: REM THEN required on this line
=num/256

Syntax

  • IF <t-cond> THEN <stmt>{:<stmt>} [ELSE <stmt>{:<stmt>}]

Associated Keywords

  • IF
  • ELSE


TIME

TIMETI.

A pseudo-variable which reads and sets the elapsed time clock.

X=TIME
TIME=100

You can use TIME to set and read BBC BASIC (Z80)'s internal clock. The value of the clock is returned in centi-seconds (one-hundredths of a second).

The clock is reset to zero when BBC BASIC is started. Note that this clock is not accurate, it is merely an approximation.

Syntax

  • TIME=<numeric>
  • <n-var>=TIME

Associated Keywords

  • TIME$
  • WAIT


TIME$

Introduction

A 24 character long string pseudo-variable which reads and sets the system clock. On the TI-84+ series this accesses the accurate hardware real-time clock. On the TI-83+ series an inaccurate software simulation of the real-time clock is implemented. This software clock resets to 12:00, 1st January 2001 every time BBC BASIC is restarted and keeps lousy time but is provided for compatibility.

The format of the character string is:

Day,dd Mon yyyy.hh:mm:ss

Where:

Day | is the day of the week (Mon, Tue, etc).
dd | is the day of the month (01, 02, etc).
Mon | is the abbreviated month name (Jan, Feb ,etc).
yyyy | is the year (1986, 1987, etc).
hh | is hours (00 to 23).
mm | is minutes (00 to 59).
ss | is seconds (00 to 59).

The format is the same as that used on the Master Series BBC Micro, but differs to that used in BBC BASIC (86) and BBC BASIC for Windows which exchange the position of the comma (,) and the full-stop (.).

clock$=TIME$
TIME$="Sun,02 Feb 1986.18:33:30"

The time, date or both time and date may be set as shown below.

TIME$="Day,dd Mon yyyy"           : REM sets the date.
TIME$="hh:mm:ss"                  : REM sets the time.
TIME$="Day,dd Mon yyyy.hh:mm:ss"  : REM sets date & time.

No error is reported if the format is not accurately adhered to, however the clock may be set incorrectly.

Syntax

  • TIME$=<str>
  • <s-var>=TIME$

Associated Keywords

  • TIME


TO

The part of the FOR...TO...STEP statement which introduces the terminating value for the loop. When the loop control variable exceeds the value following 'TO' the loop is terminated.

For example,

10 FOR i=1 TO 5 STEP 1.5
20   PRINT i
30   NEXT
40 PRINT "**********"
50 PRINT i

will print

         1
       2.5
         4
**********
       5.5

Irrespective of the initial value of the loop control variable and the specified terminating value, the loop will execute at least once. For example,

10 FOR i= 20 TO 10
20   PRINT i
30 NEXT

will print

        20

Syntax

FOR <n-var>=<numeric> TO <numeric> [STEP <numeric>]

Associated Keywords

  • FOR
  • NEXT
  • STEP


TOP

A function which returns the value of the first free location after the end of the current program.

The length of your program is given by TOP-PAGE.

PRINT TOP-PAGE

Syntax

<n-var>=TOP

Associated Keywords

  • PAGE
  • HIMEM
  • LOMEM


TRACE

TRACETR.

TRACE ON causes the interpreter to print executed line numbers when it encounters them.

TRACE X sets a limit on the size of line numbers which will be printed out. Only those line numbers less than X will appear. If you are careful and place all your subroutines at the end of the main program, you can display the main structure of the program without cluttering up the trace with the subroutines.

TRACE OFF turns trace off. TRACE is also turned off if an error is reported or you press Escape.

Line numbers are printed as the line is entered. For example,

10 FOR Z=0 TO 2:Q=Q*Z:NEXT
20 END

would trace as

[10] [20] >_

whereas

10 FOR Z=0 TO 2
20   Q=Q*Z:NEXT
30 END

would trace as

[10] [20] [20] [20] [30] >_

and

10 FOR Z=0 TO 3
20 Q=Q*Z
30 NEXT
40 END

would trace as

[10] [20] [30] [20] [30] [20] [30] [40] >_

Syntax

TRACE ON|OFF|<l-num>


TRUE

A function returning the value -1.

 10 flag=FALSE
...
100 IF answer$=correct$ flag=TRUE
...
150 IF flag PROC_got_it_right ELSE PROC_wrong

BBC BASIC (Z80) does not have true Boolean variables. Instead, numeric variables are used and their value is interpreted in a 'logical' manner. A value of 0 is interpreted as false and NOT FALSE (in other words, NOT 0 (= -1)) is interpreted as TRUE.

In practice, any value other than zero is considered TRUE. This can lead to confusion; see the keyword NOT for details.

See the Variables sub-section for more details on Boolean variables and the keyword AND for logical tests and their results.

Syntax

<n-var>=TRUE

Associated Keywords

  • FALSE
  • EOR
  • OR
  • AND
  • NOT


UNTIL

UNTILU.

The part of the REPEAT…UNTIL structure which signifies its end.

You can use a REPEAT…UNTIL loop to repeat a set of program instructions until some condition is met.

If the condition associated with the UNTIL statement is never met, the loop will execute for ever. (At least, until Escape is pressed or some other error occurs).

The following example will continually ask for a number and print its square. The only way to stop it is by pressing Escape or forcing a 'Too big' error.

10 z=1
20 REPEAT
30   INPUT "Enter a number " num
40   PRINT "The square of ";num;" is ";num*num
50 UNTIL z=0

Since the result of the test z=0 is always false, we can replace z=0 with FALSE. The program now becomes:

20 REPEAT
30   INPUT "Enter a number " num
40   PRINT "The square of ";num;" is ";num*num
50 UNTIL FALSE

This is a much neater way of unconditionally looping than using a GOTO statement. The program executes at least as fast and the section of program within the loop is highlighted by the indentation.

See the keyword REPEAT for more details on REPEAT…UNTIL loops. See the Variables sub-section for more details on Boolean variables and the keyword AND for logical tests and their results.

Syntax

UNTIL <t-cond>

Associated Keywords

  • REPEAT


USR

A function which allows a machine code routine to return a value directly.

As with CALL, the processor's registers are initialised as follows:

  • A is initialised to the least significant byte of A%
  • B is initialised to the least significant byte of B%
  • C is initialised to the least significant byte of C%
  • D is initialised to the least significant byte of D%
  • E is initialised to the least significant byte of E%
  • F is initialised to the least significant byte of F%
  • H is initialised to the least significant byte of H%
  • L is initialised to the least significant byte of L%

USR returns a 32-bit integer result composed of the processor's H, L, H' and L' registers, with H being the most significant.

Syntax

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

Associated Keywords

  • CALL


VAL

A function which converts a character string representing a number into numeric form.

X=VAL(A$)

VAL makes the best sense it can of its argument. If the argument starts with numeric characters (with or without a preceding sign), VAL will work from left to right until it meets a non numeric character. It will then 'give up' and return what it has got so far. If it can't make any sense of its argument, it returns zero.

For example,

PRINT VAL("-123.45.67ABC")

would print

-123.45

and

PRINT VAL("A+123.45")

would print

0

VAL will NOT work with hexadecimal numbers. You must use EVAL to convert hexadecimal number strings.

Syntax

<n-var>=VAL(<str>)

Associated Keywords

  • STR$
  • EVAL


VDU

VDUV.

A statement which takes a list of numeric arguments and sends their least-significant bytes as characters to the current output stream.

A 16-bit value can be sent if the value is followed by a ';'. It is sent as a pair of characters, least significant byte first.

VDU 8,8 :REM cursor left two places.
VDU &0A0D;&0A0D; :REM CRLF twice

The bytes sent using the VDU statement do not contribute to the value of COUNT, but may well change POS and VPOS.

You can use VDU to send characters direct to the current output stream without having to use a PRINT statement. It offers a convenient way of sending a number of control characters to the console.

BBC Micro VDU Emulation

All the console output is passed to a software emulation of the BBC Micro's VDU driver. The VDU codes then perform a function as similar as possible to those of the BBC Micro. The function of the various VDU codes when using the default output stream are described in the VDU Emulator section.

Syntax

VDU <numeric>{,|;<numeric>}[;]

Associated Keywords

  • CHR$


VPOS

A function returning the vertical cursor position. The top of the screen is line 0.

Y=VPOS

You can use VPOS in conjunction with POS to return to the present position on the screen after printing a message somewhere else. The example below is a procedure for printing a 'status' message at line 7. The cursor is returned to its previous position after the message has been printed.

1000 DEF PROC_message(message$)
1010 LOCAL x,y
1020 x=POS
1030 y=VPOS
1040 PRINT TAB(0,7) CHR$(7);message$;
1050 PRINT TAB(x,y);
1060 ENDPROC

Syntax

<n-var>=VPOS

Associated Keywords

  • POS


WAIT

A statement causing the program to pause for the specified number of centiseconds (hundredths of a second).

WAIT 100

This causes the program to pause for approximately one second.

Syntax

WAIT <numeric>

Associated Keywords

  • INKEY
  • TIME


WHILE

This is an experimental feature that may change in future versions.
It is provided for compatibility with the Windows version of BBC BASIC and to enhance the code readibility of the Z80 version.

A statement which is the starting point of a WHILE…ENDWHILE loop.

The purpose of a WHILE…ENDWHILE loop is to make BBC BASIC repeat a set number of instructions while some condition is satisfied. The difference between a WHILE…ENDWHILE loop and a REPEAT…UNTIL loop is that the instructions within a REPEAT…UNTIL loop are always executed at least once (the test for completion is performed at the end of the loop) whereas the instructions within a WHILE…ENDWHILE loop are not executed at all if the condition is initially FALSE (the test is performed at the start of the loop).

WHILE LEFT$(A$,1)=" "
  A$=MID$(A$,2) : REM Remove leading spaces
ENDWHILE

You must not exit a WHILE…ENDWHILE loop with a GOTO (see the sub-section on Flow Control for more details). You can force a premature end to the loop with the EXIT WHILE statement.

WHILE…ENDWHILE loops may be nested.

Syntax

  • WHILE <t-cond>

Associated Keywords

  • ENDWHILE
  • EXIT
  • REPEAT


WIDTH

WIDTHW.

A statement controlling output overall field width.

WIDTH 20

If the specified width is zero (the initial value) the interpreter will not attempt to control the overall field width.

WIDTH n will cause the interpreter to force a new line after n MOD 256 characters have been printed.

Syntax

WIDTH <numeric>

Associated Keywords

  • COUNT


¦

*¦ is an alternative method to declare a comment line. Anything following this sequence is ignored.

*¦ This is a comment.

See the REM keyword for the BASIC statement to declare comments.


BUILDINFO

This commands outputs information about the current build of BBC BASIC to the console.

Two lines are output: the first detailing the SVN revision of the build, the second detailing the date and time that the software was built. An example of the output is shown below:

Revision 577
Sat,17 Jan 2009.21:49:51

This information is provided as a way to identify specific versions of the host interface and should be included along with any bug reports.


BYE

This command exits BBC BASIC (Z80) and returns to the TI-OS.

It is synonymous with *QUIT and *EXIT.


DELETE

DELETE*DEL

Deletes the specified file. The command must be followed by a filename; the extension may be omitted (and defaults to .PRG).

*DEL TETRIS
*DEL SPRITES.VAR

See the Files section for more information on files.


DIR*.

Lists all the variables on the calculator. The syntax is similar to the MS-DOS DIR command.

  • *DIR - List all supported files on the calculator.
  • *DIR *.VAR - List all application variables.
  • *DIR Z* - List all variable names starting with the letter Z.

The variable name pattern can contain one of two wildcard characters:

  • * - Matches any number of characters.
  • ? - Matches any single character.

Device files are not reported by this command.

*CAT (for catalogue) can be used as an alias for *DIR.

Syntax

*DIR [pattern]


ERASE

ERASE*ERA

*ERASE (and its abbreviation *ERA) are synonyms for the *DELETE command.


ESC

Changes the behaviour of the Escape key.

  • *ESC ON - Pressing the Escape (On) key triggers the Escape error. This is the default behaviour.
  • *ESC OFF - Escape acts as a normal key, returning the key code 27.

Syntax

*ESC ON|OFF


EXEC

Accept console input from the specified text file instead of from the keyboard. If the extension is omitted, .PRG is assumed.

*EXEC
OSCLI "EXEC """+cmdfile$+""""

Once the entire file has been read, keyboard input is restored. *EXEC without a filename closes the file and restores keyboard input immediately.

Syntax

*EXEC [filename]


EXIT

This command exits BBC BASIC (Z80) and returns to the TI-OS.

It is synonymous with *BYE and *QUIT.


FONT

Introduction

Mixed small and large fonts

The size and appearance of characters depends on the current screen MODE. This command allows you to choose the font used when drawing text in VDU 5 mode.

The font used when rendering in the default VDU 4 mode cannot be changed as it requires that the characters fit into a fixed grid. When in VDU 4 mode text will always be printed in the default font for the current MODE even if it has been changed with *FONT.

Changing MODE resets the font to its default value.

Usage

There are two main fonts; a small 4×6 pixel font with fixed characters and a large 8×8 pixel font with user-definable characters.

  • *FONT SMALL selects the small font.
  • *FONT LARGE selects the large font.
  • *FONT resets the font to its default for the current screen MODE.

The image at the top of this page was generated with the following program:

10 MODE 3
20 VDU 5
30 MOVE 0,255 : PRINT "Small"
40 *FONT LARGE
50 MOVE 0,227 : PRINT "Large"
60 VDU 4
70 PRINT TAB(0,3) "Small (VDU 4)"

As you can see, the *FONT setting has no effect in VDU 4 mode.

Syntax

*FONT [SMALL|LARGE]


FX

The *FX command can be used to control some of the system's "special effects", such as keyboard repeat rates or manipulating the Escape condition.

*FX is in fact a convenient way to call OSBYTE routines from BASIC programs or the command line. For example, to set the keyboard's auto-repeat rate you set the routine number A to 12 and load the repeat rate into L, then call OSBYTE like this:

A%=12
L%=4
CALL &FFF4

*FX takes up to three arguments, A, L and H, and passes them to OSBYTE. The above code could therefore be rewritten as follows:

*FX 12,4

All arguments are specified in decimal. The L and H arguments are optional.

For a full list of available *FX routines see the OSBYTE section.

Syntax

*FX A[,L[,H]]

See Also

  • OSBYTE


GBUF

Introduction

All drawing operations operate on a 768 byte buffer in memory. This buffer is copied to the screen after every drawing operation providing that *REFRESH has not been switched OFF.

You may wish to create multiple screen buffers and switch between them when your program is running. Switching display buffers is extremely fast; you can perform a slow, complex series of drawing operations once, swap out the buffer then recall it in an instant when required.

Usage

*GBUF takes an optional argument that specifies the address of the buffer in hexadecimal:

*GBUF addr

If you do not pass an argument to *GBUF the buffer address is reset to BBC BASIC's internal buffer.

10 HIMEM=HIMEM-768:buf%=HIMEM : REM Allocate 768 bytes at the end of memory.
20 OSCLI"GBUF"+STR$~buf%      : REM Set this buffer as the current graphics buffer.
30 :
40 CLS:PRINT "Hello, World!"  : REM Drawing operations now act on this new buffer.
50 WAIT 500                   : REM Wait 5 seconds.
60 :
70 OSCLI"GBUF"                : REM Revert to the original internal buffer.
80 HIMEM=HIMEM+768            : REM Move HIMEM back up to its original position.

Warning

All drawing operations operate on the graphics buffer that you have specified, even after program termination. You must ensure that the buffer is in a safe place - preferably the internal buffer - when your program has terminated. The following code

10 DIM buf% 767
20 OSCLI"GBUF"+STR$~buf%

allocates 768 bytes on the heap (which starts immediately after the end of the program in memory) for use as a secondary buffer. If more lines were added to the program after running the above code it would grow into the area that used to be the heap and so into the area that contains the active graphics buffer. As this buffer is still being used any changes to it will also corrupt the program, resulting in a Bad program error.

The safest way to allocate memory is to move HIMEM down as BBC BASIC will not touch memory above HIMEM; to free the memory at the end of your program first invoke *GBUF without any arguments to revert to the internal buffer then move HIMEM back up.

Syntax

*GBUF [addr]

See Also

  • *REFRESH


GSCALE

This command allows you to set the number of logical pixels per device pixel on either axis. The number of logical pixels per device pixel usually depends on the MODE you are currently using.

For example, if you entered the following command:

*GSCALE 16

you would have 16 logical pixels per device pixel. As the calculator's screen has 96 physical pixels horizontally and 64 physical pixels vertically this gives you a logical resolution of 1536×1024, which is near to the BBC Micro's logical resolution of 1280×1024.

On the other hand,

*GSCALE 1

would have one logical pixel per device pixel. Assuming the graphics origin was in the bottom-left hand corner of the screen (as it is by default) the top-right corner would be at (95,63) in this mode.

You can set a different scale factor on the X axis to the scale factor on the Y axis by passing two arguments:

*GSCALE 2,4

This mode would have two logical pixels per device pixel in the X axis and four logical pixels per device pixel in the Y axis.

The valid scale factors are 1, 2, 4, 5, 8, 16, 32, 64 and 128. No other value is permitted.

Syntax

  • *GSCALE scale_factor
  • *GSCALE x_scale_factor,y_scale_factor


HIMEM

Moves HIMEM safely and allocates or frees memory as appropriate from the TI-OS.

*HIMEM addr

BBC BASIC allocates as much memory as it can from the TI-OS when it first loads, restricting HIMEM to a maximum value of &C000. You may wish to increase HIMEM to give BBC BASIC more memory for a large program, or you may wish to decrease HIMEM to give the TI-OS more memory to create new files in.

Assuming that HIMEM was at &C000,

*HIMEM D000

would raise HIMEM to &D000, supplying BBC BASIC with 4KB more memory than it would usually have. If there was insufficient RAM available, a No room error is triggered and HIMEM is not moved.

*HIMEM C000

would drop HIMEM back down to &C000. Unlike the HIMEM statement, the memory between the old value and new value is freed back to the TI-OS, so do not use *HIMEM to allocate memory for persistent assembly routines.

If you do not pass a value to *HIMEM then HIMEM is restored to its upper bound. This is useful if you have previously moved HIMEM yourself, for example:

REM Reserve 100 bytes at the top of memory.
HIMEM=HIMEM-100

...

REM Move HIMEM back up to let BBC BASIC reclaim that memory.
*HIMEM

*HIMEM must not be used within a subroutine, procedure, function, FOR...NEXT, REPEAT...UNTIL or GOSUB loop. It should be used early in your program.

You can use *HIMEM and EXT#-1 together to allocate all free memory to BBC BASIC.

OSCLI "HIMEM "+STR$~(HIMEM+EXT#-1)


LOAD

Load the specified file into memory at hexadecimal address aaaa. The load address must always be specified.

  • *LOAD filename aaaa
*LOAD WOMBAT AF00

You could use this to load data into the graphics buffer (located at &9340) from a picture variable.

*LOAD PIC3.PIC 9340
*REFRESH

OSCLI may also be used to load a file. However, you must take care to provide the load address as a hexadecimal number in string format.

OSCLI "LOAD "+file_name$+" "+STR$~(start_address)

See the Files section for more information about files.

Associated Keywords

  • *SAVE


QUIT

This command exits BBC BASIC (Z80) and returns to the TI-OS.

It is synonymous with *BYE and *EXIT.


REFRESH

By default, the screen is updated every time BBC BASIC displays text or graphics. There are instances when may you wish to temporarily suspend this behaviour, for example to reduce flicker when an animation is being displayed.

*REFRESH ON | The default behaviour is to update the screen as soon as graphics or text is displayed. This can result in flickery animation.
*REFRESH OFF | By disabling the automatic update and explicitly calling *REFRESH, smooth animation is possible.
  • *REFRESH forces an immediate screen refresh.
  • *REFRESH OFF disables the automatic refresh; the screen will only be updated as the result of a *REFRESH command.
  • *REFRESH ON restores the normal behaviour.

A typical render loop for animated graphics may look like this:

10 *REFRESH OFF
20 exited=FALSE
30 REPEAT
40   ...
50   ...
60   ...
70   *REFRESH
80 UNTIL exited
90 *REFRESH ON

When an error is unhandled or otherwise reported, automatic refresh is switched back on so that the error message can be seen.

Syntax

*REFRESH [ON|OFF]

See Also

  • *GBUF


RESETCHR

Resets a user-defined character to its original value.

*RESETCHR char_no

char_no is the number of the character, in decimal, to reset. You can reset a range of characters in a single go by specifying a start and end character number separated by a comma:

*RESETCHR start,end

If you don't specify any arguments all characters are reset.

*RESETCHR

See Also

  • VDU 23


SAVE

SAVE*S.

Save an area of memory to a file. If the extension is omitted, .PRG is assumed.

You must specify the start address (aaaa) and either the length of the area of memory (llll) or its end address+1 (bbbb). All values are specified in hexadecimal. There is no 'load address' or 'execute address'.

  • *SAVE filename aaaa +llll saves llll bytes starting from aaaa to file filename.
  • *SAVE filename aaaa bbbb saves data from aaaa to bbbb-1 to file filename.

The following examples would perform exactly the same operation:

*SAVE "WOMBAT" AF00 +80
*SAVE "WOMBAT" AF00 AF80

The graphics buffer is located at &9340 and picture variables can store its first 63 lines (756 bytes). To save the current screen image to the Pic2 variable you could use the following code:

*SAVE PIC2.PIC 9340+2F4

(2F4 is 756 in hexadecimal).

OSCLI can also be used to save a file.

OSCLI "SAVE "+filename$+" "+STR$~(add)+"+"+STR$~(len)

See the Files section for more information about files.

Associated Keywords

  • *LOAD


SLEEP

Introduction

By default the calculator will switch into a low power mode if you leave it waiting for a key press for more than a couple of minutes. *SLEEP can be used to set the amount of time to wait before switching into this lower power mode, disable the automatic power down feature entirely, or go into the low power mode instantly.

Details

When in the low power mode the calculator will only respond to the On key, which will switch it back on. The screen is switched off and the TIME pseudo-variable is not updated. On the TI-83+ series the software-implemented TIME$ variable is not updated either; the TI-84+ has a hardware real-time clock and so is not affected.

Setting the time-out

You can set the calculator to switch off after a particular number of idle seconds by passing a numerical argument to *SLEEP. For example,

*SLEEP 10

would switch the calculator into a low power mode after 10 seconds of inactivity.

The shortest amount of time allowed is 5 seconds. The longest amount of time allowed is 65,535 seconds (over 18 hours). A value of 0 disables the automatic power down completely. The default setting is 120 seconds, or two minutes.

Switching the calculator off instantly

If you don't pass any arguments to *SLEEP the calculator switches into the low power mode instantly.

*SLEEP

Disabling the automatic power down

If you pass OFF to *SLEEP the automatic power down is disabled.

*SLEEP OFF

This is directly equivalent to *SLEEP 0.

Resetting defaults

If you wish to reset to the default settings (two minute time-out) you can pass ON to *SLEEP:

*SLEEP ON

This is directly equivalent to *SLEEP 120.

Syntax

*SLEEP [ON|OFF|time]


SPEED

This command changes the CPU clock speed on hardware that supports it.

  • The TI-83+ CPU will run at 6MHz only.
  • The TI-83+SE, TI-84+ and TI-84+SE CPU will run at either 6MHz or 15MHz.

Numerical argument

If you pass a numerical argument to *SPEED the CPU speed will be set accordingly. For example,

*SPEED 15

sets the CPU speed to 15MHz on a TI-83+SE, TI-84+ or TI-84+SE. If you try and set the speed to a rate that the hardware does not support, such as running the above example on a regular TI-83+, a Bad command error is triggered.

SLOW or FAST

SLOW or FAST may be passed to *OSCLI to set the CPU to its slowest or fastest available speed.

*SPEED SLOW

On the regular TI-83+ both SLOW and FAST set the rate to 6MHz. On the TI-83+SE, TI-84+ and TI-84+SE the rates are 6MHz and 15MHz respectively.

Syntax

  • *SPEED clock_rate
  • *SPEED SLOW|FAST


YAXIS

This command allows you to control the orientation of the Y axis for graphics commands.

*YAXIS UP

The above command makes the Y axis increase up the screen, with the absolute origin located in the bottom-left hand corner. This is the default mode.

*YAXIS DOWN

The above command makes the Y axis increase down the screen, with the absolute origin located in the top-left hand corner.

Syntax

  • *YAXIS UP|DOWN


OSASCI

OSASCI&FFE3

When calling the OSASCI routine from machine code you will need to use the absolute address &40E3. However, when CALLing this routine from BBC BASIC it is recommended that you use the BBC Micro-compatible address &FFE3.

This outputs a character using OSWRCH. ASCII CR (13) is converted to a LF, CR sequence (13, 10) and the F register is destroyed.

See Also

  • VDU
  • OSWRCH
  • OSNEWL


OSBGET

OSBGET&FFD7

When calling the OSBGET routine from machine code you will need to use the absolute address &40D7. However, when CALLing this routine from BBC BASIC it is recommended that you use the BBC Micro-compatible address &FFD7.

This routine reads a byte from a file via its handle. The file pointer is incremented after the byte has been read.

This routine performs the same task as the BGET# function.

On entry, H contains the file handle. On exit the carry flag is set if the file pointer was at the end of the file, otherwise A contains the value read from the file.


OSBPUT

OSBPUT&FFD4

When calling the OSBPUT routine from machine code you will need to use the absolute address &40D4. However, when CALLing this routine from BBC BASIC it is recommended that you use the BBC Micro-compatible address &FFD4.

A routine which writes a byte to an open file via its handle. The file pointer is incremented after the byte has been written. This routine performs the same task as the BPUT# statement.

On entry, H contains the file handle and A contains the value to write to the file.


OSBYTE

OSBYTE&FFF4

When calling the OSBYTE routine from machine code you will need to use the absolute address &40F4. However, when CALLing this routine from BBC BASIC it is recommended that you use the BBC Micro-compatible address &FFF4.

Introduction

The OSBYTE call provides a way to invoke routines provided by the host interface or operating system to carry out a wide variety of different tasks, such as setting the keyboard repeat rates or manipulating the Escape condition.

Before calling OSBYTE you must first set the Z80 accumulator register A to the number of the OSBYTE routine you wish to call. The Z80 registers L and H can also be used as inputs or outputs depending on the specified routine.

*FX provides a more convenient way to invoke OSBYTE routines from BASIC programs or the command-line.

Several routines return values in L or H. You may be able to retrieve these values from BBC BASIC if you call OSBYTE via USR as that returns the result from HLH'L'.

Unless otherwise mentioned, only the registers A, L and H will be modified. These are analogous to the A, X and Y 6502 CPU registers in the BBC Micro version of BBC BASIC.

Routines

OSBYTE &00, *FX 0

Identify Operating System version

If L is zero this will print a message identifying the version of the TI-83+ or TI-84+ OS. If L is non-zero this message is supressed.

After execution L will contain the value 29 (&1D) to identify the hardware as a TI-83+/TI-84+ calculator.

OSBYTE &01, *FX 1

Read/write the user flag

The user flag is replaced by

This flag is unused and left free for use in your own applications. It is reset to 0 on initialisation.

OSBYTE &04, *FX 4

Enable/disable cursor editing

L determines the the function of the cursor editing keys.

  • *FX 4,0 - Enable cursor editing (default).
  • *FX 4,1 - Disable cursor editing.

When disabled the cursor editing keys return the following values:

Key | Value
Copy | &87 (135)
Left | &88 (136)
Right | &89 (137)
Down | &8A (138)
Up | &8B (139)

OSBYTE &0B, *FX 11

Set keyboard auto-repeat delay

L determines the delay before keys start repeating when held.

  • *FX 11,0 - Disables key repeating.
  • *FX 11,n - Sets the delay to n centiseconds.

The old setting is returned in L. The default delay value is 32 centiseconds.

OSBYTE &0C, *FX 12

Set keyboard auto-repeat rate

L determines the time period for repeating keys.

  • *FX 12,0 - Resets repeat delay and repeat interval to their defaults.
  • *FX 12,n - Sets the repeat interval to n centiseconds.

The old setting is returned in L. The default delay value is 8 centiseconds.

OSBYTE &7C, *FX 124

Clear Escape condition

This routine will instantly clear any pending Escape condition. If a previous call to OSRDCH had returned with the carry flag set to indicate the Escape condition you can use this routine to prevent BBC BASIC from receiving notification of the condition.

OSBYTE &7D, *FX 125

Clear Escape condition

This routine will set a pending Escape condition. Note that this is not affected by the ESC OFF command.

OSBYTE &7E, *FX 126

Acknowledge detection of an Escape condition

This routine attempts to clear the Escape condition after closing any open EXEC files.

On exit L is &FF if the condition was cleared successfully or &00 if the condition was not cleared.

OSBYTE &7F, *FX 127

Check for end-of-file on an opened file

L contains the file handle to check. On exit, L is non-zero if the end-of-file has been reached and zero if the end-of-file has not been reached.

See the EOF# keyword for more information.

OSBYTE &86, *FX 134

Read text cursor position (POS and VPOS)

On exit,

  • L contains the horizontal cursor position (POS).
  • H contains the vertical cursor position (VPOS).

OSBYTE &87, *FX 135

Read character at text cursor position

On exit, L contains the character value.

OSBYTE &C4, *FX 196

Read/write keyboard auto-repeat delay

OSBYTE &C5, *FX 197

Read/write keyboard auto-repeat period (rate)

OSBYTE &C6, *FX 198

Read/write *EXEC file handle

The value is zero if no file is currently open.

OSBYTE &C8, *FX 200

Read/write Escape effect

If the least significant bit is

  • 0, Escape functions as normal.
  • 1, Escape is ignored unless it was caused by OSBYTE &7D.

OSBYTE &DA, *FX 218

Read/write number of items in the VDU queue

This contains the negative number of pending bytes required to execute the current VDU command. Writing 0 to this location is a useful way to abandon the queue - it is recommended that you do not write any other values.

OSBYTE &ED, *FX 237

Read/write cursor editing status

OSBYTE &F1, *FX 241

Read/write user flag

See Also

  • *FX
  • OSWORD


OSCLI

OSCLI&FFF7

When calling the OSCLI routine from machine code you will need to use the absolute address &40F7. However, when CALLing this routine from BBC BASIC it is recommended that you use the BBC Micro-compatible address &FFF7.

This routine passes a string to the command-line interpreter. It performs the same job as the OSCLI BASIC statement.

On entry HL should point to the CR-terminated command string. Any leading '*'s and spaces are skipped.

 10 oscli=&40F7
 20 DIM listPrograms 16
 30 FOR pass=0 TO 1
 40   P%=listPrograms
 50   [
 60   OPT pass*2
 70   LD HL,command
 80   JP oscli
 90   .command
100   DEFM "CAT *.PRG"
110   DEFB &0D
120   ]
130 NEXT pass
140 CALL listPrograms


OSFIND

OSFIND&FFCE

When calling the OSFIND routine from machine code you will need to use the absolute address &40CE. However, when CALLing this routine from BBC BASIC it is recommended that you use the BBC Micro-compatible address &FFCE.

Introduction

This routine opens or closes a file. The Z80 register A contains the function code.

Code | Description | BBC BASIC Equivalent
A=0 | Close a file | CLOSE
A=&4x | Open a file for input | OPENIN
A=&8x | Open a file for output | OPENOUT
A=&Cx | Open a file for update | OPENUP

Close a File

To close a file call OSFIND with A set to 0 and H containing the handle of the file you wish to close. If H is 0 all opened file handles are closed.

Open a File

On entry HL points to a CR-terminated filename and the upper four bits of A specify the file access mode. On exit A will contain the file handle, or 0 on error.


OSGBPB

OSGBPB&FFD1

When calling the OSGBPB routine from machine code you will need to use the absolute address &40D1. However, when CALLing this routine from BBC BASIC it is recommended that you use the BBC Micro-compatible address &FFD1.

Introduction

The OSGBPB routines can be used to transfer a number of bytes to or from open files and retrieve file system information.

Reading or writing individual bytes at a time using BGET# (OSBGET) or BPUT# (OSBPUT) can be rather slow when you have a large number of bytes to transfer so you may wish to use this OS call to increase the speed of your program.

On entry, the Z80 register A contains the number of the routine to use defining the information to be transferred. HL points to a 13-byte control block with the following format:

Address | Function | Data Format
&00 | File handle | One byte
&01~&04 | Pointer to data in memory | Four bytes, LSB first
&05~&08 | Number of bytes/items to transfer | Four bytes, LSB first
&09~&0C | File pointer to be used for transfer | Four bytes, LSB first

The fields in the control block act as inputs and outputs. After transferring a number of bytes to or from a file the Number of bytes to transfer field is updated to contain the number of bytes left to read or write if the requested transfer could not be completed (for example, requesting to read 200 bytes from a 100 byte file). The pointer to data in memory and file pointer fields are also updated to their new values. On completion the carry flag is reset if the transfer completed successfully and set if not all of the number of bytes/items to transfer specified could be transferred.

When using OSGBPB from BASIC you may wish to use a wrapper procedure like the following. Before use you would need to allocate RAM for the control block using the DIM statement.

DEF PROC_osgbpb(cmd%,chn%,addr%,num%,ptr%)
A%=cmd%
H%=control DIV 256:L%=control
control?0=chn%
control!1=addr%
control!5=num%
control!9=ptr%
CALL &FFD1
ENDPROC

Routines

Number | Function
1 | Put bytes to file, using the new sequential pointer.
2 | Put bytes to file, ignoring the new sequential pointer.
3 | Get bytes from file, using the new sequential pointer.
4 | Get bytes from the file, ignoring the new sequential pointer.
8 | Read file names sequentially.

All other routine numbers are undefined and should not be used.

If more bytes or items have been requested than are available (eg the end of the file has been reached) the carry flag is set on exit and the number of bytes/items to transfer field in the control block ($05~$08) contains the number of bytes/items that could not be transferred. The sequential pointer and data in memory pointers are always updated to point to the next items to transfer.

When retrieving file names (A=8) the file pointer should first be set to 0 to reset to the first file and then left alone until all file names have been read. The data returned is:

  • Length of filename 1
  • Filename 1
  • Length of filename 2
  • Filename 2 ...

You can wrap routine 8 as follows for easy of use in BASIC programs:

10 osgbpb=&FFD1:DIM osgbpb_con 12:DIM osgbpb_fname 13
20 DEFPROC_ResetGetFile:osgbpb_con!9=0:ENDPROC
30 DEFFN_GetNextFile LOCAL L%,H%,A%:L%=osgbpb_con:H%=osgbpb_con DIV256:A%=8:osgbpb_con!1=osgbpb_fname:osgbpb_con!5=1:CALLosgbpb:osgbpb_fname?(1+?osgbpb_fname)=13:IF osgbpb_con!5:=""ELSE=$(osgbpb_fname+1)

You should call PROC_ResetGetFile first to reset to the first file then call FN_GetNextFile to retrieve file names. FN_GetNextFile will return the empty string ("") when there are no more file names to retrieve.

40 PROC_ResetGetFile
50 REPEAT
60   name$=FN_GetNextFile
70   IF name$<>"" PRINT name$
80 UNTIL name$=""


OSNEWL

OSNEWL&FFE7

When calling the OSNEWL routine from machine code you will need to use the absolute address &40E7. However, when CALLing this routine from BBC BASIC it is recommended that you use the BBC Micro-compatible address &FFE7.

This routine outputs an ASCII new line sequence (CR, LF) using OSWRCH. The A register is destroyed.

See Also

  • VDU
  • OSWRCH
  • OSASCI


OSRDCH

OSRDCH&FFE0

When calling the OSRDCH routine from machine code you will need to use the absolute address &40E0. However, when CALLing this routine from BBC BASIC it is recommended that you use the BBC Micro-compatible address &FFE0.

This routine waits for a keypress, returning the result in A, with the carry flag set if an Escape state was set. It is similar in functionality to the BASIC GET function.

The following example code demonstrates an assembly routine GetKey that returns the ASCII code of the pressed key or -1 if Escape was pressed.

 10 OSRDCH=&40E0
 20 OSBYTE=&40F4
 30 DIM GetKey 24
 40 FOR pass%=0 TO 2
 50   P%=GetKey
 60   [
 70   OPT 0
 80   CALL OSRDCH
 90   JR C,Escape
100   ; Escape wasn't pressed, return A in HLH'L'
110   LD L,A : LD H,0
120   EXX
130   LD HL,0
140   RET
150   .Escape
160   ; Return -1
170   SBC HL,HL
180   EXX
190   SBC HL,HL
200   ; Clear Escape condition
210   LD A,&7C : CALL OSBYTE
220   RET
230   ]
240 NEXT pass%

The above GetKey routine provides an implementation of GET that is immune to Escape being pressed, returning -1 instead.


OSWORD

OSWORD&FFF1

When calling the OSWORD routine from machine code you will need to use the absolute address &40F1. However, when CALLing this routine from BBC BASIC it is recommended that you use the BBC Micro-compatible address &FFF1.

Introduction

The OSWORD routines operate in a similar manner to the OSBYTE routines except that instead of parameters being passed in via registers they are stored in a parameter block in RAM, the address of which is passed via the HL register pair.

Routines

The routine number is loaded into the Z80's accumulator register A. When CALLing the routine from BBC BASIC you will need to set A% to the routine number.

Parameters for the routine are stored in RAM. You will need to set the Z80 register pair HL to the address of this parameter block, which in BBC BASIC can be accomplished via the H% and L% static variables.

OSWORD &01 - Read system clock

This routine reads the relative system clock (used for the BASIC TIME function). It outputs a five-byte integer to the address in HL.

10 OSWORD=&FFF1
20 DIM time 4
30 H%=time/256:L%=time
40 A%=&01
50 CALL OSWORD
60 PRINT !time

OSWORD &02 - Write system clock

This routine sets the system clock to the five-byte integer value pointed to by HL.

OSWORD &09 - Read pixel value

This routine returns the colour of a pixel at a specified point on the screen in the same manner as thePOINT function.

The inputs are as follows:

  • (HL+0) LSB of the X coordinate.
  • (HL+1) MSB of the X coordinate.
  • (HL+2) LSB of the Y coordinate.
  • (HL+3) MSB of the Y coordinate.

On exit,

  • (HL+4) contains the colour (0-127) at the specified point or 255 (-1) if the specified point was off screen.

OSWORD &0D - Read last two graphics cursor positions

The host interface keeps track of the last two visited graphics cursor positions (triangle and parallelogram filling require three points; two remembered and one passed with the PLOT command). You can use this routine to retrieve these recorded positions. HL needs to point to eight bytes of memory to receive the following values:

  • (HL+0) LSB of the previous X coordinate.
  • (HL+1) MSB of the previous X coordinate.
  • (HL+2) LSB of the previous Y coordinate.
  • (HL+3) MSB of the previous Y coordinate.
  • (HL+4) LSB of the current X coordinate.
  • (HL+5) MSB of the current X coordinate.
  • (HL+6) LSB of the current Y coordinate.
  • (HL+7) MSB of the current Y coordinate.

The values returned are all absolute coordinates in relation to the top-left hand corner of the screen.

An example of the usage of this routine is shown below. It is an assembly program that can be used to retrieve the current graphics origin (set with VDU 29 command). It works by moving the graphics cursor to (0,0) then reading back the current cursor position.

 10 REM OS call routine constants
 20 OSWRCH=&40EE
 30 OSWORD=&40F1
 40 :
 50 DIM GetOrigin 90
 60 FOR pass%=0 TO 1
 70   P%=GetOrigin
 80   [
 90   OPT pass%*2
100   ;
110   ; Check there are 2 arguments
120   LD A,(IX+0) : CP 2 : RET NZ
130   ;
140   ; Check they are both integers
150   LD A,(IX+1) : CP 4 : RET NZ
160   LD A,(IX+4) : CP 4 : RET NZ
170   ;
180   ; MOVE to the origin by invoking VDU 25,5,0;0;
190   LD A,25 : CALL OSWRCH
200   LD A,5 : CALL OSWRCH
210   ; Output 4 zeroes to move to (0,0).
220   LD B,4
230   .lp XOR A : CALL OSWRCH : DJNZ lp
240   ;
250   ; Invoke OSWORD &0D to read last two cursor positions
260   LD HL,PrevX
270   LD A,&0D : CALL OSWORD
280   ;
290   ; Now we know the origin we need to output it.
300   LD L,(IX+2) : LD H,(IX+3)
310   LD DE,(CurrX) : CALL OutputCoord
320   LD L,(IX+5) : LD H,(IX+6)
330   LD DE,(CurrY) : CALL OutputCoord
340   RET
350   ;
360   ; 8 bytes of storage for cursor positions
370   .PrevX : DEFW 0 : .PrevY : DEFW 0
380   .CurrX : DEFW 0 : .CurrY : DEFW 0
390   ;
400   ; Outputs 16-bit value DE to 32-bit variable at HL
410   .OutputCoord
420   LD (HL),E : INC HL
430   LD (HL),D : INC HL
440   SLA D
450   SBC A,A
460   LD (HL),A : INC HL
470   LD (HL),A : RET
480   ]
490 NEXT pass%

The routine can now be CALLed to retrieve the current graphics origin:

VDU 29,48;-32;
CALL GetOrigin,x%,y%
PRINT "Origin = (";x%;",";y%;")"

See Also

  • OSBYTE


OSWRCH

OSWRCH&FFEE

When calling the OSWRCH routine from machine code you will need to use the absolute address &40EE. However, when CALLing this routine from BBC BASIC it is recommended that you use the BBC Micro-compatible address &FFEE.

This OS call routine outputs the value in the accumulator to the current output stream. It is identical in behaviour to the BASIC VDU statement and so can be used for other purposes as well as outputting text (such as plotting shapes).

All registers are preserved.

See Also

  • VDU
  • OSASCI
  • OSNEWL


Introduction

TI-83+/TI-84+ assembly API

BBC BASIC (Z80) for the TI-83+/TI-84+ provides two standard ways to access its extensive library:

  • BASIC keywords such as PRINT or GET.
  • BBC Micro MOS API routines such as OSWORD or OSGBPB.

A third way has been added to the TI-83+ and TI-84+ version of BBC BASIC (Z80). This will unfortunately result in programs that do not run in other versions of BBC BASIC but does provide access to some useful routines.

Invoking the routines

Each routine is assigned a number which is loaded into the accumulator (A%). The BASIC CALL statement is then used to call &4083, the entrypoint for the assembly API, along with any arguments. For example, routine 1, UCASE$, could be invoked like this:

str$="Hello"
A%=1:CALL&4083,str$

The routines are designed to be easy to invoke from BASIC. If you need to invoke them from assembly then you will need to pass the address of a parameter table in RAM in IX - see CALL for more information.

Unless otherwise stated all regular registers are destroyed.


0 Glob (Pattern Matching)

This routine performs a primitive type of pattern matching. Its main use in the TI-83+/TI-84+ implementation of BBC BASIC (Z80) is filtering filenames when using the *DIR command.

A%=0:CALL&4083,result%,pattern$,input$

pattern$ defines the pattern to check input$ against. result% is the output of the routine and will equal TRUE if input$ matched pattern$, FALSE otherwise.

The pattern can contain one of two wildcard characters:

  • * - Matches any number of characters.
  • ? - Matches any single character.

The pattern is case-insensitive. Here are some examples of patterns:

pattern$ | input$ | result%
test | test | TRUE
test | TEST | TRUE
cat | dog | FALSE
*og | dog | TRUE
*og | frog | TRUE
b??k | bank | TRUE
b??k | book | TRUE
b??k | brick | FALSE
b*k | brick | TRUE

pattern$ and input$ can be movable or fixed strings. They may not contain NUL or CR characters. result% can be a real or integer variable.

BASIC wrapper function

You can wrap up the routine as a standard BASIC function using the following snippet:

DEFFN_glob(pat$,in$)LOCALA%:A%=0:CALL&4083,A%,pat$,in$:=A%

You could then invoke it like this:

IF FN_glob("*ee*", "Sheep") PRINT "Matches." ELSE PRINT "Does not match."

which would output

Matches.


1 UCASE$

This routine converts any lower case characters in a string to upper case.

A%=1:CALL&4083,string$

All arguments are passed by reference. You may pass multiple strings at a time. Both movable strings and fixed strings are supported; all other types are ignored.

The following program:

10 hello$="Hello,"
20 DIM world 30:$world="World!"
30 A%=1:CALL&4083,hello$,$world
40 PRINT hello$'$world

would output:

HELLO,
WORLD!

BASIC wrapper function

You can wrap up the routine as a standard BASIC function using the following snippet:

DEFFN_UCASE$(s$)LOCALA%:A%=1:CALL&4083,s$:=s$

You could then invoke it like this:

PRINT FN_UCASE$("Hello, World!")

which would output

HELLO, WORLD!

See Also

  • LCASE$


2 LCASE$

This routine converts any upper case characters in a string to lower case.

A%=2:CALL&4083,string$

All arguments are passed by reference. You may pass multiple strings at a time. Both movable strings and fixed strings are supported; all other types are ignored.

The following program:

10 hello$="Hello,"
20 DIM world 30:$world="World!"
30 A%=2:CALL&4083,hello$,$world
40 PRINT hello$'$world

would output:

hello,
world!

BASIC wrapper function

You can wrap up the routine as a standard BASIC function using the following snippet:

DEFFN_LCASE$(s$)LOCALA%:A%=2:CALL&4083,s$:=s$

You could then invoke it like this:

PRINT FN_LCASE$("Hello, World!")

which would output

hello, world!

See Also

  • UCASE$


3 LTRIM$

This routine trims whitespace (spaces, tabs, carriage returns and line-feeds) from the start (left) of a string.

A%=3:CALL&4083,string$

All arguments are passed by reference. You may pass multiple strings at a time. Both movable strings and fixed strings are supported; all other types are ignored.

The following program:

10 str$="  Hello  "
20 A%=3:CALL&4083,str$
30 PRINT "<"+str$+">"

would output:

<Hello  >

BASIC wrapper function

You can wrap up the routine as a standard BASIC function using the following snippet:

DEFFN_LTRIM$(s$)LOCALA%:A%=3:CALL&4083,s$:=s$

You could then invoke it like this:

PRINT "<"+FN_LTRIM$("  Hello  ")+">"

which would output

<Hello  >

See Also

  • RTRIM$
  • TRIM$


4 RTRIM$

This routine trims whitespace (spaces, tabs, carriage returns and line-feeds) from the end (right) of a string.

A%=4:CALL&4083,string$

All arguments are passed by reference. You may pass multiple strings at a time. Both movable strings and fixed strings are supported; all other types are ignored.

The following program:

10 str$="  Hello  "
20 A%=4:CALL&4083,str$
30 PRINT "<"+str$+">"

would output:

<  Hello>

BASIC wrapper function

You can wrap up the routine as a standard BASIC function using the following snippet:

DEFFN_RTRIM$(s$)LOCALA%:A%=4:CALL&4083,s$:=s$

You could then invoke it like this:

PRINT "<"+FN_RTRIM$("  Hello  ")+">"

which would output

<  Hello>

See Also

  • LTRIM$
  • TRIM$


5 TRIM$

This routine trims whitespace (spaces, tabs, carriage returns and line-feeds) from the start and end of a string.

A%=5:CALL&4083,string$

All arguments are passed by reference. You may pass multiple strings at a time. Both movable strings and fixed strings are supported; all other types are ignored.

The following program:

10 str$="  Hello  "
20 A%=5:CALL&4083,str$
30 PRINT "<"+str$+">"

would output:

<Hello>

BASIC wrapper function

You can wrap up the routine as a standard BASIC function using the following snippet:

DEFFN_TRIM$(s$)LOCALA%:A%=5:CALL&4083,s$:=s$

You could then invoke it like this:

PRINT "<"+FN_TRIM$("  Hello  ")+">"

which would output

<Hello>

See Also

  • LTRIM$
  • RTRIM$


6 REPLACE$

This routine replaces a all instances of a search string within one string with a replacement string.

A%=6:CALL&4083,string$,find$,replace$

All arguments are passed by reference and must be either movable strings or fixed strings.

The following program:

10 string$="Replace one thing with another thing."
20 find$="thing"
30 replace$="STRING"
40 A%=6:CALL&4083,string$,find$,replace$
50 PRINT string$

would output:

Replace one STRING with another STRING.

If either string$ or find$ is an empty string, the original string is left untouched. If replace$ is an empty string, all instances of find$ are removed from string$.

BASIC wrapper function

You can wrap up the routine as a standard BASIC function using the following snippet:

DEFFN_REPLACE$(s$,f$,r$)LOCALA%:A%=6:CALL&4083,s$,f$,r$:=s$

You could then invoke it like this:

PRINT FN_REPLACE$("BBC BASIC is a good programming language.", "good ", "great")

which would output

BBC BASIC is a great programming language.


7 REVERSE$

This routine reverses all characters in a string.

A%=7:CALL&4083,string$

All arguments are passed by reference and must be either movable strings or fixed strings. You may pass multiple arguments at once. Other types are ignored.

The following program:

10 hello$="Hello,"
20 DIM world 30:$world="World!"
30 A%=7:CALL&4083,hello$,$world
40 PRINT hello$'$world

would output:

,olleH
!dlroW

BASIC wrapper function

You can wrap up the routine as a standard BASIC function using the following snippet:

DEFFN_REVERSE$(s$)LOCALA%:A%=7:CALL&4083,s$:=s$

You could then invoke it like this:

PRINT FN_REVERSE$("Hello, World!")

which would output

!dlroW ,olleH


Bad program

From time to time BBC BASIC (Z80) checks to see that the program in memory is of the correct format. If it is unable to follow the program from the start to the 'program end marker' it will report this untrappable error. The error can be caused by a read error, by only loading part of the program or by overwriting part of the program in some way. (Machine code programmers beware). Without a full understanding of how a program is stored in memory, there is little you can do to recover a bad program.


LINE space

A program line is too long to be represented in BBC BASIC (Z80)'s internal format.


No room

This untrappable error indicates that all the computer's available memory was used up whilst a program was running. This error may occur as a result of numerous assignments to string variables, as in a string sort. See the explanation of String Variables and Garbage in the Variables sub-section for details.


RENUMBER space

When BBC BASIC RENUMBERs a program it has to build a cross-reference table of line numbers. If there is insufficient memory to hold this table, the 'RENUMBER space' error results.


Silly

This error message will be issued if you try to RENUMBER a program or enter AUTO with a step size of 0. AUTO with a step size of more than 255 will work, but it will be evaluated MOD 256.


Sorry

This error is triggered if you try and use a BBC BASIC (Z80) feature that has not been implemented in the TI-83+/TI-84+ port.


1 Out of range

This assembly language error will be reported if you tried to perform a relative jump of more than +127 or -128 bytes.


4 Mistake

This error will be generated if BBC BASIC (Z80) is unable to make any sense at all of the input line.


5 Missing ,

This error message is generated if BBC BASIC (Z80) was unable to find a comma where one was expected. The following example would give rise to this error.

20 PRINT TAB(10 5)


6 Type mismatch

This error indicates that a number was encountered when a string was expected and vice-versa. Don't forget that this can occur if the actual parameters and the formal parameters for a function or procedure do not correspond. (See article on Procedures and Functions for details of parameter passing to functions and procedures).


7 No FN

If BBC BASIC (Z80) encounters an end-of-function without calling a function definition, this error message will be issued. If you forget to put multi-line function definitions out of harm's way at the end of the program you are very likely to get this error message. (See the section on Procedures and Functions).

10 DEF FN_error()
20 =7


9 Missing "

This error message is generated if BBC BASIC (Z80) was unable to find a double-quote where one was expected. The following example would give rise to this error.

10 name$="Douglas


10 Bad DIM

Arrays must be positively dimensioned. In other words, the numbers within the brackets must not be negative. This error would be produced by the following example.

DIM table(20,-10)


11 DIM space

This error will be generated if:

  • There is insufficient room for an array when you try to dimension it.
  • An attempt has been made to reserve a negative amount of memory.


12 Not LOCAL

If you try to define a variable as LOCAL outside a procedure or function, this error message will be generated. If you forget to put multi-line function definitions out of harm's way at the end of the program you are very likely to get this error message. (See the section on Procedures and Functions).


13 No PROC

If BBC BASIC (Z80) encounters an ENDPROC without performing (calling) a procedure definition, this error message will be issued. If you forget to put multi-line procedure definitions out of harm's way at the end of the program you are very likely to get this error message. (See the sub-section on Procedures and Functions).


14 Array

This error occurs when BBC BASIC (Z80) thinks it should be accessing an array, but does not know which one.


15 Subscript

If you try to access an element of an array less than zero or greater than the size of the array you will generate this error. Both lines 20 and 30 of the following example would give rise to this error message.

10 DIM test(10)
20 test(-4)=20
30 test(30)=10


16 Syntax error

A command was terminated incorrectly. In other words, the first part of the command was recognized, but the rest of it was meaningless or incomplete. Unlike Mistake, BBC BASIC (Z80) was able to recognise the start of the command.

X=SIN()


17 Escape

Error triggered by pressing the Escape key.


18 Division by zero

Mathematically, dividing by zero gives an infinitely large answer. The computer is unable to understand the concept of infinity (it's not alone) and this error is generated. If there is any possibility that the divisor might be zero, you should test for this condition before carrying out the division. For example:

200 IF divisor=0 THEN PROC_error ELSE ...


19 String too long

You will get this error message if your program tries to generate a string which is longer than 255 characters.


20 Too big

This error will occur if a number is entered or calculated which is too big for BBC BASIC (Z80) to cope with.

X=1E39


21 -ve root

This error message will occur if BBC BASIC (Z80) attempted to calculate the square root of a negative number. It is possible for this error to occur with ASN and ACS as well as SQR.

 90 num=-20
100 root=SQR(num)


22 Log range

Logarithms for zero and negative numbers do not exist. This error message will be generated if you try to calculate the LOG of zero or a negative number or raise a negative number to a non-integer power.


23 Accuracy lost

Before BBC BASIC (Z80) calculates trigonometric functions (SIN, COS, etc) of very large angles the angles are reduced to +/- PI radians. The larger the angle, the greater the inaccuracy of the reduction, and hence the result. When this inaccuracy becomes unacceptable, BBC BASIC (Z80) will issue an 'Accuracy lost' error message.

 X=SIN(1E7)


24 Exp range

The EXP function is unable to cope with powers greater than 88. If you try to use a larger power, this error will be generated.


26 No such variable

Variables are brought into existence by assigning a value to them or making them LOCAL in a function or procedure definition. This error message will be generated if you try to use a variable on the right-hand side of an assignment or access it in a PRINT statement before it has been created. As shown below, you can create variables very simply.

10 count=0
20 name$=""


27 Missing )

This error message is generated if BBC BASIC was unable to find a closing bracket where one was expected. The following example would give rise to this error.

10 PRINT SQR(num


28 Bad HEX

Hexadecimal numbers can only include the numbers 0 to 9 and A to F. If you try to form a hex number with other characters this error will occur. For example:

PRINT &HEX : REM Invalid character X


29 No such FN/PROC

When BBC BASIC (Z80) encounters a name beginning with FN or PROC it expects to be able to find a corresponding function or procedure definition. This error will occur if such a definition does not exist.


30 Bad call

This error indicates that a procedure or function has been incorrectly called.


31 Arguments

This error indicates that too many or too few arguments have been passed to a procedure or function or an invalid formal parameter has been used. See the section on Procedures and Functions for more information.


32 No FOR

This error message indicates that BBC BASIC (Z80) has found a NEXT statement without first encountering a FOR statement.


33 Can't match FOR

BBC BASIC (Z80) has been unable to find a FOR statement corresponding to the NEXT statement.


34 FOR variable

The variable in a FOR...NEXT loop must be a numeric variable. If you use a constant or a string variable this error message will be generated. For example, the following statements are not legal.

20 FOR name$=1 TO 20
20 FOR 10=1 TO 20


36 No TO

This error message will be generated if BBC BASIC (Z80) encounters a FOR...NEXT loop with the TO part missing.


38 No GOSUB

This error message will be generated if BBC BASIC (Z80) finds a RETURN statement without first encountering a GOSUB statement. (See the section on Flow Control for more information).


39 ON syntax

This error will be reported if the ON...GOTO statement was misformed. For example, the following statement is not legal. (Refer to the keyword ON for details of legal statements).

20 ON x TIME=0


40 ON range

This error will be generated if, in a simple ON...GOTO/GOSUB/PROC statement, the control variable was less than 1 or greater than the number of entries in the ON list. These exceptions can be trapped in ON GOTO/GOSUB/PROC statements by using the ELSE option. The first example below will generate an 'ON range' error, whilst the second is correct.

10 num=4
20 ON num GOTO 100,200,300
10 num=4
20 ON num GOTO 100,200,300 ELSE 1000


41 No such line

This error will occur if BBC BASIC (Z80) tries to GOTO, GOSUB, TRACE or RESTORE to a non-existent line number.


42 Out of DATA

If your program tried to read more items of DATA than there were in the data list, this error will be generated. You can use RESTORE to return the data pointer to the first data statement (or to a particular line with a data statement) if you wish. The following example tries to read four items of data, when only three have been defined.

10 RESTORE
20 READ A,B,C,D
30 DATA 1,2,3


43 No REPEAT

This error message indicates that BBC BASIC (Z80) has found an UNTIL statement without first encountering a REPEAT statement.


45 Missing#

This error will occur if BBC BASIC (Z80) is unable to find a hash (#) symbol where one was expected. The following example would cause this error.

CLOSE 7


204 Bad name

This error is generated if an invalid file name is used. See the Files section for more information.


254 Bad command

This is a general error that is triggered by attempting to invoke a star command that does not exist or by passing it invalid arguments.


BBC BASIC for TI-OS Programmers

Introduction

This section aims to help programmers familiar with the programming language built-in to the TI-83+ and TI-84+ operating system by discussing its features and the BBC BASIC equivalents.

Input and Output

Input

BBC BASIC's INPUT statement is very similar than the TI-OS Input statement.

Prompt

There is no direct equivalent for the TI-OS Prompt statement. You can use INPUT as a substitute - for example,

INPUT "X=?"X

performs the same task as the TI-OS command Prompt X.

Disp

The standard BASIC PRINT statement performs the same task as the TI-OS statement Disp.

DispGraph, DispTable

As BBC BASIC only has a single screen that mixes text and graphics there are no equivalent statement to the TI-OS DispGraph or DispTable.

Output(

The TAB statement can be used to set the cursor position as part of a PRINT statement.

getKey

There is no direct BBC BASIC equivalent to this function, but there are a number of alternatives.

  • GET waits for an alphanumeric key to be pressed and returns its ASCII code.
  • GET$ waits for an alphanumeric key to be pressed and returns its character as a string.
  • INKEY(n) where n≥0 returns the ASCII code of a pressed alphanumeric key or -1 if one is not pressed within n centiseconds.
  • INKEY$(n) where n≥0 returns a string containing the alphanumeric character generated by pressing that key or an empty string if one is not pressed within n centiseconds.
  • INKEY(n) where n<0 checks if the key with code n is pressed and returns TRUE if it is or FALSE if it isn't.

INKEY(0) is the closest equivalent to the TI-OS getKey function, but it does not return a value if a non-alphanumeric key (such as the cursor keys or modifiers) is pressed. To check the state of the non-alphanumeric keys you will need to use INKEY(n) where n is the key's code and n<0.

ClrHome

CLS is BBC BASIC's equivalent to the TI-OS ClrHome statement. It will clear the text viewport to the current text background colour (set with COLOUR).

ClrTable

BBC BASIC does not display table of results, so there is no equivalent statement.

GetCalc(, Get( and Send(

These features are not currently implemented.

Drawing Operations

ClrDraw

BBC BASIC's equivalent statement to ClrDraw is CLG, which will clear the graphics viewport to the current graphics background colour (set with GCOL).

Line(

To draw a line you first need to MOVE the graphics cursor to the start of the line then DRAW to the end of it. This will draw a line in the current foreground colour. For more advanced line-drawing operations (including support for dotted and dashed lines) you will need to use the PLOT statement.

Horizontal and Vertical

BBC BASIC does not have any equivalent drawing operation to the Horizontal and Vertical statements. You can get the same effect by drawing a line with either both Y coordinates or both X coordinates set to the same value.

Tangent(, DrawF, Shade( and DrawInv

BBC BASIC does not graph functions, so there are no equivalents to the Tangent(, DrawF, Shade( and DrawInv statements.

Circle(

Outlined or filled circles or ellipses can be drawn using the PLOT modes 144-151, 152-159, 192-199 or 200-207.

The following example code defines a procedure that draws a circle outline in the current background colour given an origin and a radius.

DEF PROC_circle(x,y,r)
MOVE x,y
PLOT 145,0,r
ENDPROC

Text(

You can draw text anywhere on the screen using the VDU 5 mode, then use the PRINT statement as normal. The following example code defines a procedure that acts in a similar method to the TI-OS Text( statement.

DEF PROC_text(y,x,text$)
VDU 5
MOVE x,y
PRINT text$
VDU 4
ENDPROC

Note the reversed x and y parameters.

Pt-On(, Pt-Off(, Pxl-On( and Pxl-Off(

PLOT modes 64-71 can be used to set the colour of individual pixels.

Pt-Change( and Pxl-Change(

You can use the PLOT modes 64-71 along with an inverting plot mode to toggle the state of pixels. The following code example defines a procedure that acts in a similar way to the TI-OS Pxl-Change( statement.

DEF PROC_pxlChange(y,x)
PLOT 70,x,y
ENDPROC

Not the reversed x and y parameters.

pxl-Test(

BBC BASIC's POINT function is equivalent to the TI-OS pxl-Test(. Like the other pxl- functions the order of x and y parameters is reversed.


EXTERR

In order to issue an error which BASIC can process properly you must do the following:

  1. Load the A register with the appropriate error number. If this is an error which exists in other versions of BBC BASIC, you should use the same number (e.g. "Escape" is error 17). If you need to allocate numbers for your own errors, please use only values greater than 127. If the error number is zero the error is "fatal", i.e. untrappable by the user with ON ERROR. You should use this with "catastrophic" errors from which the user cannot hope to recover.
  2. Call the routine EXTERR, accessible via the address &4080. Despite the fact that it is CALLed this routine never returns to the caller. A CALL is used simply to pass the address of the error string which follows.
  3. Place the required error string immediately following the CALL EXTERR, terminated with a NUL character (ASCII 00). BASIC will store a pointer to this string, used if REPORT is subsequently issued, so you should not subsequently overwrite the string if it is in RAM.

For example, to issue the "Escape" error from your code:

LD A,17             ; Code for "Escape"
CALL EXTERR         ; Tell BASIC to process error
DEFM "Escape"+CHR$0 ; Error string terminated by NUL

If you prefer the error string to be elsewhere, the equivalent can be achieved as follows:

LD A,17      ; Code for "Escape"
LD HL,ERRMES ; Pointer to error string
PUSH HL      ; Put address on stack
JP EXTERR    ; Tell BASIC to process error

BASIC resets its stack pointer (to the current value of HIMEM) when an error

occurs so there is no need to ensure that SP has any particular value when EXTERR is called, except (of course) that it must point to a location where the address of the error string can be PUSHed without doing any damage.


Format of Program and Variables in Memory

Memory Map

Workspace RAM

BBC BASIC (Z80) uses 768 (&300) bytes of RAM as a workspace. It contains the values of resident interpreter variables, LOMEM, HIMEM, etc. The full list is as follows.

Address | Description
&9E00~&9EFF | The string accumulator.
&9F00~&9FFF | The INPUT buffer.
&A000~&A06B | The static variables. 108 bytes holding the values of the 27 integer variables @% to Z% inclusive. The variable values are stored as described later in this section and they each occupy 4 bytes.
&A06C~&A0D7 | 54 2-byte values (108 bytes in all) which point to the first item in the linked lists of dynamic variables starting with the characters A to Z (26) and _ to z (28). If no variables starting with the given initial character exists, the pointer contains zero.
&A0D8~&A0D9 | A 2-byte pointer to the linked list of function names. If no function is currently active, this contains zero.
&A0DA~&A0DB | A 2-byte pointer to the linked list of procedure names. If no procedure is currently active, this contains zero.
&A0DC~&A0DD | The 2-byte value of PAGE.
&A0DE~&A0DF | The 2-byte value of TOP (TOP > PAGE).
&A0E0~&A0E1 | The 2-byte value of LOMEM.
&A0E2~&A0E3 | A 2-byte pointer to the first free location after the heap.
&A0E4~&A0E5 | The 2-byte value of HIMEM (LOMEM ≤ FREE < HIMEM).
&A0E8~&A0E9 | A 2-byte value holding the current TRACE status. TRACE OFF sets it to zero, TRACE ON to &FFFF and TRACE nnn sets it to nnn (line numbers less than nnn are traced).
&A0EA~&A0EB | A 2-byte value holding the next AUTO line number. If zero, AUTO is not active.
&A0EC~&A0ED | A 2-byte pointer to the tail of the ON ERROR statement in the user's program. If zero, no ON ERROR statement is active (ON ERROR OFF).
&A0EE~&A0EF | A 2-byte pointer to the last error string (used by REPORT).
&A0F0~&A0F1 | A 2-byte pointer to the current DATA item in the user's program. Initialised to point to the first data item (if any) when the program is RUN.
&A0F2~&A0F3 | The 2-byte value of ERL (the line number at which the last error occurred).
&A0F4~&A0F5 | BBC BASIC copies the program text pointer to this location every so often (at the beginning of each line, for example). When an error occurs, it is used to determine ERL.
&A0F6~&A0FA | A 33 bit pseudo random number updated by RND. Five bytes are used to hold this number, the fifth byte containing only the 33rd bit.
&A0FB | The 1-byte value of COUNT (the number of printed characters output since the last new line).
&A0FC | The 1-byte value of WIDTH. Zero signifies that BBC BASIC (Z80) inserts no automatic new-lines.
&A0FD | The 1-byte value of ERR (the number of the last error).
&A0FE | A byte containing the LISTO value.
&A0FF | A 1-byte value containing the increment for the AUTO command.

Memory Management

There is little you can do to control the growth of the stack. However, with care, you can control the growth of the heap. You can do this by limiting the number of variables you use and by good string variable management.

Limiting the Number of Variables

Each new variable occupies room on the heap. Restricting the length of the names of variables and limiting the number of variables used will limit the size of the heap. However, of the techniques available to you, this is the least rewarding. In addition, it leads to incomprehensible programs because your variable names become meaningless. You should keep this technique in the back of your mind whilst you are programming, but only apply it rigorously if you are really stuck for space.

String Management

Garbage Generation

Unlike numeric variables, string variables do not have a fixed length. When you create a string variable it is added to the heap and sufficient memory is allocated for the initial value of the string. If you subsequently assign a longer string to the variable there will be insufficient room for it in its original position and the string will have to be relocated with its new value at the top of the heap. The initial area will then become 'dead' and the heap will have grown by the new length of the string. The areas of 'dead' memory are called garbage. As more and more re-assignments take place, the heap grows and eventually there is no more room. Thus, it is possible to run out of room for variables even though there should be enough space.

Memory Allocation for String Variables

You can overcome the problem of 'garbage' by reserving enough memory for the longest string you will ever put into a variable before you use it. You do this simply by assigning a string of spaces to the variable. If your program needs to find an empty string the first time it is used, you can subsequently assign a null string to it. The same technique can be used for string arrays. The example below sets up a single dimensional string array with room for 20 characters in each entry, and then empties it.

10 DIM names$(10)
20 FOR i=0 TO 10
30   name$(i)=STRING$(20," ")
40 NEXT
50 stop$=""
60 FOR i=0 TO 10
70   name$(i)=""
80 NEXT

Assigning a null string to stop$ prevents the space for the last entry in the array being recovered when it is emptied.

Program Storage in Memory

The program is stored in memory in the format shown below. The first program line commences at PAGE.

Length | LSB | MSB | … | … | … | … | … | &0D
 | Line Number |  | Program Line Statements |  |  |  |  | CR

Line Length

The line length includes the line length byte. The address of the start of the next line is found by adding the line length to the address of the start of the current line. The end of the program is indicated by a line length of zero and a line number of &FFFF.

Line Number

The line number is stored in two bytes, LSB first. The end of the program is indicated by a line number of &FFFF and a line length of zero.

Statements

With the exception of the symbols '*', '=' and '[' and the optional reserved word LET, each statement in the line commences with the appropriate reserved word token. Reserved words are tokenised wherever they occur. A token is indicated by bit 7 of the byte being set. Statements within a line are separated by colons.

Line Terminator

Each program line (except the last) is terminated by a carriage-return (&0D).

Variable Storage in Memory

Variables are held within memory as linked lists (chains). The first variable in each chain is accessed via an index which is maintained by BBC BASIC (Z80). There is an entry in the index for each of the characters permitted as the first letter of a variable name. Each entry in the index has a word (two bytes) address field which points to the first variable in the linked list with a name starting with its associated character. If there are no variables with this character as the first character in the name, the pointer word is zero. The first word of all variables holds the address of the next variable in the chain. The address word of the last variable in the chain is zero. All addresses are held in the standard Z80 format - LSB first.

The first variable created for each starting character is accessed via the index and subsequently created variables are accessed via the index and the chain. Consequently, there is some speed advantage to be gained by arranging for all your variables to start with a different character. Unfortunately, this can lead to some pretty unreadable names and programs.

Integer Variables

Integers are held in two's complement format. They occupy 4 bytes, with the LSB first. Bit 7 of the MSB is the sign bit. To make up the complete variable, the address word, the name and a separator (zero) byte are added to the number. The format of the memory occupied by an integer variable called NUMBER% is shown below. Note that since the first character of the name is found via the index, it is not stored with the variable.

LSB | MSB | U | M | B | E | R | % | &00 | LSB | … | … | MSB
Address of next variable starting with the same letter. |  | Rest of Name |  |  |  |  |  |  | Value

The smallest amount of space is taken up by a variable with a single letter name. The static integer variables, which are not included in the variable chains, use the names A% to Z%. Thus, the only single character names available for dynamic integer variables are a% to z% plus _% and £%. As shown below, integer variables with these names will occupy 8 bytes.

LSB | MSB | % | &00 | LSB | … | … | MSB
Address of next variable starting with the same letter. |  |  |  | Value

Real Variables

Real numbers are held in binary floating point format. The mantissa is held as a 4 byte binary fraction in sign and magnitude format. Bit 7 of the MSB of the mantissa is the sign bit. When working out the value of the mantissa, this bit is assumed to be 1 (a decimal value of 0.5). The exponent is held as a single byte in 'excess 127' format. In other words, if the actual exponent is zero, the value of stored in the exponent byte is 127. To make up the complete variable, the address word, the name and a separator (zero) byte are added to the number. The format of the memory occupied by a real variable called NUMBER is shown below.

LSB | MSB | U | M | B | E | R | &00 | LSB | … | … | MSB | Exp
Address of next variable starting with the same letter. |  | Rest of Name |  |  |  |  |  | Mantissa |  |  |  | Exponent

As with integer variables, variables with single character names occupy the least memory. (However, the names A to Z are available for dynamic real variables). Whilst a real variable requires an extra byte to store the number, the '%' character is not needed in the name. Thus, integer and real variables with the same name occupy the same amount of memory. However, this does not hold for arrays, since the name is only stored once.

In the following examples, the bytes are shown in the more human-readable manner with the MSB on the left.

The value 5.5 would be stored as shown below.

Mantissa |  |  |  | Exponent
0011 0000 | 0000 0000 | 0000 0000 | 0000 0000 | 1000 0010
&30 | &00 | &00 | &00 | &82

Because the sign bit (underlined) is assumed to be 1, this would become:

Mantissa |  |  |  | Exponent
1011 0000 | 0000 0000 | 0000 0000 | 0000 0000 | 1000 0010
&B0 | &00 | &00 | &00 | &82

The equivalent in decimal is:

    (0.5+0.125+0.0625) * 2^(130-127)
=   0.6875 * 2^3
=   0.6875 * 8
=   5.5

BBC BASIC (Z80) stores integer values in real variables in a special way which allows the faster integer arithmetic routines to be used if appropriate. The presence of an integer value in a real variable is indicated by the stored exponent being zero. Thus, if the stored exponent is zero, the real variable is being used to hold an integer and the 4 byte mantissa holds the number in normal integer format.

Depending on how it is put there, an integer value can be stored in a real variable in one of two ways. For example,

number=5

will set the exponent to zero and store the integer &00 00 00 05 in the mantissa. On the other hand,

number=5.0

will set the exponent to &82 and the mantissa to &20 00 00 00.

If all this seems a little complicated, try using the following program to accept a number from the keyboard and display the way it is stored in memory. The program displays the 4 bytes of the mantissa in 'human readable order' followed by the exponent byte. Look at what happens when you input first 5 and then 5.0 and you will see how this corresponds to the explanation given above. Then try -5 and -5.0 and then some other numbers. (The program is an example of the use of the byte indirection operator. See the Indirection section for details).

 10 NUMBER=0
 20 DIM A% -1
 30 REPEAT
 40   INPUT"NUMBER PLEASE "NUMBER
 50   PRINT "& ";
 60   :
 70   REM Step through mantissa from MSB to LSB
 80   FOR I%=2 TO 5
 90     REM Look at value at address A%-I%
100     NUM$=STR$~(A%?-I%)
110     IF LEN(NUM$)=1 NUM$="0"+NUM$
120     PRINT NUM$;" ";
130   NEXT
140   :
150   REM Look at exponent at address A%-1
160   N%=A%?-1
170   NUM$=STR$~(N%)
180   IF LEN(NUM$)=1 NUM$="0"+NUM$
190   PRINT " & "+NUM$''
200 UNTIL NUMBER=0

The layout of the variable NMBR in memory is shown below.

 |  |  |  |  |  | Mantissa |  |  |  |
LSB | MSB | M | B | R | &00 | LSB | … | … | MSB | Exp | …
 |  |  |  |  |  | A%-5 points here |  |  | A%-2 points here | A%-1 points here | A% points here

String Variables

String variables are stored as the string of characters. Since the current length of the string is stored in memory an explicit terminator for the string in unnecessary. As with numeric variables, the first word of the complete variable is the address of the next variable starting with the same character. However, since BBC BASIC (Z80) needs information about the length of the string and the address in memory where the it starts, the overheads for a string are more than for a numeric. The format of a string variable called NAME$ is shown below.

LSB | MSB | A | M | E | $ | &00 | Length | Max | LSB | MSB
Address of next variable starting with the same letter. |  | Rest of Name |  |  |  |  | Current Length | Maximum Length | String Start Address

When a string variable is first created in memory, the characters of the string follow immediately after the two bytes containing the start address of the string and the current and maximum lengths are the same. While the current length of the string does not exceed its length when created, the characters of the string will follow the address bytes. When the string variable is set to a string which is longer than its original length, there will be insufficient room in the original position for the characters of the string. When this happens, the string will be placed on the top of the heap and the new start address will be loaded into the two address bytes. The original string space will remain, but it will be unusable. This unusable string space is called 'garbage'. See the Variables section for ways to avoid creating garbage.

Because the original length and the current length of the string are each stored in a single byte in memory, the maximum length of a string held in a string variable is 255 characters.

Fixed Strings

You can place a string starting at a given location in memory using the indirection operator '$'. For example,

$&8000="This is a string"

would place &54 (T) at address &8000, &68 (h) at address &8001, etc. Because the string is placed at a predetermined location in memory it is called a 'fixed' string. Fixed strings are not included in the variable chains and they do not have the overheads associated with a string variable. However, since the length of the string is not stored, an explicit terminator (&0D) is used. Consequently, in the above example, byte &8010 would be set to &0D.

Array variables

Information about the array is stored along with its name, including the number of dimensions and number of elements in each dimension.

 |  |  |  |  |  |  |  | Repeated as necessary
LSB | MSB | A | M | E | ( | &00 | Dimensions | LSB | MSB | LSB | MSB | …
Address of next variable starting with the same letter. |  | Rest of Name |  |  |  |  | Number of dimensions | Number of elements |  | Number of elements |  | Array Data

The number of elements stored for each dimension is the total number of elements, not the upper bound; that is, an array dimensioned as array%(10) would have 11 elements.

For example, the array

DIM array%(4,9,2)

would be stored as follows:

  • Address of next variable starting with the same letter (two bytes).
  • rray%(
  • &00 terminator.
  • &03 for three dimensions.
  • &05, &00 - first dimension has five elements.
  • &0A, &00 - second dimension has ten elements.
  • &03, &00 - third dimension has three elements.

Following this information is the array data itself. Integers and real numbers are stored directly as four or five byte values respectively. Strings are referenced via a four byte block detailing the current length, maximum length and address of the first character in the same way that regular string variables are referenced.

Array elements are stored sequentially with the last dimension first. For example, with the array%(4,9,2) example above the order of elements is (0,0,0), (0,0,1), (0,0,2), (0,1,0), (0,1,1), (0,1,2), (0,2,0) etc.


FPP

Introduction

BBC BASIC makes use of a floating-point arithmetic package, or FPP, to perform calculations and conversions between string and number forms. It uses all the Z80's general purpose registers, including IX, IY and the "alternate" (shadow) registers, but does not use the R register or the I register nor does it disable or enable interrupts or change the interrupt mode. It is fully interruptible.

The FPP requires no private or shared workspace, it uses registers and the stack for all working and temporary storage. Stack requirements should not exceed fifty bytes.

Operations provided

The FPP provides sixteen operations which take two numeric parameters and produce a numeric result (AND, DIV, EOR, MOD, OR, <=, <>, >=, <, =, >, +, -, *, / and ^), sixteen numeric functions (ABS, ACS, ASN, ATN, COS, DEG, EXP, INT, LN, LOG, NOT, RAD, SGN, SIN, SQR, TAN), four numeric constants (ZERO,

FONE, TRUE, PI), two numeric/string conversion routines (VAL, STR$), two format conversion routines (FIX, FLOAT) and two miscellaneous routines (TEST, COMPARE).

All numeric operations will accept either integer or floating-point parameters, converting where necessary. Returned values may be in integer or floating-point format, as appropriate.

Numeric range and precision

Integers are stored in 4 bytes, and may represent values from -2147483648 to +2147483647. Floating-point numbers are stored in 5 bytes (4 byte mantissa, 1 byte exponent) and may represent values from approximately ±5.9E-39 to ±3.4E38, with a resolution of about nine significant figures.

Considerable care has been taken in coding the FPP to preserve the greatest degree of accuracy consistent with the use of a 32-bit mantissa. However, complex operations such as the transcendental functions make use of several intermediate results, each of which is stored only with the normal precision. It is therefore possible for errors to accumulate and for the final result to be less accurate than would be desirable. This problem is aggravated in certain special cases, such as the logarithm of numbers close to 1. No guarantee can be given that the accuracy will be sufficient for any specific application. As always, in financial applications you are strongly advised to use only integer arithmetic.

Numeric representation

Details of the formats of integers and floating-point numbers may be found in the Format of Program and Variables in Memory appendix except that, in the case of the FPP, numbers are held in the processor's registers rather than in memory. Two floating-point numbers may be held in the registers at any one time, as follows:

 | Number 1 | Number 2
Mantissa MS byte | H | D
. | L | E
. | H' | D'
Mantissa LS byte | L' | E'
Exponent byte | C | B

As described in the Format of Program and Variables in Memory appendix integer values are denoted by the "exponent" (C or B register) being zero.

Interface details

All FPP operations are accessed via a common entry point, the operation required being specified by an 8-bit "operation code" passed in the A register. The entry point is the base address of the FPP code, &4087:

LD A,opcode
CALL fpp

The argument of a numeric function is passed in registers HLH'L'C and the result is returned in registers HLH'L'C. Operators (addition, multiplication etc.) each take two operands and return a single result. The operands are passed in HLH'L'C (left) and DED'E'B (right), and the result is returned in HLH'L'C. The result of TEST and COMPARE is returned in the A register.

For information on the register usage of the numeric/string conversion functions see the detailed descriptions.

Exception handling

If an operation completes without error it returns with the zero flag set and the carry flag reset. If an exception occurs during an operation it returns with the zero flag reset, the carry flag set and an error code in the A register. In this case the returned value in the other registers is meaningless.

The possible error codes (decimal) are as follows:

  1. Bad operation code
  18. Division by zero
  20. Too big
  21. -ve root
  22. Log range
  23. Accuracy lost
  24. Exp range

Registers affected

On return from the FPP, any or all of the following registers may have been altered:

  • A,B,C,D,E,H,L,F,A',B',C',D',E',H',L',F',IX

The IY, SP and I registers are returned unchanged.

Details of FPP operations

Opcode | Operation | Description | Parameters | Results
0 | AND | Integer bitwise logical AND | HLH'L'C & DED'E'B | HLH'L'C (C = 0)
1 | DIV | Integer quotient after division | HLH'L'C (left) DED'E'B (right) | HLH'L'C (C = 0)
2 | EOR | Integer bitwise logical exclusive-OR | HLH'L'C & DED'E'B | HLH'L'C (C = 0)
3 | MOD | Integer remainder after division | HLH'L'C (left) DED'E'B (right) | HLH'L'C (C = 0)
4 | OR | Integer bitwise logical OR | HLH'L'C & DED'E'B | HLH'L'C (C = 0)
5 <= Test for less-than or equal-to HLH'L'C (left) DED'E'B (right) HLH'L'C (C = 0, HLH'L' = 0 FALSE or -1 TRUE)
6 <> Test for not equal to HLH'L'C & DED'E'B HLH'L'C (C = 0, HLH'L' = 0 FALSE or -1 TRUE)
7 >= Test for greater-than or equal-to HLH'L'C (left) DED'E'B (right) HLH'L'C (C = 0, HLH'L' = 0 FALSE or -1 TRUE)
8 < Test for less than HLH'L'C (left) DED'E'B (right) HLH'L'C (C = 0, HLH'L' = 0 FALSE or -1 TRUE)
9 = Test for equality HLH'L'C & DED'E'B HLH'L'C (C = 0, HLH'L' = 0 FALSE or -1 TRUE)
10 * Integer or floating-point multiplication HLH'L'C & DED'E'B HLH'L'C
11 + Integer or floating-point addition HLH'L'C & DED'E'B HLH'L'C
12 > Test for greater than HLH'L'C (left) DED'E'B (right) HLH'L'C (C = 0, HLH'L' = 0 FALSE or -1 TRUE)
13 - Integer or floating-point subtraction HLH'L'C (left) DED'E'B (right) HLH'L'C
14 ^ Integer or floating-point involution (raise to power) HLH'L'C (left) DED'E'B (right) HLH'L'C
15 / Floating-point division HLH'L'C (left) DED'E'B (right) HLH'L'C
16 | ABS | Absolute value | HLH'L'C | HLH'L'C
17 | ACS | Arc cosine (inverse cosine) | HLH'L'C | HLH'L'C (radians)
18 | ASN | Arc sine (inverse sine) | HLH'L'C | HLH'L'C (radians)
19 | ATN | Arc tangent (inverse tangent) | HLH'L'C | HLH'L'C (radians)
20 | COS | Cosine | HLH'L'C (radians) | HLH'L'C
21 | DEG | Convert radians to degrees | HLH'L'C (radians) | HLH'L'C (degrees)
22 | EXP | Exponential (raise e to the power of the argument) | HLH'L'C | HLH'L'C
23 | INT | Integer part (floor function) | HLH'L'C | HLH'L'C (C = 0)
24 | LN | Natural (Napierian) logarithm | HLH'L'C | HLH'L'C
25 | LOG | Base-10 (Common) logarithm | HLH'L'C | HLH'L'C
26 | NOT | Bitwise logical NOT (one's complement) | HLH'L'C | HLH'L'C (C = 0)
27 | RAD | Convert degrees to radians | HLH'L'C (degrees) | HLH'L'C (radians)
28 | SGN | Sign (signum) | HLH'L'C | HLH'L'C (=-1 if negative, =0 if zero, =+1 if positive; C = 0)
29 | SIN | Sine | HLH'L'C (radians) | HLH'L'C
30 | SQR | Square root | HLH'L'C | HLH'L'C
31 | TAN | Tangent | HLH'L'C (radians) | HLH'L'C
32 | ZERO | Return the floating-point & integer constant zero | HL=&0000, H'L'=&0000, C=0
33 | FONE | Return the floating-point constant one | HL=&0000, H'L'=&0000, C=&80
34 | TRUE | Return the integer constant minus one | HL=&FFFF, H'L'=&FFFF, C=0
35 | PI | Return the floating-point constant PI | HLH'L'C (= 3.141592654)
36 | VAL | Return the numeric value of a string | IX addresses string in memory, terminated by a NUL | HLH'L'C. If the string does not represent a number, 0 is returned. IX addresses the terminating character (not necessarily the NUL).
37 STR$ Return the string representation of a number
  • HLH'L'C = number to be converted
  • DE = destination address in memory for string
  • IX addresses format variable (@%), only (IX+1) & (IX+2) used
 String stored in memory, DE addresses byte following last character
38 | FIX | Truncate a number to an integer | HLH'L'C (if C=0 the number is returned unchanged) | HLH'L'C (C = 0). The "too big" error may result.
39 | FLOAT | Convert an integer to floating-point format | HLH'L'C (if C<>0 the number is returned unchanged) | HLH'L'C
40 | TEST | Test a number for zero and sign | HLH'L'C | If zero, A=0; if positive A=&40; if negative A=&C0
41 | COMPARE | Compare two numeric values | HLH'L'C (left) DED'E'B (right) | If equal, A=0; If left>right A=&40; If left<right A=&C0


Mathematical Functions

BBC BASIC (Z80) has more intrinsic mathematical functions than many other versions of BASIC. Those that are not provided may be calculated as shown below.

Function | Calculation
SECANT | SEC(X)=1/COS(X)
COSECANT | CSC(X)=1/SIN(X)
COTANGENT | COT(X)=1/TAN(X)
Inverse SECANT | ARCSEC(X)=ACS(1/X)
Inverse COSECANT | ARCCSC(X)=ASN(1/X)
Inverse COTANGENT | ARCCOT(X)=ATN(1/X) or =PI/2-ATN(X)
Hyperbolic SINE | SINH(X)=(EXP(X)-EXP(-X))/2
Hyperbolic COSINE | COSH(X)=(EXP(X)+EXP(-X))/2
Hyperbolic TANGENT | TANH(X)=EXP(-X)/(EXP(X)+EXP(-X))*2+1
Hyperbolic SECANT | SECH(X)=2/(EXP(X)+EXP(-X))
Hyperbolic COSECANT | CSCH(X)=2/(EXP(X)-EXP(-X))
Hyperbolic COTANGENT | COTH(X)=EXP(-X)/(EXP(X)-EXP(-X))*2+1
Inverse Hyperbolic SIN | ARCSINH(X)=LN(X+SQR(X*X+1))
Inverse Hyperbolic COSINE | ARCCOSH(X)=LN(X+SQR(X*X-1))
Inverse Hyperbolic TANGENT | ARCTANH(X)=LN((1+X)/(1-X))/2
Inverse Hyperbolic SECANT | ARCSECH(X)=LN((SQR(-X*X+1)+1)/X)
Inverse Hyperbolic COSECANT | ARCCSCH(X)=LN((SGN(X)*SQR(X*X+1)+1)/X
Inverse Hyperbolic COTANGENT | ARCCOTH(X)=LN((X+1)/(X-1))/2
LOGn(X) | LOGn(X)=LN(X)/LN(n) or =LOG(X)/LOG(n)


SIRCS Command and Device Codes

Introduction

BBC BASIC (Z80) for the TI-83+/TI-84+ has some support for sending and receiving data to and from SIRCS compatible remote controls. Please see the Files section for further information.

Device Codes

Code | Device
&01 | TV
&02 | VTR1
&03 | Teletext
&04 | Widescreen
&06 | MDP/LaserDisk
&07 | VTR2
&0B | VTR3
&0C | Surround Sound Processor
&10 | Audio/Cassette Deck and Tuner
&11 | CD Player
&12 | Pro-Logic/Equalizer
&1A | DVD Player
&A4 | TV Digital Effects (15-bit)
&093A | PlayStation 2 (DVD) (20-bit)
&1B5A | PlayStation 2 (PS2) (20-bit)

Command Codes

TV

ID | Function
&00 | 1 Button
&01 | 2 Button
&02 | 3 Button
&03 | 4 Button
&04 | 5 Button
&05 | 6 Button
&06 | 7 Button
&07 | 8 Button
&08 | 9 Button
&09 | 10 Button/0 Button
&0B | Enter
&10 | Channel Up
&11 | Channel Down
&12 | Volume Up
&13 | Volume Down
&14 | Mute
&15 | Power
&16 | Reset TV
&17 | Audio Mode: Mono/SAP/Stereo
&18 | Picture Up
&19 | Picture Down
&1A | Color Up
&1B | Color Down
&1E | Brightness Up
&1F | Brightness Down
&20 | Hue Up
&21 | Hue Down
&22 | Sharpness Up
&23 | Sharpness Down
&24 | Select TV Tuner
&25 | Cycle Auxillary/External Modes
&26 | Balance Left
&27 | Balance Right
&29 | Surround On/Off
&2A | Aux/Ant
&2F | Power Off
&30 | Time Display
&36 | Sleep Timer
&3A | Channel Display
&3B | Channel Jump
&3F | Teletext Mode
&40 | Select Input Video 1
&41 | Select Input Video 2
&42 | Select Input Video 3
&4A | Noise Reduction On/Off
&4E | Cable/Broadcast
&4F | Notch Filter On/Off
&58 | PIP Channel Up
&59 | PIP Channel Down
&5B | PIP On
&5C | Freeze Screen
&5E | PIP Position
&5F | PIP Swap
&60 | Guide
&61 | Video Setup
&62 | Audio Setup
&63 | Exit Setup
&6B | Auto Program
&70 | Treble Up
&71 | Treble Down
&72 | Bass Up
&73 | Bass Down
&74 | + Key
&75 | - Key
&78 | Add Channel
&79 | Delete Channel
&7D | Trinitone On/Off
&7F | Displays a Red RtestS on the Screen

Teletext

Code | Function
&4C | Red Button
&4D | Green Button
&4E | Yellow Button
&4F | Blue Button

DVD

Code | Function
&00 | 1 Button
&01 | 2 Button
&02 | 3 Button
&03 | 4 Button
&04 | 5 Button
&05 | 6 Button
&06 | 7 Button
&07 | 8 Button
&08 | 9 Button
&09 | 10 Button/0 Button
&0B | Enter
&0E | Return
&0F | Clear
&1A | Title
&1B | Menu
&1F | Program
&28 | Time
&2A | A↔B
&2C | Repeat
&30 | Previous
&31 | Next
&32 | Play
&33 | Scan «
&34 | Scan »
&35 | Shuffle
&38 | Stop
&39 | Pause
&54 | Display
&60 | Slow «
&61 | Slow »
&63 | Subtitle
&64 | Audio
&65 | Angle
&79 | ↑ Up
&7A | ↓ Down
&7B | ← Left
&7C | → Right

PlayStation 2

Code | Function
&50 | Select
&51 | L3
&52 | R3
&53 | Start
&54 | ↑ Up
&55 | → Right
&56 | ↓ Down
&57 | ← Left
&58 | L2
&59 | R2
&5A | L1
&5B | R1
&5C | △ Triangle
&5D | ○ Circle
&5E | Ｘ Cross
&5F | □ Square


Tokeniser

Introduction

BBC BASIC programs are internally stored in a tokenised format. Certain components of a line of program code, such as keywords, are replaced with a single-byte token. For example, the keyword ENDPROC is represented by the single byte value &E1. This saves space (ENDPROC only takes up 1 byte instead of 7) and allows the interpreter to recognise keywords more efficiently.

Tokeniser Process

The tokeniser reads the input string from left to right and substitutes recognised keywords with their tokens (as listed in the Keyword Tokens section below).

Keyword Flags

The tokeniser maintains a state which controls the way that it tokenises statements. Each keyword has a number of flags which can be used to control the state of the tokeniser.

  • Conditional flag. If this is set then the keyword is not tokenised if it is followed by an alphanumeric character. This would allow, for example, TIMER to be used as a variable name as the TIME part of it would not be tokenised.
  • Middle flag. If encountered the tokeniser is put into middle of statement mode after the keyword has been tokensied.
  • Start flag. If encountered the tokeniser is put into start of statement mode after the keyword has been tokenised. Being at the start of a statement affects the way pseudo-variables and star commands are tokenised.
  • FN/PROC flag. If this is set then the name immediately following the token is not tokenised. For example, this would allow you to declare a PROC_PRINT as the PRINT component would not be tokenised.
  • Line number flag. If encountered then the following statements are interpreted as line numbers. This mode is disabled when a character other than a number, comma or space is encountered.
  • REM flag. If encountered then the remainder of the line is left untokenised.
  • Pseudo-variable flag. If this is set then &40 is added to the token value if the keyword was found at the start of the line. This gives pseudo-variables (such as TIME) two different tokens; one when used as a statement, the other when used as a function.

Other Symbols

The following symbols also affect tokenising:

  • & - skips tokenising the following hex number. For example, the DEF in &DEF is not tokenised.
  • " - skips tokenising the following string constant.
  • : - puts the tokeniser into start of statement mode.
  • * - disables the tokeniser if encountered at the start of the statement.

Line Numbers

Certain keywords are followed by a line number. These line numbers are tokenised to speed up decoding. However, due to some constraints, such as each byte in the tokenised line number needing to below &80 (to prevent it looking like another token) and above &20 (to prevent it from being &0D, the program line terminator) converting a line number into its tokenised form is a relatively complex procedure.

Each tokenised line number is four bytes in size, and is made up like this:

  • Byte 0 - &8D, the line number token.
  • Byte 2 - bits 0-5 are bits 0-5 of the LSB of the line number; bit 6 is 1 and bit 7 is 0.
  • Byte 3 - bits 0-5 are bits 0-5 of the MSB of the line number; bit 6 is 1 and bit 7 is 0.

Byte 1 is more complicated and is formed as shown:

Byte 1 Bit | Value
0 | 0
1 | 0
2 | bit 6 of MSB (inverted)
3 | bit 7 of MSB
4 | bit 6 of LSB (inverted)
5 | bit 7 of LSB
6 | 1
7 | 0

In a C-like programming language the conversion may be carried out using the following code:

ushort line = 1234; // Line number to convert.
byte byte0 = 0x8D;
byte byte1 = (((line & 0x00C0) >> 2) | ((line & 0xC000) >> 12)) ^ 0x54;
byte byte2 = ((line >> 0) & 0x3F) | 0x40;
byte byte3 = ((line >> 8) & 0x3F) | 0x40;

The process can be reversed to retrieve the original line number.

Keyword Tokens

Token | Keyword | Flags
80 | AND | --------
81 | DIV | --------
82 | EOR | --------
83 | MOD | --------
84 | OR | --------
85 | ERROR | -----S--
86 | LINE | --------
87 | OFF | --------
88 | STEP | --------
89 | SPC | --------
8A | TAB( | --------
8B | ELSE | ---L-S--
8C | THEN | ---L-S--
8D | line no. | --------
8E | OPENIN | --------
8F | PTR | -P----MC
90 | PAGE | -P----MC
91 | TIME | -P----MC
92 | LOMEM | -P----MC
93 | HIMEM | -P----MC
94 | ABS | --------
95 | ACS | --------
96 | ADVAL | --------
97 | ASC | --------
98 | ASN | --------
99 | ATN | --------
9A | BGET | -------C
9B | COS | --------
9C | COUNT | -------C
9D | DEG | --------
9E | ERL | -------C
9F | ERR | -------C
Token | Keyword | Flags
A0 | EVAL | --------
A1 | EXP | --------
A2 | EXT | -------C
A3 | FALSE | -------C
A4 | FN | ----F---
A5 | GET | --------
A6 | INKEY | --------
A7 | INSTR | --------
A8 | INT | --------
A9 | LEN | --------
AA | LN | --------
AB | LOG | --------
AC | NOT | --------
AD | OPENUP | --------
AE | OPENOUT | --------
AF | PI | -------C
B0 | POINT( | --------
B1 | POS | -------C
B2 | RAD | --------
B3 | RND | -------C
B4 | SGN | --------
B5 | SIN | --------
B6 | SQR | --------
B7 | TAN | --------
B8 | TO | --------
B9 | TRUE | -------C
BA | USR | --------
BB | VAL | --------
BC | VPOS | -------C
BD | CHR$ | --------
BE | GET$ | --------
BF | INKEY$ | --------
Token | Keyword | Flags
C0 | LEFT$( | --------
C1 | MID$( | --------
C2 | RIGHT$( | --------
C3 | STR$ | --------
C4 | STRING$( | --------
C5 | EOF | -------C
C6 | AUTO | ---L----
C7 | DELETE | ---L----
C8 | LOAD | ------M-
C9 | LIST | ---L----
CA | NEW | -------C
CB | OLD | -------C
CC | RENUMBER | ---L----
CD | SAVE | ------M-
CE | PUT | --------
CF | PTR | --------
D0 | PAGE | --------
D1 | TIME | --------
D2 | LOMEM | --------
D3 | HIMEM | --------
D4 | SOUND | ------M-
D5 | BPUT | ------MC
D6 | CALL | ------M-
D7 | CHAIN | ------M-
D8 | CLEAR | -------C
D9 | CLOSE | ------MC
DA | CLG | -------C
DB | CLS | -------C
DC | DATA | --R-----
DD | DEF | --------
DE | DIM | ------M-
DF | DRAW | ------M-
Token | Keyword | Flags
E0 | END | -------C
E1 | ENDPROC | -------C
E2 | ENVELOPE | ------M-
E3 | FOR | ------M-
E4 | GOSUB | ---L--M-
E5 | GOTO | ---L--M-
E6 | GCOL | ------M-
E7 | IF | ------M-
E8 | INPUT | ------M-
E9 | LET | -----S--
EA | LOCAL | ------M-
EB | MODE | ------M-
EC | MOVE | ------M-
ED | NEXT | ------M-
EE | ON | ------M-
EF | VDU | ------M-
F0 | PLOT | ------M-
F1 | PRINT | ------M-
F2 | PROC | ----F-M-
F3 | READ | ------M-
F4 | REM | --R-----
F5 | REPEAT | --------
F6 | REPORT | -------C
F7 | RESTORE | ---L--M-
F8 | RETURN | -------C
F9 | RUN | -------C
FA | STOP | -------C
FB | COLOUR | ------M-
FC | TRACE | ---L--M-
FD | UNTIL | ------M-
FE | WIDTH | ------M-
FF | OSCLI | ------M-