RTR logo

BBC BASIC for Windows

BBC BASIC for SDL 2.0

Keywords PRINT# to WIDTH



PRINT#

P.#

A statement which writes the internal form of a numeric or string 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, eight bytes or ten bytes of binary data (see the section entitled Format of data in memory). Strings are written as the bytes in the string (in the correct order) plus a carriage return.

The format of data files differs according to the *FLOAT mode in effect at the time (in *FLOAT 40 mode numeric values are written as 5 bytes, in *FLOAT 64 mode they are written as 8 bytes and in *FLOAT 80 mode they are written as 10 bytes). You must ensure that when numeric values are read with INPUT# (or READ#) the same *FLOAT mode is in effect as when the values were written.

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' ASCII 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 the format of the file is completely under your control.

Syntax

PRINT#<numeric>{,<numeric>|<string>}

Associated Keywords

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

PRIVATE

A statement to declare variables for private use inside a function (FN) or procedure (PROC).

PRIVATE saves the value(s) of the specified variable(s) on the stack, and sets their values to those they had when the function or procedure was last called. The original values are restored from the stack on exit from the function or procedure (i.e. at '=' or ENDPROC). The variables need not have been previously declared.

An entire array may be made PRIVATE, following which it is in an undimensioned state. Before the private array can be used within the function or procedure it must be dimensioned using a DIM statement. The new dimensions can be the same as or different from those of a global array with the same name. PRIVATE arrays are allocated on the heap, but can be accessed only in the function or procedure in which they are declared.

Similarly an entire structure may be made PRIVATE, following which it is in an undeclared state. Before the private structure can be used within the function or procedure it must be declared using a DIM statement. The new format (number and type of members) can be the same as or different from that of a global structure with the same name. PRIVATE structures are allocated on the heap, but can be accessed only in the function or procedure in which they are declared.

See also LOCAL which is similar to PRIVATE except that the variables are initialised to zero/null on each entry to the function/procedure rather than holding their values from one call to the next.

PRIVATE A$,X,Y%,items()
If a function or procedure is called recursively, any PRIVATE variables will acquire the values they had in the calling function/procedure. PRIVATE variables behave like globals, except that they cannot be 'seen' outside the (dynamic) scope of the function/procedure in which they are declared. It is important that your program does not 'jump out' of a function/procedure whilst PRIVATE variables are in use (e.g. as the result of an ON ERROR statement). You are advised to use ON ERROR LOCAL and RESTORE LOCAL within the function/procedure to ensure that PRIVATE variables are properly cleaned up in the event of an error:
PRIVATE b$,x,y%,struct{}
ON ERROR LOCAL RESTORE LOCAL : ERROR ERR, REPORT$
Beware that an asynchronous error (such as pressing Escape) could happen between the PRIVATE and ON ERROR statements. If that is a concern, temporarily disable such errors (e.g. using *ESC OFF).

Syntax

PRIVATE <n-var>|<s-var>|<array()>{,<n-var>|<s-var>|<array()>}
PRIVATE <struct{}>{,<struct{}>}

Associated Keywords

DEF, ENDPROC, FN, LOCAL, ON, PROC

PROC

A keyword used to identify a user-defined procedure. PROC is followed immediately by the procedure name; the first character of a procedure name may be an underline (or a digit).

A procedure may take any number of parameters of any type (or none). It does not have to be defined before it is called.

A procedure definition is terminated by ENDPROC.

Procedures are re-entrant and the parameters (arguments) are normally passed by value. The keyword RETURN can be used in the procedure definition to specify that a parameter should instead be passed by reference. Arrays and structures are always passed by reference.

 INPUT"Number of discs "F
 PROC_hanoi(F,1,2,3)
 END
 :
 DEF PROC_hanoi(A,B,C,D)
 IF A=0 THEN ENDPROC
 PROC_hanoi(A-1,B,D,C)
 PRINT"Move disk ";A" from ";B" to ";C
 PROC_hanoi(A-1,D,C,B)
 ENDPROC
Single-line procedures can be placed anywhere within your program. Multi-line procedures must be placed where they will not be executed 'out of sequence', this usually means at the end of the program after the END statement. See the Procedures and functions sub-section for more information.

PROC may alternatively be followed by a numeric value contained in parentheses. This causes the procedure pointed to by the specified value to be called (an indirect call):

pptr% = ^PROC_hanoi()
PROC(pptr%)(a, b, c, d)
See the Indirect procedure and function calls sub-section for more information.

Syntax

PROC(<numeric>)[(<exp>{,<exp>})]
PROC<name>[(<exp>{,<exp>})]

Associated Keywords

DEF, ENDPROC, FN, LOCAL, PRIVATE, RETURN

