This page covers 1001H-2002H of the Model III ROM. The ONLY difference between the Model I v1.3 ROM and the Model III ROM in this entire range is located at 1B5DH-1B5FH. On the Model I, that address loaded HL with the contents of memory location 40A4H, the start of data. On the Model III, that adress is a GOSUB to unprotect the screen and load HL with the start of data.
There is no difference between the early Model III ROM and the later Model III ROM in this range. The Model 4 ROM is also identical to the Model III ROM in this range.
This routine initializes the input buffer for an ASCII conversion. It is called by the FLOATING to ASCII Conversion Routine (at 0FBEH) and by the BINARY to ASCII Conversion Routine (at 0FAFH).
This routine gets called by the FLOATING to ASCII Conversion Routine (0FBEH-0FC0H) if the value being converted is either Single Precision or Double Precision. This will print a single or double precision number in free format
This routine will print a SINGLE PRECISION or DOUBLE PREVISION number that has fractional digits
This routine will print a number without integer digits.
This routine will print trailing zeroes.
This routine will print an integer in fixed format/floating point notation.
This routine will print a SINGLE or DOUBLE PRECISION number in fixed format/floating point notation.
This routine will scale (normalize) the number in the accumulator so that all the digits are in the integer part (i.e., between 99,999 and 999,999). The signed base 10 exponent is returned in Register A. Registers D and E are unchanged.
This routine is to convert a SINGLE precision value to an INTEGER which will be the decimal digits. Divide the integer equivalent by 100,000 and 10,000. Use the code at 1335H to convert the last 1000 to ASCII.
This routine computes the square root of any value in ACCumulator. It processes it by raising n to the power of 0.5. The root is left in ACCumulator as a single precision value. Single-precision values only should be used
A call to 13F2H raises the single precision value which has been saved to the STACK to the power specified in ACCumulator. The result will be returned in ACCumulator. The method of computation is e ** (y ln x).
NOTE: To use a ROM call to raise a single precision number (the base) to a single precision power (the exponent), store the base (single precision) in registers BCDE, and store the exponent (also single precision) in 4121H-4124H and then CALL 13F7H. The result (in single precision format) is in 4121H-4124H and in approximately 50 milliseconds.
A call to 1439H raises E (natural base) to the value in REG 1 which must be a single precision value. The result will be returned in REG 1 as a single precision number.
NOTE: To use a ROM call to find EXP(X), where X is a single precision variable, store the value of X in 4121H-4124H and then CALL 1439H. The result (in single precision format) is in 4121H-4124Hin approximately 28 milliseconds. NOTE: A fatal error occurs if the result is as large as 2 to the power of 127.
This is a general purpose summation routine which computes the series SUM ((((x^2 * c0+c1)x^2 +c2)x^2 + ... cN)x for I=0 to N when entered at 149AH If entered at 14A9H the series changes to SUM ((((x*c0+c1)x*c2)x+c3)x+...cN. On entry, the x is held in BC/DE and HL points to a list containing the number of terms followed by the coefficients.
NOTE: To run a RND(J) function via a ROM call just The RND(J) function (with J a nonzero integer) load the value of J into the HL register pair. Then CALL 14CCH and then CALL 0A7FH. The result (in integer format) is in 4121H-4122H and in HL in approximately 5.7 milliseconds. The input variable J must have a value between 1 and 32767, inclusive, or an FC error will occur.
NOTE: To run a RND(0) function via a ROM call just CALL 14F0H. No input variable is necessary. The result (in single precision format) is in 4121H-4124H in approximately 2.4 milliseconds.
COS routine. Single-precision only.(REG 1 = COS(REG 1)).
A call to 1541H computes the cosine for an angle given in radians. The angle must be a floating point value in REG 1; the cosine will be returned in REG 1 as a floating point value.
NOTE: To use a ROM call to find COS(X), where X is a single precision variable (in radians), store the value of X in 4121H-4124H and then CALL 1541H. The result (in single precision format) is in 4121H-4124Hin approximately 25 milliseconds.
A call to 1549H returns the sine as a single precision value in REG 1. The sine must be given in radians in REG 1.
Assume X <= 360 degrees.
Recompute x as x=x/360 so that x=< 1.
If x <= 90 degrees go to step 7.
If x <= 180 degrees then x=0.5-x and then go to step 7.
If x <= 270 degrees then x=0.5-x.
Recompute x as x=x-1.0.
Compute SIN using the power series.
NOTE: To use a ROM call to find SIN(X), where X is a single precision variable, store the value of X in 4121H-4124H and then CALL 1547H. The result (in single precision format) is in 4121H-4124Hin approximately 25 milliseconds. NOTE: The argument (X) must be in radians.
Single-precision only.(REG 1 = TAN(REG 1)).
A call to 15A8H computes the tangent of an angle in radians. The angle must be specified as a single precision value in REG 1. The tangent will be left in REG 1.
Uses the fact that TAN(x) = SIN(x) / COS(x)
NOTE: To use a ROM call to find TAN(X), where X is a single precision variable (in radians), store the value of X in 4121H-4124H and then CALL 15A8H. The result (in single precision format) is in 4121H-4124Hin approximately 54 milliseconds. NOTE: A fatal error occurs if the result is as large as 2 to the power of 127, which will be the case if the value of X is sufficiently close to any odd multiple of pi/2 radians.
Single-precision only.(REG 1 = ATN(REG 1)).
A call to 15BD returns the angle in radians, for the floating point tangent value in REG 1. The angle will be left as a single precision value in REG 1.
The method of computation used in this routine is:
Test the sign of the tangent to see if a negative angle is in the 2nd or 4th quadrant. Set the flag to force the result to positive on exit. If the value is negative, invert the sign.
Test magnitude of tangent. If it is < 1 go to step 3. Otherwise, compute its reciprocal and put the return address on the stack that will calculate pi/2 - series value.
Evaluate the series: (((x^2*c0+c1) x^2+c2) ... c8)x
If the flag from step 1 is not set, then invert the sign of the series result.
If the original value is < 1 then return to the caller. Otherwise, compute pi/2-value from step 4 and then return.
NOTE: To use a ROM call to find ATN(X), where X is a single precision variable, store the value of X in 4121H-4124H and then CALL 15BDH. The result (in single precision format, in radians) is in 4121H-4124Hin approximately 27 milliseconds.
The original ROM source code makes an interesting note about the order of these reserved words. Some reserved words are contained in other reserved words, which will cause a problem. They given examples of:
SO, the smaller word always has to appear later in the reserved word table.
Word
Token
Address
Word
Token
Address
18C9-18F6 - STORAGE LOCATION FOR LEVEL II BASIC ERROR MESSAGES - "ERRTAB"
18C9
"NF"
NEXT without FOR Error Message (Error 00H)
18CB
"SN"
Syntax Error Error Message (Error 02H)
18CD
"RG"
RETURN without GOSUB Error Message (Error 04H)
18CF
"OD"
Out of DATA) Error Message (Error 06H)
18D1
"FC"
Illegal Function Call Error Message (Error 08H)
18D3
"OV"
Overflow Error Message (Error 0AH)
18D5
"OM"
Out of Memory Error Message (Error 0CH)
18D7
"UL"
Underfined Line Number Error Message (Error 0EH)
18D9
"BS"
Subscript out of Range Error Message (Error 10H)
18DB
"DD"
Redimensioned Array Error Message (Error 12H)
18DD
"/0"
Division by Zero Error Message (Error 14H)
18DF
"ID">
Illegal Direct Operation Error Message (Error 16H)
18E1
"TM"
Type Mismatch Error Message (Error 18H)
18E3
"OS"
Out of String Message (Error 1AH)
18E5
"LS"
Out of Memory Error Message (Error 1CH)
18E7
"ST"
String Too Long Error Message (Error 1EH)
18E9
"CN"
Can't Continue Error Message (Error 20H)
18EB
"NR"
No RESUME Error Message (Error 22H)
18ED
"RW"
RESUME Without Error Error Message (Error 24H)
18EF
"UE"
Unprintable Error Error Message (Error 26H)
18F1
"HO"
Missing Operand Error Message (Error 28H)
18F3
"FD"
Bad file Data Error Message (Error 2AH)
18F5
"L3"
Disk BASIC Command Error Message (Error 2CH)
18F7-1904 - STORAGE LOCATION FOR THE SINGLE PRECISION DIVISION ROUTINE
This code is moved from 18F7-191DH to 4080H-40A5H during non-disk initial setup.
18F7
SUB 00H
Subtract the LSB
18F9
LD L,A
Restore the value to L
18FA
LD A,H
Get the middle byte
18FB
SBC A,00H
Subtract the middle byte
18FD
LD H,A
Move the difference to H
18FF
SBC A,00H
Subtract the MSB
1901
LD B,A
Move it back to A
1905-191C - STORAGE LOCATION FOR VALUES PLACED IN RAM UPON INITIALIZATION.
This code is moved to 408E during non-disk initial setup.
1918H
X
Difference between M1 and M3 ROMs: 1917H - 1918H contains 434CH in the Model I, 444CH in the Model III. This value is loaded to 40A0H (the start of string space pointer) during power-up.
191CH
X
Difference between M1 and M3 ROMs: 191BH - 191CH contains 42E9H in the Model I, 43E9H in the Model III. This value is loaded to 40A4H (the start of BASIC program pointer) during power-up.
191DH-1935H - MESSAGE STORAGE LOCATION
191D-1923H
"Error"
The Level II BASIC ERROR message is stored here.
"in"
The Level II BASIC IN message is stored here.
"READY"
The Level II BASIC READY message is stored here.
"Break"
The Level II BASIC BREAK message is stored here.
1936-1954 - SCAN STACK ROUTINE
This routine is called with DE as the address of the NEXT index. It scans the stack backwards looking for a FOR push. If one is found, it gets the address of the index and compares with the DE that was in place when this routine was called. If it is equal, then it exits with A=0 and HL=Address of the variable. If it is not equal it will keep scanning until no FOR push is found and then exit with A<>0.
1936-1938
LD HL,0004H
Load register pair HL with 4 so that we can backspace.
1939
ADD HL,SP
Add the 4 (held in HL) to the current value of the stack pointer. HL will hold the current stack pointer, the stack point will bump forward 4.
193A
LD A,(HL)
Load register A with the value held at the current stack point MINUS 4.
193B
INC HL
Bump the value of the memory pointer in register pair HL so as to backspace one more byte in case a FOR token is located.
193C-193D
CP 81H
Check to see if the value in register A (which is the current stack pointer - 4) is a FOR token.
193E
RET NZ
Return if the value in register A isn't a FOR token. This returns with A being non-zero because there was no FOR push.
193F
LD C,(HL)
Load register C with the LSB of the FOR's variable address.
1940
INC HL
Bump the value of the memory pointer in register pair HL so as to backspace the current stack pointer by yet another byte.
1941
LD B,(HL)
Load register B with the MSB of the FOR's variable address.
1942
INC HL
Bump the value of the memory pointer in register pair HL so now HL will be the address of the FOR variable on the stack.
1943
PUSH HL
Save the value in register pair HL (which is the address of the FOR variable) to the stack.
1944
LD L,C
Load register L with the LSB of the FOR variable's address in register C.
1945
LD H,B
Load register H with the MSB of the FOR variable's address in register B.
1946
LD A,D
Load register A with the MSB of the variable address in register D. This sets up fto test the user specified variable address.
1947
OR E
Check to see if the variable address in register pair DE is equal to zero.
1948
EX DE,HL
Exchange the variable address in register pair HL with the variable address in register pair DE so that DE will now hold the address of the FOR variable from the stack.
1949-194A
Skip the next 2 opcodes if the variable address in register pair DE was equal to zero.
194B
EX DE,HL
Exchange the variable address in register pair HL with the variable address in register pair DE so that HL will now have the address of the FOR variable from the stack.
194C
RST 18H
This routine was entered with DE being the address of the
NEXT index, so we need to compare that against the index from the stack. To do this, we RST 18 to see if the variable address in HL is the same as in DE, so we call the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as:
- HL<DE: CARRY SET
- HL>DE: NO CARRY
- HL><DE: NZ
- HL=DE: Z
LD BC,000EH
Load register pair BC with the value to backspace to next FOR token (which is 10).
1950
POP HL
Get the memory pointer from the stack of the sign of the increment flag and put it in register pair HL.
1951
RET Z
Return if the FOR block matched the NEXT index block.
1952
ADD HL,BC
If it didn't match, execute that 10 byte stepback in BC for the next possible FOR push.
1953-1954
Keep looking until the appropriate FOR block has been located.
1955-1962 - DATA MOVEMENT ROUTINE
This routine moves a variable into another area specified by the caller. On entry BC is set as the end address of the list to move (which is the upper limit); DE is set as the start address of the list to move; and HL is the end of the area to move it to.
1955-1957
GOSUB to 196CH to make sure there's enough room in memory for the string area.
1958
PUSH BC
Save the end address of the list to move (stored in BC) to the stack.
1959
EX (SP),HL
Save the end address of the list to move (stored in the stack now) to register pair HL.
195A
POP BC
Get the end address of the move from the stack and put it in register pair BC.
195B
RST 18H
Now we need to check to see if the memory pointer in HL is the same as the memory pointer in DE (to see if the move is finished), so we call the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as:
- HL<DE: CARRY SET
- HL>DE: NO CARRY
- HL><DE: NZ
- HL=DE: Z
195C
LD A,(HL)
Get a byte from the source list and put it in register A.
195D
LD (BC),A
Save the byte into wherever BC is pointing.
RET Z
Return if finished with the move (i.e., the memory pointer in register pair HL is the same as the value of the memory pointer in register pair DE).
195F
DEC BC
Decrement the source address (in register pair BC).
1960
DEC HL
Decrement the destination address (in register pair HL).
1961-1962
Loop until the list was moved.
1963-197D - MEMORY CHECK ROUTINE - Computes the amount of space between HL and the end of memory at FFC6H.
1963
PUSH HL
Save the value in register pair HL to the stack.
1964-1966
LD HL,(40FDH)
Load register pair HL with the starting address of free memory (which is stored at 40FDH).
NOTE: 40FDH-40FEH holds the pointer to the starting address of free memory.
1967-1968
LD B,00H
Load register B with zero.
1969
ADD HL,BC
Add 2 times the number of bytes required to start of free area (held in register pair BC) to the value in register pair HL.
196A
ADD HL,BC
Add the value in register pair BC to the value in register pair HL leaving HL to now contain the end of the free area.
196B-196C
3EH E5H
Z-80 Trick! See the general explanation at 10F8H.
196C
Save the new free area pointer (which is the start) to the stack.
196D-196E
LD A,C6H
Load register A with C6H (which is the the LSB of FFC6H; the top of memory).
196F
SUB L
Subtract the LSB of the value of the new memory pointer in register L from the value in register A.
1970
LD L,A
Load register L with the adjusted value in register A (i.e., the free memory pointer resulting from subtracting the new starting address).
1971-1972
LD A,FFH
Load register A with the MSB of the top of memory.
1973
SBC A,H
Subtract the MSB of the new memory pointer in register H from the value in register A. If the free space list exceeds FFC6 then the CARRY FLAG gets set, meaning memory overflowed.
1974-1975
If the CARRY FLAG is set, display a ?OM ERROR since we are out of memory.
1976
LD H,A
Next we need to determine if the free space list has overflowed the stack area so first we load register H with the adjusted value in register A.
1977
ADD HL,SP
Add the value of the stack pointer to the adjusted value in register pair HL.
1978
POP HL
Get the value from the stack and put it in register pair HL.
1979
RET C
If the CARRY FLAG is set, then we have no overflow - so we better RETURN because the next step is an OM error processor.
197A-197B - OM ERROR entry point.
197A-197B
LD E,0CH
Load register E with the ?OM ERROR.
197C-197D
Display an ?OM ERROR message.
197E-1AF7 - LEVEL II BASIC COMMAND MODE
197E-1980
LD HL,(40A2H)
Load register pair HL with the value of the current BASIC line number.
NOTE: 40A2H-40A3H holds the current BASIC line number.
1981
LD A,H
Load register A with the MSB of the current BASIC line number in register H.
1982
AND L
Combine the LSB of the current BASIC line number in register L with the MSB of the current line number in register A.
1983
INC A
Bump the value of the combined BASIC line number in register A. If the current line is FFFFH then we have not started execution of a BASIC program yet (meaning we are still in the inputting phase).
1984-1985
Jump to 198EH if Level II BASIC is still in the command mode (rather than being in execution mode).
1986-1988
LD A,(40F2H)
Load register A with contents of 40F2H.
NOTE: 40F2H holds the error flag.
1989
OR A
Check to see if the error flag is set.
198A-198B
LD E,22H
Load register E with a ?NR ERROR code.
198C-198D
Jump to 19A2H if the error flag is set (meaning there was no RESUME address).
198E-1990
Otherwise, jump to 1DC1H (the READY routine) because there was an error in the input phase.
1991-1993
LD HL,(40DAH)
Load register pair HL with the DATA line number (which is stored at 16602).
NOTE: 40DAH-40DBH holds DATA line number.
1994-1996
LD (40A2H),HL
Save the DATA line number in register pair HL.
NOTE: 40A2H-40A3H holds the current BASIC line number.
1997-1998
LD E,02H
Load register E with a ?SN ERROR code.
SN ERROR entry point.
LD E,14H
Load register E with a 14H which is the ?/0 ERROR code.
199C-199E
LD BC,001EH
Load register BC with a ?NF ERROR code.
?NF ERROR entry point.
199F-19A1
LD BC,241EH
Load register BC with a ?RW ERROR code.
?RW ERROR entry point.
LD HL,(40A2H)
Load register pair HL with the value of the current BASIC line number which has the error.
NOTE: 40A2H-40A3H holds the current BASIC line number.
19A5-19A7
LD (40EAH),HL
Save the value of the current BASIC line number with the error in register pair HL.
NOTE: 40EAH-40EBH holds the line number with error.
19A8-19AA
LD (40ECH),HL
Save the value of the current BASIC line number with the error in register pair HL.
NOTE: 40ECH-40EDH holds EDIT line number.
LD BC,19B4H
Load register pair BC with the return address of 19B4H which is the continuation address after a reinitialization.
LD HL,(40E8H)
Load register pair HL with the value of the stack pointer (which is stored at 40E8H).
NOTE: 40E8H-40E9H holds Stack pointer pointer.
19B1-19B3
Jump to 1B9AH to reinitialize the system variables.
19B4
Get the value from the stack and put it in register pair BC, which should be 0000H.
19B5
LD A,E
Load register A with the value of the error code in register E.
19B6
LD C,E
Load register C with the value of the error code in register E.
19B7-19B9
LD (409AH),A
Save the value of the error code (from in register A) into 409AH.
NOTE: 409AH holds the RESUME flag.
19BA-19BC
LD HL,(40E6H)
Load register pair HL with the value of the current BASIC program pointer (which is stored in 40E6H) (i.e., the address of the last byte executed in the current line).
NOTE: 40E6H-40E7H holds the temporary storage location.
19BD-19BF
LD (40EEH),HL
Save the value of the current BASIC program pointer (which is stored in 40EEH) in register pair HL.
NOTE: 40EEH-40EFH is used by RESUME.
19C0
EX DE,HL
Load register pair DE with the value of the current BASIC program pointer in register pair HL.
19C1-19C3
LD HL,(40EAH)
Load register pair HL with the value of the last number line executed (which is stored in 16618).
NOTE: 40EAH-40EBH holds the line number with error.
19C4-19C5
LD A,H
AND L
The easiest way to test a 2 Byte Register is to AND the MSB and LSB together, as the only way to get 1111 would be if both the LSB and MSB were 1111. Here, HL las the last line number executed.
19C6
INC A
Bump the value of the combined current BASIC line number. This will test to against FFFFH which would mean we are still in the input phase.
19C7-19C8
Jump to 19D0H if Level II BASIC is in the command mode (meaning the line number was FFFFH, which then flipped to zero on the prior INC command).
19C9-19CB
LD (40F5H),HL
Save the value of the current BASIC line number in register pair HL to (40F5H).
NOTE: 40F5H-40F6H holds the last line number executed.
19CC
EX DE,HL
Load register pair HL with the value of the current BASIC program pointer in register pair DE.
19CD-19CF
LD (40F7H),HL
Save the value of the current BASIC program pointer (which is stored in 16631) in register pair HL.
NOTE: 40F7H-40F8H holds the last byte executed.
19D0-19D2
LD HL,(40F0H)
Load register pair HL with memory contents held at (40F0H).
NOTE: 40F0H-40F1H holds the ON ERROR adress.
19D3
LD A,H
Load register A with the MSB of the ON ERROR address in register H.
19D4
OR L
Combine the LSB of the ON ERROR address in register L with the MSB of the ON ERROR address in register A.
19D5
EX DE,HL
Load register pair DE with the ON ERROR address in register pair HL.
19D6-19D8
LD HL,40F2H
Load register pair HL with the address of the error flag (which is 40F2H).
NOTE: 40F2H holds the error flag.
19D9-19DA
Jump to 19E3H (to error out) if there isn't an ON ERROR address.
19DB
AND (HL)
Combine the value of the error flag at the location of the memory pointer in register pair HL with the combined value of the ON ERROR address in register A.
19DC-19DD
Jump to 19E3H (to error out) if register A is non zero (meaning that there was no ON ERROR address).
19DE
DEC (HL)
Decrement the value of the error flag at the location of the memory pointer in register pair HL so that RESUME will work.
19DF
EX DE,HL
Load register pair HL with the ON ERROR address in register pair DE.
19E0-19E2
Jump to 1D36H to make that happen.
19E3
XOR A
Zero register A.
19E4
LD (HL),A
Clear the error override flag by save a zero (from register A) as the current error flag at the location of the memory pointer in register pair HL..
19E5
LD E,C
Load register E with the value of the error code in register C.
19E6-19E8
We need to position the video to the next line, so go display a carriage return on the video display if necessary.
19E9-19EB
LD HL,18C9H
Load register pair HL with the starting address for the table of error messages.
19EC-19EE
CALL 41A6H
Go to the DOS link at 41A6H (whcih would load and execute BASIC error messages as supplied by DOS).
NOTE: 41A6H-41E4H holds DOS links.
In NEWDOS 2.1, this would be a call to load a DISK BASIC error, with Register E holding the error number.
19EF
LD D,A
Since we are non-DOS, we continue by loading register D with zero.
19F0-19F1
LD A,3FH
Load register A with a "?" (which is ASCII code 3FH).
19F2-19F4
GOSUB to 032AH to display the question mark in register A.
19F5
ADD HL,DE
Add the value of the error code in register pair DE to the starting address of the table of error messages in register pair HL.
19F6
LD A,(HL)
Load register A with the first character of the error message at the location of the table pointer in register pair HL.
19F7-19F9
GOSUB to 032AH to display the first character of the error message in register A.
19FA
RST 10H
Error codes are 2 characters so we need to set the second character of the error in register A, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:- The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
- Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
- The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
- The string must be terminated by a byte of zeros.
19FB-19FD
GOSUB to 032AH to display the second character of the error message in register A.
19FE-1A00
LD HL,191DH
Load register pair HL with 191DH which is the starting address of the READY message.
1A01
PUSH HL
Save the starting address of the READY message (held in HL) to the stack.
1A02-1A04
LD HL,(40EAH)
Load register pair HL with the value of the current BASIC line number (i.e., the statement causing the error).
NOTE: 40EAH-40EBH holds the line number with error.
1A05
EX (SP),HL
Exchange the value of the current BASIC line number in register pair HL with the starting address of the Level II BASIC ERROR message to the stack.
1A06-1A08
We need to display the Level II BASIC ERROR message so we call the WRITE MESSAGE routine at 28A7H.
NOTE:- The routine at 28A7 displays the message pointed to by HL on current system output device (usually video).
- The string to be displayed must be terminated by a byte of machine zeros or a carriage return code 0D.
- If terminated with a carriage return, control is returned to the caller after taking the DOS exit at 41D0H (JP 5B99H).
1A09
POP HL
Get the value of the BASIC line number with the error from the stack and put it in register pair HL.
1A0A-1A0C
LD DE,FFFEH
Load register pair DE with FFFEH.
This basically reserves the line number 65534 as a trigger for the next few steps.
1A0D
RST 18H
Now we need to compare the BASIC line number causing the error (held in HL) with FFFEH (held in DE) so as to see if we are in the initialization routine, so we call the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as:
- HL<DE: CARRY SET
- HL>DE: NO CARRY
- HL><DE: NZ
- HL=DE: Z
1A0E-1A10
Jump to 0674H if we are in the initialization routine because the error line number was FFFEH.
1A11
LD A,H
We need to see if were in command mode, which is signalled by CURRENT LINE NUMBER of 0. The first step is to load register A with the MSB of the current BASIC line number in register H.
1A12
AND L
Combine the LSB of the current BASIC line number in register L with the MSB of the current BASIC line number in register A.
1A13
INC A
Bump the combined value of the current BASIC line number in register A to test to see if the line number is 00H (meaning command mode).
1A14-1A16
GOSUB to 0FA7H to display the current BASIC line number in register pair HL if Level II BASIC isn't in the command mode.
1A17H
3E C1
Z-80 Trick! See the general explanation at 10F8H.
Get the value from the stack and put it in register pair BC.
1A19 - "$READY" - Jump to Model II BASIC "READY"
To exit from a machine-language program into BASIC's immediate mode, jump (not call) to $READY.
1A19-1A1BH
"READY"
Go set the current output device to the video display.
Re-entry into BASIC command mode entry point. (see 6CCH also).
1A1C-1A1E
CALL 41ACH
Go call the DOS link at 41ACH.
In NEWDOS 2.1, this is the start of BASIC just before BASIC shows the READY prompt.
1A1F-1A21
Go turn off the cassette recorder.
1A22-1A24
Go display a carriage return if necessary.
1A25-1A27
LD HL,1929H
Load register pair HL with the starting address of the Level II BASIC READY message.
1A28-1A2A
We need to display the Level II BASIC READY message, so we call the WRITE MESSAGE routine at 28A7H.
NOTE:- The routine at 28A7 displays the message pointed to by HL on current system output device (usually video).
- The string to be displayed must be terminated by a byte of machine zeros or a carriage return code 0D.
- If terminated with a carriage return, control is returned to the caller after taking the DOS exit at 41D0H (JP 5B99H).
1A2B-1A2D
LD A,(409AH)
Load register A with the value of the current error code.
NOTE: 409AH holds the RESUME flag.
1A2E-1A2F
SUB 02H
Check to see if the current error code is a ?SN ERROR code by subtracting 2 from the error code, resulting in a zero if its a SN ERROR and any other number if it isn't..
1A30-1A32
GOSUB to 2E53H to the EDIT mode if the current error code is a SN ERROR code.
1A33 - Many routines jump here as the start of the Level II BASIC interpreter.
If the jump here was from an AUTO call, (40E4H) will have the increment number, (40E1H) will be 0 if no AUTO and non-zero if AUTO, and (40E2H) will have the starting line number.
1A33-1A35
LD HL,FFFFH
Load register pair HL with the command mode line number of FFFFH.
NOTE: FFFFH is the command mode line number.
1A36-1A38
LD (40A2H),HL
Save the line number in register pair HL as the current BASIC line number.
NOTE: 40A2H-40A3H holds the current BASIC line number.
1A39-1A3B
LD A,(40E1H)
Load register A with the value of the AUTO flag. It will be zero if not in AUTO, and anything else if in AUTO.
1A3C
OR A
Check to see if in the AUTO mode.
1A3D-1A3E
Jump to 1A76H if not in the AUTO mode.
1A3F-1A41
LD HL,(40E2H)
We are in AUTO mode so load register pair HL with the current AUTO line number.
NOTE: 40E2H-40E3H holds Current BASIC line number.
1A42
PUSH HL
Save the current AUTO line number (stored in register pair HL) to the stack.
1A43-1A45
GOSUB to 0FAFH to call the HL TO ASCII routine at 0FAFH (which converts the value in the HL register pair (assumed to be an integer) to ASCII and display it at the current cursor position on the video screen) to display the AUTO line number.
1A46
POP DE
Get the current AUTO line number from the stack and put it in register pair DE.
1A47
PUSH DE
Save the current AUTO line number in register pair DE to the stack.
1A48-1A4A
Call the SEARCH FOR LINE NUMBER routine at 1B2CH which looks for the line number specified in DE. Returns C/Z with the line found in BC, NC/Z with line number is too large and HL/BC having the next available location, or NC/NZ with line number not found, and BC has the first available one after that.
1A4B-1A4C
LD A,"*"
Load register A with a * (which will be code for a matching line number).
1A4D-1A4E
If the call to 1B2CH shows a matching line number was found in the BASIC program (by returning a C), skip the next instruction so that register A keeps the "*".
1A4F-1A50
LD A,20H
If we are here, then there was no matching line number so we need to change the next character from a "*" (which is loaded into register A which but is not applicable) to a space.
Go display the character in register A on the video display (which will be a "*" if a matching line number was found).
1A54-1A56
GOSUB to 0361H to get input into the buffer.
1A57
POP DE
Get the current line number from the stack and put it in register pair DE.
1A58-1A59
Skip the next 3 opcodes if the BREAK key wasn't pressed.
1A5A
XOR A
The BREAK key was pressed so we need to zero register A to clear the AUTO increment flag.
1A5B-1A5D
LD (40E1H),A
Save the value in register A as the current AUTO flag (to turn off AUTO).
NOTE: 40E1H will hold 0 if no AUTO and non-zero if AUTO.
1A5E-1A5F
Jump to the normal command mode "READY" routine at 1A19H.
If we are here, then the BREAK key was not pressed.
1A60-1A62
LD HL,(40E4H)
Load register pair HL with the value of the AUTO increment.
NOTE: 40E4H-40E5H holds the AUTO increment number.
1A63
ADD HL,DE
Since we didn't BREAK out of the routine we need to keep processing the AUTO so we add the value of the AUTO line number in register pair DE with the AUTO increment value in register pair HL.
1A64-1A65
If that addition to the next AUTO line number causes an overflow (by triggering the CARRY FLAG), jump to 1A5AH which is the same as if the BREAK key was hit.
1A66
PUSH DE
Save the current AUTO line number in register pair DE to the stack.
1A67-1A69
LD DE,FFF9H
Load register pair DE with the maximum BASIC line number of FFF9H (=65529).
There is an explanation at 1E5AH as to why 65529 is the highest possible line number (vs 65535 which would make more sense).
1A6A
RST 18H
Now we need to compare the adjusted
AUTO line number (in HL) with the maximum BASIC line number (in DE), so we call the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as:
- HL<DE: CARRY SET
- HL>DE: NO CARRY
- HL><DE: NZ
- HL=DE: Z
1A6B
POP DE
Get the current AUTO line number from the stack and put it in register pair DE.
1A6C-1A6D
If the adjusted AUTO line number in register pair HL is too large, jump to 1A5AH which is the same as if the BREAK key was hit.
1A6E-1A70
LD (40E2H),HL
Save the adjusted AUTO line number in register pair HL as the current AUTO line number.
NOTE: 40E2H-40E3H holds Current BASIC line number.
1A71-1A72
OR FFH
Load register A with the AUTO flag value.
1A73-1A75
Jump to the EDIT routine to save the current BASIC line.
1A76-1A77
LD A,3EH
Load register A with a > (the prompt that follows READY)
1A78-1A7A
Go display the Level II BASIC prompt in register A on the video display.
1A7B-1A7D
GOSUB to 0361H to accept input. HL will hold the buffer address for that input.
1A7E-1A80
Jump to 1A33H if the BREAK key was pressed.
1A81
RST 10H
Since we need to bump the current input buffer pointer in register pair HL until it points to the first character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:- The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
- Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
- The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
- The string must be terminated by a byte of zeros.
1A82
INC A
Bump the value of the character in register A. This sets the status flags but saves the CARRY FLAG.
1A83
DEC A
Decrement the value of the character in register A so we can test for an end of statement.
1A84-1A86
JUMP to 1A33H if we have an end of statement.
1A87
PUSH AF
Save the value in register pair AF to the stack (including the CARRY FLAG).
1A88-1A8A
Call the ASCII TO INTEGER routine at 1E5AH.
NOTE:- The routine at 1E5A converts the ASCII string pointed to by HL to an integer deposited into DE. If the routine finds a non-numerica character, the conversion is stopped
1A8BH - This little looping routine is to clear any trailing blanks between the line number and the statement.
1A8B
DEC HL
Decrement the value of the input buffer pointer in register pair HL.
1A8C
LD A,(HL)
Load register A with the value of the character at the location of the input buffer pointer in register pair HL.
1A8D-1A8E
CP 20H
Check to see if the character at the location of the input buffer pointer in register A is a space.
1A8F-1A90
Loop back to 1A8BH if the character at the location of the input buffer pointer in register A is a space.
1A91
INC HL
Bump the value of the input buffer pointer in register pair HL so that it points to the first character following a line number.
1A92
LD A,(HL)
Load register A with that character.
1A93-1A94
CP 20H
Check to see if the character at the location of the input buffer pointer in register A is a space.
1A95-1A97
If it is a space then skip it by a GOSUB to 09C9H which bumps the value of the input buffer pointer in register pair HL if necessary.
1A98
PUSH DE
Save the BASIC line number in register pair DE (which was converted from ASCII to an integer in 1A88H through a call to 1E5AH) to the stack.
1A99-1A9B
Tokenize the input via a GOSUB to 1BC0H. BC will equal the length of the encoded statement when its done.
1A9C
POP DE
Get the value of the BASIC line number (which is an integer) from the stack.
1A9D
POP AF
Get the CARRY FLAG (from the 1A81H character fetch) and put it in register pair AF.
1A9E-1AA0
LD (40E6H),HL
Save the input buffer pointer in register pair HL.
NOTE: 40E6H-40E7H holds the temporary storage location.
1AA1-1AA3
CALL 41B2H
Go call the DOS line at 4182H.
In NEWDOS 2.1, this is the input scanner after tokenizing the current statement.
1AA4-1AA6
Jump to 1D5AH if there wasn't a line number with the input (meaning it was a direct statement or a system command).
1AA7
PUSH DE
Save the BASIC line number (as an integer stored in register pair DE) to the stack.
1AA8
PUSH BC
Save the length of the tokenized input (stored in register pair BC) to the stack.
1AA9
XOR A
Zero register A.
1AAA-1AAC
LD (40DDH),A
Save the value in register A (which is a 00H) as the input flag.
NOTE: 40DDH holds INPUT flag.
1AAD
RST 10H
Since we need find the first token, we have to bump the current input buffer pointer in register pair HL until it points to the next character by calling the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:- The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
- Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
- The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
- The string must be terminated by a byte of zeros.
1AAF
PUSH AF
Save the status flag to the stack.
1AB0
EX DE,HL
Load register pair HL with the integer value of the BASIC line number (held in register pair DE).
1AB1-1AB3
LD (40ECH),HL
Save the integer value of the line number (held in register pair HL) to 40ECH.
NOTE: 40ECH-40EDH holds EDIT line number.
1AB4
EX DE,HL
Exchange the value of the input buffer pointer in register pair DE with the integer value of the BASIC line number in register pair HL. This will fill DE with the line number for the search routine in the next instruction.
1AB5-1AB7
Call the SEARCH FOR LINE NUMBER routine at 1B2CH which looks for the line number specified in DE. Returns C/Z with the line found in BC, NC/Z with line number is too large and HL/BC having the next available location, or NC/NZ with line number not found, and BC has the first available one after that.
1AB8
PUSH BC
Save the address of the line number in the BASIC program (if it exists) in register pair BC to the stack.
1AB9-1ABB
If there wasn't a matching line number in the BASIC program, GOSUB to 2BE4H to move the closest line number up in memory to make room for another line.
1ABC
POP DE
Get the integer address of the BASIC line number from the stack and put it in register pair DE.
1ABD
POP AF
Restore the status from the 1AADH token scan into register pair AF.
1ABE
PUSH DE
Save the integer address of the BASIC line number to the stack.
1ABF-1AC0
Jump to 1AE8H if there was a matching line number in the BASIC program; otherwise we move on and a new line has to be added as follows.
1AC1
POP DE
Get the address of the BASIC line number from the stack and put it in register pair DE.
1AC2-1AC4
LD HL,(40F9H)
Load register pair HL with the end of the BASIC program pointer.
- Note: 40F9H-40FAH holds the starting address of the simple variable storage area.
1AC5
EX (SP),HL
Exchange the length of the tokenized input to the stack with the end of the BASIC program pointer in register pair HL.
1AC6
POP BC
Get the end of the BASIC program pointer from the stack and put it in register pair BC.
1AC7
ADD HL,BC
Add the end of the BASIC program pointer in register pair BC to the value of the length of the tokenized input in register pair HL.
1AC8
PUSH HL
Save the adjusted end of the BASIC program pointer in register pair HL to the stack.
1AC9-1ACB
Go check to see if there is enough room in memory for the new BASIC line by GOSUB to 1955H.
1ACC
POP HL
Get the new end of the BASIC program pointer from the stack and put it in register pair HL.
1ACD-1ACF
LD (40F9H),HL
Save the new end of the BASIC program pointer in register pair HL.
- Note: 40F9H-40FAH holds the starting address of the simple variable storage area.
1AD0
EX DE,HL
Load register pair HL with the address of the BASIC line.
1AD1
LD (HL),H
Save the MSB of the address of the BASIC line in register H.
1AD2
POP DE
Get the value of the BASIC line number from the stack and put it in register pair DE.
1AD3
PUSH HL
Save the value of the memory pointer in register pair HL to the stack.
1AD4
INC HL
Bump the value of the memory pointer in register pair HL (which bumps it to the LSB of the line number entry).
1AD5
INC HL
Bump the value of the memory pointer in register pair HL (which bumps it to the MSB of the line number entry).
1AD6
LD (HL),E
Save the LSB of the BASIC line number in register E at the location of the memory pointer in register pair HL.
1AD7
INC HL
Bump the value of the memory pointer in register pair HL.
1AD8
LD (HL),D
Save the MSB of the BASIC line number in register D at the location of the memory pointer in register pair HL. At this point DE should have the binary value for the new line number.
1AD9
INC HL
Bump the value of the BASIC line number in register pair HL.
1ADA
EX DE,HL
Load register pair DE with first data byte address following the line number (held in register pair HL).
1ADB-1ADD
LD HL,(40A7H)
Load register pair HL with the value of the tokenized input pointer
Note: 40A7H-40A8H holds Input Buffer pointer.
1ADE
EX DE,HL
Exchange the value of the memory pointer in register pair DE with the value of the tokenized input pointer in register pair HL.
1ADF
DEC DE
Decrement the value of the tokenized input buffer pointer in register pair DE.
1AE0
DEC DE
Decrement the value of the tokenized input buffer pointer in register pair DE.
1AE1
LD A,(DE)
Load register A with the value at the location of the tokenized input buffer pointer in register pair DE.
1AE2
LD (HL),A
Save the value in register A at the location of the memory pointer in register pair HL.
1AE3
INC HL
Bump the store address (held in register pair HL).
1AE4
INC DE
Bump the fetch address (held in register pair DE).
1AE5
OR A
Check to see if the character in register A is an end of the line character.
1AE6-1AE7
Loop until the whole of the new BASIC line has been stored in memory.
1AE8
POP DE
Get the address of the line in the program table from the stack and put it in register pair DE.
1AE9-1AEB
Go update line pointers for all lines following the new line.
1AEC-1AEE
CALL 41B5H
Go call the DOS link at 41B5H.
In NEWDOS 2.1, this is the input scanner after updating the PST (Program Statement Table).
1AEF-1AF1
Update all the BASIC line pointers.
1AF2-1AF4
CALL 41B8H
Go call the DOS link at 41B8H.
In NEWDOS 2.1, this is the input scanner after reinitializing BASIC
1AF5-1AF7
Go get the input again.
1AF8-1B0F - LINE POINTERS ROUTINE
This routine fixes the line pointers in a BASIC program. This is useful, for instance for a renumber program which has to move BASIC program lines from one location in memory to an other, which means that the line pointers would no longer be valid. This routine will fix them. Registers A, HL and DE are used.
1AF8
LD HL,(40A4H)
Load register pair HL with the start of the BASIC program pointer (called the PST).
- Note: 40A4H-40A5H holds the starting address of BASIC program text also known as the PROGRAM STATEMENT TABLE (PST).
1AFB
EX DE,HL
Move the PST address to DE.
1AFC
LD H,D
Load register H with the MSB of the memory pointer in register D.
1AFD
LD L,E
Load register L with the LSB of the memory pointer in register E.
1AFE
LD A,(HL)
Load register A with the value at the location of the memory pointer in register pair HL.
1AFF
INC HL
Bump the value of the memory pointer in register pair HL.
1B00
OR (HL)
Since the first 2 bytes of each line contains the address of the next line, a 0000H would signify the end byte. With this, check to see if the character at the location of the memory pointer in register pair HL is an end of the BASIC program character.
INC HL
Since HL is the 'beginning of statment pointer', we need to skip over the 3rd and 4th bytes, so bump the value of the memory pointer in register pair HL.
1B03
INC HL
Bump the value of the memory pointer in register pair HL.
1B04
INC HL
Bump the value of the memory pointer in register pair HL.
1B05
XOR A
Zero register A and clear the flags.
1B06
CP (HL)
Check to see if the character at the location of the memory pointer in register HL is an end of the BASIC line character.
1B07
INC HL
Bump the value of the memory pointer in register pair HL.
1B08
Loop until the end of the BASIC line character is found.
1B0A
EX DE,HL
Exchange the starting address of the current BASIC line in register pair DE with the starting address of the next BASIC line in register pair HL.
1B0B
LD (HL),E
Save the LSB of the next BASIC line's starting address in register E at the location of the memory pointer in register pair HL.
1B0C
INC HL
Bump the value of the memory pointer in register pair HL.
1B0D
LD (HL),D
Save the MSB of the next BASIC line's starting address in register D at the location of the memory pointer in register pair HL.
1B0E-1B0F
Loop until the end of the program has been found.
1B10-1B48 - EVALUATE LINE NUMBERS
This is called by LIST and DELETE. It converts the starting and ending linbers (X-Y) to binary and saves the ending line number on the stack. Then the code locates the program table address for the starting line. The routine leaves the address of the starting line in BC and the ending line number in the stack.
1B10-1B12
LD DE,0000H
Load register pair DE (which will be the line counter) with zero.
1B13
PUSH DE
Save the value in register pair DE to the stack.
1B14-1B15
Jump to 1B1FH if there aren't any line numbers to be evaluated.
1B16
POP DE
Get the value from the stack and put it in register pair DE (which will be the line number).
1B17-1B19
Go evaluate the line number at the location of the current BASIC program pointer in register pair HL and return with the line number's binary value in register pair DE.
1B1A
PUSH DE
Save the first line number's value (stored in register pair DE) to the stack.
1B1B-1B1C
Jump if there isn't a second line number to be evaluated given (i.e, LIST 3000-).
1B1D-1B1E
RST 08H
CEH
If we are here, there is a second line number. That that would have to be preceded by a - at the location of the current BASIC program pointer in register pair HL, call the COMPARE SYMBOL routine which comparess the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call. If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the Aregister and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase).
LD DE,FFFAH
Load register pair DE with the default second line number of FFAFH.
1B22-1B24
Go evaluate the second line number at the location of the current BASIC program pointer in register pair HL and return with the line number's binary value in register pair DE. Will return with Z flag set if it was a number.
1B25-1B27
Go to the Level II BASIC error routine and display a SN ERROR message if the data which followed the token wasn't a line number.
1B28
EX DE,HL
Load register pair HL with the value of the second line number in register pair DE and load register pair DE with the value of the current BASIC program pointer in register pair HL.
1B29
POP DE
Get the value of the first line number from the stack and put it in register pair DE.
1B2A
EX (SP),HL
Exchange the return address to the stack with the value of the second line number in register pair HL.
1B2B
PUSH HL
Save the value of the return address in register pair HL to the stack so we can properly exit later.
1B2C - This routine searches a BASIC program for a BASIC line with a line number matching the value in the DE register pair.
To use this routine, the required line number must be placed in the DE register pair. When a match is found, this routine sets the CARRY FLAG; the BC register pair points to the start of the required line, and the HL register points to the start of the next line. HL, AF and BC are used.
This is the the SEARCH FOR LINE NUMBER routine at 1B2C, which searches the Program Statement Table (PST) for a BASIC statement with the line number specified in the DE register pair. All registers are used. The exit conditions are:
C/Z=Line Found and BC is the starting address of the line in the PST and HL is the address following;
NC/Z=Line not found or too large and HL/BC will have the address of the next available PST location; and
NC/NZ=Line not found and BC=Address of the first line number greater than the one specified and HL will be the address of the following line.
1B2C
LD HL,(40A4H)
Load register pair HL with the value of the start of the BASIC program pointer.
- Note: 40A4H-40A5H holds the starting address of BASIC program text also known as the PROGRAM STATEMENT TABLE (PST).
1B2F
LD B,H
Load register B with the value of the MSB of the memory pointer in register H.
1B30
LD C,L
Load register C with the LSB of the memory pointer in register L. Now BC will hold the address of the current line in the PST.
1B31
LD A,(HL)
Load register A with the LSB of the address of the next line (held in register pair HL).
1B32
INC HL
Bump the value of the memory pointer in register pair HL to the MSB of the address of the next line.
1B33
OR (HL)
Combine the value at the location of the memory pointer in register pair HL with the value in register A and set the status flags.
1B34
DEC HL
Restore HL to the start of the current line.
1B35
RET Z
Return if this is the end of PST (=the end of the BASIC program).
1B36
INC HL
It's not the end so we need HL to point the line number for the current line which means it must advance by 2. Bump the value of the memory pointer in register pair HL.
1B37
INC HL
Bump the value of the memory pointer in register pair HL.
1B38
LD A,(HL)
Load register A with the LSB of the current BASIC line number at the location of the memory pointer in register pair HL.
1B39
INC HL
Bump the value of the memory pointer in register pair HL to point to the MSB of the current BASIC line number.
1B3A
LD H,(HL)
Load register H with the MSB of the current BASIC line number at the location of the memory pointer in register pair HL.
1B3B
LD L,A
Load register L with the LSB of the current BASIC line number in register A.
1B3C
RST 18H
Now we need to compare the value of the current BASIC line number in HL and the first line number (in DE), so we call the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as:
- HL<DE: CARRY SET
- HL>DE: NO CARRY
- HL><DE: NZ
- HL=DE: Z
1B3D
LD H,B
Load register H with the MSB of the memory pointer in register B.
1B3E
LD L,C
Load register L with the LSB of the memory pointer in register C.
1B3F
LD A,(HL)
Load register A with the value at the location of the memory pointer in register pair HL.
1B40
INC HL
Bump the value of the memory pointer in register pair HL.
1B41
LD H,(HL)
Load register H with the MSB of the next BASIC line pointer at the location of the memory pointer in register pair HL.
1B42
LD L,A
Load register L with the LSB of the next BASIC line pointer in register A to form the address of the next line in HL.
1B43
CCF
Complement the value of the CARRY FLAG. The carry will be set if the current line number is < the value in DE. This will clear the CARRY FLAG.
1B44
RET Z
Return if the first line number in register pair DE is the same as the current BASIC line number. The line numbers match, so exit C, Z, BC=address of the current line, and HL=address of the next line.
If we are here, then we have no match.
1B45
CCF
Complement (reverse) the CARRY FLAG.
1B46
RET NC
If the first line number in register pair DE is less than the current BASIC line number. BC will be the address of the current line and HL will be the address of the next line.
1B47
Loop until the location of the line number has been found in the BASIC program.
1B49-1B5C - LEVEL II BASIC NEW ROUTINE
1B49
RET NZ
Go to the Level II BASIC error routine and display a ?SN ERROR message if there is any input following the NEW token.
1B4A-1B4C
Call the CLEAR SCREEN routine at 01C9 (which cleans the screen, changes to 64 characters, and homes the screen).
LD HL,(40A4H)
Load register pair HL with the start of the PST (the start of the BASIC program).
- Note: 40A4H-40A5H holds the starting address of BASIC program text also known as the PROGRAM STATEMENT TABLE (PST).
1B50
GOSUB to the TROFF routine at 1DF8H (which just loads A with a zero for TROFF, and puts that 0 into 411BH).
1B53
LD (40E1H),A
Reset the AUTO flag by putting a zero (which is in A due to the GOSUB to the TROFF statement in the above instruction) into 40E1H.
1B56
LD (HL),A
We need to initialize the PST, and the way to do that is to zero the first two bytes so ... save a zero at the location of the memory pointer in register pair HL.
1B57
INC HL
... bump the value of the memory pointer in register pair HL ...
1B58
LD (HL),A
... and save a zero at the location of the memory pointer in register pair HL.
1B59
INC HL
Bump the value of the memory pointer in register pair HL.
1B5A
LD (40F9H),HL
Save the value in register pair HL at 40F9H to initialize the start of the variable list table as the end of the PST.
- Note: 40F9H-40FAH holds the starting address of the simple variable storage area.
1B5D-1BB2 - LEVEL II BASIC RUN ROUTINE
Differences between M1 and M3 ROMs: The locations 1B5DH - 1B5FH are part of the RUN, NEW, EDIT, etc. commands; in the Model I these three bytes contain a LD HL,(40A4H) instruction (resets HL to point to the start of the BASIC program). In the Model III, this has been replaced by a CALL 046BH instruction, which unprotects the video display in addition to resetting HL to the start of the BASIC program.
- This routine does a lot of variable resets and other things that are common to NEW as well, so NEW just does the special NEW stuff and than passes right through to here to reset the rest.
- To use a ROM call to RUN a BASIC program, starting with its first line, execute the following instructions:
LD HL,1D1EH
PUSH HL
JP 1B5DH
The ability to RUN a BASIC program from an assembly language program is valuable for linking the two programs.
*1B5D-1B5F
GOSUB to 046BH to unprotect the screen and point HL to the start of data.
1B60
DEC HL
Decrement the value in register pair HL to backspace.
LD (40DFH),HL
Save the adjusted value in register pair HL into 40DFH.
NOTE: 40DFH-40E0H is used by DOS.
1B64-1B65
LD B,1AH
Load register B with the number of variable names to be initialized (which is 26).
1B66-1B68
LD HL,4101H
Load register pair HL with the starting address of the variable declaration table (which is 4101H).
NOTE: 4101H-411AH holds Variable Declaration Table.
1B69-1B6A
LD (HL),04H
Set the variable at the location of the memory pointer in register pair HL to a single precision variable.
1B6B
INC HL
Bump the value of the memory pointer in register pair HL to the next variable.
1B6C-1B6D
Loop until all 26 variables have been set to single precision.
1B6E
XOR A
Zero register A.
1B6F-1B71
LD (40F2H),A
Save the value in register A (which is a zero) as the current value of the RESUME flag to say that there is no error for RESUME to handle.
NOTE: 40F2H holds the error flag.
1B72
LD L,A
Zero register L.
1B73
LD H,A
Zero register H.
1B74-1B76
LD (40F0H),HL
Save a zero (held in register pair HL) as the current ON ERROR address.
NOTE: 40F0H-40F1H is used by ON ERROR.
1B77-1B79
LD (40F7H),HL
Save a zero (held in register pair HL) as the current BREAK, STOP, or END address.
NOTE: 40F7H-40F8H holds the last byte executed.
1B7A-1B7C
LD HL,(40B1H)
Load register pair HL with the top of the memory pointer held in 40B1H.
NOTE: 40B1H-40B2H holds MEMORY SIZE? pointer.
1B7D-1B7F
LD (40D6H),HL
Save the top of memory pointer (held in register pair HL) as the next available address in the string space pointer.
NOTE: 40D6H-40D7H holds Next available location in string space pointer.
1B80-1B82
Go do a RESTORE (which will mess with DE and HL).
1B83-1B85
LD HL,(40F9H)
Load register pair HL with the end of the BASIC program pointer.
- Note: 40F9H-40FAH holds the starting address of the simple variable storage area.
1B86-1B88
LD (40FBH),HL
Save the value in register pair HL as the new simple variables pointer.
- Note: 40FBH-40FCH holds the starting address of the BASIC array variable storage area.
1B89-1B8B
LD (40FDH),HL
Save the value in register pair HL as the new array variables pointer.
NOTE: 40FDH-40FEH holds the pointer to the starting address of free memory.
1B8C-1B8E
CALL 41BBH
Go call the DOS line at 41BBH.
In NEWDOS 2.1 this initializes BASIC for a new routine.
1B8FH - Inside the RUN routine - Initialize the Level II BASIC variables and pointers
1B8F
POP BC
Get the return address from the stack because we are about to change the stack pointer.
1B90-1B92
LD HL,(40A0H)
Load register pair HL with the start of string space pointer.
- Note: 40A0H-40A1H holds the start of string space pointer.
1B93
DEC HL
Decrement the value of the memory pointer in register pair HL.
1B94
DEC HL
Decrement the value of the memory pointer in register pair HL (so now HL has the sart of the string space pointer - 2).
1B95-1B97
LD (40E8H),HL
Save the string space pointer - 2 (in register pair HL) as the stack pointer
Note: 40E8H-40E9H holds Stack pointer pointer.
1B98
INC HL
Bump the value of the memory pointer in register pair HL.
1B99
INC HL
Bump the value of the memory pointer in register pair HL so it is back to being the start of the string space pointer.
1B9A
LD SP,HL
Load the stack pointer with the start of the string space pointer (held in register pair HL).
1B9B-1B9D
LD HL,40B5H
Load register pair HL with the start of the string work area (which is 40B5H).
NOTE: 40B5H-40D2H holds Temporary string work area.
1B9E-1BA0
LD (40B3H),HL
Save the value in register pair HL as the next available location in the string work area pointer.
NOTE: 40B3H-40B4H holds Next available location in the temporary string work area pointer.
1BA1-1BA3
GOSUB 038BH to set the current output device to the video display.
1BA4-1BA6
Go turn off the cassette recorder.
1BA7
XOR A
Zero register A.
1BA8
LD H,A
Zero register H.
1BA9
LD L,A
Zero register L.
1BAA-1BAC
LD (40DCH),A
Clear the FOR statement flag.
NOTE: 40DCH holds FOR flag.
1BAD
PUSH HL
Save the value in register pair HL (which is RUN) to the stack.
1BAE
PUSH BC
Save the value in register pair BC (which is the address to continue executing code) to the stack.
1BAF-1BB1
LD HL,(40DFH)
Load register pair HL with the current value of the BASIC program pointer.
NOTE: 40DFH-40E0H holds Used by DOS.
1BB3-1BBF - KEYBOARD INPUT ROUTINE
This is the last of the general purpose input routines. This routine functions identically to the 361H routine with the exception that it prints a "?" on the screen (like INPUT does with BASIC) before allowing input from the keyboard.
To use a ROM call to display "?" on the video screen at the current cursor position (Non-DOS Systems Only), and then to input a string of up to 240 characters, execute CALL 1BB3H. The input string will be in consecutive memory locations starting at the address contained in 40A7H-40A8H, with a zero byte at the end. The HL register pair will contain an address one less than the starting address of the stored input.
1BB3-1BB4H
"INPUT"
LD A,3FH
Load register A with a ?.
1BB5-1BB7
Go display the ? (stored in register A) on the video display.
1BB8-1BB9
LD A,20H
Load register A with a space.
1BBA-1BBC
Go display the space in register A on the video display.
1BBD-1BBF
Jump to the keyboard input routine at 0361H.
1BC0-1C8F - TOKENIZE INPUT ROUTINE
1BC0
XOR A
Zero register A.
1BC1-1BC3
LD (40B0H),A
Save the value in register A as the current value of the tokenization flag.
NOTE: 40B0H holds the temporary storage location.
1BC1-1BC3
LD (409FH),A
Save the value in register A into the DATA FLAG held in 409FH.
NOTE: Bit 0 HIGH means inside a quote. Bit 1 HIGH means inside a DATA. Bit 2 HIGH means inside a REM.
NOTE: In the original Model III ROM, this byte was placed into 40B0H which was just a temporary storage location.
1BC4
LD C,A
Zero register C.
1BC5
EX DE,HL
Load register pair DE with the address of the first character after the line number (as stored in register pair HL).
1BC6-1BC8
LD HL,(40A7H)
Load register pair HL with the starting address of the input buffer.
NOTE: 40A7H-40A8H holds Input Buffer pointer.
1BC9
DEC HL
We need to backspace twice so ... decrement the value of the input buffer pointer in register pair HL.
1BCA
DEC HL
... and again decrement the value of the input buffer pointer in register pair HL.
1BCB
EX DE,HL
Exchange the string address - 2 from HL into DE, and the current input string address from DE into HL.
1BCC
LD A,(HL)
Load register A with the character at the current input string address (in register pair HL).
1BCD-1BCE
CP 20H
Check to see if the character in register A is a space.
1BCF-1BD1
Jump to 1C5BH if the character in register A is a .
1BD2
LD B,A
Load register B with the value of the character in register A.
1BD3-1BD4
CP 22H
Check to see if the character in register A is a ".
1BD5-1BD7
Jump to 1C77H if the character in register A is a ". 1C77H will move the entire field between the quotes into the a code string.
1BD8
OR A
Check to see if the character in register A is an end of the input character and set the status flags.
1BD9-1BDB
Jump to 1C7DH if the character in register A is an end of the input character.
1BDC-1BDE
LD A,(40B0H)
Load register A with the value of the tokenization flag for DATA.
NOTE: 40B0H holds the temporary storage location.
1BDC-1BDE
LD A,(409FH)
Load register A with the value of the DATA FLAG.
NOTE: Bit 0 HIGH means inside a quote. Bit 1 HIGH means inside a DATA. Bit 2 HIGH means inside a REM.
NOTE: In the original Model III ROM, this byte was read from 40B0H which was just a temporary storage location.
1BDF
OR A
Check to see if a DATA statement is being processed.
1BE0
LD A,(HL)
Load register A with the value of the next character.
1BE1-1BE3
Jump to 1C5BH if a DATA statement is being processed.
1BE4-1BE5
CP 3FH
Check to see if the character in register A is a ? (meaning a PRINT statement).
1BE6-1BE7
LD A,B2H
Load register A with a PRINT token of B2H.
1BE8-1BEA
Jump to 1C5BH if the character at the location of the input buffer pointer in register pair HL is a ?. This will replace the ? with PRINT.
1BEB
LD A,(HL)
Re-fetch the current character (from the memory location of the input buffer pointer in register pair HL) and put it into Register A.
1BEC-1BED
CP 30H
Check to see if the character in register A is less than a zero character (alpha numeric).
NOTE: Results from a CP:
- Z: A and * are the same
- NZ: A and * are NOT the same
- C: A < *
- NC: A => *
1BEE-1BEF
Jump to 1BF5H if the character in register A is less than a zero character, meaning it is not a digit or letter.
1BF0-1BF1
CP 3CH
Check to see if the character in register A is less than < character (which is a test to see if it is 0-9, :, ;, <, constant or special character.
NOTE: Results from a CP:
- Z: A and * are the same
- NZ: A and * are NOT the same
- C: A < *
- NC: A => *
1BF2-1BF4
Jump to 1C5BH if the character in register A is 0-9, :, ;, <, constant or special character.
1BF5
PUSH DE
Save the value of the input buffer pointer in register pair DE to the stack.
1BF6-1BF8
LD DE,164FH
Load register pair DE with the starting address of the reserved words list.
1BF9
PUSH BC
Save the value in Register Pair BC to the STACK.
1BFA-1BFC
LD BC,1C3DH
Load register pair BC with the return address after matching the reserved word list.
1BFD
PUSH BC
Save the return address in register pair BC to the stack .
1BFE-1BFF
LD B,7FH
Load register B with the initial reserved words counter.
1C00
LD A,(HL)
Load register A with the character at the location of the input buffer pointer in register pair HL.
1C01-1C02
CP 61H
Check to see if the character in register A is lower?case.
NOTE: Results from a CP:
- Z: A and * are the same
- NZ: A and * are NOT the same
- C: A < *
- NC: A => *
1C03-1C04
Jump to 1C0CH if the character in register A isn't lowercase.
1C05-1C06
CP 7BH
Check to see if the character in register A is lower?case.
1C07-1C08
Jump down 2 instructions to 1C0CH if the character in register A isn't lowercase.
1C09-1C0A
AND 5FH
Make the lowercase character in register A upper?case.
1C0B
LD (HL),A
Save the adjusted character in register A at the location of the input buffer pointer in register pair HL.
1C0C
LD C,(HL)
Load register C with the character at the location of the input buffer pointer in register pair HL.
1C0D
EX DE,HL
Exchange the input buffer pointer in register pair HL with the reserved words list pointer in register pair DE.
1C0E
INC HL
Bump the value of the reserved words list pointer to the next reserved word and put that in register pair HL.
1C0F
OR (HL)
Check to see if bit 7 of the character at the location of the reserved words list pointer in register pair HL is set.
1C10-1C12
Jump to 1C0EH if the character at the location of the reserved words list pointer in register pair HL doesn't have bit 7 set.
1C13
INC B
Bump the value of the reserved words counter in register B.
1C14
LD A,(HL)
Load register A with the character at the location of the reserved words list pointer in register pair HL.
1C15-1C16
AND 7FH
Reset bit 7 (the sign bit) of the character in register A.
1C17
RET Z
Return if this is the end of the reserved words list.
1C18
CP C
Check to see if the character in register C is the same as the character at the location of the reserved words list pointer in register A.
1C19-1C1A
Jump to 1C0EH if the characters don't match.
1C1B
EX DE,HL
Exchange the value of the reserved words list pointer in register pair HL with the value of the input buffer pointer in register pair DE.
1C1C
PUSH HL
Save the starting address of the current symbol (stored register pair HL) to the stack.
1C1D
INC DE
Bump the value of the reserved words list pointer in register pair DE.
1C1E
LD A,(DE)
Load register A with the character at the location of the reserved words list pointer in register pair DE.
1C1F
OR A
Check to see if bit 7 of the character in register A is set.
1C20-1C22
Jump to 1C39H if we have the control element (i.e., bit 7 of the character in register A is set).
1C23
LD C,A
Load register C with the character in register A.
1C24
LD A,B
Load register A with the value of the reserved words counter in register B.
1C25-1C26
CP 8DH
Check to see if the current reserved word being checked is GOTO.
1C27-1C28
Jump to 1C2BH if the current reserved word being checked isn't GOTO.
1C29
RST 10H
Since we need to skip spaces we need to bump the current input buffer pointer in register pair HL until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:- The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
- Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
- The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
- The string must be terminated by a byte of zeros.
1C2A
DEC HL
Decrement the value of the input buffer pointer in register pair HL.
1C2B
INC HL
Bump the value of the input buffer pointer in register pair HL to point to the next character.
1C2C
LD A,(HL)
Load register A with the next element from the string input (i.e., the character at the location of the input buffer pointer in register pair HL).
1C2D-1C2E
CP 61H
Check to see if the character in register A is lower-case. Results:
- If A=61H it sets the ZERO FLAG
- If A<61H then the CARRY FLAG will be set
- if A>=61H then the NO CARRY FLAG will be set.
If A is a not lower case then C will be set.
1C2F-1C30
Jump to 1C33H if the character in register A isn't lowercase.
1C31-1C32
AND 5FH
Mask A against 5FH (Binary: 0101 1111) to turn off bits 5 and 7 (which locks A to be between 00H and 7FH).
1C33
CP C
Check to see if the character in register A (the input element) matches the character in register C (the syntax element).
1C34-1C35
Jump back to 1C1DH if the character in the input matches the reserved words character.
1C36
POP HL
If we didn't just jump away, we need to restart the scan from the last point in the syntax list (which is stored in the stack) and put it into HL.
1C37-1C38
Jump back to 1C0CH.
1C39
LD C,B
Load register C with the value of the reserved words counter in register B.
1C3A
Get the value from the stack and put it in register pair AF (which is just disposing of the HL push from 1C1CH).
1C3B
EX DE,HL
Exchange the current string with the syntax tree address for the string.
1C3D
EX DE,HL
Exchange the reserved words list pointer in register pair HL with the input buffer pointer in register pair DE.
1C3E
LD A,C
Load register A with the value of the reserved words counter in register C.
1C3F
POP BC
Get the value from the stack and put it in register pair BC (basically to clear the return address from the stack).
1C40
POP DE
Get the input buffer pointer -2 from the stack and put it in register pair DE.
1C41
EX DE,HL
Exchange the input buffer pointer in register pair HL with the input buffer pointer in register pair DE. HL will be the buffer origin - 2 and DE will be the current string address.
1C42-1C43
CP 95H
Check to see if the token in register A is an ELSE token.
1C44-1C45
LD (HL),3AH
Save a colon at the location of the input buffer pointer -2 in register pair HL.
1C46-1C47
Jump to 1C4AH if the token in register A isn't an ELSE token.
1C48
INC C
Bump the value of the counter in register C (which is tracking the token buffer).
1C49
INC HL
Bump the value of the input buffer pointer in register pair HL (which is the token buffer).
1C4A-1C4B
CP 0FBH
Check to see if the token in register A is a REM token.
1C4C-1C4D
Jump to 1C5AH if the token in register A isn't a REM token.
1C4E-1C4F
LD (HL),3AH
Save a ":" at the memory location of the input buffer pointer in register pair HL.
1C50
INC HL
Bump the value of the input buffer pointer in register pair HL (because we just inserted a :).
1C51-1C52
LD B,93H
Load register B with a REM token.
1C53
LD (HL),B
Save the REM token in register B at the memory location of the input buffer pointer in register pair HL.
1C54
INC HL
Bump the value of the input buffer pointer in register pair HL (because we just inserted a REM token).
1C55
EX DE,HL
Exchange the value of the input buffer pointer in register pair HL with the value of the input buffer pointer in register pair DE.
1C56
INC C
Bump the value of the counter in register C.
1C57
INC C
Bump the value of the counter in register C.
1C58-1C59
Jump to 1C77H to move the comment to the token buffer.
1C5A
EX DE,HL
Exchange the value of the input buffer pointer in register pair HL with the value of the input buffer pointer in register pair DE.
INC HL
Bump the value of the input buffer pointer in register pair HL.
1C5C
LD (DE),A
Save the value of the token in register A at the location of the input buffer pointer in register pair DE.
1C5D
INC DE
Bump the value of the input buffer pointer in register pair DE.
1C5E
INC C
Bump the value of the counter in register C (which is the index/counter for the next syntax element).
1C5F-1C60
SUB 3AH
Check to see if the character in register A is a : to flag a multi-statement line.
1C61-1C62
Jump to 1C67H if the character in register A is a colon and we have a multi-statement line.
1C63-1C64
CP 4EH
Check to see if the token in register A is a DATA token.
1C65-1C66
Jump to 1C6AH if the token in register A is NOT a DATA token.
LD (40B0H),A
Save the value in register A as the tokenization flag for DATA.
NOTE: 40B0H holds the temporary storage location.
LD (409FH),A
Save the value in register A into the DATA FLAG held in 409FH.
NOTE: Bit 0 HIGH means inside a quote. Bit 1 HIGH means inside a DATA. Bit 2 HIGH means inside a REM.
NOTE: In the original Model III ROM, this byte was placed into 40B0H which was just a temporary storage location.
SUB 59H
Check to see if the token in register A is a REM token.
1C6C-1C6E
Jump to 1BCCH if the token in register A isn't a REM token.
1C6F
LD B,A
Load register B with a zero.
1C70
LD A,(HL)
Load register A with the character at the location of the input buffer pointer in register pair HL.
1C71
OR A
Check to see if the character in register A is an end of the input character.
1C72-1C73
Jump out of this loop to 1C7DH if the character in register A is an end of the input character.
1C74
CP B
Check to see if the character in register B matches the character in register A.
1C75-1C76
Jump to 1C5BH if the character in register B matches the character in register A.
1C77
INC HL
Bump the value of the input buffer pointer in register pair HL.
1C78
LD (DE),A
Save the character in register A at the location of the input buffer pointer in register pair DE.
1C79
INC C
Bump the value of the counter in register C.
1C7A
INC DE
Bump the value of the input buffer pointer in register pair DE.
1C7B-1C7C
Loop until a 'end of statement' or a ending quote is found.
Still Inside the TOKENIZE INPUT ROUTINE - This routine is called if the character in register A is an end of the input character.
1C7D-1C7F
LD HL,0005H
Load register pair HL with a five.
1C80
LD B,H
Load register B with zero.
1C81
ADD HL,BC
Add 5 to the length of the token buffer so far.
1C82
LD B,H
Load register B with the MSB of the value in register H.
1C83
LD C,L
Load register C with the LSB of the value in register L.
1C84-1C86
LD HL,(40A7H)
Load register pair HL with the start address of the input buffer.
NOTE: 40A7H-40A8H holds the pointer to the start of the Input Buffer.
1C87
DEC HL
Decrement the value of the input buffer pointer in register pair HL.
1C88
DEC HL
Decrement the value of the input buffer pointer in register pair HL.
1C89
DEC HL
Decrement the value of the input buffer pointer in register pair HL.
1C8A
LD (DE),A
Zero the location of the input buffer pointer in register pair DE.
1C8B
INC DE
Bump the value of the input buffer pointer in register pair DE.
1C8C
LD (DE),A
Zero the location of the input buffer pointer in register pair DE.
1C8D
INC DE
Bump the value of the input buffer pointer in register pair DE.
1C8E
LD (DE),A
Zero the location of the input buffer pointer in register pair DE.
1C90-1C95 - RST 0018H CODE
The RST 18H code is located here. (Unsigned compare (HL-DE)).
This is the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as:
- HL<DE: CARRY SET
- HL>DE: NO CARRY
- HL><DE: NZ
- HL=DE: Z
1C90H
"CHLDE"
LD A,H
Load register A with the MSB of the value in register H.
1C91
SUB D
Subtract the value of the MSB of the value in register D from the MSB of the value in register A.
1C92
RET NZ
Return if the MSB of the value in register D doesn't equal the MSB of the value in register H.
1C93
LD A,L
Load register A with the LSB of the value in register L.
1C94
SUB E
Subtract the LSB of the value in register E from the LSB of the value in register A.
1C96-1CA0 - RST 0008H CODE
The RST 8H code is located here.
This is the COMPARE SYMBOL routine which comparess the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call. If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the Aregister and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase).
1C96
LD A,(HL)
Load register A with the character at the location of the current BASIC program pointer in register pair HL.
1C97
EX (SP),HL
Save the return address of the routine by exchanging the value of the current BASIC program pointer in register pair HL with the value of the return address to the stack.
1C98
CP (HL)
Check to see if the character at the location following the RST 08H call (stored in register pair HL) is the same as the character in register A.
1C99
INC HL
Bump the value of the return address in register pair HL.
1C9A
EX (SP),HL
Restore the return address (meaning the RST 08H plus 1 byte plus 1 byte) to the stack pointer.
1C9B-1C9D
Jump to the RST 0010H code if the characters match.
1C9E-1C90
If they don't match, jump to the ?SN ERROR routine.
1CA1-1D1D - Level II BASIC FOR ROUTINE
1CA1-1CA2
LD A,64H
Load register A with the value for the FOR flag.
1CA3-1CA5
LD (40DCH),A
Save the value in register A as the current value of the FOR flag.
NOTE: 40DCH holds FOR flag.
1CA6-1CA8
Go evaluate the N=M portion of the expression.
1CA9
EX (SP),HL
Exchange the value of the current BASIC program pointer in register pair HL with the value to the stack.
1CAA-1CAC
GOSUB to 1936H to check to see if there is a FOR statement to the stack already using the same variable name (called the index).
1CAD
POP DE
Get the current BASIC program pointer from the stack (which should be the TO token and put it in register pair DE.
1CAE-1CAF
If there isn't a matching FOR statement to the stack, skip the next 4 instructions (which are preparing for a NEXT WITHOUT FOR error) and jump to 1CB5H. If one is found, on exit HL will equal the starting address of the FOR push.
1CB0
ADD HL,BC
Add the value in register pair BC (which is the offset to the end of the stack frame) to the value in register pair HL. After this addition, we should be pointing to the end of the first FOR frame push.
1CB1
LD SP,HL
Reset the stack pointer to end of the first FOR frame push. This also frees up the stack space and prepares for a NF error.
1CB2-1CB4
LD (40E8H),HL
Save the value in register pair HL as the stack pointer, get ready for a NF error.
NOTE: 40E8H-40E9H holds Stack pointer pointer.
1CB5
EX DE,HL
Exchange the value of the current BASIC program pointer in register pair DE with the value of the stack pointer address in register pair HL.
1CB6-1CB7
LD C,08H
Load register C with the 1/2 the amount of space needed.
1CB8-1CBA
Go check to see if there is enough memory (i.e., 16 bytes) left by calling 1963H (which is the MEMORY CHECK ROUTINE).
1CBB
PUSH HL
Save the value of the current BASIC program pointer (which is the code string address before the TO) in register pair HL to the stack.
1CBC-1CBE
Keep scanning the current BASIC program (pointer is in register pair HL) until it points to the end of the BASIC statement.
1CBF
EX (SP),HL
Exchange the adjusted value of the current BASIC program pointer in register pair HL with the value of the current BASIC program pointer to the stack.
1CC0
PUSH HL
Save the value of the current BASIC program pointer in register pair HL to the stack. This should be pointing to the TO token.
1CC1-1CC3
LD HL,(40A2H)
Load register pair HL with the value (in binary) of the current BASIC line number.
NOTE: 40A2H-40A3H holds the current BASIC line number.
1CC4
EX (SP),HL
Exchange the value of the current BASIC line number in register pair HL with the value of the current BASIC program pointer to the stack.
1CC5-1CC6
RST 08H
BDH
Since the character at the location of the current BASIC program pointer in register pair HL must be TO token (BDH) so call the COMPARE SYMBOL routine which comparess the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call. If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the Aregister and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase).
1CC7
RST 20H
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register according to the data mode flag (40AFH).
The results are returned as follows:
- Integer = NZ/C/M/E and A is -1
- String = Z/C/P/E and A is 0
- Single Precision = NZ/C/P/O and A is 1
- Double Precision is NZ/NC/P/E and A is 5.
1CC8-1CCA
If that test shows we have a STRING, go to the Level II BASIC error routine and display a TM ERROR message.
1CCB-1CCD
If that test shows we have a DOUBLE PRECISION number, go display a ?TM ERROR message.
1CCE
PUSH AF
We have an integer, so let's keep going and save the value in register pair AF (the type flags) to the stack.
lCCFH-lCDl
Go evaluate the expression at the location of the current BASIC program pointer in register pair HL (which should be the TO side) and return with the result in REG 1.
1CD2
POP AF
Restore the index type flags from the from the stack and put it in register pair AF.
1CD3
PUSH HL
Save the value of the current BASIC program pointer (which is the code string after the TO pointer) in register pair HL to the stack.
1CD4-1CD6
Jump if the current number type is single precision.
1CD7-1CD9
Call the CONVERT TO INTEGER routine at 0A7FH (where the contents of REG 1 are converted from single or double precision to integer and deposited into HL).
1CDA
EX (SP),HL
Exchange the integer value in register pair HL (the current TO value) with the value of the current BASIC program pointer to the stack.
1CDB-1CCD
LD DE,0001H
Load register pair DE with a default STEP value of 1.
1CDE
LD A,(HL)
Load register A with the character at the location of the current BASIC program pointer in register pair HL.
1CDF-1CE0
CP CCH
Check to see if the character in register A is CCH which is the STEP token.
1CE1-1CE3
So now we have a STEP token so we have to get the step value into DE. To do this, GOSUB to 2B01H to evaluate the expression at the location of the current BASIC program pointer in register pair HL and return with the integer value in register pair DE if the character in register A is a STEP token.
1CE4
PUSH DE
Save the STEP index value (in register pair DE) to the stack.
1CE5
PUSH HL
Save the current BASIC program pointer (in register pair HL) to the stack.
1CE6
EX DE,HL
Exchange the STEP value (from DE) with the value of the current BASIC program pointer (in register pair HL). Now HL will have the value so the next call can test its size.
1CE7-1CE9
GOSUB to 099EH to get the sign of the STEP value into A. It will be A=+1 if positive and A=-1 if negative.
1CEA-1CEB
Jump down to 1D0EH to skip the convert to single precision code which follows.
Need the TO value to be integer so GOSUB to the CONVERT TO SINGLE PRECISION routine at 0AB1H (which converts the contents of REG 1 from integer or double precision into single precision).
1CEF-1CF1
Call 09BF which loads the SINGLE PRECISION value in REG 1 (the TO value in integer) into register pair BC/DE.
1CF2
POP HL
Get the value of the current BASIC program pointer from the stack (which should be the end of the TO expression) and put it in register pair HL.
1CF3H,1CF4
PUSH BC
PUSH DE
Save all 4 bytes of the TO value to the stack.
1CF5-1CF7
LD BC,8100H
Load register pair BC with the exponent and the MSB for a single precision constant.
1CF8
LD D,C
Zero the NMSB for the single precision constant in register D.
1CF9
LD E,D
Zero the LSB for the single precision constant in register E. Register pairs BC and DE now hold a single precision constant equal to one.
1CFA
LD A,(HL)
Load register A with the character at the location of the current BASIC program pointer in register pair HL.
1CFB-1CFC
CP CCH
Check to see if the character in register A is a STEP token.
1CFD-1CFE
LD A,01H
Load register A with the default STEP value (in this case, 1).
1CFF-1D00
Skip over the next unstructions by jumping down to 1D0FH if the character at the location of the current BASIC program pointer in register A isn't a STEP token.
1D01-1D03
Go evaluate the expression at the location of the current BASIC program pointer (which is the STEP instruction and return with the result in REG 1
1D04
PUSH HL
Save the value of the current BASIC program pointer in register pair HL to the stack.
1D05-1D07
Convert the STEP value to single precision by calling the CONVERT TO SINGLE PRECISION routine at 0AB1H (which converts the contents of REG 1 from integer or double precision into single precision).
1D08-1D0A
Load the STEP value into BC/DE by calling 09BF which loads the SINGLE PRECISION value in REG 1 into register pair BC/DE.
1D0B-1D0D
Go get the sign for the STEP value (held in REG 1) into register A. A will be +1 if positive, and -1 if negative.
1D0E
POP HL
Get the value of the current BASIC program pointer from the stack and put it in register pair HL.
1D0F
PUSH BC
Save the exponent and the NMSB for the single precision value in register pair BC to the stack.
1D10
PUSH DE
Save the NMSB and the LSB for the single precision value in register pair DE to the stack.
1D11
LD C,A
Load register C with the sign value for the STEP value in register A.
1D12
RST 20H
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register according to the data mode flag (40AFH).
The results are returned as follows:
- Integer = NZ/C/M/E and A is -1
- String = Z/C/P/E and A is 0
- Single Precision = NZ/C/P/O and A is 1
- Double Precision is NZ/NC/P/E and A is 5.
1D13
LD B,A
Load register B with type-adjusted and sign value of the number type flag test in register A.
1D14
PUSH BC
Save the type-adjusted and sign value in register pair BC to the stack.
1D15
PUSH HL
Save the value of the current BASIC program pointer in register pair HL to the stack.
1D16-1D18
LD HL,(40DFH)
Load register B with a FOR x=y token.
NOTE: 40DFH-40E0H holds Used by DOS.
1D19
EX (SP),HL
Put the code address string into HL and put the address of the x variable into the stack.
1D1A-1D1B
LD B,81H
Load register B with the FOR token.
1D1C
PUSH BC
Save the FOR and token and the sign of the STEP increment BC to the stack.
1D1D
INC SP
Bump the value of the stack pointer to leave a one byte gap. By continuing onward, we will wind up continuing the execution of the code string.
1D1E-1D77 - LEVEL II BASIC INTERPRETER
1D1E-1D20
GOSUB to 0358H to check to see if a key has been pressed.
1D21
OR A
Set the flags to test for what key was pressed.
1D22-1D24
GOSUB to 1DA0H if the key pressed was a SHIFT-@. This will save the address of the last byte executed in the current line.
1D25-1D27
LD (40E6H),HL
Save the value of the current BASIC program pointer.
NOTE: 40E6H-40E7H holds the temporary storage location.
1D28-1D2B
LD (40E8H),SP
Save the value of the stack pointer.
NOTE: 40E8H-40E9H holds Stack pointer pointer.
1D2C
LD A,(HL)
Load register A with the value at the location of the current BASIC program pointer in register pair HL.
1D2D-1D2E
CP 3AH
Check to see if the character in register A is a :.
1D2F-1D30
If the character is a :, jump to 1D5AH since that means this is a brand new statement on this line.
1D31
OR A
There wasn't a colon, so the only valid thing we can find now is an END OF LINE character. This will check to see if the character in register A is an end of the BASIC line character.
1D32-1D34
Go to the Level II BASIC error routine and display a ?SN ERROR message if the character in register A isn't an end of the BASIC line character.
1D35
INC HL
So now we know that we have another line number to check, so bump the value of the current BASIC program pointer in register pair HL.
1D36
LD A,(HL)
Load register A with the LSB of the next BASIC line pointer at the location of the current BASIC program pointer in register pair HL.
1D37
INC HL
Bump the value of the current BASIC program pointer in register pair HL.
1D38
OR (HL)
Check to see if the next BASIC line pointer is equal to zero.
1D39-1D3B
Jump to 197EH if this is the end of the BASIC program.
1D3C
INC HL
If we are here, it was not the end of the BASIC program so we need to bump the value of the current BASIC program pointer in register pair HL.
1D3D
LD E,(HL)
Load register E with the LSB of the BASIC line number at the location of the current BASIC program pointer in register pair HL.
1D3E
INC HL
Bump the value of the current BASIC program pointer in register pair HL.
1D3F
LD D,(HL)
Load register D with the MSB of the BASIC line number at the location of the current BASIC program pointer in register pair HL.
1D40
EX DE,HL
Exchange the value of the BASIC line number in register pair DE with the value of the current BASIC program pointer in register pair HL.
1D41-1D43
LD (40A2H),HL
Save the value of the BASIC line number in register pair HL.
NOTE: 40A2H-40A3H holds the current BASIC line number.
1D44 - Honor a TRON by showing the line number if it is in effect.
1D44-1D46
LD A,(411BH)
Before we move on, we need to honor a TRON, if its in effect so first we load register A with the value of the TRON flag.
NOTE: 411BH holds the TRON/TROFF flag.
1D48-1D49
Jump out of this routine to 1D59H if TROFF.
1D4A
PUSH DE
If we are here, we have to process the code to show the "<nnnn>" of a TRON. First, save the value of the current BASIC program pointer in register pair DE to the stack.
1D4B-1D4C
LD A,3CH
Load register A with a <.
1D4D-1D4F
Go display the < that preceeds the line number in TRON output
1D50-1D52
Call the HL TO ASCII routine at 0FAFH (which converts the value in the HL register pair (assumed to be an integer) to ASCII and display it at the current cursor position on the video screen) to display the current BASIC line number.
1D53-1D54
LD A,3EH
Load register A with a >
1D55-1D57
Go display the > that follows the line number in TRON output
1D58
POP DE
Get the value of the current BASIC program pointer from the stack and put it in register pair DE.
1D59 - Done with the TRON, so let us continue.
1D59
EX DE,HL
Load register pair HL with the value of the current BASIC program pointer in register pair DE.
RST 10H
We need to get the next token. We bump the current input buffer pointer in register pair HL until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:- The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
- Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
- The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
- The string must be terminated by a byte of zeros.
1D5B-1D5D
LD DE,1D1EH
Load register pair DE with the return address to go to after executing one verb.
1D5E
PUSH DE
Save that return address in register pair DE to the stack.
1D5F
Return (back to 1D1EH) if the character at the location of the current BASIC program pointer (in register pair HL) is an end of the BASIC line character.
1D60-1D61
SUB 80H
Check to see if the character at the location of the current BASIC program pointer in register A is a token. This is accomplished because tokens range from 80H-FBH so this would give an index of the current token.
1D62-1D64
Jump to 1F21H if the character in register A isn't a BASIC token.
1D65-1D66
CP 3CH
Check to see if the token in register A is below the TAB( token.
1D67-1D69
Jump out of here to 2AE7H if the token in register A is greater than or equal to a TAB( token, meaning TAB( to MID$(.
1D6A
RLCA
Multiply the token value in register A by two. This doubles the remainder of the routine address offset.
1D6B
LD C,A
Load the adjusted token value in register C from register A.
1D6C-1D6D
LD B,00H
Load register B with zero so that BC now holds "00" and (2 x the token).
1D6E
EX DE,HL
Load register pair DE with the value of the current BASIC program pointer in register pair HL.
1D6F-1D71
LD HL,1822H
Load register pair HL with the list of BASIC execution addresses.
1D72
ADD HL,BC
Add the value of the token offset in register pair BC to the starting address of the list of BASIC execution addresses in register pair HL.
1D73
LD C,(HL)
Load register C with the LSB of the execution address at the location of the memory pointer in register pair HL.
1D74
INC HL
Bump the value of the memory pointer in register pair HL.
1D75
LD B,(HL)
Load register B with the MSB of the execution address at the location of the memory pointer in register pair HL.
1D76
PUSH BC
Save the value of the execution address in register pair BC to the stack.
1D77
EX DE,HL
Load register pair HL with the value of the current BASIC program pointer in register pair DE (i.e., restore the code string address).
1D78-1D90 - RST 0010H CODE
The RST 10H code is located here. This is the EXAMINE NEXT SYMBOL routine which loads the next character from the string pointed to by the HL register set into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric. Blanks and control codes 09 and OB are ignored causing the following character to be loaded and tested. The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one. The string must be terminated by a byte of zeros).
1D78H
"FETCH"
INC HL
Bump the value of the current BASIC program pointer in register pair HL to the next character.
1D79
LD A,(HL)
Load register A with the value of the character at the location of the current BASIC program pointer in register pair HL.
1D7A-1D7B
CP 3AH
Check to see if the character at the location of the current BASIC program pointer in register A is greater than or equal to a
:. Results:
- If A=: it sets the ZERO FLAG
- If A<: then the CARRY FLAG will be set
- if A>=: then the NO CARRY FLAG will be set.
1D7C
RET NC
Return if the character at the location of the current BASIC program pointer in register A is greater than or equal to a : (meaning :, ;, < ... Y, Z.
1D7D-1D7E
CP 20H
Check to see if the character at the location of the current BASIC program pointer in register A is a space.
1D7F-1D81
Loop if the character at the location of the current BASIC program pointer in register A is a space.
1D82-1D83
CP 0BH
Check to see if the character at the location of the current BASIC program pointer in register A is greater than or equal to 0BH (meaning it is not a control code). Results:
- If A=0BH it sets the ZERO FLAG
- If A<0BH then the CARRY FLAG will be set
- if A>=0BH then the NO CARRY FLAG will be set.
1D84-1D85
Jump if the character at the location of the current BASIC program pointer in register A if greater than or equal to 0BH.
1D86-1D87
CP 09H
Check to see if the character at the location of the current BASIC program pointer in register A is greater than or equal to 09H (meaning a horizontal tab). Results:
- If A=09H it sets the ZERO FLAG
- If A<09H then the CARRY FLAG will be set
- if A>=09H then the NO CARRY FLAG will be set.
1D88-1D8A
Loop back up to get the next character if if the character at the location of the current BASIC program pointer in register A is greater than or equal to 09H.
1D8B-1D8C
CP 30H
Check to see if the character at the location of the current BASIC program pointer in register A is greater than or equal to a
0. Results:
- If A=0 it sets the ZERO FLAG
- If A<0 then the CARRY FLAG will be set
- if A>=0 then the NO CARRY FLAG will be set.
1D8D
CCF
Complement (invert) the CARRY FLAG so that it will set the CARRY FLAG if that ascii character is numeric (i..e, greater than or equal to 30H).
1D8E
INC A
Clear the CARRY FLAG if it is not numeric (i.e., it is less than 30).
1D8F
DEC A
Set the status flags (except for the CARRY FLAG) according to the character at hand.
1D91-1D9A - LEVEL II BASIC RESTORE ROUTINE
1D91
EX DE,HL
Save the contents of HL by loading its contents into DE.
1D92-1D94
LD HL,(40A4H)
Load register pair HL with the start of the BASIC program pointer.
- Note: 40A4H-40A5H holds the starting address of BASIC program text also known as the PROGRAM STATEMENT TABLE (PST).
1D95
DEC HL
Backspace from the start of the BASIC program pointer.
1D96-1D98
LD (40FFH),HL
Save the start of the program pointer -1 into 40FFH.
NOTE: 40FFH-4100H holds READ pointer.
1D99
EX DE,HL
Restore the HL from being held in DE.
1D9B-1DAD - SCAN KEYBOARD ROUTINE
1D9B-1D9D
GOSUB to 0358H to scan the keyboard.
1D9E
OR A
Set the flags (to see if a key was pressed).
1D9F
RET Z
Return if a key wasn't pressed.
1DA0H - Inside the SCAN KEYBOARD ROUTINE - This will process a SHIFT + @ (Pause) Keypress
1DA0-1DA1
CP 60H
Check to see if the key pressed in register A is a SHIFT + @.
1DA2-1DA4
If you got a SHIFT + @ we now need to honor that by waiting for yet another key to be pressed.
1DA5-1DA7
LD (4099H),A
Save the key pressed in register A as the value of the last key pressed.
NOTE: 4099H holds the Last key pressed.
1DA8
DEC A
Check to see if the BREAK key was pressed.
1DA9H-1DADH - Inside the SCAN KEYBOARD ROUTINE - This will process a STOP.
1DA9
RET NZ
Return if the BREAK key wasn't pressed.
This is the STOP entry point.
1DAA
INC A
Readjust the value of the key pressed in register A.
1DAB-1DAD
Jump into the applicable portion of the code that processes END.
1DAE-1DE3 - LEVEL II BASIC END ROUTINE
1DAE
RET NZ
Return and display a ?SN ERROR message if there is anything following the END token.
1DAF
PUSH AF
Save the value in register pair AF to the stack.
1DB0-1DB2
CALL Z,41BBH
If this is a DOS system, then call the DOS link at 41BBH instead of continuing here.
1DB3
POP AF
Restore the END status to the A register.
LD (40E6H),HL
Save the value of the current BASIC program pointer in register pair HL.
NOTE: 40E6H-40E7H holds the temporary storage location.
1DB7-1DB9
LD HL,40B5H
Load register pair HL with the starting address of the temporary string work area.
NOTE: 40B5H-40D2H holds Temporary string work area.
1DBA-1DBC
LD (40B3H),HL
Save the value in register pair HL as the new temporary string work area pointer.
NOTE: 40B3H-40B4H holds Next available location in the temporary string work area pointer.
1DBD-1DBFH
21 F6 FF
Z-80 space saving trick
1DBE-1DBF
OR FFH
Set the flags.
1DC0
POP BC
Get the value from the stack and put it in register pair BC. This clears out the stack.
LD HL,(40A2H)
Load register pair HL with the value of the current BASIC line number in binary.
NOTE: 40A2H-40A3H holds the current BASIC line number.
1DC4
PUSH HL
Save the value of the current BASIC line number (in binary) in register pair HL to the stack.
1DC5
PUSH AF
Save the value in register pair AF to the stack. A will be 0 if it is an END and A will be a 1 if it is a STOP.
1DC6
LD A,L
These 3 instructions test to see if we are in command mode by testing for an uninitialized line (meaning a line number of FFFF). First, load register A with the LSB of the current BASIC line number in register L.
1DC7
AND H
Combine the MSB of the current BASIC line number in register H with the LSB of the current BASIC line number in register A.
1DC8
INC A
Bump the combined value of the current BASIC line number in register A.
1DC9-1DCA
Increasing FFFF by 1 would flip the Z flag on, meaning there was no line number. If there was no line number, skip the nex 3 instructions and go to 1D44H.
1DCB-1DCD
LD (40F5H),HL
If we are here, we have a line number so save the line number we ended on in register pair HL.
NOTE: 40F5H-40F6H holds the last line number executed.
1DCE-1DD0
LD HL,(40E6H)
Load register pair HL with the value of the current BASIC program pointer .
NOTE: 40E6H-40E7H holds the temporary storage location.
1DD1-1DD3
LD (40F7H),HL
Save the value of the current BASIC program pointer in register pair HL.
NOTE: 40F7H-40F8H holds the last byte executed.
1DD4-1DD6
Go set the current output device to the video display.
1DD7-1DD9
Go display a carriage return if necessary.
1DDA
POP AF
Restore A so we can see if this is an END (where A=0) or a STOP (where A=1).
1DDB-1DDD
LD HL,1930H
Load register pair HL with the starting address of the BREAK message.
1DDE-1DE0
Jump to 1A06H if it was a BREAK or a STOP that halted program execution.
1DE1-1DE3
At this point it was either due to an END statement or an error while in command mode so jump to 1A18H (note: This uses a Z-80 trick as 1A18H is in the middle of a 2 Opcode instruction starting at 1A17H).
1DE4-1DF6 - LEVEL II BASIC CONT ROUTINE.
1DE4-1DE6
LD HL,(40F7H)
Load register pair HL with the value of the continuation address.
NOTE: 40F7H-40F8H holds the last byte executed.
1DE7-1DE8
LD A,H
OR L
Test HL for 0. The easiest way to test a 2 byte register for zero is to load the MSB into A and then OR it with the LSB. if the MSB was 0 and the LSB was 0, then A will be 0.
1DE9-1DEA
LD E,20H
Load register E with a ?CN ERROR code.
1DEB-1DED
If HL was zero, then a CONT isn't possible, so JUMP to 19A2H to display a ?CN ERROR.
1DEE
EX DE,HL
If we are here, there was a valid return line number, so load register pair DE with the value of the continuation line number in register pair HL.
1DEF-1DF1
LD HL,(40F5H)
Load HL with the value of the last BASIC line number executed.
NOTE: 40F5H-40F6H holds the last line number executed.
1DF2-1DF4
LD (40A2H),HL
Save the last line number executed in register pair HL (which had the error) as the current BASIC line number.
NOTE: 40A2H-40A3H holds the current BASIC line number.
1DF5
EX DE,HL
Swap so that HL will be the address of the continuation line.
1DF6
RET
Return (continue running but from the CONT line number).
1DF7H-1DFCH - TRON and TROFF Routine
1DF7H - TRON Entry Point (Set A with AFH)
1DF7-1DF8
LD A,AFH
Load register A with AFH (Decimal: 175), which is the value for TRON when placed into 411BH.
1DF8H - TROFF Entry Point (Set A with 00H)
1DF8
XOR A
Z-80 trick. This command is only visible if jumped to. This zeros register A.
1DF9-1DFC - COMMON CODE SHARED BY TRON AND TROFF - Put A into (411BH)
1DF9-1DFB
LD (411BH),A
Save the value in register A as the current value of the TRON/TROFF flag.
NOTE: 411BH holds the TRON/TROFF flag. 0=off (TROFF), 175=on (TRON)
1DFD-1DFF - DISK ROUTINE NOT USED BY LEVEL II BASIC.
1E00H-1E3CH - DEFxxx Routine
1E00-1E02 - INSIDE THE DEFxxx ROUTINE - DEFSTR Entry Point
1E00-1E01
LD E,03H
Load register E with the DEFSTR string number type flag (03H).
1E02H
32 1B 41
Z-80 Trick! See the general explanation at 10F8H.
1E03H-1E05H - INSIDE THE DEFxxx ROUTINE - DEFINT Entry Point
1E03-1E04
LD E,02H
Load register E with the DEFINT integer number type flag (02H).
1E05H
011 1E 04
Z-80 Trick! See the general explanation at 10F8H.
1E06H-1E08H - INSIDE THE DEFxxx ROUTINE - DEFSNG Entry Point
1E06-1E07
LD E,04H
Load register E with the DEFSNG single precision number type flag (04H).
1E08H
011 E0 08
Z-80 Trick! See the general explanation at 10F8H.
1E09-1E0AH - INSIDE THE DEFxxx ROUTINE - DEFDBL Entry Point
1E09-1E0A
LD E,08H
Load register E with the DEFDBL double precision number type flag (08H).
1E0BH-1E3CH - INSIDE THE DEFxxx ROUTINE - Common code shared by all the above - All of those can either have a - for a range of values or be separated by ,. This code needs to figure out the variables that followed the DEF??? instruction and then set the variable type (which is currently sitting in Register E) in the variable table.
1E0B-1E0D
GOSUB to 1E3DH to check the value at memory location (HL), which would be the current BASIC program pointer, to see if it is a letter. If its not, CARRY is set. If it is, CARRY is clear.
1E0E-1E10
LD BC,1997H
Load register pair BC with a return address which will return to the ?SN ERROR routine.
1E11
PUSH BC
Save the ?SN ERROR address (in register pair BC) to the stack.
1E12
RET C
Return if the character at the location of the current BASIC program pointer in register A isn't alphabetic (meaning that DEF??? wasn't followed by a letter).
1E13-1E14
SUB 41H
Subtract 41H from the letter's value in register A so that it will be in the range of 0-25.
1E15
LD C,A
Load register C with the adjusted value in register A.
1E16
LD B,A
Load register B with the adjusted value in register A.
1E17
RST 10H
Since we now need bump the value of the current BASIC program pointer until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:- The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
- Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
- The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
- The string must be terminated by a byte of zeros.
1E18-1E19
CP CEH
Check to see if the character at the location of the current BASIC program pointer in register A is a -.
1E1A-1E1B
If it's not a - we know this isn't a range, so jump to 1E25H because we don't need to get any more variables.
1E1C
RST 10H
If we are here, then we know the
DEF??? has a range, so we need another character. We bump the value of the current BASIC program pointer until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:- The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
- Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
- The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
- The string must be terminated by a byte of zeros.
1E1D-1E1F
GOSUB to 1E3DH to check the value at memory location (HL), which would be the current BASIC program pointer, to see if it is a letter. If its not, CARRY is set. If it is, CARRY is clear.
1E20
RET C
Return if the character at the location of the current BASIC program pointer in register A isn't alphabetic.
1E21-1E22
SUB 41H
Subtract 41H from the letter's value in register A so that it will be in the range of 0-25.
1E23
LD B,A
Load register B with the adjusted value in register A.
1E24
RST 10H
Since we now need bump the value of the current BASIC program pointer until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:- The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
- Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
- The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
- The string must be terminated by a byte of zeros.
1E25
LD A,B
Load register A with the value of the second letter in register B.
1E26
SUB C
Subtract the value of the first letter in register C from the value of the second letter in Register A.
1E27
RET C
If the CARRY FLAG is set (meaning that varible names are not in ascending order ... the one in Register C is earlier than the one in Register A), return (to a syntax error).
1E28
INC A
Bump the value in register A so that it holds the number of variable names to be changed.
1E29
EX (SP),HL
Clear the error address and save the current code string address.
1E2A-1E2C
LD HL,4101H
Load register pair HL with 4101H which is the starting address of the variable declaration table.
NOTE: 4101H-411AH holds Variable Declaration Table.
1E2D-1E2E
LD B,00H
Load register B with zero.
1E2F
ADD HL,BC
Find the next entry in the type table by adding the value of the first letter in register pair BC to the value of the starting address of the variable declaration table in register pair HL.
1E30
LD (HL),E
E was set on entry to string, integer, single precision, or double precision as applicable. Save the number type flag in register E at the location of the memory pointer in register pair HL.
1E31
INC HL
Bump the value of the memory pointer in register pair HL.
1E32
DEC A
Decrement the count of the number of variables to be changed in register A.
1E33-1E34
Loop until all of the variables in the DEFxxx range have been changed.
1E35
POP HL
Restore the code string pointer into register pair HL.
1E36
LD A,(HL)
Load A with the character at the location of the current BASIC program pointer in register pair HL.
1E37-1E38
CP 2CH
Check to see if the character at the location of the current BASIC program pointer in register A is a ,.
1E39
RET NZ
Return if the character at the location of the current BASIC program pointer in register A isn't a ,.
1E3A
RST 10H
Since we now need bump the value of the current BASIC program pointer until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:- The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
- Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
- The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
- The string must be terminated by a byte of zeros.
1E3B-1E3C
Loop until done with all the variables.
1E3D-1E44 - EXAMINE VARIABLE - See if the value pointed to at the memory location (HL) is an ASCII letter. C Flag is set for yes, NC Flag for no.
1E3D
LD A,(HL)
Load register A with the character at the location of the current BASIC program pointer in register pair HL.
1E3E-1E3F
CP 41H
Check to see if the character at the location of the current BASIC program pointer in register A is less than an
A. Results:
- If A=A it sets the ZERO FLAG
- If A<A then the CARRY FLAG will be set
- If A>=A then the NO CARRY FLAG will be set
1E40
RET C
Return if the character at the location of the current BASIC program pointer in register A is less than an A.
1E41-1E42
CP 5BH
Check to see if the character at the location of the current BASIC program pointer in register A is greater than a
Z. Results:
- If A=Z it sets the ZERO FLAG
- If A<Z then the CARRY FLAG will be set
- If A>=Z then the NO CARRY FLAG will be set
1E43
CCF
Complement the value of the CARRY FLAG. On exit this routine will have the CARRY FLAG set if the character at the location of the current BASIC program pointer in register A isn't alphabetic and will have the CARRY FLAG cleared if the character at the location of the current BASIC program pointer in register A is alphabetic.
1E45-1E4E - EXAMINE VARIABLE
This is called when evaluating a subscript for a variable reference. It will evaluate if the value is positive or negative.
1E45
RST 10H
Get the next symbol from the input. Bump the value of the current BASIC program pointer until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:- The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
- Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
- The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
- The string must be terminated by a byte of zeros.
1E46-1E48
GOSUB to 2B02H to evaluate the expression at the current location of the BASIC program pointer in register pair HL and return with the integer result in register pair DE.
1E49
RET P
Return if the integer result in register pair DE is positive. If it is negative, flow down to the ?FC ERROR.
1E4A - FC ERROR entry point.
1E4A-1E4B
LD E,08H
Load register E with an ?FC ERROR code.
1E4C-1E4E
Display a ?FC ERROR message. If this is from a pass through, the error wll show if the integer result in register pair DE is negative.
1E4F-1E79 - ASCII TO BINARY
1E4F
LD A,(HL)
Load register A with the character at the location of the current BASIC program (which is pointed to by register pair HL).
1E50-1E51
CP 2EH
Check to see if the character at the location of the current BASIC program pointer in register A is a
.. Results:
- If A=. it sets the ZERO FLAG
- If A<. then the CARRY FLAG will be set
- If A>=. then the NO CARRY FLAG will be set
1E52
EX DE,HL
Load register pair DE with the value of the current BASIC program pointer in register pair HL.
1E53-1E55
LD HL,(40ECH)
Load register pair HL with the current BASIC line number.
NOTE: 40ECH-40EDH holds EDIT line number.
1E56
EX DE,HL
Exchange the value of the current BASIC program pointer in register pair DE with the current BASIC line number in register pair HL.
1E57-1E59
Jump to the RST 10H (EXAMINE NEXT SYMBOL) routine if the character at the location of the current BASIC program pointer in register A is a ..
1E5A - "DECBIN" - Converts numeric ASCII string pointed to by the HL register pair, to HEX and places the result in the DE register pair. After execution HL points to the delimiter and the A register contains the delimiter value. The Z flag is set if the delimiter equals 00 or 3A. Z is reset if any other delimiter is used. If there is no string at the location pointed to by HL the routine will return a MO ERROR (missing operand). If the result in the DE register pair exceeds FFFFH an OV ERROR (overflow) results.
1E5AH
DEC HL
Backspace HL (the current BASIC program pointer) to the current character.
1E5B-1E5D
LD DE,0000H
Load register pair DE with zero.
1E5E
RST 10H
Re-process that previous character through a RST 10H call.
NOTE:- The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
- Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
- The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
- The string must be terminated by a byte of zeros.
1E5F
RET NC
Return if the character at the location of the current BASIC program pointer in register A isn't numeric.
1E60
PUSH HL
Save the value of the current BASIC program pointer in register pair HL to the stack.
1E61
PUSH AF
Save the value in register pair AF (which is the digit plus flags resulting from the RST 10H call) to the stack.
1E62-1E64
LD HL,1998H
Load register pair HL with 6552.
Why 6552? Well, since the Z-80 has no multiply function, checking for any possible arbitrary number would require 4 branches for each step in the 'add to itself until it hits * 10' plus another 4 when adding the last digit. The TRS-80 ROM didn't have that kind of room, nor the time to do all that, so they needed a cheat and that cheat was to let it go as high 65529. After all, 6552 + 1 more digit can NEVER exceed 65535, but 6553 + 1 digit sure can!
So with this trick, the ROM just needs to first check the number against 6552, which, when multiplied by 10, and adding one more digit, will never exceed 65529 (because 9 is the highest one number can go).
By using this trick, only 1 comparison is needed (is it greater or less than 6552) ... at the cost of 4 usable line numbers/memory size setting in the 6553x range.
Wait, you say. 65535-65529 is 6 numbers, so why do you say 4. Well, another shortcut the ROM uses is that it assumes anything at line number 65535 is being entered in direct mode (i.e., no line number; just a command), so 65535 couldn't be a line number. Similarly, in 1A09, 65534 is reserved to trigger the BASIC interpreter to jump to the initial powerup routine in the ROM (i.e., a reboot) so you couldn't use that line number either.
1E65
RST 18H
Now we need to check to see if the integer value in DE is greater than 6552, so we call the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as:
- HL<DE: CARRY SET
- HL>DE: NO CARRY
- HL><DE: NZ
- HL=DE: Z
1E66-1E68
Go to the Level II BASIC error routine and display a SN ERROR message if the value in register pair DE is greater than 6552.
1E69
LD H,D
Load register H with the MSB of the integer total in register D.
This is so we can multiply HL (which should hold the number 6552) by 10.
1E6A
LD L,E
Load register L with the LSB of the integer total in register E.
This is so we can multiply HL (which should hold the number 6552) by 10.
1E6B
ADD HL,DE
Multiply the integer value in register pair HL by two.
1E6C
ADD HL,HL
Add HL to itself, which is the same as multiplying the integer value in register pair HL by two. The integer result in register pair HL is now equal to the integer value in register pair DE times four.
1E6D
ADD HL,DE
Add the integer value in register pair DE to the integer value in register pair HL. The integer result in register pair HL is now equal to the integer value in register pair DE times five.
1E6E
ADD HL,HL
Add HL to itself, which is the same as multiplying the integer value in register pair HL by two. The integer result in register pair HL is now equal to the integer value in register pair DE times ten. Now HL is 65520.
1E6F
POP AF
Put the last ASCII digit (from the stack) into AF.
1E70-1E71
SUB 30H
Convert the ASCII digit in register A to binary.
1E72
LD E,A
Load register E with the binary value of the character in register A.
1E73-1E74
LD D,00H
Load register D with zero so that DE will be 0000 through 0009 (the binary equivalent of the digit).
1E75
ADD HL,DE
Add the binary value of the character in register pair DE to the integer value in register pair HL
As noted above, adding in any digit can only result in HL going to 65529.
1E76
EX DE,HL
Swap DE and HL. This will have the effect of setting DE to be 10(base 10) * DE + A.
1E77
POP HL
Restore the pointer to the next digit (from the stack) into HL.
1E78-1E79
Loop until the ASCII to binary conversion has been completed.
1E7A-1EA0 - LEVEL II BASIC CLEAR ROUTINE. If Z FLAG is set, no number of bytes was provided (i.e., CLEAR instead of CLEAR 20).
1E7A-1E7C
Jump to 1B61H (which will set all 26 variables to single precision) if there isn't a number of bytes specified to clear for string space.
1E7D-1D7F
GOSUB to 1E46H to evaluate the number of bytes to be reserved for string space and return with the integer result in register pair DE.
1E80
DEC HL
Decrement the current BASIC program pointer in register pair HL.
1E81
RST 10H
Evaluate the next instruction through a RST 10H call. This will bump the value of the current BASIC program pointer until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:- The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
- Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
- The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
- The string must be terminated by a byte of zeros.
1E82
RET NZ
Return out of the routine if the character at the location of the current BASIC program pointer isn't an end of the BASIC statement character.
1E83
PUSH HL
Save the value of the current BASIC program pointer in register pair HL to the stack.
1E84-1E86
LD HL,(40B1H)
Load the top of memory pointer into register pair HL.
NOTE: 40B1H-40B2H holds MEMORY SIZE? pointer.
1E87
LD A,L
Load register A with the LSB of the top of memory pointer in register L.
1E88
SUB E
Subtract the LSB of the number of bytes for string space in register E from the LSB of the top of memory pointer in register A.
1E89
LD E,A
Load register E with the LSB of the start of string space in register A.
1E8A
LD A,H
Load register A with the MSB of the top of memory pointer in register H.
1E8B
SBC A,D
Subtract the MSB of the number of bytes for string space in register D from the MSB of the top of memory pointer in register A.
1E8C
LD D,A
Load register D with the MSB of the start of string space pointer in register A.
1E8D-1E8F
If the CARRY FLAG was triggered there isn't enough memory for the amount of string space specified, so go show a ?OM ERROR message.
1E90-1E92
LD HL,(40F9H)
Load register pair HL with the end of the BASIC program pointer.
- Note: 40F9H-40FAH holds the starting address of the simple variable storage area.
1E93-1E95
LD BC,0028H
Load register pair BC with the least amount of space needed for BASIC program variables.
1E96
ADD HL,BC
Add the value in register pair BC to the end of BASIC program pointer in register pair HL.
1E97
RST 18H
Now we need to check to the adjusted end of the BASIC program pointer (in HL) with the start of the string space pointer (in DE), so we call the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as:
- HL<DE: CARRY SET
- HL>DE: NO CARRY
- HL><DE: NZ
- HL=DE: Z
1E98-1E9A
Display an ?OM ERROR message if the start of string space pointer in register pair DE is less than the adjusted end of the BASIC program pointer in register pair HL.
1E9B
EX DE,HL
Put the new start of the string area address into HL.
1E9C-1E9E
LD (40A0H),HL
Load the start of string space pointer with HL.
- Note: 40A0H-40A1H holds the start of string space pointer.
1E9F
POP HL
Restore the code string pointer back into HL.
1EA3-1EB0 - LEVEL II BASIC RUN ROUTINE. If Z FLAG is set, no line number was provided (i.e., RUN instead of RUN nnnn).
1EA3-1EA5
JUMP to 1B5DH if there isn't a line number specified after the RUN token.
1EA6-1EA8
CALL 41C7H
GOSUB to 41C7H which is where the RUN nnnn code would be under DOS.
If we are here, then the command was RUN nnnn and we are in Cassette BASIC.
1EA9-1EAB
GOSUB to 1B61H to initialize the BASIC variables and pointers.
1EAC-1EAE
LD BC,1D1EH
Load register pair BC with the continuation addres in the execution driver.
1EAF-1EB0
Jump to 1EC1H to use the GOTO code to begin execution at the nnnn line.
1EB1-1EC1 - LEVEL II BASIC GOSUB ROUTINE
Can be used to execute the equivalent of a GOSUB statement from an assembly program. It allows a BASIC subroutine to be called from an assembly subroutine. After the BASIC subroutine executes, control returns to the next statement in the assembly program. All registers are used. On entry, the HL must contain an ASCII string with the starting line number of the subroutine.
1EB1-1EB2
LD C,03H
Load register B with the number of bytes needed for the GOSUB push.
1EB3-1EB5
Go make sure that there's enough memory for the GOSUB push.
1EB6
POP BC
Get the return address from the stack and put it in register pair BC.
1EB7
PUSH HL
Save the value of the current BASIC program pointer in register pair HL to the stack.
1EB8
PUSH HL
Create a hole to be filled in later by once again saving the value of the current BASIC program pointer to the stack.
1EB9-1EBB
LD HL,(40A2H)
Load register pair HL with the value of the current BASIC line number in binary.
NOTE: 40A2H-40A3H holds the current BASIC line number.
1EBC
EX (SP),HL
Put the binary value for the current line number into the hole in the stack AND restore the code string pointer.
1EBD-1EBE
LD A,91H
Load register A with a GOSUB token.
1EBF
PUSH AF
Save the GOSUB marker (in register pair AF) to the stack.
1EC0
INC SP
Bump the value of the stack pointer.
1EC1
PUSH BC
Save the return address in register pair BC (which is to the GOTO code) to the stack.
1EC2-1EDD - LEVEL II BASIC GOTO ROUTINE. Register pair DE should hold the nnnn for the GOTO nnnn command.
1EC2-1EC4
We need to put the line number to branch to into DE so we GOSUB to the ASCII TO INTEGER routine at 1E5A.
NOTE:- The routine at 1E5A converts the ASCII string pointed to by HL to an integer deposited into DE. If the routine finds a non-numerica character, the conversion is stopped
1EC5-1EC7
GOSUB to 1F07H to bump the current BASIC program pointer in register pair HL until it points to the end of the current BASIC line.
1EC8
PUSH HL
Save the value of the current BASIC program pointer in register pair HL to the stack.
1EC9-1ECB
LD HL,(40A2H)
Load register pair HL with the binary equivalent of the last line number.
NOTE: 40A2H-40A3H holds the current BASIC line number.
1ECC
RST 18H
Now we need to compare the value of the current BASIC line number (in HL) with the value of the line number to branch to (in DE), so we call the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as:
- HL<DE: CARRY SET
- HL>DE: NO CARRY
- HL><DE: NZ
- HL=DE: Z
1ECD
POP HL
Get the value of the current BASIC program pointer from the stack and put it in register pair HL.
1ECE
INC HL
Bump the value of the current BASIC program pointer in register pair HL so as to restore the code string address. DE holds the line number specified.
1ECF-1ED1
If the line number to branch to (in register pair DE) is greater than the current BASIC line number then GOSUB to 1B2FH to find where the line number is located at a LATER location.
1ED2-1ED4
If the line number to branch to (in register pair DE) is less than the current BASIC line number, then go find where the line number is located by calling the SEARCH FOR LINE NUMBER routine at 1B2CH which looks for the line number specified in DE. Returns C/Z with the line found in BC, NC/Z with line number is too large and HL/BC having the next available location, or NC/NZ with line number not found, and BC has the first available one after that.
1ED5
LD H,B
Load register H with the MSB of the new BASIC program pointer in register B. BC is still holding the address of the requested line number.
1ED6
LD L,C
Load register L with the LSB of the new BASIC program pointer in register C.
1ED7
DEC HL
Decrement the value of the current BASIC program pointer in register pair HL to get to the start of the line.
1ED8
RET C
If a line number was found, RETURN from this routine to the execution driver (to start execution at the new line number).
Inside the GOTO ROUTINE - If we are here, the line number nnnn was not found, so error out.
1ED9-1EDA
LD E,0EH
Load register E with an ?UL ERROR code.
1EDB-1EDD
Since the line number wasn't found, display a ?UL ERROR message.
1EDE-1E04 - LEVEL II BASIC RETURN ROUTINE
Returns control to the BASIC statement following the last GOSUB call. An assembly program called by a BASIC subroutine may wish to return directly to the orginal caller without returning through the subroutine entry point. This exit can be used for that return. The return address to the stack for the call to the assembly program must be cleared before returning via 1EDFH.
1EDE
RET NZ
Display a ?SN ERROR message if there is anything following the RETURN token.
1EDF-1EE0
LD D,FFH
Load register D with FFH (a dummy address for the search routine).
1EE1-1EE3
GOSUB to 1936H to backspace the stack pointer by four and return with the value at the location of the stack pointer in register A.
1EE4
LD SP,HL
Load the stack pointer with the new value in register pair HL.
1EE5-1EE7HS
LD (40E8H),HL
Save the stack pointer position in register pair HL.
NOTE: 40E8H-40E9H holds Stack pointer pointer.
1EE8-1EE9
CP 91H
Check to see if the value in register A is a GOSUB token.
1EEA-1EEB
LD E,04H
Load register E with a ?RG ERROR code.
1EEC - ?RG ERROR entry point.
1EEC-1EEE
Display a ?RG ERROR message if there isn't a GOSUB push to the stack.
1EEF
POP HL
Get the binary value of the GOSUB line number from the stack and put it in register pair HL.
1EF0-1EF2
LD (40A2H),HL
Save the GOSUB line number in register pair HL as the current BASIC line number.
NOTE: 40A2H-40A3H holds the current BASIC line number.
1EF3
INC HL
Bump the value of the current BASIC line number in register pair HL.
1EF4
LD A,H
OR L
The way to test HL for 0 is to LOAD A,H and OR L, so A will be 0 only if BOTH H and L were 0. If HL=0 then HL was FFFFH and we have an overflow or a command mode.
1EF6-1EF7
Jump if Level II BASIC is in the command mode.
1EF8H-lEFA
LD A,(40DDH)
If we are here, we may have a one liner! Load register A with the command mode flag.
NOTE: 40DDH holds INPUT flag.
lEFB
OR A
Check for the command mode.
1EFC-1EFE
Jump to 1A18H if Level II BASIC is in the command mode.
1EFF-1F01
LD HL,1D1EH
Load register pair HL with the return address.
1F02
EX (SP),HL
Exchange the value of the current BASIC program pointer to the stack with the return address in register pair HL.
1F03H
3E E1
Z-80 Trick! See the general explanation at 10F8H.
Prepare to scan to the end of the GOSUB by restoring HL from the STACK.
1F05-1F20 - SCAN ROUTINE
This is also the DATA entry point.
1F05H
01
Z-80 Trick! See the general explanation at 10F8H.
1F06H
3A
Z-80 Trick! See the general explanation at 10F8H.
1F07-1F08
LD C,00H
Load register C with zero.
1F09-1F0A
LD B,00H
Load register B with zero.
LD A,C
Load register A with the stop scan character in register C.
1F0C
LD C,B
Load register C with the stop scan character in register B.
1F0D
LD B,A
Load register B with the stop scan character in register A.
LD A,(HL)
Load register A with the character at the location of the current BASIC program pointer in register pair HL.
1F0F
OR A
Check to see if the character at the location of the current BASIC program pointer in register A is an end of the BASIC line character.
1F10
RET Z
Return if the character at the location of the current BASIC program pointer in register A is an end of the BASIC line character.
1F11
CP B
Check to see if the character at the location of the current BASIC program pointer in register A is the same as the stop scan character in register B.
1F12
RET Z
Return if the character at the location of the current BASIC program pointer in register A is the same as the stop scan character in register B.
1F13
INC HL
Bump the value of the current BASIC program pointer in register pair HL.
1F14-1F15
CP 22H
Check to see if the character at the location of the current BASIC program pointer in register A is a ".
1F16-1F17
Loop if the character at the location of the current BASIC program pointer in register A is a quote.
1F18-1F19
SUB 8FH
Check to see if the character at the location of the current BASIC program pointer in register A is a IF token.
1F1A-1F1B
Loop back to 1F0EH if the character at the location of the current BASIC program pointer in register A isn't an IF token.
1F1C
CP B
Check to see if the character at the location of the current BASIC program pointer in register A is the same as the character in register B.
1F1D
ADC A,D
Add the value in register D to the value in register A.
1F1E
LD D,A
Load register D with the value in register A.
1F1F-1F20
Loop back to 1F0EH until scan is completed.
1F21-1F6B - LEVEL II BASIC LET ROUTINE
1F21-1F23
Call the FIND ADDRESS OF VARIABLE routine at 260DH which searches the Variable List Table for a variable name which matches the name in the string pointed to in HL, and return the address of that variable in DE (and if there is no variable, it creates it, zeroes it, and returns THAT location).
1F24-1F25
RST 08H
D5H
Test if the variable name is followed by a =. Since the character at the location of the current BASIC program pointer in register pair HL must be an EQUAL sign (D5) so call the COMPARE SYMBOL routine which comparess the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call. If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the Aregister and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase).
1F26
EX DE,HL
Exchange the address of the variable in register pair DE with the value of the current BASIC program pointer in register pair HL.
1F27-1F29
LD (40DFH),HL
Save the addres of the variable in register pair HL.
NOTE: 40DFH-40E0H holds Used by DOS.
1F2A
EX DE,HL
Exchange the value of the current BASIC program pointer in register pair DE with the address of the variable in register pair HL.
1F2B
PUSH DE
Save the address of the variable in register pair DE to the stack.
1F2C
RST 20H
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register according to the data mode flag (40AFH).
The results are returned as follows:
- Integer = NZ/C/M/E and A is -1
- String = Z/C/P/E and A is 0
- Single Precision = NZ/C/P/O and A is 1
- Double Precision is NZ/NC/P/E and A is 5.
1F2D
PUSH AF
Save the value in register pair AF to the stack. A will be -1 for an integer, 0 for a string, 1 for single precision, and 5 for double precision.
1F2E-1F30
Go evaluate the expression at the location of the current BASIC program pointer in register pair HL and return with the result in REG 1.
1F31
POP AF
Get the value from the stack and put it in register pair AF.
1F32
EX (SP),HL
Exchange the address of the variable to the stack with the value of the current BASIC program pointer in register pair HL.
1F33-1F34
ADD A,03H
Adjust the value in register A so that it will hold the correct number type flag (i.e., A will be 2 for integer, 3 for string, 4 for single precision, and 8 for double precision).
1F35-1F37
Go to 2819H to convert the result in REG 1 to the same number type for the variable .
1F38-1F3A
Go save the result of the expression.
1F3B
PUSH HL
Save the address of the variable in register pair DE to the stack.
1F3C-1F3D
Jump if the result of the expression wasn't a string.
1F3E-1F40
LD HL,(4121H)
Load register pair HL with the starting address of the string's VARPTR in REG 1.
1F41
PUSH HL
Save the VARPTR for the string result in register pair HL to the stack.
1F42
INC HL
Bump the value of the VARPTR for the string result in register pair HL.
1F43
LD E,(HL)
Load register E with the LSB of the address for the string at the location of the VARPTR for the string in register pair HL.
1F44
INC HL
Bump the value of the VARPTR for the string result in register pair HL.
1F45
LD D,(HL)
Load register D with the MSB of the address for the string at the location of the VARPTR for the string in register pair HL.
1F46-1F48
LD HL,(40A4H)
Load register pair HL with the start of the BASIC program.
- Note: 40A4H-40A5H holds the starting address of BASIC program text also known as the PROGRAM STATEMENT TABLE (PST).
1F49
RST 18H
Now we need to compare the start of the BASIC program area (in HL) with the address of the string result in DE, so we call the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as:
- HL<DE: CARRY SET
- HL>DE: NO CARRY
- HL><DE: NZ
- HL=DE: Z
1F4A-1F4B
Jump if the address of the string result in register pair DE is less than the start of the BASIC program area in register pair HL.
1F4C-1F4E
LD HL,(40A0H)
Load register pair HL with the start of the string space pointer.
- Note: 40A0H-40A1H holds the start of string space pointer.
1F4F
RST 18H
Now we need to compare the start of the string space pointer (in HL) with the address of the string result in DE, so we call the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as:
- HL<DE: CARRY SET
- HL>DE: NO CARRY
- HL><DE: NZ
- HL=DE: Z
1F50
POP DE
Get the VARPTR for the string result from the stack and put it in register pair DE.
1F51-1F52
Jump if the address of the string result in register pair DE was less than the start of the string space pointer in register pair HL.
1F53-1F55
LD HL,(40F9H)
Load register pair HL with the simple variables pointer.
- Note: 40F9H-40FAH holds the starting address of the simple variable storage area.
1F56
RST 18H
Now we need to compare the address of the VARPTR for the string result in register pair DE with the simple variables pointer in register pair HL, so we call the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as:
- HL<DE: CARRY SET
- HL>DE: NO CARRY
- HL><DE: NZ
- HL=DE: Z
1F57-1F58
Jump if the address of the VARPTR for the string result in register pair DE is less than the simple variables pointer in register pair HL.
1F59-1F5AH
3E D1
LD A,D1H
Z-80 Trick
1F5A
POP DE
Get the VARPTR for the string result from the stack and put it in register pair DE.
1F5B-1F5D
Go adjust the temporary string work area pointers.
1F5E
EX DE,HL
Exchange the VARPTR for the string in register pair DE with the string's address in register pair HL.
1F5F-1F61
Go move the string into string space.
1F62-1F64
Go adjust the temporary string work area pointers.
1F65
EX (SP),HL
Exchange the address of the variable in register pair BL with the address of the variable to the stack.
1F66-1F68
Go move the result to its proper location in memory.
1F69
POP DE
Get the address of the variable from the stack and put it in register pair DE.
1F6A
POP HL
Get the value of the current BASIC program pointer from the stack and put it in register pair HL.
1F6C-1FAE - LEVEL II BASIC ERROR ON ROUTINE
1F6C-1F6D
CP 9EH
Check to see if the character at the location of the current BASIC program pointer in register A is an ERROR token (since this is supposed to be ON ERROR.
1F6E-1F6F
Jump down to 1F95H if the character at the location of the current BASIC program pointer in register A isn't an ERROR token.
1F70
RST 10H
If we are here, we have
ON ERROR but we do need to see what's next. Since we now need bump the value of the current BASIC program pointer until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:- The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
- Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
- The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
- The string must be terminated by a byte of zeros.
1F71-1F72
RST 08H
8DH
The next valid character at the location of the current BASIC program pointer in register pair HL must be a GOTO token (=8DH) so call the COMPARE SYMBOL routine which comparess the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call. If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the Aregister and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase).
1F73-1F75
Convert the next constant into binary (with the result in DE). To do this, call the ASCII TO INTEGER routine at 1E5A.
NOTE:- The routine at 1E5A converts the ASCII string pointed to by HL to an integer deposited into DE. If the routine finds a non-numerica character, the conversion is stopped
1F76
LD A,D
OR E
To test DE for zero, LOAD A,D and then OR E. A will be 0 only if BOTH D and E were 0
1F78-1F79
Jump to 1F83H if the line number in register pair DE is equal to zero.
1F7A-1F7C
Go find the location of the line number in register pair DE and return with the location of the line number in register pair BC.
1F7DH,1F7E
LD D,B
LD E,C
Put the line number from BC into DE
1F7F
POP HL
Get the value of the current BASIC program pointer from the stack and put it in register pair HL.
1F80-1F82
Display a ?UL ERROR message if the BASIC line doesn't exist.
1F83
EX DE,HL
Exchange the location of the BASIC line in register pair DE with the value of the current BASIC pro gram pointer in register pair HL.
1F84-1F86
LD (40F0H),HL
Save the location of the BASIC line in register pair HL.
NOTE: 40F0H-40F1H is used by ON ERROR.
1F87
EX DE,HL
Exchange the value of the current BASIC program pointer in register pair DE with the location of the BASIC line in register pair HL.
1F88
RET C
RETURN out of this routine to the execution driver if it was not ON ERROR GOTO 0000.
1F89-1F8B
LD A,(40F2H)
Load register A with the value of the error flag.
NOTE: 40F2H holds the error flag.
1F8C
OR A
Check to see if the error flag is set.
1F8D
RET Z
RETURN out of this routine to the execution driver if the override flag is not set.
1F8E-1F90
LD A,(409AH)
Load register A with the error code.
NOTE: 409AH holds the RESUME flag.
1F91
LD E,A
Load register E with the value of the error code in register A.
1F92-1F94
Go to the Level II error routine and display the error message for the error code in register E.
1F95 - Still in the ON routine, but we know it isn't ON ERROR. We now need to deal with the possibility that it was an ON n GOTO or ON n GOSUB.
1F95-1F97
First we need to get the n so go evaluate the expression at the location of the current BASIC program pointer and return with the result in register pair DE.
1F98
LD A,(HL)
Load register A with the next character (which should be a token) at the location of the current BASIC program pointer in register pair HL.
1F99
LD B,A
Save that token into register B.
1F9A-1F9B
CP 91H
Check to see if the character at the location of the current BASIC program pointer in register A is a GOSUB token.
1F9C-1F9D
Skip the next 2 opcodes if the character at the location of current BASIC program pointer in register A is a GOSUB token .
1F9E-1F9F
RST 08H
8DH
Now let's test to see if the next character is the token for a GOTO, call the COMPARE SYMBOL routine which comparess the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call. If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the Aregister and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase).
1FA0
DEC HL
Decrement the value of the current BASIC program pointer in register pair HL to point to the GOTO token.
1FA1
LD C,E
Load register C with the LSB of the expression after the ON token in register E (i.e., the "n" from ON n GOTO).
1FA2
DEC C
Decrement the line number counter in register C.
1FA3
LD A,B
Load register A with the token in register B (which is either a GOSUB or GOTO token).
1FA4-1FA6
Jump to 1D60H if the line number has been found.
1FA7-1FA9
Evaluate the line number at the location of the current BASIC program pointer and return with the result in register pair DE.
1FAA-1FAB
CP 2CH
Check to see if the character at the location of the current BASIC program pointer in register A is a comma. If not, it is the ent of the statement.
1FAC
RET NZ
Return if the character at the location of the current BASIC program pointer in register A isn't a ,.
1FAD-1FAE
Loop until the line number has been located.
1FAF-1FF3 - LEVEL II BASIC RESUME ROUTINE
1FAF-1FB1
LD DE,40F2H
Load register pair DE with the address of the Level II BASIC error flag.
NOTE: 40F2H holds the error flag.
1FB2
LD A,(DE)
Load register A with the error flag at the location of the memory pointer in register pair DE. It will be FF if there is an error, and a zero otherwise.
1FB3
OR A
Check for an error.
1FB4-1FB6
If there was no error, then display an ?RW ERROR message.
1FB7
INC A
Clear the error flag in register A.
1FB8-1FBA
LD (409AH),A
Save the new error flag in register A.
NOTE: 409AH holds the RESUME flag.
1FBB
LD (DE),A
Save the new error flag in register A at the location of the memory pointer in register pair DE.
1FBC
LD A,(HL)
Load register A with the character at the location of the current BASIC program pointer in register pair HL.
1FBD-1FBE
CP 87H
Check to see if the character at the location of the current BASIC program pointer in register A is a NEXT token.
1FBF-1FC0
Jump down to 1FCDH if the character at the location of the current BASIC program pointer in register A is a NEXT token (as in RESUME NEXT).
1FC1-1FC3
Get the binary equivalent of the line number into DE by calling the ASCII TO INTEGER routine at 1E5A.
NOTE:- The routine at 1E5A converts the ASCII string pointed to by HL to an integer deposited into DE. If the routine finds a non-numerica character, the conversion is stopped
1FC4
RET NZ
Return to the execution driver if there wasn't a line number at the location of the current BASIC program pointer.
1FC5
LD A,D
OR E
To test DE against zero, LOAD A, D and OR E, so A will be 0 only if BOTH D and E are zero
1FC7-1FC9
Jump to the GOTO code at 1EC5H if the line number in register pair DE isn't equal to zero (i.e., it was RESUME nnnn).
1FCA
INC A
Bump the value in register A so that it will indicate RESUME 0.
1FCB-1FCC
Jump to the RESUME 0 at 1FCFH.
1FCD
RST 10H
Since we now need bump the value of the current BASIC program pointer until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:- The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
- Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
- The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
- The string must be terminated by a byte of zeros.
1FCE
RET NZ
Return if this is the end of the BASIC statement.
1FCF - This is the RESUME 0 routine
1FCF-1FD1
LD HL,(40EEH)
Get the value of the current BASIC program pointer and put it in register pair HL.
NOTE: 40EEH-40EFH is used by RESUME.
1FD2
EX DE,HL
Load register pair DE with the value of the current BASIC program pointer in register pair HL.
1FD3-1FD5
LD HL,(40EAH)
Load register pair HL with the current BASIC line number.
NOTE: 40EAH-40EBH holds the line number with error.
1FD6-1FD8
LD (40A2H),HL
Save the value of the current BASIC line number in register pair HL. This is where we will resume execution.
NOTE: 40A2H-40A3H holds the current BASIC line number.
1FD9
EX DE,HL
Load register pair HL with the value of the current BASIC program pointer in register pair DE.
1FDA
RET NZ
Return to the execution driver if this is RESUME 0.
1FDB
LD A,(HL)
Get the character at the location of the current BASIC program pointer in register pair HL and put it in register A.
1FDC
OR A
Check the character at the location of the current BASIC program pointer in register A to see if its an end of the BASIC line character.
1FDD-1FDE
Jump forward to 1FE3H if the character at the location of the current BASIC program pointer in register A isn't an end of the BASIC line character.
1FDF
INC HL
Bump the value of the current BASIC program pointer in register pair HL to skip over the zero byte terminator.
1FE0
INC HL
Bump the value of the current BASIC program pointer in register pair HL to skip over the LSB of the pointer to the next statement.
1FE1
INC HL
Bump the value of the current BASIC program pointer in register pair HL to skip over the MSB of the pointer to the next statement.
1FE2
INC HL
Bump the value of the current BASIC program pointer in register pair HL to skip over the LSB of the line number in binary for the line following the error.
1FE3
INC HL
Bump the value of the current BASIC program pointer in register pair HL to skip over the MSB of the line number in binary for the line following the error.
1FE4
LD A,D
Load register A with the MSB of the line number with the error in register D.
1FE5
AND E
Combine the LSB of the line number with the error in register E with the MSB of the line number with the error in register A. This begins the test for the end of program marker.
1FE6
INC A
Bump the combined value of the line number with the error in register A. This will finish the test of DE by turning the FFFFH into 0000H.
1FE7-1FE9
Jump to 1F05H if Level II BASIC isn't in the command mode.
1FEA-1FEC
LD A,(40DDH)
Load register A with the command mode flag.
NOTE: 40DDH holds INPUT flag.
1FED
DEC A
Check to see if the command mode flag in register A is set.
1FEE-1FF0
Jump to 1DBEH if Level II BASIC is in the command mode.
1FF1-1FF3
Exit the routine by jumping to 1F05H.
1FF4H-2007 - LEVEL II BASIC ERROR ROUTINE - Evaluates n for ERROR n
1FF4-1FF6
Go evaluate the expression at the location of the current BASIC program pointer in register pair HL and return with the result in A.
1FF7
RET NZ
Return if this isn't the end of the BASIC statement.
1FF8
OR A
Set up to check to see if the error number in register A is equal to zero.
1FF9-1FFB
Display an ?FC ERROR message if the error code in register A is equal to zero.
1FFC
DEC A
Subtract one from the error code in register A.
1FFD
ADD A,A
Multiply the error code in register A by two (so now A = 2(A-1)).
1FFE
LD E,A
Load register E with 2(A-1).
1FFF-2000
CP 2DH
Check to see if the error code in register A is less than 2DH. Results:
- If A=2DH it sets the ZERO FLAG
- If A<2DH then the CARRY FLAG will be set
- if A>=2DH then the NO CARRY FLAG will be set.
2001-2002
Jump forward 1 instruction (i.e., skip the line that sets up for an error of ?UE ERROR) if the error code (in register A) is in range (i.e., less than 45).