Commands direct the Sorcerer to arrange memory and input/output facilities, to list and edit programs and to handle other housekeeping details in support of program execution. The Sorcerer accepts commands after it prints READY and is at command level. All of these except CONT may be used also in indirect mode.
Takes the Sorcerer out of Standard BASIC, into the Power-On Monitor. To got back into BASIC, give the Monitor command PP. (This is for a warm start, that is, returning to BASIC with the memory intact. To do a cold start, which is the same as a reset, type PP X, that is PP followed by a space and any character.) (Or GO DFFA for warm start and GO DFFD for cold start.)
Sets all program variables to zero.
CLEAR |< expression>|
Same as CLEAR but sets string space to the value of the expression. If no argument is given, string space remains unchanged. Normally string space is set to 50 bytes, some of which Standard BASIC uses for its own purposes. Use this to avoid getting the OS error message.
CLOAD |<program name>| |<unit number>|
Loads the program designated by <program name> into memory from the designated tape unit. Erases everything currently in memory before loading program. The program name should not contain more than five characters. The Sorcerer does not recognize non-alphanumeric characters in a program name. Omitting <unit number> defaults to unit #1. Omitting <program name> loads the next program encountered into memory. If you specify <unit number> you must also specify <program name>. Youmust leave a space between <program name> and <unit number>.
CLOAD* <unit number> <array name>
Loads the specified array from the designated cassette unit. You must include the <unit number> 1 or 2). You must leave a space between the <unit number> and the <array name>. Give the array name without parentheses (and without argument).
Continues program execution after a CTRL C or a STOP statement. Execution resumes at the statement after the break occurred. CONT is useful in debugging, especially when you suspect an infinite loop. Typing CTRL 0 causes a break in execution and puts the Sorcerer into command level. You can then use direct mode statements to print intermediate values, change the values of variables, etc. Restart the program by typing the CONT command, or by giving a direct mode GOTO statement. You cannot use CONT after a direct mode error or if you modify the program during the break, as that resets all variables and arrays. (However, you may still use a direct mode GOTO.)
CSAVE |<program name>| |<unit number>|
Saves the program currently in memory on the designated cassette tape under the name specified by the first five characters of the <program name> (which must be alphanumeric). It no tape unit is specified, the program is saved on unit #1. If you omit the <program name> option, the program is saved with no name. You must specify a program name if you specify a tape unit. Be sure to leave a space between <program name> and <unit number>.
CSAVE* <unit number> <array name>
Saves the named array on the designated cassette tape. You must include the <unit number> (1 or 2) and leave a space between <unit number> and <array name>. Name the array but do not use parentheses or an argument.
LIST |<line number>|
Lists the program currently in memory, starting with the specified line. If no <line number> is given, starts with the lowest numbered line. Listing is terminated either by the end of the program or by typing CTRL C. You may temporarily stop the listing by holding down the RUN STOP key.
Deletes the current program and clears all variables and arrays. Use before entering a new program.
NULL <integer expression>
This routine is for printing with serial printers with slow mechanical carriage returns, to prevent losing characters at the beginnings of lines. Parallel printers have a ''handshake" procedure whereby the printers acknowledge receipt of characters and don't need nulls. Sets the number of nulls to be printed at the end of each line. For 10 character per second tape punches, <integer expression> should be >=3. For 30 CPS punches, it should be 2 or 3. When tapes are not being punched, <integer expression> should be -3 for TTYs and TTY compatible CRTs. It should be 2 or 3 for 30 CPS hard copy printers. The default value is 0. If your Sorcerer is not connected to a paper punch or a line printer, you won't have to worry about this command.
RUN |<line number>|
Starts execution of the program currently in memory at the line specified. If the line number is omitted, execution begins at the lowest line number.
RUN |<line number>| works like CLEAR, it clears all variables. If you don't want to lose the values of variables, use the direct mode GOTO command.
In the following table, X and Y stand for any expressions. L stands for any logical expression, I and J stand for expressions whose values are truncated to integers. and V and W are any variable names. The formal for a Standard BASIC line is
where nnn is the line number.
DATA DATA <list>
Specifics data to be read by a READ statement. List elements can be numbers or strings or both. List elements are separated by commas.
DEF DEF FNV(<W>)=<X>
Defines a user-defined numerical function. Function name is FN followed by a legal variable name. Definitions are restricted to one line and one, statement (64 characters, which includes the whole program statement).
DIM DIM<V>(<I>|,J...|)|, ...|
Allocates space for array variables. More than one variable may be dimensioned by one DIM statement, up to the limit of the line. The value of each expression gives the maximum subscript possible. The smallest subscript is 0. Without a DIM statement, an array is assumed to have maximum subscript of 10 for each dimension referenced. For example, A(I,J) is assumed to have 121 elements, from A(0,0) to A(10,10) unless otherwise dimensioned in a DIM statement.
Terminates execution of a program.
FOR FOR <V>=<X> TO <Y>|STEP <Z>|
Allows repeated execution of the same statements. First execution sets V=X. Execution proceeds normally until NEXT is encountered. Z is added to V, then if Z<0 and V>=Y, or if Z>0 and V<=Y the Sorcerer branches back to the statement after FOR. Otherwise, execution continues with the statement after NEXT. If Z is riot specified, the default value is 1.
GOTO GOTO <nnnn>
Unconditional branch to line number nnnn.
GOSUB GOSUB <nnnn>
Unconditional branch to subroutine beginning at the line nnnn. Expects a RETURN at the logical end of the subroutine.
IF...GOTO IF <X> GOTO <nnnn>
Same as IF... THEN except GOTO can only be followed by a line number and not another statement.
or IF <X> THEN <line number>
or IF <X> THEN <statement>|:<statement>...|
or IF <L> THEN <line nurnber>
or IF <L> THEN <statement>|:<statement>...|
If value of X is not 0, or if L is true, the Sorcerer branches to the line number or statement(s) after THEN. If X is 0 or L is false, goes to the line after IF ... THEN.
INPUT INPUT |<"prompt string">;|<V>|,<W>...|
Causes the Sorcerer to request input from the terminal. Values typed on the terminal are assigned to the variables in the list. If the <"prompt string"> option is used, first prints the prompt string on the screen, and then requests input. In both cases, the request for input is indicated by a ?. If more than one input is requested (by pulling more than one variable in the list) and not enough responses are entered, responds with ??. Both numeric and string variables may be used in the list and they may be intermingled, you may not respond to a numeric request with a string.
LET LET <V>=<X>
Assigns the value of the expression to the variable. The word LET is optional.
NEXT NEXT |<V>||,<W> ... |
Last statement of a FOR ... NEXT Loop. V is the variable of the most recent loop. W of the next most recent and so on. (In other words, list the variables in reverse order of the FOR statements. NEXT without a variable terminates the most recent FOR loop, or in a series of nested loops, the outermost FOR loop.
ON...GOTO ON <I> GOTO <list of line numbers>
Branches to line whose number is Ith in the list. List elements are separated by commas. If I=0 or > number of elements in the list, execution continues at next statement. If I<0 or >255, an error results. If I is not an integer, it is truncated.
ON...GOSUB ON <I> GOSUB <list of line numbers>
Same as ON ... GOTO except list elements are initial line numbers of subroutines. If I is not an integer, it is truncated
PRINT PRINT <X>|,<Y>...|
Causes values of expressions in the list to be printed on the terminal (or certain control functions to be executed). Spacing is determined by punctuation.
Punctuation Spacing-next printing begin:
, at beginning of next 14 column zone
If there is no punctuation between elements, the Sorcerer assumes the use of a semicolon, unless they are the same kind of elements, in which case the Sorcerer does not know where one ends and the other begins. That is, it has no trouble distinguishing PRINT A$B$CHR$(34)X but gets confused by PRINT XYZ if X, Y and Z are supposed to be three variables. If no punctuation at the end of a line, then the next printing begins at the start of the next line.
READ READ <V>|,<W>...|
Assigns values in DATA statements to variables. Values are assigned in sequence starting with the first value in the first DATA statement going to the first variable, and so on.
REM REM |<remark>|
Allows insertion of remarks. Not executed, but may be branched into. Everything after REM (and on the same line) is treated as a remark, so be careful.
10 REM REMARK :GOTO 100 nothing happens
10 GOTO 100:REM REMARK this executes
Allows data from DATA statements to be reread. Next READ statement after RESTORE begins with first data of first DATA statement
Terminates a subroutine. Branches to the statement (which could be on the same line as the GOSUB) after the most recent GOSUB.
Stops program execution. The Sorcerer enters command level and prints BREAK IN LINE nnnn.
You may not find these very useful in writing simple programs in Standard BASIC, but if you become familiar with the Sorcerer's machine language, you will find them helpful in debugging programs.
First you need to know something about I/O ports.
The Sorcerer's CPU recognizes up to 256 I/O ports (numbered 0 to 255). An I/O port is similar to a memory address: you can read numbers from it and write numbers to it, provided there is hardware actually present at the port. I/O ports are usually used for communication between the CPU and input/output devices (such as printers and TTYs).
The Sorcerer uses only four of the available ports (252, 253, 254 and 255; FC, FD, FE and FF hex). Certain S-100 devices use I/O ports rather than memory addresses (some disk controller cards, for instance); you can use these devices with the Exidy S-100 Expansion Unit, provided you get I/O port numbers to 251 or below.
Three BASIC commands use the I/O ports. INP and OUT read and write to the ports in the same way that PEEK and POKE read and write to memory addresses. WAIT tests a port and causes the BASIC program to wait until the port's bits meet certain conditions.
INP is a function (as is PEEK). I must be an integer from 0 to 255, The value of INP(I) is just the number which is in I/O port I at the time BASIC evaluates this function.
110 B=A AND 32
120 IF B=32 THEN PRINT "X";
130 PRINT " "
140 GOTO 100
The video screen's horizontal sync pulse appears at bit 5 of I/O port 254 (FE hex). Line 100 looks at this port and line 110 throws away bits 0 through 4 and 6 and 7, leaving only logical bit 5 (the "32" bit). When B=32 there is a sync pulse and B=0 otherwise. So the program prints an X whenever it sees a sync pulse and a blank otherwise.
This is a command (as is POKE). I and J must both be integers in the range 0 to 255. OUT sends the byte signified by J to output port I.
WAIT WAIT <I,M>|,<T>|
I, M and T must all be integers from 0 to 255. I is the number of the I/O port, M specifies which bits are to be tested, and T specifies a condition the tested bits must satisfy.
How to use WAIT: Decide which bits of the I/O port you want to test. Write down the eight-bit binary number which has 1s at those bit positions and 0s elsewhere; convert it to decimal notation. This number is M. Now decide which of the tested bits you want to be 1s and which you want to be 0s. Write down the eight bit binary number which has a 1 at each bit place where you are looking for a 0, a 0 at each bit place you are looking for a 1, and a 0 at each untested bit place. Convert this number to decimal notation, to get T.
Example: WAIT 254,31,24
Look at I/O porl 254 and pause the program until:
a) One or more of the bottom three bits is a 1.
b) Either of the next two bits is a 0.
We are only testing the bottom five bits, so
We are looking for 1s in the lower three bits, 0s in the next two, and we're not checking top three.
Note that the program will continue when only one of the tested bits meets its specified condition-they don't all have to.
It you don't specify T BASIC assumes T=0. WAIT I,M then tests the bits of J specified by M, and pauses until one or more of those bits is a 1.
In technical terms, the content of the port is XORed with T and the result is ANDed with M. Execution is suspended until a non-zero value results. M picks the bits of port J to be tested and execution is suspended until those bits differ from the corresponding bits of T. Execution resumes at the next statement after the WAIT.
WAIT 20,6 Execution stops until either bit 1 or bit 2
of port 20 are equal to 1. (Bit 0 is least
significant bit, 7 is the most significant.
Execution resumes at the next statement.
WAIT 10,255,7 Execution stops until any of the most significant
5 bits of port 10 are one, or any of the least
significant 3 bits are zero. Execution resumes at
the next statement.
Another use of WAIT is given in the second "bouncing ball" program in Chapter 12. Try removing lines 60 and 130. The ball "drops out" (disappears) on parts of its path because it is out of sync. The WAIT statement stops the program until it is in sync with the video screen's horizontal sync pulse.
In principle, you could write a TTY driver program in BASIC, using INP, OUT and WAIT (although such a driver would be much slower than one written in machine language). Write on the TTY's printer by giving OUT commands to the serial or parallel I/O port (252 and 255, respectively). Read the TTY's keyboard by looking at the port with the INP function. In either case, you must synchronize the Sorcerer with the TTY. Use the WAIT command to check the status ports (253 and 254) and pause the program until the handshake bits go high.
Data may be entered into memory from a BASIC program in decimal form and is stored in memory in hexadecimal form. Use the POKE statement with this format:
where I and J are integer expressions. POKE stores the byte J into the location specified by the value of I (location first, and then what you are putting into that location). I must be less an 32768 and J must be in the range 0 to 255. Data may be POKEd into memory above location 32768 by making I a negative number. In that case compute I by subtracting 65536 from the desired address. To POKE data into location 45000, for example, I is 45000-65536=-20536. Take care not to POKE data into the storage area used by Standard BASIC or you may POKE the system to death, and have to and start again. In fact, you should POKE machine language subroutines only into a "safe" area. You may also POKE into screen RAM or to change user-definable graphics characters.
The complementary function to POKE is PEEK. The format for a PEEK call is:
where I is an integer expression specifying the address from which a byte is read. Choose I in the same way as in the POKE statement. The value returned is an integer between 0 and 255. A major use of PEEK and POKE is to pass arguments and results to and from machine language subroutines.
Use POKE to do something; it is a command. Use PEEK to look at something; it is a function and you'll have to do something to PEEK to see what it is, such as PRINT PEEK(X) or IF PEEK(X)=, etc.
Table of Contents | Prev | Next
The Trailing Edge