PTR

A pseudo-variable allowing the random-access pointer of the file whose channel number 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#, PRINT# or GET$#) 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 (see the section on Disk files) 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. If you do this, you must remember to CLOSE the file when you have finished with it in order to update the directory entry.

By using PTR# you have complete control over where you read and write data in a file. This is a simple concept, but it may initially be difficult to grasp its many ramifications. The Disk files section has a number of examples of the use of PTR#.

BBC BASIC for Windows version 6.12a or later and BBC BASIC for SDL 2.0 only
PTR may be used to return the address of a string: PTR(string$). Unlike the alternative construction !^string$ this is compatible with 64-bit versions of BBC BASIC, so is normally to be preferred.

BBC BASIC for Windows version 6.14a or later and BBC BASIC for SDL 2.0 only
PTR may also be used to set or return a pointer to an array, a structure, a procedure or a function: PTR(array()), PTR(struct{}), PTR(PROCname) or PTR(FNname). If the procedure or function receives parameters, add a pair of parentheses to the name: PTR(PROCname()) or PTR(FNname()).

Syntax

PTR#<numeric>=<numeric>
PTR(<s-var>)=<numeric>
PTR(<array()>)=<numeric>
PTR(<struct{}>)=<numeric>
PTR(<FNname|PROCname>)=<numeric>
<n-var>=PTR#<numeric>
<n-var>=PTR(<s-var>)
<n-var>=PTR(<array()>)
<n-var>=PTR(<struct{}>)
<n-var>=PTR(<FNname|PROCname>)

Associated Keywords

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

QUIT

A statement which causes the BASIC program to end and its window to close. The difference between QUIT and END is that END leaves the window open and any results displayed, whereas QUIT closes the window (and does not close open files). QUIT has the same effect as *QUIT and *BYE.

If you are writing a program with the intention that it will be compiled you should normally exit with QUIT rather than END. If the CLOSE button (and the close option on the window menu) has been trapped with ON CLOSE then QUIT (or *QUIT or *BYE) is the only way to close the window.

QUIT may optionally be followed by an integer parameter which determines the program's exit code. This is only useful if the program has been compiled to a standalone executable and run from a command prompt (or another program). When run from a command prompt the exit code is copied into the ERRORLEVEL environment variable.

Syntax

QUIT [<numeric>]

Associated Keywords

END, ON CLOSE, STOP

RAD

A function which converts degrees to radians.
X=RAD(Y)
X=SIN RAD(90)
BBC BASIC 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#

A statement which is synonymous with INPUT#. READ# and INPUT# have identical effects; READ# is implemented in the interests of improved compatibility with other dialects of BASIC.

Syntax

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

Associated Keywords

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

RECTANGLE

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' (BASIC's output window). The origin can be changed using the VDU29 command or the ORIGIN statement.

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

RECTANGLE can also be used to copy or move a rectangular area of the screen to a different place. In this case RECTANGLE is followed by the X and Y coordinates of the bottom left-hand corner of the source rectangle, the width and height of the rectangle, the keyword TO and finally the X and Y coordinates of the bottom left-hand corner of the destination rectangle. To move the rectangle rather than copy it, use RECTANGLE FILL. To swap two rectangular areas use RECTANGLE SWAP.

RECTANGLE xpos,ypos,width,height
RECTANGLE FILL 400,500,200
RECTANGLE 100,100,200,200 TO 300,300
RECTANGLE FILL srcx,srcy,dx,dy TO dstx,dsty
RECTANGLE SWAP x1,y1,dx,dy TO x2,y2
RECTANGLE is also used in the MOUSE RECTANGLE statement.

Syntax

RECTANGLE [FILL] <numeric>,<numeric>,<numeric>[,<numeric>] [TO <numeric>,<numeric>]
RECTANGLE SWAP <numeric>,<numeric>,<numeric>[,<numeric>] TO <numeric>,<numeric>

Associated Keywords

FILL, MOUSE, SWAP, TO

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

REM WSCONVERT REV 2.30
REM 5 AUG 84
REM Converts 'hard' carriage-returns to 'soft'
REM ones in preparation for use with WS.

Syntax

REM any text

Associated Keywords

None

REPEAT

REP.

A statement which is the starting point of a REPEAT...UNTIL loop. The purpose of a REPEAT...UNTIL loop is to make BBC BASIC repeat a set number of instructions until some condition is satisfied:
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 (see the sub-section on Program Flow Control for more details). You can force a premature end to the loop with the EXIT REPEAT statement.

REPEAT...UNTIL loops may be nested.

Syntax

REPEAT

Associated Keywords

EXIT, UNTIL, WHILE

REPORT/REPORT$

A statement (REPORT) which outputs, and a string function (REPORT$) which returns, the error string associated with the last error which occurred.

You can use these keywords within your own error handling routines to print out or process an error message for those errors you are not able to cope with.

The example below is an error handling routine designed to clear the screen before reporting the error:

  ON ERROR MODE 3 : REPORT : PRINT " at line ";ERL : END
See the sub-section on Error Handling and the keywords ERR, ERL and ON ERROR for more details.

Syntax

REPORT
<s-var> = REPORT$

Associated Keywords

ERR, ERROR, ERL, ON ERROR

RESTORE

RES.

A statement which moves the data pointer. RESTORE can be used at any time in a program to set the line from where READ reads the next DATA item.

RESTORE on its own resets the data pointer to the first data item in the program.

RESTORE followed by a line number or label 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 followed by a plus sign (+) and a positive numeric value sets the data pointer to the first item of data in the line offset from the line containing the RESTORE statement by the specified number of lines (or the next DATA statement if the specified line does not contain any data). When using values greater than +1 it is advisable to put the DATA statements immediately after the RESTORE statement to avoid incorrect results if the program is compiled.

RESTORE
RESTORE 100
RESTORE +2
RESTORE (10*A+20)
RESTORE (mydata)
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.

RESTORE DATA

RESTORE DATA causes the DATA pointer saved by a previous LOCAL DATA statement to be restored from the stack.

RESTORE ERROR

RESTORE ERROR causes the error-trapping status saved by a previous ON ERROR LOCAL statement to be restored from the stack.

RESTORE LOCAL

RESTORE LOCAL (which can be used only inside a user-defined procedure or function) restores the values of formal parameters and LOCAL/ PRIVATE variables to those they had before the procedure/function was called. RESTORE LOCAL also performs the action of RESTORE ERROR. This is primarily intended for use within an ON ERROR LOCAL error handler.

Syntax

RESTORE [<l-num>]
RESTORE [(<numeric>)]
RESTORE +<numeric>
RESTORE DATA
RESTORE ERROR
RESTORE LOCAL

Associated Keywords

READ, DATA, ON ERROR LOCAL

RETURN

R.

A statement causing a RETURN to the statement after the most recent GOSUB statement, or a RETURN to the calling program after a CALL statement, or a RETURN to the original code following an event trapped with ON CLOSE, ON MOUSE, ON MOVE, ON SYS or ON TIME.

You use RETURN at the end of a subroutine to make BBC BASIC 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 as well. The sub-section on Program Flow Control explains why.

RETURN may optionally be followed by a destination (line-number or label) which causes the subroutine or event-handler to return to the specified line rather than to continue execution from where it was called.

Syntax

RETURN
RETURN <l-num>
RETURN (<numeric>)
RETURN is also used in a function or procedure DEFinition to specify that a parameter should be passed by reference rather than by value. When used with a whole array or structure parameter, RETURN allows the array or structure to be declared (using DIM) within the function or procedure. When used with a procedure or (particularly) function parameter RETURN specifies that a pointer to the function, not the value returned by the function, will be received by the formal parameter.

Associated Keywords

CALL, DEF, GOSUB, ON GOSUB ON CLOSE, ON MOUSE, ON MOVE, ON SYS, ON TIME

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. RIGHT$ may also be used to the left of an equals sign to change the end of a string whilst leaving the rest alone.

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)
RIGHT$(A$,3) = B$
For example,
name$="BBC BASIC for Windows"
FOR i=3 TO 13
  PRINT RIGHT$(name$,i)
NEXT
END
would print
ows
dows
ndows
indows
Windows
 Windows
r Windows
or Windows
for Windows
 for Windows
C for Windows
When using RIGHT$ on the left of an equals sign, and the expression to the right of the equals sign evaluates to a string with fewer characters than the specified sub-string length, only that number of characters is changed. For example:
A$ = "BBC BASIC"
RIGHT$(A$,4) = "ZZ"
will set A$ equal to "BBC BASZZ". Although the sub-string length is set to four, only the last two characters are actually modified since that is the length of the string "ZZ".

RIGHT$(A$) is shorthand for RIGHT$(A$,1), in other words it returns or sets the last character of A$.

Syntax

<s-var>=RIGHT$(<string>[,<numeric>])
RIGHT$(<s-var>[,<numeric>])=<string>

Associated Keywords

LEFT$, MID$, INSTR

RND

A function which returns a random number. The type and range of the number returned depends upon the optional parameter.
RND returns a random integer 0 - &FFFFFFFF.
RND(n) returns an integer in the range 1 to n (n>1).
RND(1) returns a real number in the range 0.0 to .99999999.
If n is negative the pseudo random sequence generator is set to a number based on n and n is returned.

If n is 0 the last random number is returned in RND(1) format.

X=RND(1)
X%=RND
N=RND(6)

Syntax

<n-var>=RND[(<numeric>)]

Associated Keywords

None

RUN

A statement which starts or restarts execution of the program.
RUN
All variables except the static variables @% 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
RUN <string>

Associated Keywords

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.

SGN returns:

+1for positive numbers
0for zero
−1for negative numbers

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

SOUND

A statement which generates sounds using the sound card (if fitted). If no suitable sound card is fitted, or if the sound system is currently in use by another program, the trappable Device unavailable error will result.

The SOUND statement is followed by four parameters which specify the sound channel to be used (and special effects), the amplitude of the note (or the envelope number), the (initial) pitch of the note and how long the note is to last.

SOUND Channel,Amplitude,Pitch,Duration

Channel/Effects

If the channel/effects value is represented by the hexadecimal number &HSFC the individual digits (nibbles) have the following meaning:

C = channel number: There are four sound channels, numbered 0 to 3. Channel 0 is a special channel that can produce 'noise'; channels 1-3 are used to produce 'tones'. Channel 0 can be configured to be a 'tone' channel by adding 128 to the *TEMPO value.

F = flush control: If F is 1, the sound statement in which it occurs 'flushes' any notes waiting in the queue for that channel. This causes the sound to be played immediately.

S = synchronisation: If S is 0 the note is played as soon as the last note on that channel has completed (i.e. reached the start of the 'release' phase). If S is non-zero the note does not play until a corresponding note on another channel is ready to be played. A value of S=1 implies that there is one other note in the group, S=2 implies two other notes (i.e. a total of three) etc.

H = hold note: If H=1 any note currently playing on the selected channel is allowed to continue without being interrupted. The Amplitude and Pitch parameters are ignored. If an envelope is in use, the release phase is entered.

Amplitude/Envelope

If the Amplitude parameter is negative or zero it determines the loudness of the note, from −15 (loudest) to 0 (silent). If the Amplitude parameter is positive it selects one of 16 envelopes (1-16). See the keyword ENVELOPE for more details.

Pitch

This sets the pitch of the note (initial pitch in the case of a pitch envelope), in units of quarter-semitones. Middle C is generated with the value 100 and International Standard Pitch (440 Hz) with the value 136.

To go up or down an octave, the Pitch must be changed by 48.

To go up a perfect 5th, the Pitch must be increased by 28.

Increasing the Pitch by 1 will increase the frequency of the note produced by ¼ of a semitone.

 Octave Number
Note  2 34 56 7
B 4896 144192240 
A# 4492 140188236 
A 4088 136184232 
G# 3684 132180228 
G 3280 128176224 
F# 2876 124172220 
F 2472 120168216 
E 2068 116164212 
D# 1664 112160208 
D 1260 108156204252
C# 856 104152200248
C 452 100148196244
If the channel number is zero, the pitch parameter behaves differently. Values 4 to 7 result in 'white' noise and values 0 to 3 result in periodic 'buzzing' noises. Values 3 and 7, which on the BBC Micro allow you to control the 'pitch' of the noise, are not implemented. They have the same effect as values 1 and 5 respectively.

Duration

This sets the duration of the note, in units of twentieths of a second (by default). A value of −1 signifies 'play indefinitely' (i.e. the note will sound until you explicitly stop it by pressing <Esc>, sending another note with the 'flush control' set to 1, or executing the SOUND OFF statement). In the case of an amplitude envelope, the duration is the period before the note enters the 'release' phase.

The duration can have any value between −1 and 254.

You can change the units of the duration parameter to a value between 1 centisecond (1/100 second) and 5 centiseconds (1/20 second), using the *TEMPO command.

Examples

The example below simply generates two notes one after the other. The first note is middle C and it sounds for one (20/20) second. The second note is C1; it sounds for two (40/20) seconds.
SOUND 1,-15,100,20
SOUND 1,-15,148,40
In the next example, the first SOUND statement has a duration of −1. This will cause the note to continue until a SOUND statement with bit 4 of the channel number set cancels it (or <Esc> is pressed). The second line sets up another note and adds it to the sound queue. However, this note does not sound immediately because the first note is still sounding. After a short pause the final SOUND statement is executed. The channel number has bit 4 set (add 16 to the channel number), so the sound queue is flushed by this command and its note (middle C) is sounded immediately. The sound added to the queue by the second SOUND statement is lost when the sound queue is flushed.
SOUND 1,-15,52,-1
SOUND 1,-15,56,50
WAIT 200
SOUND &11,-15,100,10
The following example illustrates the use of the synchronisation parameter. The first two SOUND statements specify that notes should be played on channels 1 and 3, but because their S values are set to 2 they wait until a third channel (also with S = 2) is ready to play. The third SOUND statement plays a high-pitched sound on channel 2 for one second, but since S = 0 channels 1 and 3 continue to wait. The fourth SOUND statement then plays a note on channel 2 with S = 2; as a result all three channels start to play simultaneously:
SOUND &201,-15,100,20
SOUND &203,-15,116,20
SOUND 2,-15,200,20
SOUND &202,-15,128,20
The next example uses a pitch ENVELOPE. The sound produced is a slow 'warble' about the chosen note. Each step of the envelope is 0.1 (10/100) seconds. The pitch of the note will change by ¼ semitone every step of section 1 of the envelope, by −¼ semitone for every step of section 2, and by ¼ semitone again for every step of section 3. Section 1 will last for 10 steps (1 second), section 2 for 20 (2 seconds) steps and section 3 for 10 steps. The SOUND statement initially sounds middle C. The duration is −1, so you will need to press <Esc> to stop it.
ENVELOPE 1,10,1,-1,1,10,20,10,126,0,0,-126,126,0
SOUND 1,1,100,-1
The final example uses an amplitude ENVELOPE, and also illustrates the use of the 'hold' (H) bit. The envelope specifies an initial attack rate of 5 until the level reaches 126, followed by a decay rate of −5 until the level reaches 63. The level is then maintained (sustain = 0) for the rest of the note's duration, after which the level falls to zero at a rate of −5 during the 'release' phase.

The second SOUND statement has the 'hold' bit set, causing the note being played on channel 1 to continue for another ¾ second, which is enough for the release phase to complete (the amplitude and pitch parameters in this SOUND statement are ignored). If it were not present, the release phase would never occur since another note is waiting to sound on the same channel:

ENVELOPE 1,1,0,0,0,0,0,0,5,-5,0,-5,126,63
SOUND 1,1,148,40
SOUND &1001,-15,100,15
SOUND 1,-15,200,10

Syntax

SOUND <numeric>,<numeric>,<numeric>,<numeric>
SOUND OFF

Associated Keywords

ENVELOPE

SPC

A statement which prints a number of spaces to the screen. The argument specifies the number of spaces to be printed.

SPC can only be used within a PRINT or INPUT statement.

PRINT DATE;SPC(6);SALARY

INPUT SPC(10) "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 'Negative 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>)

Associated Keywords

None

STEP

S.

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.

FOR cost=20 TO 5 STEP -5
  PRINT cost,cost*1.15
NEXT
STEP is also used in the TRACE STEP statement.

Syntax

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

Associated Keywords

FOR, TO, NEXT

STOP

A statement which is syntactically equivalent 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. 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 may get unexpected results.

Syntax

STOP

Associated Keywords

END, QUIT

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>,<string>)

Associated Keywords

None

SUM

A function which returns the sum of all the elements of a numeric array (floating-point, integer or byte) or the concatenation of all the strings in a string array.
DIM marks%(10)
marks%() = 0,1,2,3,4,5,6,7,8,9,10
PRINT SUM(marks%())
The above program segment will print the value 55, being the sum of the eleven values in the array marks%(10).

If the array has more than one dimension, all the elements in all the dimensions are summed:

DIM grid(7,7)
grid() = PI
PRINT SUM(grid())
This will print the value 201.06193, being PI * 64 (64 being the number of elements in the 8 x 8 array).

SUMLEN

A function which returns the total length of all the strings in a string array. The difference between SUMLEN(array$()) and LENSUM(array$()) is that the former will work correctly whatever the total length of the strings, whereas the latter may result in the String too long error.

Syntax

<n-var>=SUM(<n-array()>)
<s-var>=SUM(<s-array()>)
<n-var>=SUMLEN(<s-array()>)

Associated Keywords

DIM

SWAP

A statement which swaps (exchanges) the contents of two variables, two arrays or two structures. The variables or arrays must be of the same type, for example two integer numeric variables, or two string arrays. If the types differ, a Type mismatch error will result. If two arrays are swapped, their dimensions are also swapped. If two structures are swapped, their formats (number and type of members) are also swapped.
SWAP a,b
SWAP Coat$,Hat$
SWAP A$(),B$()
SWAP my_struct{},your_struct{}
SWAP is also used in the RECTANGLE SWAP statement.

Syntax

SWAP <n-var>,<n-var>
SWAP <s-var>,<s-var>
SWAP <array()>,<array()>
SWAP <struct{}>,<struct{}>

Associated Keywords

DIM, RECTANGLE

SYS

A statement which calls an Operating System API (Application Program Interface) function or a function in a Shared Object (e.g. a DLL). SYS is followed by the function's address or the function's name as a (case sensitive) string plus, optionally, a list of comma-separated numeric or string parameters to be passed to the function. A 32-bit integer value may be returned from the function by adding TO followed by a numeric variable name. Exceptionally, if a 64-bit integer variable is specified (e.g. big%%) a 64-bit value is assumed to be returned.
SYS "MessageBeep", 16
SYS "GetTickCount" TO tick%
SYS "PlaySound", "SystemStart", 0, &10001
BBC BASIC for Windows version 6.12a or later and BBC BASIC for SDL 2.0 only
A 64-bit floating point ('double') value may be returned from the function by specifying a variable of that type after the TO:
SYS "GetModuleHandle", "msvcrt.dll" TO msvcrt%
SYS "GetProcAddress", msvcrt%, "atof" TO `atof`
SYS `atof`, "1.23456789" TO double#
PRINT double#
SYS is a very powerful statement. It allows you to access the full range of facilities provided by the Operating System. Further details can be found in the Accessing the Windows API or Accessing the SDL 2.0 API sections.

BBC BASIC for Windows version 6.14a or later and BBC BASIC for SDL 2.0 only
SYS may be used as a function; it returns the numeric equivalent (address) of a named API routine. Calling an API function by address is often significantly faster than calling it by name.

SYS is also used in the ON SYS statement.

Syntax

SYS <numeric>|<string> {,<numeric>|<string>} [TO <n-var>]
<n-var>=SYS(<string>)

Associated Keywords

CALL, ON SYS

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.

PRINT TAB(10);A$
TAB(X) may not have the desired effect if a proportional-spaced font is selected, or when UTF-8 mode is enabled.

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 coordinates are with respect to the current text viewport; column 0 is normally on the left and row 0 is normally at the top, but this can be changed using VDU 23,16. If the specified coordinates correspond to a location outside the current text viewport the behaviour is undefined.

PRINT TAB(X,Y);B$
Note that text written in the VDU 5 (print text at graphics cursor) mode is not affected by TAB(X,Y). In that mode you must position the text using graphics statements (for example MOVE). You can achieve a similar functionality to TAB(X,Y) by using the following user-defined function:
DEF FNTAB(X%,Y%) : X% = X%*16 : Y% = 1023-Y%*32
= CHR$25+CHR$4+CHR$(X%)+CHR$(X%DIV256)+CHR$(Y%)+CHR$(Y%DIV256)
which you would call in a context such as
PRINT FNTAB(5,5) "Text in VDU 5 mode"
The constants in the above function are correct for screen MODEs 0 and 8. For other modes replace 16 with the appropriate character width, 32 with the appropriate character height and 1023 with one less than the height of the current graphics viewport (all in BBC BASIC graphics units).

Syntax

PRINT TAB(<numeric>[,<numeric>])
INPUT TAB(<numeric>[,<numeric>])

Associated Keywords

POS, VPOS, PRINT, INPUT

TAN

T.

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

TH.

An optional part of the IF... THEN ... ELSE statement. It introduces the action to be taken if the testable condition evaluates to a non-zero value.
IF A=B THEN 3000
IF A=B THEN PRINT "Equal" ELSE PRINT "Help"
IF A=B THEN
  PRINT "Equal"
ELSE
  PRINT "Help"
ENDIF
You need to use THEN if it is: or you wish to exit from a function as a result of the test:
DEF FN_test(a,b,num)
IF (a>b) THEN =num
=num/256
When THEN introduces a multi-line IF ... ENDIF statement it must be the very last thing on the line, not even followed by a REMark.

THEN may be followed immediately by a semicolon (;) to aid translation of the ELSEIF keyword available in some other BASIC dialects, for example:

IF condition1 THEN
  PROCone
ELSEIF condition2 THEN;
  PROCtwo
ELSEIF condition3 THEN;
  PROCthree
ENDIF
This facility is intended for use only by automatic translators, rather than in new programs.

Syntax

IF <t-cond> THEN <stmt>{:<stmt>} [ELSE <stmt>{:<stmt>}]
IF <t-cond> THEN
ELSEIF <t-cond> THEN;

Associated Keywords

IF, ELSE, ENDIF

TIME

TI.

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's internal clock. The value of the clock is returned in centi-seconds (one-hundredths of a second) and it is quite accurate. However, you should not assume that TIME is updated 100 times per second; depending on the Operating System, it may change less frequently (each update adding a value greater than 1 to the elapsed time count when necessary). For this reason, a delay loop such as REPEAT UNTIL TIME=T can fail. The compound conditional test REPEAT UNTIL TIME >=T should always be used.

TIME is also used in the ON TIME statement.

Syntax

TIME=<numeric>
<n-var>=TIME

Associated Keywords

TIME$, ON TIME, WAIT

TIME$

A 24 character long string pseudo-variable which reads and sets the system clock. The format of the character string is:

Day.dd Mon yyyy,hh:mm:ss

Where:

Dayis the day of the week (Mon, Tue, etc).
ddis the day of the month (01, 02, etc).
Monis the abbreviated month name (Jan, Feb ,etc).
yyyy   is the year (2003, 2004, etc).
hhis hours (00 to 23).
mmis minutes (00 to 59).
ssis seconds (00 to 59).
The format is similar to that used on the Master Series BBC Micro except that the full-stop and comma are exchanged.
clock$=TIME$
TIME$="Sun.02 Feb 2003,18:33:30"
The time, date or both time and date may be set as shown below.
TIME$="Day.dd Mon yyyy"           sets the date.
TIME$="hh:mm:ss"                  sets the time.
TIME$="Day.dd Mon yyyy,hh:mm:ss"  sets date & time.
When setting the clock, the day of the week is ignored and may be omitted.

The first example below sets only the date and the second sets the date and the time.

TIME$="02 Feb 2003"

clock$="Mon.03 Feb 2003,22:31:15"
TIME$=clock$
No error is reported if the format is not accurately adhered to, however the clock may be set incorrectly.

Because the system clock is a shared resource, and changing it could adversely affect other programs, you can only assign a new value to TIME$ in BBC BASIC for Windows, and only if you have the appropriate administrative privileges.

Syntax

TIME$=<string>
<s-var>=TIME$

Associated Keywords

TIME

TINT

A function which returns an integer containing the RGB (Red, Green, Blue) value of the physical colour at the specified screen coordinates. If the point is outside the graphics viewport, then the value −1 is returned.

The colour is packed into a 32-bit integer such that the red component is in the least-significant byte, the green component is in the second byte and the blue component is in the third byte. Each component can have a value between 0 (black) and 255 (maximum brightness). The most-significant byte is always zero, except when the value −1 is returned. For example, if the returned value is &FF0000 the colour is a bright blue, and if the value is &400040 the colour is a dark purple.

The difference between TINT and POINT is that TINT returns the physical colour whereas POINT returns the logical colour (palette index). Beware that in BBC BASIC for SDL 2.0 POINT and TINT are very slow.

rgb% = TINT(X,Y)
You can use TINT to find out the colour of the screen at the specified point and take action accordingly. In an adventure game, for example, the swamps may be marked in green. If the explorer ventured into a green area he must be in the swamp and 'swamp type demons' would be activated.

Syntax

<n-var>=TINT(<numeric>,<numeric>)

Associated Keywords

PLOT, DRAW, MOVE, GCOL, POINT

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,

FOR i=1 TO 5 STEP 1.5
  PRINT i
  NEXT
PRINT "**********"
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,
FOR i= 20 TO 10
  PRINT i
NEXT
will print
        20
TO is also used in the SYS, RECTANGLE and MOUSE statements, and in the GET$#channel function.

Syntax

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

Associated Keywords

FOR, GET$, MOUSE, NEXT, RECTANGLE, STEP, SYS

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

TR.

A statement which causes the interpreter to print executed line numbers when it encounters them. TRACE ON prints all line numbers that are executed.

TRACE X sets a limit on the range of line numbers which will be printed out. Only those line numbers less than X will appear. If you are careful to place all your subroutines, procedures and functions at the end of the program, you can display the main structure of the program without cluttering up the trace.

TRACE OFF turns trace off. TRACE is also turned off if an error is reported or you press <Esc>.

An alternative (and often better) way of tracing execution of your program is with the Trace command in the Utilities menu.

TRACE STEP ON (or TRACE STEP) enables single-step (pause) mode so you can step through a section of your program one statement (or line) at a time. TRACE STEP OFF restores normal execution.

Syntax

TRACE ON|OFF|<l-num>
TRACE ON|OFF|(<numeric>)
TRACE STEP [ON|OFF]

Associated Keywords

None

TRUE

A function returning the value −1.
flag=FALSE
....
IF answer$=correct$ flag=TRUE
....
IF flag PROC_got_it_right ELSE PROC_wrong
BBC BASIC does not have true Boolean variables. This can lead to confusion; see the keyword NOT for details.

Syntax

<n-var>=TRUE

Associated Keywords

AND EOR FALSE NOT OR

UNTIL

U.

A keyword which marks the end of a REPEAT ... UNTIL loop.

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 <Esc> 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 <Esc> or forcing a 'Too big' error.

z=1
REPEAT
  INPUT "Enter a number " num
  PRINT "The square of ";num;" is ";num*num
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:
REPEAT
  INPUT "Enter a number " num
  PRINT "The square of ";num;" is ";num*num
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.

Syntax

UNTIL <t-cond>

Associated Keywords

REPEAT

USR

A function which allows an assembly language routine to return a value directly.

USR calls the machine code subroutine whose start address is its argument. When running on a 32-bit x86 CPU, the processor's EAX, EBX, ECX and EDX registers are initialised to the contents of A%, B%, C% and D% respectively (see also CALL). FLAGS is initialised to the least significant word of F%. However, you cannot disable interrupts nor enter single-step mode by setting F% because this could affect the operation of BBC BASIC.

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

USR provides you with a way of calling a machine code routine which is designed to return one integer value. Parameters are passed via the processor's registers and the machine code routine returns a 32-bit (signed) integer result in the processor's EAX register.

X=USR(lift_down)
Unlike CALL, USR returns a result. Consequently, you must assign the result to a variable. It may help your understanding if you look upon CALL as the machine code equivalent to a PROCedure and USR as equivalent to a Function.

Operating system interface

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

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.

If you want to force conversion to a 64-bit double, even when in *FLOAT40 mode, you can do so by adding a # (hash) suffix to the supplied string:

A# = VAL("1.234#")
nr# = VAL("7899876553.#")
Note that you should use this facility only when you are certain a numeric co-processor is available, since it bypasses the normal check carried out when *FLOAT64 is executed.

Syntax

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

Associated Keywords

STR$, EVAL

VDU

V.

A statement which takes a list of numeric arguments and sends their least-significant bytes as characters to the VDU emulator.

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.

It is very important that the correct number of bytes be sent, as appropriate for the particular VDU command. If too few are sent, the 'remaining' bytes will be taken from subsequent VDU or PRINT statements, sometimes with (at first sight) extremely strange results. This problem can be circumvented by terminating the VDU statement with the '|' character which ensures that sufficient bytes are sent.

VDU 8,8 :REM cursor left two places.
VDU &0A0D;&0A0D; :REM CRLF twice
VDU 23,1,0| : REM disable cursor
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 individual characters directly to the screen without having to use a PRINT statement. It offers a convenient way of sending 'control characters'.

In UTF-8 mode each character may require 1, 2 or 3 bytes depending on its position within the Basic Multilingual Plane.

Syntax

VDU <numeric>{,|;<numeric>}[;][|]

Associated Keywords

CHR$, PRINT

VPOS

A function returning the row number containing the text cursor (caret). VPOS returns the position of the cursor with respect to the text viewport; row 0 is normally at the top, but this may be changed using VDU 23,16.
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 23. The cursor is returned to its previous position after the message has been printed.
DEF PROC_message(message$)
LOCAL x,y
x=POS
y=VPOS
PRINT TAB(0,23) CHR$(7);message$;
PRINT TAB(x,y);
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.

WAIT 0 results in only a short pause (typically about 1 millisecond), but does give other programs an opportunity to run; it can be useful in preventing your program consuming 100% of the processor's time.

WAIT without a parameter does nothing; it is provided for compatibility with Acorn's BASIC 5 (in which it waits for the next vertical-retrace event).

Syntax

WAIT [<numeric>]

Associated Keywords

INKEY, TIME

WHEN

A keyword which is part of the CASE... ENDCASE clause. WHEN precedes the value (or values) against which the CASE variable is tested. WHEN must be the first item on the program line.
CASE die% OF
  WHEN 1,2,3 : bet$ = "lose"
  WHEN 4,5,6 : bet$ = "win"
  OTHERWISE bet$ = "cheat"
ENDCASE

Syntax

WHEN <numeric>{,<numeric>} : {<stmt>}
WHEN <string>{,<string>} : {<stmt>}

Associated Keywords

CASE, OF, OTHERWISE

WHILE

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

W.

A statement controlling the overall field width for text output.
WIDTH 80
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 written; it also affects output to the printer.

WIDTH may not have the desired effect if a proportional-spaced font is selected, or when UTF-8 mode is enabled.

WIDTH can also be used as a function. It returns the current field width.

WIDTH may also be used to measure the width, in BBC BASIC graphics units, of a string as it would be displayed in the main output window using the current font and character set (ANSI or UTF-8):

w% = WIDTH("Hello world!")
Note that because of kerning, and especially in the case of italic text, the returned value may not be precise.

Syntax

WIDTH <numeric>
<n-var> = WIDTH
<n-var> = WIDTH(<string>)

Associated Keywords

COUNT

Left CONTENTS

CONTINUE Right


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