Model III ROM Explained – Part 3



2003 – UE ERROR entry point.

2003-2004
LD E,26H
Load register E with the ERROR code for a ?UE ERROR.
2005-2007
Go to the Level II BASIC error routine and display the appropriate error message.


2008-2038 – LEVEL II BASIC AUTO ROUTINE

2008-200A
LD DE,000AH
Load DE with a default starting line number of ten.
200B
PUSH DE
Save the default stack line number in DE to the stack.
200C-200D
Jump down to 2025H if this is the end of the AUTO statement (meaning that no parameters were provided).
200E-2010
If we are here, then there were parameters after the AUTO statement so we need to GOSUB to 1E4FH to evaluate the line number at the current location of the BASIC program pointer in HL and return with the result in DE.
2011
EX DE,HL
Since there is no such Z-80 command as EX (SP),DE we now need to do some swapping to get DE into (SP). First, exchange the value of the line number in DE with the value of the current BASIC program pointer in HL.
2012
EX (SP),HL
Next, exchange the default line number (to the stack from the above push of DE) with the line number that the user provided (in HL).
2013-2014
Jump down to 2026H if this is the end of the AUTO statement (meaning that only 1 parameter was provided).
2015
EX DE,HL
Load HL with the value of the current BASIC program pointer in DE.
2016-2017
RST 08H
2C
If we are here, then we have an AUTO command with one parameter (starting line number) and we have not finished with the command. Since the only valid addition to that would be a trailing ,, we need to test the current BASIC program pointer in HL for a COMMA (=2CH), by calling the COMPARE SYMBOL at RST 08H.

NOTE: The RST 08H routine compares 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 the next execution address (i.e, the RST 08H instruction + 2) with the next symbol in the A Register 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).
2018
EX DE,HL
If we are here, then it matched (a ?SN ERROR would have occurred otherwise) so load DE with the value of the current BASIC program pointer in HL.
2019-201B
LD HL,(40E4H)
Load HL with the last AUTO increment value.
Note: 40E4H-40E5H holds AUTO increment.
201C
EX DE,HL
Exchange the value of the current BASIC program pointer in DE with the last AUTO increment value in HL.
201D-201E
Jump to 2025H if this is the end of the BASIC statement (meaning, we got AUTO nn, but no further parameter).
201F-2021
If we are here, there was a second parameter so we GOSUB to 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
2022-2024
If that prior GOSUB found a non-numeric character it aborted with a NZ, so if there is a NZ, jump to 1997H to show a ?SN ERROR.
2025
EX DE,HL
Exchange the AUTO increment number in DE with the value of the current BASIC program pointer in HL.
2026
LD A,H
Load register A with the MSB of the AUTO increment number in register H. (This is step 1 of a test to see if HL is zero)
2027
OR L
Combine the LSB of the AUTO increment number in register L with the MSB of the AUTO increment number in register A. (This is step 2 of a test to see if HL is zero)
2028-202A
That all tested the value of HL to see if it was zero. If it was, jupm to 1E4AH to show a ?FC ERROR message.
202B-202D
LD (40E4H),HL
Save the value of the AUTO increment number in HL.
Note: 40E4H-40E5H holds AUTO increment.
202E-2030
LD (40E1H),A
Set the AUTO flag to non-zero. We know A is non-zero because we would have jumped 2 instruction ago if it was.
2031
POP HL
Get the starting line number from the stack and put it in HL.
2032-2034
LD (40E2H),HL
Save the line number in HL as the next AUTO line number.
Note: 40E2H-40E3H holds Current BASIC line number.
2035
POP BC
Clean up the stack.
2036-2038
Jump to the Level II BASIC command mode.


2039-2066 – LEVEL II BASIC IF ROUTINE

2039-203B
GOSUB to 2337H to evaluate the BASIC expression pointed to by HL and return with the result in REG 1.
203C
LD A,(HL)
Load register A with the character at the location of the current BASIC program pointer in HL.
203D-203E
CP 2CH
Check to see if the character at the location of the current BASIC program pointer in register A is a ,.

Notes:

  • 2C is a , in ASCII
  • A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.
203F-2041
If the character at the location of the current BASIC program pointer in register A is a , then go bump the value of the current BASIC program pointer in HL until it points to the next character.
2042-2043
CP CAH
Check to see if the character at the location of the current BASIC program pointer in register A is a THEN token

Notes:

  • CAH is a THEN token.
  • A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.
2044-2046
If Z flag is set, the character at the location of the current BASIC program pointer in register A is a THEN token, so we need to bump the value of the current BASIC program pointer until it points to the next character.
2047
DEC HL
Decrement the value of the current BASIC program pointer in HL so that we are still positioned at the THEN token.
2048
PUSH HL
Save the value of the current BASIC program pointer to the stack.
2049-204B
GOSUB to 0994H to see if the expression after the IF token was true or false.
204C
POP HL
Restore the address of the current position in the current statement (from the stack) into HL.
204D-204E
Jump down to 2056H if the expression was false.
204F
RST 10H
We need the next character in the BASIC program so 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.
2050-2052
Jump to the GOTO routine if the character at the location of the current BASIC program pointer in HL is numeric.
2053-2055
Jump to the execution driver at 1D5FH to evaluate the rest of the statement string.

2056-2057
LD D,01H
Load register D with the scan counter (as we will need to count the number of times to scan to the end of line).

2058-205A
Go scan the BASIC statement.
205B
OR A
Check to see if this is the end of the BASIC instruction.
205C
RET Z
Return if this is the end of the BASIC statement.

205D
RST 10H
We need the next character in the BASIC program so 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.
205E-205F
CP 95H
Check to see if the character at the location of the current BASIC program pointer in register A is an ELSE token.

Notes:

  • 95H is a ELSE in ASCII
  • A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.
2060-2061
Loop back to 2058H until an ELSE token is found.
2062
DEC D
Decrement the value of the scan counter.
2063-2064
Loop back to 2058H until all of the ELSE tokens have been found.
2065-2066
Jump to 204FH to evaluate the rest of the expression.


2067-206E – LEVEL II BASIC LPRINT ROUTINE

2067-2068
LD A,01H
Load register A with the output device code for the printer.
2069-206B
LD (409CH),A
Save the value in register A as the current output device type number.
  • Note: 409CH holds the current output device flag:
    • -1=cassette,
    • 0=video; or
    • 1=printer.
*206C-206E
Skip a few instructions and pick up at 207CH.
Differences between M1 and M3 ROMs: All of the changes from 206DH – 20F7H first appeared in the “new” ROMs of the Model I. The changes were made to allow the use of multiple @’s in a PRINT statement.


206F-2177 – LEVEL II BASIC PRINT ROUTINE

206F-2071
Call the DOS exit link at 41CAH.
*2072-2073
CP ‘#’
Check the character at the location of the current BASIC program pointer in register A to see if it’s an #.
*2074-2075
Jump to 207CH if it is not a #.
*2076-2078
GOSUB to 0284H to [Turn the tape on, no header].
*2079-207B
LD (409CH),A
Load the memory location at 409CH with A, to route output to cassette.
*207C
DEC HL
Decrement HL to back up.
*207D
RST 10H
We need to check for the end of the statement as the next character in the BASIC program so 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.
*207E-2080
GOSUB to 20FEH if it was the end of statement, so we can process a new line.
*2081-2083
And if it was the end of the statement then JUMP to 2169H to finish up.
*2084
OR 20H
With this MASK, we are getting readh to check to see if it was a @.
*2086
CP 60H
Compare against a “‘” (which is actually a @ on the TRS-80).
*2088-2089
JUMP to 20A5H if it is not a @.
*208A
GOSUB to 2B01H to evaluate the PRINT@ expression (which is at the location of the current BASIC program pointer in HL and return with the result in DE).
*208D
Check to see if the location in DE is greater than 1023H. A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.
*208F
If that check resulted in no CARRY flag, jump to 1E4AH to show a ?FC error.
*2092
PUSH HL
Push the current code string address (held in HL) to the stack.
*2093
LD HL,3C00H
Load HL with the start of the display area.
*2096
ADD HL,DE
Add DE to HL so that HL now will be the start of the diplay area PLUS the PRINT@ offset position.
*2097
LD (4020H),HL
Store the cursor position of the screen address matching the PRINT@ position into the display DCB held in memory location 4020H.
  • 4020H-4021H: Holds the video memory address of the current cursor position.
*209A
LD A,E
E is the current position within the line.
*209B
AND 3FH
Make it not exceed 63 and then save it ….
*209D
LD (40A6H),A
… into the current cursor offset (which is held in 40A6H).
*20A0
POP HL
Restore the code string address to HL
*20A2
RST 08H
2C
At this point we have a PRINT@nnnn so the only valid next character is a , so we need to call RST 08H to check against 2C, the code for comma.

NOTE: The RST 08H routine compares 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 the next execution address (i.e, the RST 08H instruction + 2) with the next symbol in the A Register 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).
*20A3-20A4
JUMP to 206CH to [NEXT ITEM].
*20A5
LD A,(HL)
2C
Put the next token (held in the memory location pointed to by HL) into A.
*20A6-20A7
CP 0BFH
Compare the device flag.
  • NOTE: A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.)
*20A8-20AA
… and return to the execution driver.
*20AB-20AC
CP BCH
Test for a TAB token.

Notes:

  • BCH is a TAB in ASCII
  • A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.
*20AD-20AF
and if it is a TAB token (meaning the command is PRINT TAB, jump down to 2137H.
*20B0
PUSH HL
Continuing on a PRINT#, save the current position in the input stream into the stack.
*20B1-20B2
CP 2CH
Test for a ,.

Notes:

  • 2CH is a , in ASCII
  • A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.
*20B3-20B4
If there is a comma, jump down to 2108H to get the next item.
*20B5-20B6
CP 3BH
Since its not a comma, next we need to check for a ;.

Notes:

  • 3BH is a ; in ASCII
  • A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.
*20B7-20B8
If it is a ;, jump down to 2117H to process.
*20B9
GOSUB to 2337H [to evaluate the expression].
*20BC
EX (SP),HL
Swap (SP) for HL to restore the position.
20BD
RST 20H
Check its data type with a call to 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
  • and Double Precision is NZ/NC/P/E and A is 5.
20BE
If it is a string, jump down to 20F2H.
20C0
GOSUB to the routine at 0FBDH to convert the binary to ASCII and move to the print buffer.
20C3
GOSUB to the routine at 2865H to build a literal string pool entry for the ASCII number.
20C6
GOSUB to a DOS exit if needed
20C9
LD HL,(4121H)
Put the address of the current print string into HL.
20CC
LD A,(409CH)
Get the output device type flag and put it into A.
  • Note: 409CH holds the current output device flag:
    • -1=cassette,
    • 0=video; or
    • 1=printer.
20CF
OR A
Test the output device type flag.
20D0
If we writing to a cassette (i.e., PRINT#) jump to 20E9H.
20D3
If, instead, we do NOT have a LPRINT, jump down to 20DDH.
20D5-20D7
LD A,(409BH)
If we are here, we have a LPRINT so load A with the current carriage position.
Note: 409BH holds the printer carriage position.
20D8
ADD A,(HL)
Add the length of the string to be sent to the printer at the location of the memory pointer in HL to the current carriage position in register A.
20D9-20DA
CP 84H
Check to see if the adjusted length in register A is greater than 132.
  • NOTE: A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.)
20DB-20DC
Jump forward to 20E6H.
20DD-20DF
LD A,(409DH)
Load register A with the video line size.
Note: 409DH holds the size of line on the video display.
20E0
LD B,A
Load register B with the video line size in register A.
20E1-20E3
LD A,(40A6H)
Load register A with the current video line position.
Note: 40A6H holds the current cursor line position.
20E4
ADD A,(HL)
Add the length of the string to be sent to the video display at the location of the memory pointer in HL to the value of the current video line position in register A.
20E5
CP B
Check to see if the length in register A is greater than the video line length.
  • NOTE: A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.)

20E6-20E8
If NC is set, the new line will overflow the buffer so send a carriage return to the current output device.
20E9-20EB
Go send the string to the current output device.
20EC-20ED
LD A,20H
Load register A with a space.
20EE-20F0
Go send the space in register A to the current output device.
20F1
OR A
Check to see if register A is equal to zero.
20F2-20F4
If necessary go send the string to the current output device.
20F5
POP HL
Restore the current code string to HL
20F6-20F8
Loop to 207CH until an end of statement code is found. Going all the way back to 207CH will also test for a PRINT @, thus permitting a PRINT @ to appear other than first.
20F9-20FB
LD A,(40A6H)
Load register A with the number of characters printed on the current line.
Note: 40A6H holds the current cursor line position.
20FC
OR A
Check to see if any characters have been printed on the current line.
20FD
RET Z
Return out of this routine if we are at the start of a line.


20FE – This routine outputs a carriage return (0DH) to a device determined by flag stored at (409CH).

  • NOTE: This routine may be CALLed at 20F9H, in which case it will not perform the above action if the video display cursor is already positioned at the beginning of a line, as determined by checking the contents of the cursor position flag at 40A6H (if zero, cursor is at start of line). This routine CALLs the routine at 032AH and also CALLs a Disk BASIC link at 41D0H.
20FE-20FF
LD A,0DH
Otherwise, we need to skip to the next line so load register A with a carriage return.
2100-2102
Go send the carriage return in register A to the current output device.
2103-2105
Call the DOS link at 41D0H.
In NEWDOS 2.1, this is called when skipping to next line on a video during a BASIC output operation.
2106
XOR A
Zero register A and the carry flags.
2107
RET
Return back to the calling routine.


2108 – This is the jump point for a continuation of the PRINT# code.

2108-210A
Call the DOS link at 4103H.
In NEWDOS 2.1, this is called at the start of PRINT on cassette and during PRINT TAB.
210B-210D
LD A,(409CH)
Load register A with the value of the current output device flag..
  • Note: 409CH holds the current output device flag:
    • -1=cassette,
    • 0=video; or
    • 1=printer.
210E
OR A
Test the value of the current output device flag in register A.
  • M will be set if the value in A is negative.
  • P will be set if the value in A is positive or zero.
210F-2111
Jump down a few instructions to 2119H if the printer or the video display is the current output device.
2112-2113
LD A,2CH
So now that we know the current device is cassette, we will load register A with a ,.
2114-2116
Send the , in register A to current output device. In this case, it is the cassette recorder because we otherwise would have jumped away at 210FH.
2117-2118
Jump forward to 2164H to fetch the next character from the code string.
2119-211A
We landed here from 210FH knowing that the current output device flag was either video or printer. Now we need to break that down too, so if the device flag is the video display, jump down to 2123H.
211B-211D
LD A,(409BH)
We’re here because the output device is a printer. First, load register A with the current carriage position.
Note: 409BH holds the printer carriage position.
211E-211F
CP 70H
Check to see if the current carriage position in register A is greater than 112.
  • NOTE: A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.)
2120-2122
Jump forward a few instructions to 212BH.
2123-2125
LD A,(409EH)
We were jumped to this point because the output device is the video display. So load register A with the video line length.
Note: 409EH holds the size of line on the printer.
2126
LD B,A
Load register B with the video line length in register A.
2127-2129
LD A,(40A6H)
Load register A with the current video line position.
Note: 40A6H holds the current cursor line position.
212A
CP B
Test to see if there is room on this line by checking to see if the current video line position in register A is equal to the video line length in register B.
  • NOTE: A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.)

212B-212D
If the NC is set, there is no room on the current line, so we need to GOSUB to 20FEH to print a carriage return on the current output device.

212E-212F
If this is the end of the line on the current output device jump forward to 2164H.
2130-2131
SUB 10H
Check to see if there are at least 16 spaces left on the current line for the current output device.

2132-2133
Loop back until there are at least 16 spaces left on the current line.
2134
CPL
Figure the number of spaces to be sent to the current output device.
2135-2136
Jump to 215AH to print those spaces/blanks.


2137 – TAB logic.

  • This routine is the TAB function for video or printer (determined by flag at 409CH). On entry: E register contains desired TAB position, HL points to start of message to be displayed (or zero byte if no message). This routine does extensive string processing and may not be the most efficient method of achieving the desired result, particularly if it is desired only to tab over a number of spaces. Also, this routine CALLs several Disk BASIC links which may have to be “plugged”. 2169 – Reset device type flag at 409CH to zero (output to video display), also turns off cassette drive if necessary. CALLs Disk BASIC link at 41BEH prior to return.
2137-2139
GOSUB forward to 2B1BH to evaluate the tab number at the location of the current BASIC program pointer in HL and return with the result in register A.
213A-213B
AND 3FH
The results are in A so mask the tab number in register A so that it doesn’t exceed 63.
Difference between M1 and M3 ROMs: This also first appeared in the “new” ROMs of the Model I, as part of an AND 7FH instruction located at 213AH. In the original version the instruction was AND 3FH. The operand of the instruction sets the maximum argument for the TAB function, thus the early TRS-80’s could only handle a maximum TAB (63) while the latest Models can go as high as TAB (127).
213C
LD B,A
Load register B with the value of the tab number from register A.
213D-213E
RST 08H
29
At this point, we have a TAB(nn, so the next character needs to be a ). Since the character at the location of the current BASIC program pointer in HL must be a “)”, call the COMPARE SYMBOL at RST 08H.

NOTE: The RST 08H routine compares 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 the next execution address (i.e, the RST 08H instruction + 2) with the next symbol in the A Register 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).
213F
DEC HL
Decrement the value of the current BASIC program pointer in HL so that it points to the (.
  • To use a ROM call to locate the cursor at position n on the current display line, where n is an integer between 0 and 3FH, inclusive, first load the E register with the value of n and then load the HL register pair with the address of a zero byte in memory. Once that’s done CALL 213FH.
    • NOTE 1: The cursor position cannot be moved backward by this procedure. If n is not greater than the current cursor position on the line, no change will occur.
    • NOTE 2: To locate the cursor at a given position on the screen (the function of the PRINT@ command in BASIC), the simplest procedure is to modify the cursor position bytes, which are located at 4020H-4021H. The address contained in these memory cells is that of the position in video memory (3C00H-3FFFH) at which the (abstract) cursor resides. This cursor position controls subsequent printing via the subroutine at 28A7H
    • DISK SYSTEM CAUTION: The subroutine at 213FH has three exits to DISK BASIC, with RAM transfer points at 41BEH, 41C1H, and 41D3H. To use this routine safely, either be certain that DISK BASIC is in place, or have your assembly language program fill locations 41BEH, 41C1H, and 41D3H with RET’s (C9H), before calling the routine.
2140
Save the value of the current BASIC program pointer in HL to the stack.
2141-2143
Call the DOS link at 41DCH.
2144-2146
LD A,(409CH)
Load register A with the value of the current output device flag..
  • Note: 409CH holds the current output device flag:
    • -1=cassette,
    • 0=video; or
    • 1=printer.
2147
OR A
Test the value of the current output device flag in register A.
2148-214A
Display a ?FC ERROR message if the current output device is the cassette recorder.
214B-214D
Jump forward a few instructions to 2153H if the current output device is the video display.
214E-2150
LD A,(409BH)
Since we have already jumped away if the current output device is to cassette or screen, if we are here we know that this is to go to the printer, so load register A with the current carriage position.
Note: 409BH holds the printer carriage position.
2151-2152
Jump over the next instruction (which is a video instruction).
2154-2155
LD A,(40A6H)
Load register A with the current video line position.
Note: 40A6H holds the current cursor line position.
2156
CPL
When we land here, A holds either the current carriage position (printer) or the current line position (video). Regardless, complement (make negative) that value.
2157
ADD A,E
Add the tab number in register B to the adjusted line position in register A so that A=-current position + tab.

2158-2159
Jump forward a few instructions to 2164H to skip over the actual TAB effectuation routine if the tab number in register B is less than the line position in register A.
215A
INC A
Bump the number of spaces to be printed in register A.
215B
LD B,A
Load register B with the number of spaces to be printed in register A.
215C-215D
LD A,20H
Load register A with a space.
215E-2160
Send the space in register A to the current output device.
2161
DEC B
Decrement the value of the space counter in register B.
2162-2163
Loop back to 215EH until all of the spaces have been displayed/printed.

2164
POP HL
Restore the position in of the current BASIC program pointer (from the stack) into HL.
2165
RST 10H
We need the next character in the BASIC program so 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.
*2166-2168
Jump back to 2081H to process the rest of the PRINT TAB statement.
Difference between M1 and M3 ROMs: This corrects a jump back into the revised PRINT command routine.

2169 – This routine resets the device type flag at 409CH to zero (output to video display), also turns off cassette drive if necessary. CALLs Disk BASIC link at 41BEH prior to return.

2169-216B
LD A,(409CH)
If we land here, we need to turn off the cassette and reset the current output device to be video. To do this we first load register A with the current output device flag..
  • Note: 409CH holds the current output device flag:
    • -1=cassette,
    • 0=video; or
    • 1=printer.
216C
OR A
Test the value of the current output device flag in register A. If the M flag is set, A was negative.
216D-216F
If the current output device flag is the cassette recorder, GOSUB to 01F8H to turn it off.
2170
XOR A
Clear Register A (which will set A to 0) and clear the status flags.
2171-2173
LD (409CH),A
Save the value in register A (which is 0) as the current value of the output device flag.
  • Note: 409CH holds the current output device flag:
    • -1=cassette,
    • 0=video; or
    • 1=printer.
2174-2176
Call the DOS link at 41BEH.
In NEWDOS 2.1, this initializes the system output device.
2177
RET
Return.


2178-217E – MESSAGE STORAGE LOCATION FOR REDO MESSAGE

2178-217E
“?REDO”
The ?REDO message is stored here.


217F-2285 – LEVEL II BASIC INPUT AND READ ROUTINES

217F-2181
LD A,(40DEH)
Load register A with the read flag.
Note: 40DEH holds READ flag.
2182
OR A
Check to see if the read flag is set.
2183-2185
If the read flag is set, go give a ?SN ERROR.
2186-2188
LD A,(40A9H)
Now we know the read flag is NOT set, so we need to load register A with the input type flag.
Note: 40A9H holds Cassette input flag.
2189
OR A
Check to see if the cassette recorder is the current input device.
218A-218B
LD E,2AH
Load register E with the ?FD ERROR code.
218C-218E
If the current input device is the cassette recorder, go give a ?FD ERROR.
218F
POP BC
Clean up the stack.
2190-2192
LD HL,2178H
Load HL with the starting address of the ?REDO message.
2193-2195
We need to display the ?REDO, 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).
2196-2198
LD HL,(40E6H)
Get the value of the current BASIC program pointer in HL.
Note: 40E6H-40E7H holds Temporary storage location.
2199
RET
Return out of this routine.


219A – INPUT logic

219A-219C
Check to see if there is an illegal direct in the input statement.
219D
LD A,(HL)
Load register A with the character at the location of the current BASIC program pointer in HL.
219E-21A0
Call the DOS link at 41D6H.
In NEWDOS 2.1 this is called at the beginning of INPUT processing.
21A1-21A2
SUB 23H
Check to see if the character at the location of the current BASIC program pointer in register A is a #.
21A3-21A5
LD (40A9H),A
Set the current input device flag for the cassette recorder.
Note: 40A9H holds cassette input flag.
21A6
LD A,(HL)
Load register A with the character at the location of the current BASIC program pointer in HL.
21A7-21A8
Jump to 21C9H if there is keyboard input.
21A9-21AB
If we are here, then the input is coming from the cassette, so GOSUB to 0293H to read the cassette leader and find the sync byte.
21AC
PUSH HL
Save the current BASIC program pointer in HL to the stack.
21AD-21AE
LD B,FAH
Load register B with the size of the input buffer.
21AF-21B1
LD HL,(40A7H)
Load HL with the starting address of the input buffer.
Note: 40A7H-40A8H holds the input Buffer pointer.
21B2-21B4
Calls the READ ONE BYTE FROM CASSETTE routine at 0235H (which reads one byte from the cassette drive specified in register A, and returns the byte in register A).
21B5
LD (HL),A
Save the byte read from the cassette recorder in register A at the location of the input buffer pointer in HL.
21B6
INC HL
Bump the value of the input buffer pointer in HL.
21B7-21B8
CP 0DH
Check to see if the character read from the cassette recorder in register A is a carriage return.

Notes:

  • 0DH is a ENTER in ASCII
  • A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.
21B9-21BA
Jump out of this routine if the character read from the cassette recorder in register A is a carriage return.
21BB-21BC
Loop back to 21B2H until the input buffer is full.

21BD
DEC HL
Decrement the value of the input buffer pointer in HL.
21BE-21BF
LD (HL),00H
Save a zero at the location of the input buffer pointer in HL.
21C0-21C2
GOSUB to 01F8H to put a 00H at the end of the tape and turn the cassette recorder off.
21C3-21C5
LD HL,(40A7H)
Load HL with the starting address of the input buffer.
Note: 40A7H-40A8H holds the input Buffer pointer.
21C6
DEC HL
Decrement the value of the input buffer pointer in HL.
21C7-21C8
Jump to 21EBH to store a comma there so we can use the READ processing.

21C9-21CB
LD BC,21DBH
Load BC with a return address of 21DBH.
21CC
PUSH BC
Save the value of the return address in BC to the stack.
21CD-21CE
CP 22H
Check to see if the character at the location of the current BASIC program pointer in register A is a quote.

Notes:

  • 22H is a in ASCII
  • A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.
21CF
Return to 21DBH if the character at the location of the current BASIC program pointer in register A isn’t a quote.

21D0-21D2
Go set up pointers for the prompting message in the temporary string work area.
21D3-21D4
RST 08H
3B
Since the character at the location of the current BASIC program pointer in HL must be a “;”, call the COMPARE SYMBOL routine at RST 08H.

NOTE: The RST 08H routine compares 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 the next execution address (i.e, the RST 08H instruction + 2) with the next symbol in the A Register 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).
21D5
PUSH HL
Save the value of the current BASIC program pointer in HL to the stack.
21D6-21D8
Go display the prompting message.
21D9
POP HL
Restore the code string address (from the stack) into HL.
21DA
Return to 21DBH.

21DB
PUSH HL
Save the value of the current BASIC program pointer in HL to the stack.
21DC-21DE
Print the ? prompt and get the input from the keyboard.
21DF
POP BC
Get the value of the current BASIC program pointer from the stack and put it in BC.
21E0-21E2
Jump back to 1DBEH if the BREAK key was pressed.
21E3
INC HL
Bump the value of the input buffer pointer in HL.
21E4
LD A,(HL)
Load register A with the character at the location of the input buffer pointer in HL.
21E5
OR A
Test the value of the character at the location of the input buffer pointer in register A.
21E6
DEC HL
Decrement the value of the input buffer pointer in HL.
21E7
PUSH BC
Save the value of the current BASIC program pointer in BC to the stack.
21E8-21EA
Jump if the character at the location of the input buffer pointer in register A is an end of the input character.
21EB-21EC
LD (HL),2CH
Save a comma at the location of the current input buffer pointer in HL.
21ED-21EE
Jump to 21F4H (which address uses a Z-80 trick).


21EF – READ logic

21EF
PUSH HL
Save the current BASIC program pointer in HL.
21F0-21F2
LD HL,(40FFH)
Load HL with the location of the last DATA statement read.
Note: 40FFH-4100H holds READ pointer.
21F3-21F4
OR AFH
Set register A to a non-zero value if entered from the READ routine and zero if entered from the INPUT routine.
21F5-21F7
LD (40DEH),A
Save the value of the input type flag in register A.
Note: 40DEH holds READ flag.
21F8
EX (SP),HL
Exchange the start of the input pointer in HL with the current BASIC program pointer to the stack.
21F9-21FA
Skip over the next instruction.
21FB-21FC
RST 08H
2C
Since the character at the location of the current BASIC program pointer in HL must be a ,, call the COMPARE SYMBOL at RST 08H.

NOTE: The RST 08H routine compares 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 the next execution address (i.e, the RST 08H instruction + 2) with the next symbol in the A Register 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).
21FD-21FF
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).
2200
EX (SP),HL
Exchange the value of the current BASIC program pointer in HL with the start of the input buffer pointer to the stack.
2201
PUSH DE
Save the variable’s address in DE to the stack.
2202
LD A,(HL)
Load register A with the character at the location of the input buffer pointer in HL.
2203-2204
CP 2CH
Check to see if the character at the location of the input buffer pointer register A is a ,.
  • NOTE: A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.)
2205-2206
Jump to 222DH if the character at the location of the input buffer pointer in register A is a ,.
2207-2209
LD A,(40DEH)
Load register A with the input type flag.
Note: 40DEH holds READ flag.
220A
OR A
Check for READ or INPUT.
220B-220D
Jump to 2296H if the input type flag in register A indicates READ.
220E-2210
LD A,(40A9H)
Load register A with the value of the cassette input flag.
Note: 40A9H holds Cassette input flag.
2211
OR A
Check to see if the input is from the cassette recorder.
2212-2213
LD E,06H
Load register E with an ?OD ERROR code.
2214-2216
Go to the Level II BASIC error routine and display an ?OD ERROR message if the input is from the cassette recorder.
2217-2218
LD A,3FH
Load register A with a “?”.
2219-221B
GOSUB to 032AH which is a general purpose output routine that outputs a byte from the A register to video, tape or printer (based on what is in 409CH).
221C-221E
Go get the keyboard input.
221F
POP DE
Get the address of the variable to be set from the stack and put it in DE.
2220
POP BC
Get the value of the current BASIC program pointer from the stack and put it in BC.
2221-2223
Jump to 1DBEH if the BREAK key was pressed.
2224
INC HL
Bump the value of the input buffer pointer in HL.
2225
LD A,(HL)
Load register A with the character at the location of the input buffer pointer in HL.
2226
OR A
Check to see if the character at the location of the input buffer pointer in register A is an end of the input character.
2227
DEC HL
Decrement the value of the input buffer pointer in HL.
2228
PUSH BC
Save the value of the current BASIC program pointer in BC to the stack.
2229-222B
Jump if the character at the location of the input buffer pointer in register A is an end of the input character.
222C
PUSH DE
Save the variable’s address in DE to the stack.
222D-222F
Call the DOS link at 41DCH.
In NEWDOS 2.1, this is called during READ processing when a variable has been read.
2230
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
  • and Double Precision is NZ/NC/P/E and A is 5.
2231
PUSH AF
Save the number type of the variable to the stack.
2232-2233
If that test shows we do NOT have a STRING, jump to 224DH.
2234
RST 10H
We need the next character in the BASIC program so 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.
2235
LD D,A
Load register D with the character at the location of the input buffer pointer in register A.
2236
LD B,A
Load register B with the character at the location of the input buffer pointer in register A.
2237-2238
CP 22H
Check to see if the character at the location of the input buffer pointer in register A is a quote.
  • NOTE: A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.)
2230-223A
Jump to 2240H if the character at the location of the input buffer pointer in register A is a quote.
223B-223C
LD D,3AH
Load D with the character :.
223D-223E
LD B,2CH
Load register B with the character , (the scan character).
223F
DEC HL
Decrement the value of the input buffer pointer in HL.
2240-2242
Go set up the pointers for the temporary string work area.
2243
POP AF
Get the number type for the variable from the stack and put it in register A.
2244
EX DE,HL
Load DE with the value of the input buffer pointer in HL.
2245-2247
LD HL,225AH
Load HL with the value of the return address.
2248
EX (SP),HL
Exchange the value of the return address in HL with the value of the current BASIC program pointer to the stack.
2249
PUSH DE
Save the value of the input buffer pointer in DE to the stack.
224A-224C
Go set the variable to the value of the string.

224D
RST 10H
We need the next character in the BASIC program so 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.
224E
POP AF
Load register A with the number type for the variable to be set.
224F
PUSH AF
Save the value in AF to the stack.

2250-2252
LD BC,2243H
Load BC with the value of the return address.
2253
PUSH BC
Save the return address in BC to the stack.
2254-2256
If the current number type is integer or single precision, call the ASCII TO BINARY routine at 0E6C (which converts the ASCII string pointed to by HL to binary with the result in REG 1 and the mode flag will have changed).
2257-2259
If the current number type is double precision, jump to the ASCII TO DOUBLE routine at 0E65H.
  • NOTE: 0E65H converts the ASCII string pointed to by HL to its double precision equivalent; with output left in REG 1).
225A
DEC HL
Decrement the value of the input buffer pointer in HL.
225B
RST 10H
We need the next character in the BASIC program so 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.
225C-225D
Jump to 2263H if the character at the location of the input buffer pointer in HL is an end of the input character.
225E-225F
CP 2CH
Check to see if the character at the location of the input buffer pointer in register A is a comma.
  • NOTE: A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.)
2260-2262
Jump to 217FH if the character at the location of the input buffer pointer in register A isn’t a comma.
2263
EX (SP),HL
Exchange the value of the input buffer pointer in HL with the value of the current BASIC program pointer to the stack.
2264
DEC HL
Decrement the value of the current BASIC program pointer in HL.
2265
RST 10H
We need the next character in the BASIC program so 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.
2266-2268
Go examine the next variable if the character at the location of the current BASIC program pointer in HL isn’t an end of the BASIC statement character.
2269
POP DE
Clean up the stack.


226A-226E – For ROM v1.2 – Replaced with NOPS

226F-2271
LD A,(40DEH)
Load register A with the value of the input type flag.
Note: 40DEH holds READ flag.
2272
OR A
Check to see if the input type is READ or INPUT.
2273
EX DE,HL
Load DE with the value of the current BASIC program pointer in HL.
2274-2276
Jump if the input type flag is set for READ .
2277
PUSH DE
Save the current BASIC program pointer in DE to the stack.
2278-227A
Call the DOS link at 41DFH.
In NEWDOS 2.1 this is called at the end of READ processing.
227B
OR (HL)
Check to see if this is the end of the input.
227C-227E
LD HL,2286H
Load HL with the starting address of the ?EXTRA IGNORED message.
227F-2281
We need to display the ?EXTRA IGNORED 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).
2282
POP HL
Get the value of the current BASIC program pointer from the stack and put it in HL.
2283-2285
Go turn off the cassette recorder and return to the BASIC interpreter.


2286-2295 – MESSAGE STORAGE LOCATION

2286-2295
“?Extra ignored”
The EXTRA IGNORED message is stored here.


2296-22B5 – FIND THE NEXT DATA STATEMENT ROUTINE

2296-2298
Go find the next DATA statement.
2299
OR A
Check to see if this is the end of the BASIC line.
229A-229B
Jump to 22AEH if the BASIC statement is terminated with a :.
229C
INC HL
Bump the value of the current BASIC program pointer in HL.
229D
LD A,(HL)
Load register A with the LSB of the line address at the location of the current BASIC program pointer in HL.
229E
INC HL
Bump the value of the current BASIC program pointer in HL.
229F
OR (HL)
Combine the MSB of the line address at the location of the current BASIC program in HL with the LSB of the line address in register A.
22A0-22A1
LD E,06H
Load register E with an ?OD ERROR code.
22A2-22A4
Go to the Level II BASIC error routine and display an OD ERROR message if this is the end of the BASIC program.
22A5
INC HL
Bump the value of the current BASIC program pointer in HL.
22A6
LD E,(HL)
Load register E with the LSB of the BASIC line number at the location of the current BASIC program pointer in HL.
22A7
INC HL
Bump the value of the current BASIC program pointer in HL.
22A8
LD D,(HL)
Load register D with the MSB of the BASIC line number at the location of the current BASIC program pointer in HL.
22A9
EX DE,HL
Exchange the value of the current BASIC program pointer in HL with the value of the BASIC line number in DE.
22AA-22AC
LD (40DAH),HL
Save the BASIC line number in HL.
Note: 40DAH-40DBH holds DATA line number.
22AD
EX DE,HL
Exchange the value of the current BASIC program pointer in DE with the value of the BASIC line number in HL.
22AE
RST 10H
We need the next character in the BASIC program so 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.
22AF-22B0
CP 88H
Check to see if the character at the location of the current BASIC program pointer in register A is a DATA token.
  • NOTE: A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.)
22B1-22B2
Jump to 2296H (=find the next DATA statement routine) if the character at the location of the current BASIC program pointer in register A isn’t a DATA token.
22B3-22B5
Now we know that the current BASIC program pointer is pointing to a DATA token, so jump to 222DH.


22B6-2336 – LEVEL II BASIC NEXT ROUTINE

22B6-22B8
LD DE,0000H
Load DE with the default variable address.
22B9-22BB
To see if there is a variable which follows the NEXT token, 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).
22BC-22BE
LD (40DFH),HL
Save the value of the current BASIC program pointer (contained in 40DFH) in HL.
Note: 40DFH-40E0H holds Used by DOS.
22BF-22C1
Go search the stack for the appropriate FOR push.
22C2-22C4
Display a NF ERROR message if the appropriate FOR push wasn’t found.
22C5
LD SP,HL
Load the stack pointer with the value of the memory pointer in HL.
22C6-22C8
LD (40E8H),HL
Save the value in HL.
Note: 40E8H-40E9H holds Stack pointer pointer.
22C9
PUSH DE
Save the variable’s address in DE to the stack.
22CA
LD A,(HL)
Load register A with the value of the sign for the STEP value.
22CB
INC HL
Bump the value of the memory pointer in HL.
22CC
PUSH AF
Save the value of the sign for the STEP value in register A to the stack.
22CD
PUSH DE
Save the variable’s address in DE to the stack.
22CE
LD A,(HL)
Load register A with the number type flag for the STEP value.
22CF
INC HL
Bump the value of the memory pointer in HL.
22D0
OR A
Check the value of the number type flag for the STEP flag in register A.
22D1-22D3
Jump to 22EAH if the STEP value is an integer.
22D4-22D6
Call 09B1H (which moves a SINGLE PRECISION number pointed to by HL to REG 1).
22D7
EX (SP),HL
Exchange the value of the variable’s address to the stack with the value of the memory pointer in HL.
22D8
PUSH HL
Save the value of the variable’s address in HL to the stack.
22D9-22DB
Go add the sin le precision value at the location of the memory pomter in HL to the single precision STEP value in register pairs BC and DE. Return with the result in REG 1.
22DC
POP HL
Get the value of the variable’s address from the stack and put it in HL.
22DD-22DF
Go move the single precision result from REG 1 to the variable’s address in HL.
22E0
POP HL
Get the value of the memory pointer from the stack and put it in HL.
22E1-22E3
Call 09C2H (which loads a SINGLE PRECISION value pointed to by HL into register pairs BC and DE).
22E4
PUSH HL
Save the value of the memory pointer in HL to the stack.
22E5-22E7
Call the SINGLE PRECISION COMPARISON routine at 0A0CH.

NOTE: The routine at 0A0CH algebraically compares the single precision value in BC/DE to the single precision value REG 1.
The results are stored in A as follows:
  • A=0 if REG 1 = BCDE
  • A=1 if REG 1>BCDE; and
  • A=FFH if REG 1<BCDE.
22E8-22E9
Jump forward to to 2313H.
22EA
INC HL
We need to backspace the stack by 4 bytes to skip over the area which would hold the single precision TO value to do this we have to bump the value of the memory pointer in HL 4 times.
22EB
INC HL
Bump the value of the memory pointer in HL.
22EC
INC HL
Bump the value of the memory pointer in HL.
22ED
INC HL
Bump the value of the memory pointer in HL.
22EE
LD C,(HL)
Load register C with the LSB of the STEP value (held at the location of the memory pointer in HL).
22EF
INC HL
Bump the value of the memory pointer in HL to be the MSB of the STEP value.
22F0
LD B,(HL)
Load register B with the MSB of the STEP value at the location of the memory pointer in HL.
22F1
INC HL
Bump the value of the memory pointer in HL so that it is the stack address of the TO limit.
22F2
EX (SP),HL
Exchange HL and the value of the stack pointer so that HL will have the address of the index and the value at the stack pointer will have the ending address of the TO limit.
22F3
LD E,(HL)
Load register E with the LSB of the index.
22F4
INC HL
Bump the value of the memory pointer in HL to point to the MSB of the index.
22F5
LD D,(HL)
Load register D with the MSB of the index.
22F6
PUSH HL
Save the value of the memory pointer in HL to the stack.
22F7
LD L,C
Load register L with the LSB of the STEP value in register C.
22F8
LD H,B
Load register H with the MSB of the STEP value in register B.
22F9-22FB
With the STEP value in HL, call the INTEGER ADD routine at 0BD2H (which adds the integer value in DE to the integer in HL. The sum is left in HL and the orginal contents of DE are preserved. If overflow occurs (sum exceeds 2**15), both values are converted to single precision and then added. The result would be left in REG 1 and the mode flag would be updated).
22FC-22FE
LD A,(40AFH)
Load register A with the current value of the data type flag.
Note: 40AFH holds Current number type flag.
22FF
CP 04H
Check to see if the current value in REG 1 is single precision.
  • NOTE: A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.)
2301-2303
Show an ?OV ERROR message if the current value in REG 1 is single precision.
2304
EX DE,HL
Load DE with the index as an integer (from HL).
2305
POP HL
Restore the address of the index in the variable area to HL.
2306
LD (HL),D
Save the MSB of the result in register D at the location of the memory pointer in HL.
2307
DEC HL
Decrement the value of the memory pointer in reg� ister pair HL.
2308
LD (HL),E
Save the LSB of the result in register E at the location of the memory pointer in HL.
2309
POP HL
Restore the address of the TO value in the FOR statement to HL.
230A
PUSH DE
Save the index in DE to the stack.
230B
LD E,(HL)
Load register E with the LSB of the TO value at the location of the memory pointer in HL.
230C
INC HL
Bump the value of the memory pointer in HL to point to the MSB of the TO value.
230D
LD D,(HL)
Load register D with the MSB of the TO value at the location of the memory pointer in HL.
230E
INC HL
Bump the value of the memory pointer in HL so now it points to the line number.
230F
EX (SP),HL
Swap the TO value at the memory location pointed to by the stack with the address of the binary line number for the FOR statement (now in HL).
2310-2312
We need to compare the new index to the limit so we call the INTEGER COMPARISON routine at 0A39H (which algebraically compares two integer values in DE and HL. The contents of DE and HL are left intact. The result of the comparison is left in the A register and status register as:
If DE > HL then A will be -1;
If DE < HL then A will b +1; and
If DE = HL then A will be 0.

2313
POP HL
Restore the address of the binary line number of the FOR statement back into HL.
2314
POP BC
Get the value of the sign from the stack and put it in BC.
2315
SUB B
We need to see if the sign is the sign we expected so we subtract the value of the sign in register B from the value in register A.
2316-2318
Call 09C2H (which loads a SINGLE PRECISION value pointed to by HL into register pairs BC and DE).
2319-231A
Jump to 2324H if the index does not equal the TO limit (meaning the FOR … NEXT loop has not been completed).
231B
EX DE,HL
Load HL with the BASIC line number of the FOR statement in DE.
231C-231E
LD (40A2H),HL
Save the BASIC line number in HL as the current BASIC line number.
  • Note: 40A2H-40A3H holds the current BASIC line number.
231F
LD L,C
Load register L with the LSB of the current BASIC program pointer in register C.
2320
LD H,B
Load register H with the MSB of the current BASIC program pointer in register B.
2321-2323
Jump to 1D1AH to continue execution and restore the FOR token and GAP for FOR
2324
LD SP,HL
Restore the stack pointer – Start of expression evaluation
2325-2327
LD (40E8H),HL
Load HL with the value of the current BASIC program pointer.
Note: 40E8H-40E9H holds Stack pointer pointer.
2328-232A
LD HL,(40DFH)
Save the value of the current BASIC program pointer in HL.
Note: 40DFH-40E0H holds Used by DOS.
232B
LD A,(HL)
Load register A with the next token (i.e., the character at the location of the current BASIC program pointer in HL).
232C-232D
CP 2CH
Check to see if the character at the location of the current BASIC program pointer in register A is a ,.
  • NOTE: A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.)
232E-2330
Jump back to 1D1EH if the character at the location of the current BASIC program pointer in register A isn’t a ,.
2331
RST 10H
We need the next character in the BASIC program so 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.
2332-2334
GOSUB to 22B9H to process NEXT.
2335
RST 08H
28
Since the character at the location of the current BASIC program pointer in HL must be a (, call the COMPARE SYMBOL routine at RST 08H.

NOTE: The RST 08H routine compares 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 the next execution address (i.e, the RST 08H instruction + 2) with the next symbol in the A Register 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).


2337-27C8 – EVALUATE EXPRESSION

  • This routine evaluates a BASIC expression pointed to by the HL and stores the result in the ACC. The expression must be terminated with zero byte, comma, right bracket or colon. After execution, HL will point to the delimiter and, in the case of string expressions, the ACC will contain the address of the first of three bytes that contain string length and string address. Note that the stack is used frequently and the machine should be formatted for RUN mode in order to use this routine.
2337
DEC HL
Decrement the value of the current BASIC program pointer in HL.
2338-2339
LD D,00H
Load register D with zero.
233A
PUSH DE
Save the value in DE to the stack.
233B-233C
LD C,01H
Load register C with the number of bytes of memory required.
233D-233F
Go do a memory check.
2340-2342
Go get the value of the next part of the expression at the location of the current BASIC program pointer in HL.
2343-2345
LD (40F3H),HL
Save the value of the current BASIC program pointer (i.e., the next token) in HL.
Note: 40F3H-40F4H holds temporary storage location.
2346-2348
LD HL,(40F3H)
Load HL with the value of the current BASIC program pointer.
Note: 40F3H-40F4H holds temporary storage location.
2349
POP BC
Get the last precedence value from the stack and put it in BC.
234A
LD A,(HL)
Load register A with the character at the location of the current BASIC program pointer in HL.
234B-234C
LD D,00H
Load register D with zero.
234D-234E
SUB D4H
Check to see if the character at the location of the current BASIC program pointer in register A is an arithmetic or logical token (by subtracting 212 from it).

234F-2350
Jump to 2364H if the character at the location of the current BASIC program pointer in register A is +, , *, /, ?, AND or OR.
2351-2352
CP 03H
Check to see if the character at the location of the current BASIC program pointer in register A is a >, =, or <.
  • NOTE: A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.)

2353-2354
Jump if the character at the location of the current BASIC program pointer in register A isn’t a >, =, or <.
2355-2356
CP 01H
Set the Carry flag if >. Then test for <= or >=.
2357
RLA
Adjust the value in register A to give > as 1, = as 2, or < as 4.
2358
XOR D
Combine the current value in register A with the value of the last token examined to see if this is a legal combination of <= or => or illegal combination of <<, ==, or >>.
2359
CP D
Check for an illegal combination of operators.
235A
LD D,A
Load register D with the value in register A.
235B-235D
Display a ?SN ERROR if this is an illegal combination of operators.
235E-2360
LD (40D8H),HL
Save the address of the >, =, or < token (held in HL) to 40D8H.
Note: 40D8H-40D9H holds Temporary storage location.
2361
RST 10H
We need the next token so 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.
2362-2363
Jump back to 234DH.
2364
LD A,D
Load register A with the value of the operator in register D.
2365
OR A
Test the value of the operator in register A.
2366-2368
Jump if the operator in register A is >, =, or <.
2369
LD A,(HL)
Load register A with the character at the location of the current BASIC program pointer in HL.
236A-236C
LD (40D8H),HL
Save the address of the current BASIC program pointer in HL (which is an arithmetic operator) to 40D8H.
Note: 40D8H-40D9H holds Temporary storage location.
236D-236E
SUB 0CDH
Check to see if the operator at the location of the current BASIC program pointer in register A is an arithmetic token.
236F
RET C
Return if the character at the location of the current BASIC program pointer in register A isn’t an arithmetic token.

2370-2371
CP 07H
Check to see if the character at the location of the current BASIC program pointer in register A is a + to OR token.
2372
RET NC
Return if the character at the location of the current BASIC program pointer in register A isn’t a + to OR token.

2373
LD E,A
Load register E with the operator value in register A (which would be between 0 and 7).
E   Token
0   +
1   
2   *
3   /
4   @@
5   AND
6   OR
2374-2376
LD A,(40AFH)
Load register A with the current value of the number type flag.
Note: 40AFH holds Current number type flag.


2377 – PRINT @ logic.

2377-2378
SUB 03H
Adjust the value of the number type flag to get a -1 if integer, 0 for a string, 1 for single precision, and 5 for double precision.
2379
OR E
Combine the operator value in register E with the adjusted number type flag in register A.
237A-237C
Jump down to 298FH if the combination of the adjusted number type flag in register A and the operator value in register E indicates string addition.
237D-237F
LD HL,189AH
Load HL with the starting address of the table of precedence operator values.
2380
ADD HL,DE
Add the value of the operator in DE to the table of precedence values pointer in HL.
2381
LD A,B
Load register A with the precedence value for the last operator in register B.
2382
LD D,(HL)
Load register D with the precedence value for the current operator.
2383
CP D
Compare the precedence value for the current operator in register D with the precedence value for the last operator in register A.
2384
RET NC
Return out of this routine if the precedence value for the current operator in register D is greater than the precedence value for the last operator in register A.

2385
PUSH BC
Save the precedence value and the token for the last operator in BC to the stack.

2386-2388
LD BC,2346H
Load BC with the return address in case there is a break in precedence.
2389
PUSH BC
Save the return address in BC to the stack.
238A
LD A,D
Load register A with the precedence value for the current operator in register D.
238B-238C
CP 7FH
Check to see if the precedence value for the current operator in register A indicates an exponential operator.
238D-238F
Jump down to 23D4H if the precedence value for the current operator in register A indicates an exponential operator.
2390-2391
CP 51H
Check to see if the precedence value for the current operator in register A indicates a logical operator.

2392-2394
Jump if the precedence value for the current operator in register A indicates a logical operator.
2395-2397
LD HL,4121H
Load HL with the address of REG 1.
2398
OR A
Clear the flags.
2399-239B
LD A,(40AFH)
Load register A with the current value of the number type flag.
Note: 40AFH holds Current number type flag.
239C
DEC A
Adjust the current number type flag in register A.
239D
DEC A
Adjust the current number type flag in register A.
239E
DEC A
Adjust the current number type flag in register A. Now A will be -1=Integer, 0=String, 1=Single Precision, 5=Double Precision
239F-23A1
Display a ?TM ERROR if the current value in REG 1 is a string.
23A2
LD C,(HL)
Get the value at the location of the memory pointer in HL and put it in register C.
23A3
INC HL
Bump the value of the memory pointer in HL.
23A4
LD B,(HL)
Load register B with the value at the location of the memory pointer in HL.
23A5
PUSH BC
Save the value in BC to the stack.
23A6-23A8
Jump down to 23C5H if the current number type is an integer.
23A9
INC HL
It’s not an integer, so lets get the rest of the value by bumping the value of the memory pointer in HL.
23AA
LD C,(HL)
Load register C with the value at the location of the memory pointer in HL.
23AB
INC HL
Bump the value of the memory pointer in HL.
23AC
LD B,(HL)
Load register B with the value at the location of the memory pointer in HL.
23AD
PUSH BC
Save the value in BC (the rest of the digit) to the stack.
23AE
PUSH AF
Save the value in AF (the type – 3) to the stack.
23AF
OR A
Reset the status flags so that we can test if the current number type is double precision.
23B0-23B2
Jump down to 23C4H if the current number type is single precision.
23B3
POP AF
Clear the stack.
23B4
INC HL
Bump the value of the memory pointer in HL.

23B5-23B6
Skip the next instruction if the current number type is single precision.
23B7-23B9
LD HL,411DH
Reset HL to start of REG 1.
Note: 411DH-4124H holds REG l.
23BA
LD C,(HL)
Load register C with the rest of the double precision value (held at the location of the memory pointer in HL).
23BB
INC HL
Bump the value of the memory pointer in HL.
23BC
LD B,(HL)
Load register B with the next digit LSB (at the location of the memory pointer in HL).
23BD
INC HL
Bump the value of the memory pointer in HL to the next digit.
23BE
PUSH BC
Save the LSB/NMSB of the double precision value (held in BC) to the stack.
23BF
LD C,(HL)
Load register C with the value at the location of the memory pointer in HL.
23C0
INC HL
Bump the value of the memory pointer in HL.
23C1
LD B,(HL)
Load register B with the value at the location of the memory pointer in HL.
23C2
PUSH BC
Save the value in BC to the stack.
23C3
LD B,0F1H
06 F1
Z-80 Trick to nullify the next opcode if passing through.
23C4
POP AF
Clear the type -3 and the status push.

23C5-23C6
ADD A,03H
Adjust the number type in register A up 3.
23C7
LD C,E
Load register C with the value of the current operator token in register E (0-7).
23C8
LD B,A
Load register B with the number type flag in register A.
23C9
PUSH BC
Save the value in BC to the stack.

23CA-23CC
LD BC,2406H
Load BC with the return address of 2406H.
23CD
PUSH BC
Save the return address in BC to the stack.
23CE-23D0
LD HL,(40D8H)
Load HL with the value of the current BASIC program pointer.
Note: 40D8H-40D9H holds Temporary storage location.
23D1-23D3
Jump back to 233AH.
23D4-23D6
Call the CONVERT TO SINGLE PRECISION routine at 0AB1H (which converts the contents of REG 1 from integer or double precision into single precision).
23D7-23D9
Call 09A4 which moves the SINGLE PRECISION value in REG 1 to the stack (stored in LSB/MSB/Exponent order).
23DA-23DC
LD BC,13F2H
Load BC with the address of the exponential X^Y routine at 13F2H.
23DD-23DE
LD D,7FH
Load register D with the precedence value for an exponential operator.
23DF-23E0
Jump back to 23CDH to continue expression evaluation.
23E1
PUSH DE
Save the precedence value and the operator token in DE to the stack.
23E2-23E4
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).
23E5
POP DE
Get the precedence value and the operator token from the stack and put it in DE.
23E6
PUSH HL
Save the integer value in HL to the stack.

23E7-23E9
LD BC,25E9H
Load BC with a return address of 25E9H.
23EA-23EB
Jump back to 23CDH to continue the syntax analysis.
23EC
LD A,B
Load register A with the precedence value for the last operator in register B.
23ED-23EE
CP 64H
Check to see if the last operator was a logical operator.
23EF
RET NC
Return out of this routine if the last operator was a logical operator.

23F0
PUSH BC
Save the precedence value and the operator token for the last operator in BC to the stack.
23F1
PUSH DE
Save the precedence value and the token for the current operator from DE (either a 6, 5, or 3) to the stack.
23F2-23F4
LD DE,6404H
Load DE with the precedence value and the token for the new operator.
23F5-23F7
LD HL,25B8H
Load HL with the address of the routine to compare logical quantities …
23F8
PUSH HL
and push it to the stack.
23F9
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
  • and Double Precision is NZ/NC/P/E and A is 5.
23FA-23FC
If that test shows we do NOT have a STRING, jump back to 2395H.
23FD-23FF
LD HL,(4121H)
Load HL with the string address held at the memory location pointed to by REG 1.
2400
PUSH HL
Save the string’s address in HL to the stack.

2401-2303
LD BC,258CH
Load BC with the address of the string comparison routine.
2404-2405
Jump back to 23CDH.
2406
POP BC
Get the precedence value and the token for the last operator from the stack and put it in BC.
2407
LD A,C
Load register A with the operator token in register C.
2408-240A
LD (40B0H),A
Save the operator token in register A.
Note: 40B0H holds Temporary storage location.
240B
LD A,B
Load register A with the precedence value in register B.
240C-240D
CP 08H
Check the number type for the precedence value in register A.
240E-240F
Jump forward to 2438H if the number type in register A (the first operand) is double prec1sion.
2410-2412
LD A,(40AFH)
Load register A with the number type for the current result in REG 1.
Note: 40AFH holds Current number type flag.
2413-2414
CP 08H
Check to see if the current result in REG 1 is double precision.
2415-2417
Jump forward to 2460H if the current value in REG 1 is double precision.
2418
LD D,A
Load register D with the current data type flag in register A.
2419
LD A,B
Load register A with the precedence value for the last operator in register B.
241A-241B
CP 04H
Check to see if the number type for the precedence value in register A is single precision.
241C-241E
Jump forward to 2472H if the number type for the precedence value in register A is single precision.
241F
LD A,D
Load register A with the number type flag for the value in REG 1.
2420-2421
CP 03H
Check to see if the current value in REG 1 is a string.
2422-2424
Display a ?TM ERROR message if the current value in REG 1 is a string.

2325-2427
Jump forward to 247CH if the current value in REG 1 is single precision.
2428-242A
LD HL,18BFH
Load HL with the starting address of the arithmetic jump table.
242B-242C
LD B,00H
Load register B with zero.
242D
ADD HL,BC
Add the operator’s token in BC to the value of the arithmetic jump table pointer in HL.
242E
ADD HL,BC
Add the operator’s token in BC to the value of the arithmetic jump table pointer in HL.
242F
LD C,(HL)
Load register C with the LSB of the jump address at the location of the arithmetic jump table pointer in HL.
2430
INC HL
Bump the value of the arithmetic jump table pointer in HL.
2431
LD B,(HL)
Load register B with the MSB of the jump address at the location of the arithmetic jump table pointer in HL.
2432
POP DE
Get the value for the previous result from the stack and put it in DE.
2433-2435
LD HL,(4121H)
Get the value for the current result from REG 1 and put it in HL.
2436
PUSH BC
Save the arithmetic routine’s jump address in regis� ter pair BC to the stack.
2437
RET
Return.

2438-243A
Call the CONVERT TO DOUBLE PRECISION routine at 0ADBH (where the contents of REG 1 are converted from integer or single precision to double precision).
243B-243D
Go convert the current result in REG 1 to single precision.
243E
POP HL
Get the value from the stack and put it in HL.
243F-244l
LD (411FH),HL
Save the value in HL near the end of REG 1.
2442
POP HL
Get the value from the stack and put it in HL.
2443-2445
LD (411DH),HL
Save the value in HL in REG 1.
Note: 411DH-4124H holds REG l.
2446
POP BC
Get the value from the stack and put it in BC.
2447
POP DE
Get the value from the stack and put it in DE.
2448-244A
Call 09B4H (which moves the SINGLE PRECISION value in DC/DE into REG 1). This moves DE to (4121H) and BC to (4123H).

244B-244D
Convert the first value to double precision by calling the CONVERT TO DOUBLE PRECISION routine at 0ADBH (where the contents of REG 1 are converted from integer or single precision to double precision).
244E-2450
LD HL,18ABH
Load HL with the double precision arithmetic jump table’s starting address.
2451-2453
LD A,(40B0H)
Load register A with the operator token in register A.
Note: 40B0H holds Temporary storage location.
2454
RLCA
Multiply the value of the operator token in register A by two.
2455
PUSH BC
Save the value in BC to the stack so we can use it for 16 bit arithmetic.
2456
LD C,A
Load register C with the adjusted value of the operator token in register A (i.e., 2 x token).
2457-2458
LD B,00H
Load register B with zero.
2459
Add the value of the adjusted operator token in BC (which is token value * 2) to 18ABH (which is the double precision arithmetic jump table’s starting address) in HL.
245A
POP BC
Restore BC from the stack and put it in BC.
245B
LD A,(HL)
Load register A with the LSB of the jump address at the location of the arithmetic jump table pointer in HL.
245C
INC HL
Bump the value of the arithmetic jump table pointer in HL.
245D
LD H,(HL)
Load register H with the MSB of the jump address at the location of the arithmetic jump table pointer in HL.
245E
LD L,A
Load register L with the LSB of the jump address in register A.
245F
JP (HL)
Jump to the arithmetic routine whose address is in HL.
2460
PUSH BC
Save the precedence value and the operator token in BC to the stack.
2461-2463
Move the current result to the a storage area.
2464
POP AF
Load register A with the value of the current number type flag.
2465-2467
LD (40AFH),A
Save the value of the current number type flag in register A.
Note: 40AFH holds Current number type flag.
2468-2469
CP 04H
Check to see if the current result in REG 1 is single precision.
246A-246B
Jump back to 2446H if the current result in REG 1 is single precision.
246C
POP HL
Get the integer value from the stack and put it in HL.
246D-246F
LD (4121H),HL
Save the integer value in HL in REG 1.
2470-2471
Jump back to 244BH.
2472-2474
Call the CONVERT TO SINGLE PRECISION routine at 0AB1H (which converts the contents of REG 1 from integer or double precision into single precision).
2475
POP BC
Get the value from the stack and put it in BC.
2476
POP DE
Get the value from the stack and put it in DE.
2477-2479
LD HL,18B5H
Load HL with the starting address of the single precision arithmetic jump table.
247A-247B
Jump back to 2451H to perform the operation.
247C
POP HL
Get the integer value from the stack and put it in HL.
247D-247F
Call 09A4 which moves the SINGLE PRECISION value in REG 1 to the stack (stored in LSB/MSB/Exponent order).
2480-2482
Go convert the integer value in HL to single precision.
2483-2485
Call 09BF which loads the SINGLE PRECISION value in REG 1 into BC/DE.
2486
POP HL
Get the LSB/NMSB from the stack and put it in HL.
2487-2489
LD (4123H),HL
Save the value in HL in REG 1
248A
POP HL
Get the MSB and exponent from the stack and put it in HL.
248B-248D
LD (4121H),HL
Save the value in HL in REG 1.
248E-248F
Jump back to 2477H to perform the operation.


2490 – Integer divide

  • (ACC=DE / HL) Result will be in single-precision (NTF=4) and will be in the ACC.
    Divides DE by HL. Both values are converted to single precision before the division is started. The quotient is left in REG l; the mode flag is updated. The orginal contents of the DE and HL register sets are lost.
  • Note: To use a ROM call to divide two integers store the dividend in the DE register pair, and store the divisor in HL and then CALL 2490H. The result is stored in single precision format (since it is not likely to be an integer) in 4121H-4124Hin approximately 5.1 milliseconds.
2490H
“IDIV”
Save the integer value in HL to the stack.
2491
EX DE,HL
We need to convert DE to SP so first do this swap to set up the variables for the call which follows.
2492-2494
Go convert the integer value in HL to single precision and return with the result in REG 1.
2495
POP HL
Get the integer value from the stack and put it in HL.
2496-2498
Call 09A4 which moves the SINGLE PRECISION value in REG 1 to the stack (stored in LSB/MSB/Exponent order).
2499-249B
Go convert the integer value in HL to single precision and return with the result in REG 1.
249C-249E
Go do a single precision divide.
249F
RST 10H
We need the next character in the BASIC program so 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.
24A0-24A1
LD E,28H
Load register E with a ?MO ERROR code.
24A2-24A4
Display a ?MO ERROR if we are at the end of the string.
24A5-24A7
If the character at the location of the current BASIC program pointer in HL is numeric, call the ASCII TO BINARY routine at 0E6C (which converts the ASCII string pointed to by HL to binary with the result in REG 1 and the mode flag will have changed).
24A8-24AA
Check to see if the character at the location of the current BASIC program pointer in HL is alphabetic.

24AB-24AD
Jump if the character at the location of the current BASIC program pointer in HL is alphabetic.
24AE-24AF
CP 0CDH
Check to see if the character at the location of the current BASIC program pointer in register A is a + token.

Notes:

  • CDH is a + in ASCII
  • A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.
24B0-24B1
Jump if the character at the location of the current BASIC program pointer in register A is a + token.
24B2-24B3
CP 2EH
Check to see if the character at the location of the current BASIC program pointer in register A is a decimal point.

Notes:

  • 2EH is a . in ASCII
  • A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.
24B4-24B6
If the character at the location of the current BASIC program pointer in HL is a decimal point, call the ASCII TO BINARY routine at 0E6C (which converts the ASCII string pointed to by HL to binary with the result in REG 1 and the mode flag will have changed).
24B7-24B8
CP 0CEH
Check to see if the character at the location of the current BASIC program pointer in register A is a token.

Notes:

  • CEH is a in ASCII
  • A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.
24B9-24BB
Jump to 2532H if the character at the location of the current BASIC program pointer in register A is a token.
24BC-24BD
CP 22H
Check to see if the character at the location of the current BASIC program pointer in register A is a .

Notes:

  • 22H is a in ASCII
  • A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.
24BE-24C0
Jump to 2866H if the character at the location of the current BASIC program pointer in register A is a .
24C1-24C2
CP 0CBH
Check to see if the character at the location of the current BASIC program pointer in register A is a NOT token.

Notes:

  • CBH is a NOT token.
  • A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.
24C3-24C5
Jump to 25C4H if the character at the location of the current BASIC program pointer in register A is a NOT token.
24C6-24C7
CP 26H
Check to see if the character at the location of the current BASIC program pointer in register A is a &.

Notes:

  • 26H is a & in ASCII
  • A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.
24C8-24CA
Jump to 4194H (which is DOS) if the character at the location of the current BASIC program pointer in register A is a &.
24CB-24CC
CP 0C3H
Check to see if the character at the location of the current BASIC program pointer in register A is an ERR token.

Notes:

  • C3H is a ERR token.
  • A CP will return Z if there is a match against Register A, and NZ if not a match against Register A.
24CD-24CE
Jump to 24D9H if the character at the location of the current BASIC program pointer in register A isn’t an ERR token.
24CF
RST 10H
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.
24D0-24D2
LD A,(409AH)
Load register A with the value of the current error number.
Note: 409AH holds the RESUME flag.
24D3
PUSH HL
Save the value of the current BASIC program pointer in HL to the stack.
24D4-24D6
Go save the value of the current error number in register A (as an integer) as the current result in REG l.
24D7
POP HL
Get the value of the current BASIC program pointer from the stack and put it in HL.
24D8
RET
Return.

24D9-24DA
CP C2H
Check to see if the character at the location of the current BASIC program pointer in register A is a ERL token.
24DB-24DC
Jump to 24E7H if the character at the location of the current BASIC program pointer in register A isn’t an ERL token.
24DD
RST 10H
We need the next character in the BASIC program so 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.
24DE
PUSH HL
Save the value of the current BASIC program pointer in HL to the stack.
24DF-24El
LD HL,(40EAH)
Load HL with the current error line number.
Note: 40EAH-40EBH holds the line number with error.
24E2-24E3
Go save the error line number in HL as the current result in REG 1.
24E5
POP HL
Get the value of the current BASIC program pointer from the stack and put it in HL.
24E6
RET
Return.


24E7-24FEVARPTR logic.

24E7-24E8
CP 0C0H
Check to see if the character at the location of the current BASIC program pointer in register A is a VARPTR token.
24E9-24EA
Jump back to 24FFH if the character at the location of the current BASIC program pointer in register A isn’t a VARPTR token.
24EB
RST 10H
We need the next character in the BASIC program so 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.
24EC-24ED
RST 08H
28
Since the character at the location of the current BASIC program pointer in HL must be a (, call the COMPARE SYMBOL routine at RST 08H.

NOTE: The RST 08H routine compares 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 the next execution address (i.e, the RST 08H instruction + 2) with the next symbol in the A Register 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).
24EE-24F0
Jump to 24BCH to evaluate the variable name at the location of the current BASIC program pointer in HL.
24Fl-24F2
RST 08H
29
Since the character at the location of the current BASIC program pointer in HL must be a ), call the COMPARE SYMBOL routine which compares 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 A register 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).
24F3
PUSH HL
Save the value of the current BASIC program pointer in HL to the stack.
24F4
EX DE,HL
Load HL with the variable’s address in DE.
24F5
LD A,H
Load register A with MSB of the variable’s address in register H.
24F6
OR L
Combine the LSB of the variable’s address in register L with the MSB of the variable’s address in register A. This type of pattern is used to check for something being zero.
24F7-24F9
Display a ?FC ERROR if the variable’s address in HL is equal to zero, meaning that the variable is undefined.
24FA-24FC
Save the variable’s address in HL as the current result in REG l.
24FD
POP HL
Get the value of the current BASIC program pointer from the stack and put it in HL.
24FE
RET
Return to the execution driver.


24FF – Other Function Routine.

24FF-2500
CP 0C1H
Check to see if the character at the location of the current BASIC program pointer in register A is a USR token.
2501-2503
Jump to 27FEH if the character at the location of the current BASIC program pointer in register A is a USR token.
2504-2505
CP 0C5H
Check to see if the character at the location of the current BASIC program pointer in register A is a INSTR token
2506-2508
Jump to the DOS address of 419DH if the character at the location of the current BASIC program pointer in register A is an INSTR token.
2509-250A
CP 0C8H
Check to see if the character at the location of the current BASIC program pointer in register A is a MEM token.
250B-250D
If the character at the location of the current BASIC program pointer in register A is a MEM token, jump to the RETURN AMOUNT OF FREE MEMORY routine at 27C9H which computes the amount of memory remaining between the end of the variable list and the end of the stack and puts the result in REG 1 as a SINGLE PRECISION number.
250E-250F
CP 0C7H
Check to see if the character at the location of the current BASIC program pointer in register A is a TIME$ token.
2510-2512
Jump to the DOS address of 4176H if the character at the location of the current BASIC program pointer in register A is a TIME$ token.
2513-2514
CP 0C6H
Check to see if the character at the location of the current BASIC program pointer in register A is a POINT token.
2515-2517
Jump to 0132H if the character at the location of the current BASIC program pointer in register A is a POINT token.
2518-2519
CP 0C9H
Check to see if the character at the location of the current BASIC program pointer in register A is an INKEY$ token.
251A-251C
Jump to 019DH if the character at the location of the current BASIC program pointer in register A is an INKEY$ token.
251D-251E
CP 0C4H
Check to see if the character at the location of the current BASIC program pointer in register A is a STRING$ token.
241F-2421
Jump to 2A2FH if the character at the location of the current BASIC program pointer in register A is a STRING$ token.
2522-2523
CP 0BEH
Check to see if the character at the location of the current BASIC program pointer in register A is a FN token.
2524-2526
Jump to the DOS address of 4155H if the character at the location of the current BASIC program pointer in register A is a FN token.
2527-2528
SUB 0D7H
Check to see if the character at the location of the current BASIC program pointer in register A is a SGN to MID$ token.

2529-252B
Jump to 254EH if the character at the location of the current BASIC program pointer in register A is a SGN to MID$ token.
252C-252E
GOSUB to 2335H to evaluate the expression at the location of the current BASIC program pointer in HL.
252F-2530
RST 08H
29
Since the character at the location of the current BASIC program pointer in HL must be a ), call the COMPARE SYMBOL routine at RST 08H.

NOTE: The RST 08H routine compares 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 the next execution address (i.e, the RST 08H instruction + 2) with the next symbol in the A Register 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).
2531
RET
Return out of this routine.


2532 – Binary Minus Routine.

2532
LD D,7DH
Load register D with the precedence value.
2534-2536
GOSUB to 233AH to evaluate the variable at the location of the current BASIC program pointer in HL.
2537-2539
LD HL,(40F3H)
Load HL with the value of the current BASIC program pointer.
Note: 40F3H-40F4H holds Temporary storage location.
253A
PUSH HL
Save the value of the current BASIC program pointer in HL to the stack so we know where to continue.
253B-253D
Invert the sign of the current value in REG 1.
253E
POP HL
Restore the code string address from the stack and put it in HL. We need this because we return here after executing functions SNG( to MID$(.
253F
RET
Return to the expression evaluation.


2540 – This routine loads a variable to the ACC and sets the NTF. The HL must point to the ASCII variable name. After execution the HL will point to the character following the last character of the variable used. The value of the variable will be loaded in the ACC. For strings however (NTF=3), the ACC will contain the address of the first three bytes which contain the string length and string address (see Level II BASIC manual). Also note that if the variable cannot be found it will be created and given a value of zero.

2540-2542
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).
2543
PUSH HL
Save the value of the current BASIC program pointer in HL to the stack.
2544
EX DE,HL
Move the address of the variable to HL.
2545-2547
LD (4121H),HL
Save the variable’s address in HL in REG 1.
2548
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
  • and Double Precision is NZ/NC/P/E and A is 5.
2549-254B
If that test shows we do NOT have a STRING, call 09F7H to move data.
254C
POP HL
Get the address of the next symbol in the input string from the stack and put it in HL.
254D
RET
Return to the caller.


254E – This routine is for SNG( to MID$(.

254E-254F
LD B,00H
Load register B with zero.
2550
RLCA
Set A to be 2 * (token – D7H)
2551
LD C,A
Save the new token.
2552
PUSH BC
Save 0/2*(token-D7) on stack.
2553
RST 10H
Get the next character from the tokenized string by calling 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.
2554
LD A,C
Prepare to look for SGN( to CHR$( token.
2555
CP 41H
Test for the adjusted token.
2557
.Jump to 256FH if the token is SGN( to CHR$(. If not, it is a LEFT$MID$.
2559
Otherwise, GOSUB to 2335H to evaluate the expression part of the calling sequence (which requires 2 or parameters).
255C
RST 08H
2C
Use RST 08H to test for a ,.
255E
GOSUB to 0AF4H to ensure the current variable is a string, otherwise it is an error.
2561
EX DE,HL
Make sure the current variable is a string – DE is the current position in the program statement and HL is the address of the string.
2562
LD HL,(4121H)
Load HL with the string address held at the memory location pointed to by REG 1.
2565
EX (SP),HL
Put the string address to the stack.
2566
PUSH HL
Save the 00 / 2*(token-D7H) to the stack.
2567
EX DE,HL
Move the program statement position to HL.
2568
Evaluate n portion of the string function.
256B
EX DE,HL
Set DE to be the current position in the statement and set HL to be n.
256C
EX (SP),HL
Move n to stack. HL will be 2 * (token – D7H).
256D
Jump down to 2583H to process the token.
256F-2571
The below is a single variable parameter call. First, GOSUB to 252CH to evaluate the expression at the location of the current BASIC program pointer in HL.
2572
EX (SP),HL
Exchange the value of the current BASIC program pointer in HL with the operator value to the stack. HL will be 0 + 2 * (token – D7H).
2573
LD A,L
Load register A with the operator token in register L. A will be 2 * (token – D7H).
2574-2575
CP 0CH
Check to see if the operator token in register A is SGN to SQR.

2576-2577
Jump down to 257FH if the operator token in register A is SGN to SQR.
2578-2579
CP 1BH
Check the value of the adjusted operator token in register A.
257A
PUSH HL
Save the adjusted token (0 + 2*(token – D7H)) in HL to the stack.
257B-257D
If the operator token in register A is SQR to ATN, call the CONVERT TO SINGLE PRECISION routine at 0AB1H (which converts the contents of REG 1 [4121H] from integer or double precision into single precision).
257E
POP HL
Restore the adjusted token from the stack and put it in HL.
257F-2581
LD DE,253EH
Load DE with a return address of 253EH for once the function is executed.
2582
PUSH DE
Save the value of the return address in DE to the stack.
2583-2585
LD BC,1608H
Load BC with the SGN to MID$ jump table address.
2586
ADD HL,BC
Add the jump table pointer in BC with the value of the operator token in HL.
2587
LD C,(HL)
Load register C with the LSB of the jump address at the location of the jump table pointer in HL.
2588
INC HL
Bump the value of the jump table pointer in HL.
2589
LD H,(HL)
Load register H with the MSB of the jump address at the location of the jump table pointer in HL.
258A
LD L,C
Load register L with the LSB of the jump address in register C.
258B
JP (HL)
Jump to the calculated address (which is the SGNMID$ function) in HL.


258C – This routine will do a relational comparison of two strings.
It will load A with the length of the first string and BC with the string’s address. Then it will load D with the length of the second string and HL with the string’s address.

258C-258E
GOSUB to 29D7H to check to see if there is enough memory for the string.
258F
LD A,(HL)
Load register A with the length of the string at the location of the string’s VARPTR in HL.
2590
INC HL
Bump the value of the string’s VARPTR in HL so that HL points to the LSB of the string address.
2591
LD C,(HL)
Load register C with the LSB of the string’s address at the location of the string’s VARPTR in HL.
2592
INC HL
Bump the value of the string’s VARPTR in HL so that HL points to the MSB of the string address.
2594
LD B,(HL)
Load register B with the MSB of the string’s address at the location of the string’s VARPTR in HL.
2595
POP DE
Save the value of the string’s address in BC to the stack.
2596
PUSH BC
Save the string’s length in register A to the stack.
2597-2599
PUSH AF
Load HL with the second string’s VARPTR.
259A
POP DE
Get the length of the first string from the stack and put it in register D.
259B
LD E,(HL)
Load register E with the second string’s length at the location of the second string’s VARPTR in HL.
259C
INC HL
Bump the value of the second string’s VARPTR in HL.
259D
LD C,(HL)
Load register C with the LSB of the second string’s address at the location of the second string’s VARPTR in HL.
259E
INC HL
Bump the value of the second string’s VARPTR in HL.
259F
LD B,(HL)
Load register B with the MSB of the second string’s address at the location of the second string’s VARPTR in HL.
25A0
POP HL
Get the first string’s address from the stack and put it in HL.
25Al
LD A,E
Load register A with the length of the second string in register E.
25A2
OR D
Combine the first string’s length in register D with the second string’s length in register A.
25A3
RET Z
Return out of the routine if there aren’t any characters left in either string to be compared.

25A4
LD A,D
Load register A with the first string’s length in register D.
25A5-25A6
SUB 01H
Check to see if the first string’s length in register A is equal to zero.
25A7
RET C
Return if there are no more characters in the first string to be compared.

25A8
XOR A
Load register A with zero.
25A9
CP E
Check to see if the second string’s length in register E is equal to zero.
25AA
INC A
Bump the value in register A.
25AB
RET NC
Return if there aren’t anymore characters in the second string to be compared.

25AC
DEC D
Decrement the value of the first string’s length in register D.
25AD
DEC E
Decrement the value of the second string’s length in register E.
25AE
LD A,(BC)
Load register A with the character at the location of the second string pointer in BC.
25AF
CP (HL)
Compare the character at the location of the second string pointer in register A with the character at the location of the first string pointer in HL.
25B0
INC HL
Bump the value of the first string pointer in HL.
25Bl
INC BC
Bump the value of the second string pointer in BC.
25B2-25B3
Loop back to 25A1H to keep going if the characters match.
25B4
CCF
Since they are not equal, reverse the CARRY flag so 960 will give a +1 or -1.
25B5-25B7
Jump back to 0960H.
25B8
INC A
Bump the value of the current precedence value in register A.
25B9
ADC A,A
Adjust the value of the current precedence value in register A. This will give a 1 with a NC if 0 or a 0 with C if FF.
25BA
POP BC
Get the last operator value from the stack and put it in BC.
25BB
AND B
Combine the precedence value in register B with the precedence value in register A.
25BC-25BD
ADD A,FFH
Adjust the value in register A. This will give a 0 if both are equal and a CARRY if they are unequal.
25BE
SBC A,A
Check to see if the precedence values in registers A and B match. This will set A=0 if equal, and A+1 if unequal.
25BF-25Cl
Call to 098DH. This will set the current value to 00 if A is positive, and to FF if A is negative.
If the values match, set the current result in zero. If they do not match, set the current result to -1.
25C2-25CJ
Jump forward to 25D6H to continue with the expression evaluation.


25C4 – NOT Routine.

25C4-25C5
LD D,5AH
Load register D with the precedence value.
25C6-25C8
Go evaluate the expression.
25C9-25CB
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).
25CC
LD A,L
Load register A with the LSB of the integer value.
25CD
CPL
Compliment the LSB of the integer value in register A.
25CE
LD L,A
Load register L with the adjusted LSB of the integer value in register A.
25CF
LD A,H
Load register A with the MSB of the integer value in register H.
25D0
CPL
Compliment the MSB of the integer value in register A.
25Dl
LD H,A
Load register H with the adjusted MSB of the integer value in register A.
25D2-25D4
LD (4121H),HL
Save the complimented integer value in HL as the current result in REG 1
25D5
POP BC
Clean up the stack.
25D6-25D8
Jump back to 2346H to continue with the expression evaluation.


25D9 – The RST 20H code is located here. – This is the TEST DATA MODE, which 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).
TYPE   CODE   ZERO   CARRY   NEG   PARITY   A-Register
INT     02     NZ      C      N      E         -1
STR     03      Z      C      P      E          0
SNG     04     NZ      C      P      O          1
DBL     08     NZ     NC      P      E          5

25D9-25DBH
“TSTYP”
LD A,(40AFH)
Load register A with the current value of the number type flag.
Note: 40AFH holds Current number type flag.
25DC-25DD
CP 08H
Check to see if the current value in REG 1 is double precision (02=INT, 03=STR, 04=SNG, 08=DBL).

25DE-25DF
If that test shows that we have a DOUBLE PRECISION number, jump forward to 25E5H.
25E0-25El
SUB 03H
If the number is not double precision, subtract 3.
25E2
OR A
Set the status flags of the adjusted number type flag in register A.
24E3
SCF
Set the Carry flag.
25E4
RET
Return.

25E5-25E6
SUB 03H
We are dealing with a double precision number so adjust the value of the current number type flag in register A.
25E7
OR A
Test the value of the current number type flag in register A, which will exit without the CARRY flag set.
25E8
RET
Return.

25E9
PUSH BC
B has he precision alue for the last operator. Save BC to the stack.
25EA-25EC
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).
25ED
POP AF
Get the operator value from the stack and put it in register A.
25EE
POP DE
Get the return address from the stack and put it in DE.

25EF-25F1
LD BC,27FAH
Load BC with a return address of 27FAH.
25F2
PUSH BC
Save the value of the return address in BC to the stack.
25F3-25F4
CP 46H
Check to see if the operator value in register A is an OR token. A CP returns Z if the test matches A and NZ otherwise.
25F5-25F6
Jump forward a few instructions to 25FDH (to the AND code) if the operator value in register A isn’t an OR token.


25F7 – OR logic.

25F7
LD A,E
Load register A with the LSB of the first value in register E.
25F8
OR L
Combine the LSB of the first value in register A with the LSB of the second value in register L.
25F9
LD L,A
Load register L with the ORed value in register A.
25FA
LD A,H
Load register A with the MSB of the second value in register H.
25FB
OR D
Combine the MSB of the first value in register D with the MSB of the second value in register A.
25FC
Return to 27FAH (=convert the result to integer and return that integer calue to 2346H).


25FD – AND logic.

25FD
LD A,E
Load register A with the LSB of the first value in register E.
25FE
AND L
Combine the LSB of the first value in register A with the LSB of the second value in register L.
25FF
LD L,A
Load register L with the ANDed value in register A.
2600
LD A,H
Load register A with the MSB of the second value in register H.
2601
AND D
Combine the MSB of the first value in register D with the MSB of the second value in register A.
2602
Return to 27FAH (=Make the result an integer and return to 2346H).

2603
DEC HL
Decrement the value of the BASIC program pointer in HL.
2604
RST 10H
We need the next character in the BASIC program so 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.
2605
RET Z
Return if this is the end of the BASIC statement.

2606-2607
RST 08H
2C
Since the character at the location of the current BASIC program pointer in HL must be a ,, call the COMPARE SYMBOL routine at RST 08H.

NOTE: The RST 08H routine compares 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 the next execution address (i.e, the RST 08H instruction + 2) with the next symbol in the A Register 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).


2608 – DIM logic.

2608-260A
LD BC,2603H
Load BC with a return address of 2603H.
260B
Save the return address of 2603H (in BC) to the stack.


260D – This is the variable location and creation logic.

  • This routine will return the address of a variable in memory or create it if it is not found. In order to use this routine, the HL must point to the variable name (ASCII). Then, after execution, HL will point to the character following the variable name and the location of the variable will be returned in the DE register pair. For integer, single or doubleprecision (NTF=2, 4 or 8) the address returned in DE will be the same as for the VARPTR command under BASIC. (see Level II BASIC manual on VARPTR) For strings (NTF=3) however the address returned in DE will point to the first of three bytes containing the string length and string address.
    This entry point searches the Variable List Table (VLT) for a variable name which matches the name in the string pointed to by HL. If the variable exists, its address is returned in DE. If it is not defined, then it is created with an initial value ofzero and its address is returned in DE. Dimensioned and non-dimensioned variables may be located, and suffixs for data mode may be included in the name string. A byte of machine zeros must terminate the name string. All registers are used.
260C-260D
OR AFH
Reset the value in register A.
260E-2610
LD (40AEH),A
Save the value in register A as the current variable location/creation flag.
Note: 40AEH holds LOCATE/CREATE variable flag.
2611
LD B,(HL)
Load register B with the first character of the variable name.
2612-2614
GOSUB to 1E3DH to make sure the first character of the variable name is a letter.
2615-2617
Display a ?SN ERROR if the first character of the variable name isn’t a letter.
2618
XOR A
Zero register A.
2619
LD C,A
Zero register C.
261A
RST 10H
We need the next character in the BASIC program so 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.

261B-261C
Jump to 2622H if the character at the location of the current BASIC program pointer in register A is numeric.
261D-261F
GOSUB to 1E3DH to check to see if the character at the location of the current BASIC program pointer is a letter.

2620-2621
Jump to 262BH if the character at the location of the current BASIC program pointer in register A isn’t a letter.
2622
LD C,A
Load register C with the second character of the variable name in register A.
2623
RST 10H
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.

2624-2625
Loop back one optcode until a nonnumeric character is found.
2626-2628
Go check to see if the character at the location of the current BASIC program pointer in HL is alphabetic.

2629-262A
Jump back to 2623H if the character at the location of the current BASIC program pointer in HL is alphabetic.
262B-262D
LD DE,2652H
Load DE with a return address of 2652H.
262E
PUSH DE
Save the value of the return address in DE to the stack.
262F-2630
LD D,02H
Load register D with an integer number type flag.
2631-2632
CP 25H
Check to see if the character at the location of the current BASIC program pointer in register A is a %.
2633
RET Z
Return if the character at the location of the current BASIC program pointer in register A is a %.

2634
INC D
Bump register D so that it will be equal to a string number type flag (02=INT, 03=STR, 04=SNG, 08=DBL).
2635-2636
CP 24H
Check to see if the character at the location of the current BASIC program pointer in register A is a $.
2637
RET Z
Return if the character at the location of current BASIC program pointer in register A is a $.

2638
INC D
Bump register D so that it will be equal to a single precision number type flag (02=INT, 03=STR, 04=SNG, 08=DBL).
2639-263A
CP 21H
Check to see if the character at the location of the current BASIC program pointer in register A is a !.
263B
RET Z
Return if the character at the location of the current BASIC program pointer in register A is a !.

263C-263D
LD D,08H
Load register D with a double precision number type flag. We have to do this because 04H (SNG) would bump to 05H if we just did another INC, but we need 08H for DBL.
263E-263F
CP 23H
Check to see if the character at the location of the current BASIC program pointer in register A is a #.
2640
RET Z
Return if the character at the location of the current BASIC program pointer in register A is a #.

2641
LD A,B
Load register A with the first character of the variable name in register B.
2642-2643
SUB 41H
Adjust the value of the first character of the variable name in register A so that it is in the range of 0 to 25.
2644-2645
AND 7FH
Make sure the sign bit in register A isn’t set by ANDing it against 0111 1111.
2646
LD E,A
Load register E with the adjusted first character of the variable name in register A.
2647-2648
LD D,00H
Load register D with zero.
2649
PUSH HL
Save the value of the current BASIC program pointer in HL to the stack.
264A-264C
LD HL,4101H
Load HL with the starting address of the variable declaration table.
NOTE: 4101H-411AH holds Variable Declaration Table.
264D
ADD HL,DE
Add the value of the first character of the variable name in DE to the starting address of the variable declaration table in HL.
264E
LD D,(HL)
Load register D with the number type value at the location of the variable declaration table pointer in HL.
264F
POP HL
Get the value of the current BASIC program pointer from the stack and put it in HL.
2650
DEC HL
Decrement the value of the current BASIC program pointer in HL.
2651
RET
Return with data type in D.

2652
LD A,D
Load register A with the value of the number type flag in register D.
2653-2655
LD (40AFH),A
Save the number type flag for the current variable name in register A.
NOTE: 40AFH holds Current number type flag.
2656
RST 10H
We need the next character in the BASIC program so 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.
2657-2659
LD A,(40DCH)
Load register A with the FOR flag.
Note: 40DCH holds FOR flag.
265A
OR A
Test the value of the FOR flag in register A.
265B-265D
Jump to 2664H if a FOR statement is being processed.
265E
LD A,(HL)
Re-fetch the next element of the code string by loading register A with the character at the location of the current BASIC program pointer in HL.
265F-2660
SUB 28H
Check to see if the character at the location of the current BASIC program pointer in register A is a (.
2661-2663
Jump to 26E9H if the character at the location of the current BASIC program pointer in register A is a ( (meaning, it is a subscripted variable).
2664
XOR A
Zero register A.
2665-2667
LD (40DCH),A
Set the array flag to ‘no subscript’.
Note: 40DCH holds FOR flag.
2668
PUSH HL
Save the value of the current BASIC program pointer in HL to the stack.
2669
PUSH DE
Save the number type flag for the variable in DE to the stack.
266A-266C
LD HL,(40F9H)
Load HL with the value of the simple variables pointer.
  • Note: 40F9H-40FAH holds the starting address of the simple variable storage area.
266D
EX DE,HL
Load DE with the simple variables pointer in HL. We don’t care what happens to HL.
266E-2670
LD HL,(40FBH)
Load HL with the array variables pointer.
  • Note: 40FBH-40FCH holds the starting address of the BASIC array variable storage area.
2671
RST 18H
Now we need to compare the value of the simple variables pointer in DE with the array variables pointer in HL, so we call the COMPARE DE:HL 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.
2672
POP HL
Get the number type flag for the variable from stack and put it in HL.
2673-2674
Jump to 268EH if the simple variables pointer in DE is greater than or equal to the array variables pointer (meaning the variable wasn’t defined).
2675
LD A,(DE)
Load register A with the number type flag for the variable at the location of the simple variables pointer in DE.
2676
LD L,A
Load register L with the number type flag in register A.
2677
CP H
Compare the number type flag for the variable in register H to the number type flag in register A.
2678
INC DE
Bump the value of the current simple variables pointer in DE to the 2nd character name for this entry.
2679-267A
Jump to 2686H (i..e, the next variable in the list) if the number type flags don’t match.
267B
LD A,(DE)
Since the type matches, compare the 2nd character of the name by loading register A with the first character of variable name at the location of the simple variables pointer in DE.
267C
CP C
Compare the character at the location of the simple variables pointer in register A with the first character of the variable name in register C.
267D-2637
Jump to 2686H if the first characters of the variable names don’t match.
267F
INC DE
Bump the value of the current simple variables pointer in DE.
2680
LD A,(DE)
Load register A with the second character of the variable name at the location of the simple variables pointer in DE.
2681
CP B
Compare the character at the location of the simple variables pointer in register A with the first character of the variable name in register B.
2682-2684
Jump to 26CCH if the character at the location of the simple variables pointer in register A matches the first character of the variable name in register B.
2685-2686
LD A,13H
Z-80 Trick to skip the next INC DE if continuing through.
2686
INC DE
Bump to the next entry in the simple variable list part 1.
2687
INC DE
Bump the value of the simple variables pointer in DE part 2.
2688
Save the number type flag for the variable in HL to the stack so that it can be re-loaded at 2672H.
2689-268A
LD H,00H
Load register H with zero.
268B
ADD HL,DE
Add the value of the simple variables pointer in DE to the value of the number type flag in HL.
268C-268D
Loop back to 266DH.
268E
LD A,H
Load register A with the number type flag for the variable in register H.
268F
POP HL
Get the value of the current BASIC program pointer from the stack and put it in HL.
2690
EX (SP),HL
Exchange the value of the current BASIC program pointer in HL with the value to the stack.
2691
PUSH AF
Save the number type flag for the variable in register A to the stack.
2692
PUSH DE
Save the start of the array variables pointer in DE to the stack.
2693-2695
LD DE,24F1H
Load DE with a VARPTR locator return address of 24F1H.
2696
RST 18H
Now we need to compare the return address in DE with the return address in HL, so we call the COMPARE DE:HL 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.
2697-2698
Jump forward to 26CFH if this routine is called from the VARPTR routine.
2699-269B
LD DE,2543H
Load DE with a return address of the find address of variables routine at 2543H.
269C
RST 18H
We need to see if we were called from the ‘find address of variable’ routine so we need to compare the return address in DE with the return address in HL, so we call the COMPARE DE:HL 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.
269D
POP DE
Get the value of the array variables pointer from the stack and put it in DE.
269E-269F
Jump to 26D5H if this routine is called to locate the variables address.
26A0
POP AF
Clear the stack and put the value of the number type flag for the variable from the stack and put it in register A.
26Al
EX (SP),HL
Exchange the value of the current BASIC program pointer to the stack with the value of the return address in HL.
26A2
PUSH HL
Save the value of the current BASIC program pointer in HL to the stack.
26A3
PUSH BC
Save the variable’s name in BC to the stack.
26A4
LD C,A
Load register C with the value of the number type flag for the variable in register A.
26A5-26A6
LD B,00H
Load register B with zero.
26A7
PUSH BC
Save the variable’s number type flag in BC to the stack.
26A8
INC BC
Bump the value of the variable’s number type flag in BC.
26A9
INC BC
Bump the value of the variable’s number type flag in BC.
26AA
INC BC
Bump the value of the variable’s number type flag in BC. Now that we are done bumping BC, we have the type + 3 (which is 3 bytes of overhead and a spare for the variable).
26AB-26AD
LD HL,(40FDH)
Load HL with the value of the free memory pointer.
Note: 40FDH-40FEH holds Free memory pointer.
26AE
PUSH HL
Save the value of the free memory pointer in HL to the stack.
26AF
ADD HL,BC
Add the value of the variable’s number type flag in BC to the value of the free memory pointer in HL.
26B0
POP BC
Get the value of the free memory pointer from the stack and put it in BC.
26Bl
PUSH HL
Save the value of the new free memory pointer in HL to the stack.
26B2-26B4
Move the array variables up in memory.
26B5
POP HL
Get the value of the new free memory pointer from the stack and put it in HL.
26B6-26B8
LD (40FDH),HL
Save the value of the new free memory pointer in HL to lock in that variable space.
NOTE: 40FDH-40FEH holds Free memory pointer.
26B9
LD H,B
Load register H with the MSB of the new array variables pointer in register B.
26BA
LD L,C
Load register L with the LSB of the new array variables pointer in register C.
26BB-26BD
LD (40FBH),HL
Save the value of the new array variables pointer in HL.
  • Note: 40FBH-40FCH holds the starting address of the BASIC array variable storage area.
26BE
DEC HL
Decrement the value of the array variables pointer in HL.
26BF-26C0
LD (HL),00H
Zero the location of the memory pointer in HL.
26Cl
RST 18H
Now we need to check to see if the variable has been completely zeroed, so we call the COMPARE DE:HL 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.
26C2-26CJ
Loop back to 26BEH until the variable has been cleared.
26C4
POP DE
Get the value of the variable’s number type flag from the stack and put it in DE.
26C5
LD (HL),E
Save the value of the number type flag in register E at the location of the memory pointer in HL.
26C6
INC HL
Bump the value of the memory pointer in HL.
26C7
POP DE
Get the 2nd character of the variable’s name from the stack and put it in DE.
26C8
LD (HL),E
Save the first character of the variable’s name in register E at the location of the memory pointer in HL.
26C9
INC HL
Bump the value of the memory pointer in HL.
26CA
LD (HL),D
Save the first character of the variable’s name in register D at the location of the memory pointer in HL.
26CB
EX DE,HL
Load DE with the value of the variable pointer in HL.
26CC
INC DE
Bump the value of the variable pointer in DE.
26CD
POP HL
Get the value of the current BASIC program pointer from the stack and put it in HL.
26CE
RET
Return.

26CF
LD D,A
Load register D with the value of the current number type flag in register A.
26D0
LD E,A
Load register E with the value of the current number type flag in register A.
26D1
POP AF
Clean up the stack.
26D2
POP AF
Clean up the stack.
26D3
EX (SP),HL
Exchange the value of the return address in HL with the value of the current BASIC program pointer to the stack.
26D4
RET
Return to the VARPTR routine.


26D5 – This routine is to locate a subscripted variable.

26D5-26D7
LD (4124H),A
Zero REG 1.
26D8
POP BC
Clean up the stack.
26D9
LD H,A
Zero register H.
26DA
LD L,A
Zero register L.
26DB-26DD
LD (4121H),HL
Zero the string pointer location in REG 1.
26DE
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
  • and Double Precision is NZ/NC/P/E and A is 5.
26DF-26E0
If that test shows we do NOT have a STRING, jump to 26E7H.
26E1-26E3
LD HL,1928H
Load HL with the starting address of the Level II BASIC READY message.
26E4-26E6
LD (4121H),HL
Save the value in HL as the current string pointer.
26E7
POP HL
Get the value of the current BASIC program pointer from the stack and put it in HL.
26E8
RET
Return.


26E9 – This routine locates the address of a subscripted variable.

  • On entry D = the type of variable, B = the 1st character of the variable name, C = the 2nd character of the variable name, and HL = the current position in the input string.
26E9
PUSH HL
Save the value of the current BASIC program pointer in HL to the stack.
26EA-26EC
LD HL,(40AEH)
Load HL with the value of the locate/create flag.
Note: 40AEH holds LOCATE/CREATE variable flag and will be a 0 if in locate mode and anything other than zero if in create mode.
26ED
EX (SP),HL
Exchange the value of the locate/create flag in HL with the value of the current BASIC program pointer to the stack.
26EE
LD D,A
Zero register D.
26EF
PUSH DE
Save the variable’s number type flag in DE to the stack.
26F0
PUSH BC
Save the variable’s name in BC to the stack.
26Fl-26F3
Go evaluate the array subscript at the location of the current BASIC program pointer in HL up to a ) or ,. Return with the binary value in DE.
26F4
POP BC
Get the variable’s name from the stack (1st and 2nd character) and put it in BC.
26F5
POP AF
Get the variable’s number type flag from the stack and put it in register A.
26F6
EX DE,HL
Exchange the value of the array subscript in DE with the value of the current BASIC program pointer in HL.
26F7
EX (SP),HL
Exchange the value of the array subscript in HL with the value of the locate/create flag to the stack.
26F8
PUSH HL
Save the value of the locate/create flag in HL to the stack.
26F9
EX DE,HL
Exchange the value of the locate/create flag in HL with the value of the current BASIC program pointer in DE.
26FA
INC A
Bump the number of subscripts evaluated in register A.
26FB
LD D,A
Load register D with the number of subscripts evaluated in register A.
26FC
LD A,(HL)
Load register A with the character at the location of the current BASIC program pointer in HL.
26FD-26FE
CP 2CH
Check to see if the character at the location of the current BASIC program pointer in register A is a ,.
26FF-2700
Jump if the character at the location of the current BASIC program pointer in register A is a ,.
2701-2702
RST 08H
29
Since the character at the location of the current BASIC program pointer in HL must be a ), call the COMPARE SYMBOL routine at RST 08H.

NOTE: The RST 08H routine compares 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 the next execution address (i.e, the RST 08H instruction + 2) with the next symbol in the A Register 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).
2703-2705
LD (40F3H),HL
Save the value of the current BASIC program pointer in HL.
2706
Get the value of the locate/ create flag from the stack and put it in HL.
NOTE: 40F3H-40F4H holds Temporary storage location.
2707-2709
LD (40AEH),HL
Save the value of the locate/create flag in HL.
NOTE: 40AEH holds LOCATE/CREATE variable flag.
270A
PUSH DE
Save the number of subscripts evaluated in DE.
270B-270D
LD HL,(40FBH)
Load HL with the value of the array variables pointer.
  • Note: 40FBH-40FCH holds the starting address of the BASIC array variable storage area.
270E-270F
LD A,19H
Z-80 Trick to skip the next command of ADD HL, DE if falling through.
270F
Figure the end of the array. Note: 40FBH-40FCH holds the array variables pointer.
2710
EX DE,HL
Load DE with the value of the array variables pointer in HL.
2711-2713
LD HL,(40FDH)
Load HL with the value of the free memory pointer.
Note: 40FDH-40FEH holds Free memory pointer.
2714
EX DE,HL
Exchange the value of the free memory pointer in HL with the value of the array variables pointer in DE.
2715
RST 18H
Now we need to compare the value of the free memory pointer in DE to the value of the array variables pointer in HL, so we call the COMPARE DE:HL 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.
2716-2718
LD A,(40AFH)
Load register A with the value of the current number type flag.
Note: 40AFH holds Current number type flag.
2719-271A
Jump forward out of this loop to 2742H if the array variables pointer in HL is greater than or equal to the value of the free memory pointer in DE.
271B
CP (HL)
Compare the value of the variable’s number type flag in register A with the value of the number type flag at the location of the array variables pointer in HL.
271C
INC HL
Bump the value of the array variables pointer in HL.
271D-271E
Jump forward (but still in this loop) to 2727H if the number type flags don’t match.
271F
LD A,(HL)
Load register A with the first character of the variable name at the location of the array variables pointer in HL.
2720
CP C
Check to see if the first character of the variable at the location of the array variable pointer in register A matches the first character of the variable name in register C.
2721
INC HL
Bump the value of the array variables pointer in HL.
2722-2723
Jump forward (but still in this loop) to 2728H if the first characters of the variable names don’t match.
2724
LD A,(HL)
Load register A with the second character of the variable name at the location of the array variables pointer in HL.
2725
CP B
Compare the second character of the variable name at the location of the array variables pointer in register A matches the second character of the variable name in register B.
2727
LD A,23H
Bump the value of the array variables pointer in HL.
2728
INC HL
Bump the value of the array variables pointer in HL.
2729
LD E,(HL)
Load register E with the LSB of the offset to the next array at the location of the array variables pointer in HL.
272A
INC HL
Bump the value of the array variables pointer in HL.
272B
LD D,(HL)
Load register D with the MSB of the offset to the next array at the location of the array variables pointer in HL.
272C
INC HL
Bump the value of the array variables pointer in HL.
272D-272E
Jump back to 270FH if the variables’ names don’t match.
272F-2731
LD A,(40AEH)
Load register A with the value of the locate/create flag.
Note: 40AEH holds LOCATE/CREATE variable flag.
2732
OR A
Check the status of the locate/create flag in register A.
2733-2734
LD E,12H
Load register E with the ?DD ERROR code.
2735-2737
Display a ?DD ERROR message if the locate/create flag in register A indicates the create mode since that variable already exists.
2738
POP AF
Get the number of subscripts evaluated from the stack and put it in register A.
2739
SUB (HL)
Compare the number of subscripts evaluated in register A with the number of subscripts for the array at the location of the array variables pointer in HL (meaning, the number which was DIMmed).
273A-273C
Jump down to 2795H if the number of subscripts evaluated in register A matches the number of subscripts for the array at the location of the array variables pointer in HL.


273D – BS ERROR entry point.

273D-273E
LD E,10H
Load register E with a ?BS ERROR code.
273F-2741
Display a ?BS ERROR message if the number of subscripts evaluated in register A doesn’t match the number of subscripts for the array at the location of the array variable pointer in HL.
2742
LD (HL),A
Save the number of subscripts for the array in register A at the location of the array variables pointer in HL.
2743
INC HL
Bump the value of the array variables pointer in HL so it points to the 2nd character in the variable name (since they are saved in last, first order).
2744
LD E,A
Load register E with the number type flag for the current variable.
2745-2746
LD D,00H
Zero register D.
2747
POP AF
Get the number of subscripts evaluated from the stack and put it in register A.
2748
LD (HL),C
Save the second character of the variable’s name in register C at the location of the array variables pointer in HL.
2749
INC HL
Bump the value of the array variables pointer in HL to now point to the 1st character in the variable name (since they are saved in last, first order).
274A
LD (HL),B
Save the first character of the variable’s name in register B at the location of the array variables pointer in HL.
274B
INC HL
Bump the value of the array variables pointer in HL to the LSB of the offset to the next entry.
274C
LD C,A
Load register C with the number of subscripts evaluated in register A.
274D-274F
Figure the amount of memory space left between HL and the free memory.
2750
INC HL
Bump the value of the array variables pointer in HL.
2751
INC HL
Bump the value of the array variables pointer in HL. These 2 INC’s skip over the offset entry.
2752-2754
LD (40D8H),HL
Save the value of the array variables pointer in HL to 40D8H (which is the address of the maximum number of indices).
Note: 40D8H-40D9H holds temporary storage location.
2755
LD (HL),C
Save the number of subscripts evaluated in register C (1, 2, or 3) at the location of the array variables pointer in HL.
2756
INC HL
Bump the value of the array variables pointer in HL to point to the first subscript entry in the array table.
2757-2759
LD A,(40AEH)
Load register A with the value of the locate/create flag.
Note: 40AEH holds LOCATE/CREATE variable flag.
275A
RLA
Set the CARRY flag to be 0 for locate and 1 for create.
275B
LD A,C
Load register A with the number of subscripts evaluated in register C.
275C-275E
LD BC,000BH
Load BC with the default number of 11, which is the most entries an array can have without a DIM.

275F-2760
Jump forward to 2763H if the array is being created because it certainly wasn’t found.
2761
POP BC
Get a subscript from the stack and put it in BC.
2762
INC BC
Bump the value of the subscript in BC.
276J
LD (HL),C
Save the LSB of the subscript’s value in register C at the location of the array variables pointer in HL.
2764
INC HL
Bump the value of the array variables pointer in HL.
2765
LD (HL),B
Save the MSB of the subscript’s value in register B at the location of the array variables pointer in HL.
2766
INC HL
Bump the value of the array variables pointer in HL.
2767
PUSH AF
Save the number of subscripts evaluated in register A to the stack.
2768-276A
Go multiply the size of the subscript by the value of the number type flag to determine the amount of memory necessary for the subscript.
276B
POP AF
Get the number of subscripts evaluated from the stack and put it in register A.
276C
DEC A
Check to see if there are anymore subscripts to be evaluated.
276D-276E
Jump back to 275CH if there are anymore subscripts to be evaluated.
276F
PUSH AF
Save the number of subscripts to be evaluated in register A to the stack.
2770
LD B,D
Load register B with the MSB of the array’s length in register D.
2771
LD C,E
Load register C with the LSB of the array’s length in register E. Now BC = length of the array in bytes.
2772
EX DE,HL
Load DE with the value of the array variables pointer in HL.
2773
ADD HL,DE
Add the length of the array in HL to the value of the array variable pointer in DE.

2774-2775
Jump back to 273DH if overflow occurred.
2776-2778
Go check to see if there is enough memory for the array.
2779-277B
LD (40FDH),HL
Get the end of the array and put it in HL.
Note: 40FDH-40FEH holds free memory pointer.
277C
DEC HL
Decrement the value of the array pointer in HL.
277D-277E
LD (HL),00H
Zero the location of the array pointer in HL.
277F
RST 18H
Now we need to compare the array pointer in HL with the array variables pointer in DE, so we call the COMPARE DE:HL 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.
2780-2781
Loop until the array has been cleared.
2782
INC BC
Load BC with the array’s length in bytes plus one.
2783
LD D,A
Zero register D.
2784-2786
LD HL,(40D8H)
Load HL with the array variables pointer (=the number of indices).
Note: 40D8H-40D9H holds Temporary storage location.
2787
LD E,(HL)
Load register E with the number of subscripts for the array at the location of the array variables pointer in HL.
2788
EX DE,HL
Exchange the value of the array variables pointer in HL with the number of subscripts for the array in DE.
2789
ADD HL,HL
Multiply the number of subscripts for the array in HL by two.
278A
ADD HL,BC
Add the length of the array in BC to the number of subscripts times two in HL.
278B
EX DE,HL
Exchange the array’s length in HL with the array variables pointer in DE.
278C
DEC HL
Decrement the value of the array variables pointer in HL.
278D
DEC HL
Decrement the value of the array variables pointer in HL.
278E
LD (HL),E
Save the LSB of the offset to the next array in register E at the location of the array variables pointer in HL.
278F
INC HL
Bump the value of the array variables pointer in HL.
2790
LD (HL),D
Save the MSB of the offset to the next array in register D at the location of the array variables pointer in HL.
2791
INC HL
Bump the value of the array variables pointer in HL.
2792
POP AF
Get the value of the locate/ create flag from the stack and put it in register A.

2793-2794
Jump forward to 27C5H if the array is being created.
2795
LD B,A
Zero register B.
2796
LD C,A
Zero register C.
2797
LD A,(HL)
Load register A with the number of subscripts for the array at the location of the array variables pointer in HL.
2798
INC HL
Bump the value of the array variables pointer in HL.
2799
16H E1
Z-80 Trick to hide the next instruction (POP HL) if proceeding downward.
279A
POP HL
Get the array variables pointer from the stack and put it in HL.
279B
LD E,(HL)
Load register E with the LSB of the subscript limit at the location of the array variables pointer in HL.
279C
INC HL
Bump the value of the array variables pointer in HL.
279D
LD D,(HL)
Load register D with the MSB of the subscript limit at the location of the array variables pointer in HL.
279E
INC HL
Bump the value of the array variables pointer in HL.
279F
EX (SP),HL
Exchange the value of the array variables pointer in HL with the subscript to the stack.
27A0
PUSH AF
Save the number of subscripts for the array in register A to the stack.
27A1
RST 18H
Now we need to compare the subscript limit in DE with the subscript for the array in HL, so we call the COMPARE DE:HL 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.

27A2-27A4
Jump back to 273DH if the subscript for the array in HL is greater than the subscript limit in DE.
27A5-27A7
Multiply the previous subscript by the subscript limit.
27A8
ADD HL,DE
Add the subscript limit for the array in DE to the array pointer in HL.
27A9
POP AF
Get the number of subscripts for the array from the stack and put it in register A.
27AA
DEC A
Check to see if there are anymore subscripts to be evaluated.
27AB
LD B,H
Load register B with the MSB of the subscript pointer in register H.
27AC
LD C,L
Load register C with the LSB of the subscript pointer in register L.
27AD-27AE
Loop back to 279AH until all of the subscripts have been evaluated.
27AF-27B1
LD A,(40AFH)
Get the number type flag for the current array.
NOTE: 40AFH holds Current number type flag.
27B2
LD B,H
Load register B with the MSB of the subscript pointer in register H.
27B3
LD C,L
Load register C with the LSB of the subscript pointer in register L.
27B4
ADD HL,HL
Multiply the subscript pointer in HL by two.
27B5-27B6
SUB 04H
Check the value of the number type flag in register A.

27B7-27B8
Jump forward to 27BDH if the current number type is an integer or string.
27B9
ADD HL,HL
It isn’t an integer or a string so once again multiply the subscript pointer in HL by two (so now it is multiplied by 4).
27BA-27BB
Jump forward to 27C2H if the current number type is single precision.
27BC
ADD HL,HL
It must be double precision, so once again multiply the subscript pointer in HL by two (so now it is multiplied by 8).
27BD
OR A
Set the flags.
27BE-27C0
Jump forward to 27C2H if the current number type isn’t a string.
27C1
ADD HL,BC
The current number type is a string so add the value of the original subscript pointer in BC to the subscript pointer in HL.
27C2
POP BC
Get the value of the array variables pointer from the stack and put it in BC.
27C3
ADD HL,BC
Add the value of the array variables pointer in BC to the subscript pointer in HL.
27C4
EX DE,HL
Load DE with the variable pointer in HL.
27C5-27C7
LD HL,(40F3H)
Get the value of the current BASIC program pointer and put it in HL.
Note: 40F3H-40F4H holds Temporary storage location.
27C8
RET
Return.


27C9-27D3 – LEVEL II BASIC MEM ROUTINE

  • This is the RETURN AMOUNT OF FREE MEMORY routine at 27C9H which computes the amount of memory remaining between the end of the variable list and the end of the stack and puts the result in REG 1 as a SINGLE PRECISION number.
27C9
Zero register A and the status flags.
27CA
PUSH HL
Save the value of the current BASIC program pointer in HL to the stack.
27CB-27CD
LD (40AFH),A
Zero the number type flag.
NOTE: 40AFH holds Current number type flag.
27CE-27D0
GOSUB to the FRE routine at 27D4H.
27D1
POP HL
Get the value of the current BASIC program pointer from the stack and put it in HL.
27D2
RST 10H
We need the next character in the BASIC program so 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.
27D3
RET
Return to BASIC.


27D4-27F4 – LEVEL II BASIC FRE ROUTINE

27D4-27D6
LD HL,(40FDH)
Load HL with the start of free memory pointer.
NOTE: 40FDH-40FEH holds Free memory pointer.
27D7
EX DE,HL
Load DE with the value of the free memory pointer in HL.
27D8-27DA
LD HL,0000H
Zero HL.
27DB
ADD HL,SP
Add the value in HL (which is zero) to the current value of the stack pointer.
27DC
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
  • and Double Precision is NZ/NC/P/E and A is 5.
27DD-27DE
If that test shows we do NOT have a STRING (meaning this was really a MEM call, jump to forward to 27ECH.
27DF-27E1
Get the address of the string into HL.
27E2-27E1
Go check to see how much string space remains.
27E5-27E7
LD HL,(40A0H)
Load HL with the start of string space pointer.
NOTE: 40A0H-40A1H holds the start of string space pointer.
27E8
EX DE,HL
Load DE with the start of string space pointer in HL.
27E9-27EB
LD HL,(40D6H)
Load HL with the next available location in string space pointer.
NOTE: 40D6H-40D7H holds Next available location in string space pointer.
27EC
LD A,L
Load register A with the LSB of the next available location in string space pointer in register L.
27ED
SUB E
Subtract the LSB of the start of string space pointer in register E from the LSB of the next available location in string space pointer in register A.
27EE
LD L,A
Load register L with the LSB of the amount of string space remaining in register A.
27EF
LD A,H
Load register A with the MSB of the next available location in string space pointer in register H.
27F0
SBC A,D
Subtract the MSB of the string space pointer in register D from the MSB of the next available location of string space pointer in register A.
27F1
LD H,A
Load register H with the MSB of the amount of string space remaining in register A.
27F2-27F4
Jump to 0C66H to convert the difference between HL and DE to single precision and then RETurn out of the routine.


27F5-27FD – LEVEL II BASIC POS( ROUTINE

27F5-27F7
LD A,(40A6H)
Load register A with the current cursor line position.
Note: 40A6H holds the current cursor line position.
27F8
LD L,A
Load register L with the value of the current cursor line position in register A.
27F9
XOR A
Zero register A.
27FA
LD H,A
Load register H with zero, so now HL is 00 / cursor position.
27FB-27FD
Jump to 0A9AH.


27FE-2818 – LEVEL II BASIC USR(x) ROUTINE

27FE-2800
Go call the DOS link at 41A9H.
2801
RST 10H
We need the next character so 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.
2802-2804
GOSUB to 252CH to evaluate the expression at the location of the current BASIC program pointer in HL and return with the result in REG 1.
2805
PUSH HL
Save the value of the current BASIC program pointer in HL (=the address of the next element in the code string) to the stack.
2806-2808
LD HL,0890H
Load HL with the return address of 0890H which will clear the stack before returning to BASIC.
2809
PUSH HL
Save the value of the return address in HL to the stack.
280A-280C
LD A,(40AFH)
Load register A with the value of the current number type flag.
Note: 40AFH holds Current number type flag.
280D
PUSH AF
Save the value of the current number type flag in register A.
(02=INT, 03=STR, 04=SNG, 08=DBL).
280E-280F
CP 03H
Check to see if the current value in REG l is a string.
2810-2812
If the current result in REG l is a string then GOSUB to 29DAH to get the string address into HL.
2813
POP AF
Restore the number type flag into register A.
2814
EX DE,HL
Load DE with the value of the string address in HL.
2815-2817
LD HL,(408EH)
Load HL with the starting address of the machine language subroutine.
  • Note: 408EH-408FH holds the entry address of a machine language program to be called by a USR command.
2818
JP (HL)
Jump to the address in HL.


2819-2827 – CONVERSION ROUTINE
Usually called by LET to convert the result of arithmetic routines to the proper destination type.

2819
PUSH HL
Save the value in HL to the stack.
281A-281B
AND 07H
Mask the value of the current number type flag in register A.
281C-281E
LD HL,18A1H
Load HL with the address of the arithmetic conversion routines.
281F
LD C,A
Load register C with the value of the number type flag in register A.
(02=INT, 03=STR, 04=SNG, 08=DBL).
2820-2821
LD B,00H
Zero register B. Now BC holds 00 / type.
2822
ADD HL,BC
Add the offset (of BC) to the base arithmetic conversion routines, to find the right jump point.
2823-2825
GOSUB to 2586H to convert the current result in REG l to its proper number type.
2826
POP HL
Get the value from the stack and put it in HL.
2827
RET
Return.


2828-2835 – Save the code string address
Usually called from the INPUT routine. On entry HL has the current line number in binary.

2828
PUSH HL
Save the value of the current BASIC program pointer in HL to the stack.
2829-282B
LD HL,(40A2H)
Load HL with the value of the current BASIC line number.
  • Note: 40A2H-40A3H holds the current BASIC line number.
282C
INC HL
Bump the value of the current BASIC line number in HL to enable us to test for a direct statement.
282D
LD A,H
Load register A with the MSB of the current BASIC line number in register H.
282E
OR 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.
282F
POP HL
Get the value of the current BASIC program pointer from the stack and put it in HL.
2830
RET NZ
Return if there is a line number (i.e., this isn’t the command mode).


2831 – ID ERROR entry point.

2831-2832
LD E,16H
Load register E with the ?ID ERROR code.
2833-2835
Display an ?ID ERROR if this is the command mode.


2836-2856 – STRING ROUTINE – STR$ logic.

2836-2838
GOSUB to 0FBDH to convert the current result in REG 1 to an ASCII string.
2839-283B
Go make a temporary string work area entry.
283C-283E
Load HL with the string’s VARPTR.

283F-2841
LD BC,2A2BH
Load BC with a return address of 2A2BH (which cleans the stack and then jumps to 2884H).
2842
PUSH BC
Save the value of the return address in BC to the stack.
2843
LD A,(HL)
Load register A with the string’s length at the location of the string’s VARPTR in HL.
2844
INC HL
Bump the value of the string’s VARPTR in HL.
2845
PUSH HL
Save the value of the string’s VARPTR in HL to the stack.
2846-2848
GOSUB to 28BFH to test the remaining string area to make sure that the new string will fit.
2849
POP HL
Reload HL with the string’s VARPTR.
284A
LD C,(HL)
Load register C with the LSB of the string’s address at the location of the string’s VARPTR in HL.
284B
INC HL
Bump the value of the string’s VARPTR in HL.
284C
LD B,(HL)
Load register B with the MSB of the string’s address at the location of the string’s VARPTR in HL.
284D-284F
GOSUB to 285AH to save the string’s length and the string’s address at 40D3H.
2850
Save the value in HL (which is 40D3H) to the stack.
2851
LD L,A
Load register L with the string’s length (from register A).
2852-2854
GOSUB to 29CEH to move the string from the temp area (of BC) to the string data area (in DE).
2855
POP DE
Get the value from the stack (40D3H) and put it in DE.
2856
RET
Return.


2857-2864 – STRING ROUTINE – Set Up a String. A needs to hold the length of the string to be created.

2857-2859
GOSUB to 28BFH to make sure that there is enough string space remaining for the string. Get the address of the next string area in DE. Then save A and DE at 40D3H-40D5H.
285A-285C
LD HL,40D3H
Load HL with the address of the temporary string parameter storage area.
Note: 40D3H-40D5H holds Used for temporary string VARPTR’s.
285D
PUSH HL
Save the address of the temporary string parameter area in HL to the stack.
285E
LD (HL),A
Save the string’s length in register A at the location of the temporary string parameter storage pointer in HL.
285F
INC HL
Bump the value of the temporary string parameter storage pointer in HL.
2860
LD (HL),E
Save the LSB of the string’s address in register E at the location of the temporary string parameter storage pointer in HL.
2861
INC HL
Bump the value of the temporary string parameter storage pointer in HL.
2862
LD (HL),D
Save the MSB of the string’s address in register D at the location of the temporary string parameter storage pointer in HL.
2863
POP HL
Get the address of the temporary string parameter storage area from the stack and put it in HL.
2864
RET
Return.


2865-28A5 – STRING ROUTINE
This is the quote routine. C will be a counter.

2865H
“CSVEC”
DEC HL
Decrement the value of the current BASIC program pointer in HL.
2866-2867
LD B,22H
Load register B with a (which is really the opening search character).
2868
LD D,B
Load register D with a (which is really the ending search character).
2869
PUSH HL
Save the address of the current BASIC program pointer in HL to the stack.
286A-286B
LD C,0FFH
Load register C with a -1.
286C
INC HL
Bump the value of the current BASIC program pointer in HL to skip over that initial .
286D
LD A,(HL)
Load register A with the character at the location of the current BASIC program pointer in HL.
286E
INC C
Bump the counter in register C.
286F
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.
2870-2871
Jump to 2878H if the character at the location of the current BASIC program pointer in register A is an end of the BASIC line character.
2872
CP D
Check to see if the character at the location of the current BASIC program pointer in register A is the same as the terminating character in register D.
2873-2874
Jump to 2878H if the character at the location of the current BASIC program pointer in register A is the same as the terminating character in register D.
2875
CP B
Check to see if the character at the location of the current BASIC program point.er in register A is the same at the terminating character in register B.
2876-2877
Loop back to 286CH if the character at the location of the current BASIC program pointer in register A isn’t the same as the terminating character in register B.
2878-2879
CP 22H
Check to see if the character at the location of the current BASIC program pointer in register A is a quote.
287A-287C
If it was a quote, then GOSUB to 1D78H to bump the value of the current BASIC program pointer in HL until it points to the next character.
287D
EX (SP),HL
Exchange the value of the current BASIC program pointer in HL with the string’s address to the stack.
287E
INC HL
Bump the string’s address in HL until it points to the first character of the string.
287F
EX DE,HL
Load DE with the string’s address in HL.
2880
LD A,C
Load register A with the string’s length from register C.
2881-2883
GOSUB to 285AH to save the string’s length and the string’s address into 40D3H.
2884-2886
LD DE,40D3H
Load DE with the address of the string parameter storage area.
Note: 40D3H-40D5H holds Used for temporary string VARPTR’s.
2887-2888
LD A,D5H
This seems to be garbage. Perhaps there is a jump to 2888 which would then be PUSH DE.
2889-288B
LD HL,(40B3H)
Load HL with the next available location in the temporary string work area in HL as the string’s VARPTR in REG 1.
Note: 40B3H-40B4H holds Next available location in the temporary string work area pointer.
288C-288E
LD (4121H),HL
Save the value of the next available location in the temporary string work area in HL as the string’s VARPTR in REG 1.
288F-2890
LD A,03H
Load register A with the string number type flag.
2891-2893
LD (40AFH),A
Save the value in register A as the current number type flag.
Note: 40AFH holds Current number type flag.
2894-2896
Add the length of the string to the next available location in the temporary string work area in HL.
2897-2899
LD DE,40D6H
Load DE with the ending address of the temporary string work area.
Note: 40D6H-40D7H holds Next available location in string space pointer.
289A
RST 18H
Now we need to check to see if the updated temporary string work area location in HL isn’t greater than the ending address of the temporary string work area in DE, so we call the COMPARE DE:HL 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.
289B-289D
LD (40B3H),HL
Save the updated string work area location in HL as the next available location in the temporary string work area.
Note: 40B3H-40B4H holds Next available location in the temporary string work area pointer.
289E
POP HL
Get the value of the current BASIC program pointer from the stack and put it in HL.
289F
LD A,(HL)
Load register A with the character at the location of the current BASIC program pointer in HL.
28A0
RET NZ
Return if the updated temporary string work area location wasn’t beyond the end of the temporary string work area (meaning it overflowed, because if it overflowed …).


28A1 – ST ERROR entry point.

28A1-28A2
LD E,1EH
Load register E with a ?ST ERROR code.
28A3-28A5
Display a ?ST ERROR message if the temporary string work area has overflowed.


28A6-28BE – DISPLAY MESSAGE ROUTINE

28A6
INC HL
Bump the value of the current BASIC program pointer in HL.


28A7 – This is a general purpose output routine. It will output data to the display, printer or cassette, depending on the contents of 409CH. (0=video, -1=tape, 1=printer). The address of the first character in the string to be output must be in the HL register pair, and the string must end with a zero byte or a quote (22H).
Note: 409CH holds the current output device flag: -1=cassette, 0=video and 1=printer.
This is the WRITE MESSAGE routine, which displays 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 41D0 (JP 5B99H). This subroutine uses th literal string pool table and the string area. It should not be called if the communications region and the string area are not properly maintained.

  • This routine has essentially the same effect as the routine at 2B75H, except that text may also end with a quotation mark (22H), creates string vector before output (destroys current contents of ACCUM, sets number type flag at 40AFH to 3 – see chapter two of this book), and also uses BC & DE registers. Depends heavily on BASIC string management routines (use of 2B75H or other routines may be preferable). If string contains a carriage return (ODH) character, a CALL will be made to the Disk BASIC link at 41DOH. Used by BASIC PRINT statement. This routine may also be entered at 28A6H, in which case the HL register pair will be incremented prior to beginning to output string.
  • To use a ROM call to display a string of characters starting at the current cursor position, and to update the cursor position,store the characters in consecutive memory locations, with a zero byte at the end, then load the HL register pair with the address of the first character of the string, and then CALL 28A7H.
    • EXAMPLE: Suppose that we have the following symbolic setup:
      TITL DEFM ‘INSIDE LEVEL II’
      DEFB 0
      Then, the instructions:
      LD HL,TITL
      CALL 28A7H
      will cause “INSIDE LEVEL II” to be displayed at the current cursor position and the cursor position to be updated.
    • NOTE: If the subroutine at 28A7H is used by an assembly language program that is itself entered by a USR call, the return from the assembly language program may encounter the embarrassment of a TM error, with control passing to the Level II monitor. This occurs because the subroutine at 28A7H leaves a 3 in location 40AFH, while the USR structure requires a 2 in 40AFH upon returning. The malady is cured by storing a 2 in 40AFH before returning, or by jumping to 0A9AH instead of executing the simple RET. The problem would not occur in the first place if the assembly language program returns the value of an integer variable to the BASIC program, and it might not occur if some other ROM routine is called after the subroutine at 28A7H and before returning � if the other subroutine produces an integer output. DISK SYSTEM CAUTION: See the DISK SYSTEM CAUTION of Section 8.1 regarding the exits to DISK BASIC from the subroutine at 28A7H.
28A7-28A9H
“DSTR”
Go build a temporary string work area entry for the message at the location of the current BASIC program pointer in HL.
28AA-28AC
GOSUB to 29DAH to load HL with the string’s VARPTR.
28AD-28AF
Go get the string’s length in register D and the string’s address in BC.
28B0
INC D
Bump the value of the string’s length in register D in preparation for the following loop which starts with a DEC D.
28Bl
DEC D
Decrement the value of the string’s length in register D.
28B2
RET Z
Return if all of the characters in the string have been sent to the current output device.

28B3
LD A,(BC)
Load register A with the character at the location of the string pointer in BC.
28B4-28B6
Go send the character in register A to the current output device.
28B7-28B8
CP 0DH
Check to see if the character in register A is a carriage return.
28B9-28BB
Jump to 2103H if the character in register A is a carriage return.
28BC
INC BC
Bump the value of the string pointer in BC.
28BD-28BE
Loop until all of the characters in the string have been sent to the current output device.


28BF-28D9 – STRING ROUTINE – Compute the amount of space remaining in the string area.

28BF
OR A
Set the flags.
28C0-28Cl
0E F1
Z-80 Trick.
28Cl
POP AF
Get the string’s length from the stack and put it in register A.
28C2
PUSH AF
Save the length of the string in register A to the stack.
28C3-28C5
LD HL,(40A0H)
Load HL with the start of the string space pointer.
  • Note: 40A0H-40A1H holds the start of string space pointer.
28C6
EX DE,HL
Move the start of the string space pointer into DE. We don’t care what happens to HL.
28C7-28C9
LD HL,(40D6H)
Load HL with the next available location in string space pointer.
Note: 40D6H-40D7H holds Next available location in string space pointer.
28CA
CPL
Complement the string’s length in register A so that it is negative.
28CB
LD C,A
Load register C with the negative string’s length in register A.
28CC-28CD
LD B,0FFH
Load register B with a -1 so that BC will be the negative length of the string.
28CE
ADD HL,BC
Add the negative string’s length in BC to the next available location in string space pointer in HL.
28CF
INC HL
Bump the value of the adjusted next available location in string space pointer in HL.
28D0
RST 18H
Now we need to check to see if the adjusted next available location in string space pointer in HL is less than the start of string space pointer in DE, so we call the COMPARE DE:HL 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.

28D1-28D2
Jump forward to 28DAH if the adjusted next available location in string space pointer in HL is less than the start of string space pointer in DE.
28D3-28D5
LD (40D6H),HL
Save the value in HL as the next available location in string space pointer.
Note: 40D6H-40D7H holds Next available location in string space pointer.
28D6
INC HL
Bump the value of the next available location in string space pointer in HL.
28D7
EX DE,HL
Load DE with the next available location in string space pointer in HL.
28D8
POP AF
Get the string’s length from the stack and put it in register A.
28D9
RET
Return.


28DA-298E – STRING ROUTINE

28DA
POP AF
Get the length of the string from the stack and put it in register A. This also gets the status flag to help us find out if reorganization has already been attempted.
28DB-28DC
LD E,1AH
Load register E with an ?OS ERROR code.
28DD-28DF
Display a ?OS ERROR if there isn’t enough string space available for the string and we had already reorganized string space.
28E0
CP A
Set the flags.
28El
PUSH AF
Save the string’s length in register A to the stack.

28E2-28E4
LD BC,28C1H
Load BC with a return address of 28C1H (which would retry allocation).
28E5
PUSH BC
Save that return address to the stack.
28E6-28E8
LD HL,(40B1H)
Load HL with the top of memory pointer.
Note: 40B1H-40B2H holds MEMORY SIZE? pointer.
28E9-28EB
LD (40D6H),HL
Save the top of BASIC memory pointer in HL as the next available location in string space pointer.
Note: 40D6H-40D7H holds Next available location in string space pointer.
28EC-28EE
LD HL,0000H
Zero HL.
28EF
PUSH HL
Save the value in HL to the stack.
28F0-28F2
LD HL,(40A0H)
Load HL with the start of string space pointer.
NOTE: 40A0H-40A1H holds the start of string space pointer.
28F3
PUSH HL
Save the start of string space pointer in HL to the stack.
28F4-28F6
LD HL,40B5H
Load HL with the start of the temporary string work area pointer.
Note: 40B5H-40D2H holds Temporary string work area.
28F7
EX DE,HL
Load DE with the start of the temporary string work area pointer in HL.
28F8-28FA
LD HL,(40B3H)
Load HL with the next available location in the temporary string work area pointer.
NOTE: 40B3H-40B4H holds Next available location in the temporary string work area pointer.
28FB
EX DE,HL
Exchange the start of the temporary string work area pointer in DE with the next available location in the temporary string work area pointer in HL.
28FC
We need to see if 40B3H is pointing to the first entry (40B5H) – if the start of the temporary string work area pointer in HL is the same as the next available location in the temporary string work area pointer, so we call the COMPARE DE:HL 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.

28FD-28FF
LD BC,28F7H
Load BC with a return address of 28F7H.
2900-2902
Jump to 294AH if the temporary string work area isn’t empty.
2903
LD HL,(40F9H)
Load HL with the start of the simple variables pointer.
NOTE: 40F9H-40FAH holds the starting address of the simple variable storage area.
2906
EX DE,HL
Load DE with the simple variables pointer in HL.
2907-2909
LD HL,(40FBH)
Load HL with the start of the array variables pointer.
  • Note: 40FBH-40FCH holds the starting address of the BASIC array variable storage area.
290A
EX DE,HL
Exchange the value of the simple variables pointer in DE with the value of the array variables pointer in HL.
290B
RST 18H
Now we need to check to see if the simple variables pointer in HL is the same as the array variables pointer in DE, so we call the COMPARE DE:HL 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.
290C-290D
Jump forward to 2921H if the simple variables pointer in HL is the same as the array variables pointer in DE.
290E
LD A,(HL)
Load register A with the number type flag at the location of the simple variables pointer in HL.
290F
INC HL
Bump the value of the simple variables pointer in HL.
2910
INC HL
Bump the simple variables pointer in HL.
2911
INC HL
Bump the value of the simple variables pointer in HL.
2912-2913
CP 03H
Check to see if the variable at the location of the simple variables pointer is a string.
2914-2915
Jump to 291AH if the variable at the location of the simple variables pointer in HL isn’t a string.
2916-2918
GOSUB to 294BH to do string check.
2919
XOR A
Zero register A.
29lA
LD E,A
Zero register E.
291B-291C
LD D,00H
Zero register D.
29lD
ADD HL,DE
Add the value of the number type flag in DE to the simple variables pointer in HL.
291E-291F
Loop back to 2906H until all of the simple variables have been checked.
2920
POP BC
Clean up the stack.
2921
EX DE,HL
Load DE with the value of the array variables pointer in HL.
2922-2924
LD HL,(40FDH)
Load HL with the start of free memory pointer.
Note: 40FDH-40FEH holds Free memory pointer.
2925
EX DE,HL
Exchange the value of the array variables pointer in DE with the value of the free memory pointer in HL.
2926
RST 18H
Now we need to check to see if the array variables pointer in HL is the same as the free memory pointer in DE, so we call the COMPARE DE:HL 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.
2927-2929
Jump if the array variables pointer in register HL is the same as the start of the free memory pointer in DE.
292A
LD A,(HL)
Load register A with the number type flag at the location of the array variables pointer in HL.
292B
INC HL
Bump the value of the array variables pointer in HL.
292C-292E
Call 09C2H (which loads a SINGLE PRECISION value pointed to by HL into register pairs BC and DE).
292F
PUSH HL
Save the value of the array variables pointer in reg� ister pair HL to the stack.
2930
ADD HL,BC
Add the value of the offset to the next array in BC to the value of the array variables pointer in HL.
2931-2932
CP 03H
Check to see if the array being examined is a string.
2933-2934
Jump if the array being examined isn’t a string.
2935-2937
LD (40D8H),HL
Save the address of the next array in HL.
Note: 40D8H-40D9H holds Temporary storage location.
2938
POP HL
Get the value of the array variables pointer from the stack and put it in HL.
2939
LD C,(HL)
Load register C with the number of subscripts for the array at the location of the array variables pointer in HL.
293A-293B
LD B,00H
Zero register B.
293C
ADD HL,BC
Add the number of subscripts in the array in BC to the value of the array variables pointer in HL.
293D
ADD HL,BC
Add the number of subscripts in the array in BC to the value of the array variables pointer in HL.
293E
INC HL
Bump the value of the array variables pointer in HL.
293F
EX DE,HL
Load DE with the value of the array variables pointer in HL.
2940-2942
LD HL,(40D8H)
Load HL with the address of the next array.
Note: 40D8H-40D9H holds Temporary storage location.
2943
EX DE,HL
Exchange the value of the array variables pointer in DE with the address of the array in HL.
2944
RST 18H
Now we need to check to see if the array variables pointer in HL is the same as the address of the next array in DE, so we call the COMPARE DE:HL 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.
2945-2946
Jump to 2921H if the array variables pointer in HL is the same as the address of the next array in DE.

2947-2948
LD BC,293FH
Load BC with a return address of 293FH.
294A
PUSH BC
Save the value in BC to the stack.
294B
XOR A
Zero register A.
294C
OR (HL)
Load register A with the length of the string at the location of the array variables pointer in HL.
294D
INC HL
Bump the value of the array variables pointer in HL.
294E
LD E,(HL)
Load register E with the LSB of the string’s address at the location of the array variables pointer in HL.
294F
INC HL
Bump the value of the array variables pointer in HL.
2950
LD D,(HL)
Load register D with the MSB of the string’s address at the location of the array variables pointer in HL.
2951
INC HL
Bump the value of the array variables pointer in HL.
2952
RET Z
Return if the string’s length in register A is equal to zero.

2953
LD B,H
Load register B with the MSB of the array variables pointer in register H.
2954
LD C,L
Load register C with the LSB of the array variables pointer in register L.
2955-2957
LD HL,(40D6H)
Load HL with the location of the next available location in string space pointer.
NOTE: 40D6H-40D7H holds Next available location in string space pointer.
2958
RST 18H
Now we need to check to see if the string’s address in DE is in string space, so we call the COMPARE DE:HL 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.
2959
LD H,B
Load register H with the MSB of the array variables pointer in register B.
295A
LD L,C
Load register L with the LSB of the array variables pointer in register C.
295B
RET C
Return if the string’s address in DE is in string space.

295C
POP HL
Get the return address from the stack and put it in HL.
295D
EX (SP),HL
Exchange the value of the return address in HL with the start of string space pointer to the stack.
295E
RST 18H
Now we need to check to see if the string’s address in DE is below the start of string space pointer in HL, so we call the COMPARE DE:HL 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.
295F
EX (SP),HL
Exchange the start of string space pointer in HL with the value of the return address to the stack.
2960
PUSH HL
Save the value of the return address in HL to the stack.
2961
LD H,B
Load register H with the MSB of the array variables pointer in register B.
2962
LD L,C
Load register L with the LSB of the array variables pointer in register C.
2963
RET NC
Return if the string’s address in DE is below the string space pointer.

2964
POP BC
Get the return address from the stack and put it in BC.
2965
POP AF
Clean up the stack.
2966
POP AF
Clean up the stack.
2967
PUSH HL
Save the value of the array variables pointer in HL to the stack.
2968
PUSH DE
Save the string’s address in DE to the stack.
2969
PUSH BC
Save the value of the return address in BC to the stack.
296A
RET
Return.

296B
POP DE
Load DE with the address of the last string put into the temporary string work area.
296C
POP HL
Get the temporary string work area pointer from the stack and put it in HL.
296D
LD A,L
Load register A with the LSB of the temporary string work area pointer in register L.
296E
OR H
Combine the MSB of the temporary string work area pointer in register H with the LSB of the temporary string work area pointer in register A.
296F
RET Z
Return if the temporary string work area is empty.

2970
DEC HL
Decrement the value of the temporary string work area pointer in HL.
2971
LD B,(HL)
Load register B with the MSB of the string’s address at the location of the temporary string work area pointer in HL.
2972
DEC HL
Decrement the value of the temporary string work area pointer in HL.
2973
LD C,(HL)
Load register C with the LSB of the string’s address at the location of the temporary string work area pointer in HL.
2974
PUSH HL
Save the value of the temporary string work area pointer in HL to the stack.
2975
DEC HL
Decrement the value of the temporary string work area pointer in HL.
2976
LD L,(HL)
Load register L with the string’s length at the location of the temporary string work area pointer in HL.
2977-2978
LD H,00H
Zero register H.
2979
ADD HL,BC
Add the length of the string in HL to the string’s address in BC.
297A
LD D,B
Load register D with the MSB of the string’s address in register B.
297B
LD E,C
Load register E with the LSB of the string’s address in register C.
297C
DEC HL
Decrement the value of the string’s ending address in HL.
297D
LD B,H
Load register B with the MSB of the string’s ending address in register H.
297E
LD C,L
Load register C with the LSB of the string’s ending address in register L.
297F-2981
LD HL,(40D6H)
Load HL with the next available location in string space pointer.
NOTE: 40D6H-40D7H holds Next available location in string space pointer.
2982-2984
Move the string from the temporary storage location to string space.
2985
POP HL
Get the temporary string work area pointer from the stack and put it in HL.
2986
LD (HL),C
Save the LSB of the string’s address in register Cat the location of the temporary string work area pointer in HL.
2987
INC HL
Bump the value of the temporary string work area pointer in HL.
2988
LD (HL),B
Save the MSB of the string’s address in register B at the location of the temporary string work area pointer in HL.
2989
LD L,C
Load register L with the LSB of the string’s address in register C.
298A
LD H,B
Load register H with the MSB of the string’s address in register B.
298B
DEC HL
Decrement the string’s address in HL.
298C-298E
Jump to 28E9H.


298F-29C5 – STRING ADDITION ROUTINE – Concatenate two strings.

298F
PUSH BC
Save the operator value in BC to the stack.
2990
PUSH HL
Save the value of the current BASIC program pointer in HL to the stack.
2991-2993
LD HL,(4121H)
Load HL with the first string’s VARPTR (from REG 1).
2994
EX (SP),HL
Exchange the value of the first string’s VARPTR in HL with the value of the current BASIC program to the stack.
2995-2997
GOSUB to 249FH to evaluate the expression at the location of the current BASIC program pointer in HL.
2998
EX (SP),HL
Exchange the value of the current BASIC program pointer in HL with the value of the first string’s VARPTR to the stack.
2999-299B
Go make sure the current result in REG 1 is a string.
299C
LD A,(HL)
Load register A with the first string’s length at the location of the first string’s VARPTR in HL.
299D
PUSH HL
Save the value of the first string’s VARPTR in HL to the stack.
299E-29A0
LD HL,(4121H)
Load HL with the second string’s VARPTR in REG 1.
29A1
PUSH HL
Save the second string’s VARPTR in HL to the stack.
29A2
ADD A,(HL)
Add the length of the second string at the location of the second string’s VARPTR in HL to the length of the first string in register A.
29A3-29A4
LD E,1CH
Load register E with a ?LS ERROR code.
29A5-29A7
Display a ?LS ERROR message if the combined lengths of the strings is greater than 255.
29A8-29AA
Go make sure that there is enough string space for the new string.
29AB
POP DE
Get the second string’s VARPTR from the stack and put it in DE.
29AC-29AE
Go update the temporary string work area.
29AF
EX (SP),HL
Exchange the second string’s VARPTR in HL with the first string’s VARPTR to the stack.
29B0-29B2
Go update the temporary string work area.
29B3
PUSH HL
Save the value of the first string’s VARPTR in HL to the stack.
29B4-29B6
LD HL,(40D4H)
Load HL with the second string’s address.
29B7
EX DE,HL
Load DE with the second string’s address in HL.
29B8-29BA
Go move the first string to its temporary storage location.
29BB-29BD
Go move the second string to its temporary storage location.
29BE-29C0
LD HL,2349H
Load HL with the return address.
29C1
EX (SP),HL
Exchange the value of the return address in HL with the value of the current BASIC program pointer to the stack.
29C2
PUSH HL
Save the value of the current BASIC program pointer in HL to the stack.
29C3-29C5
Jump to 2884H.


29C6-29D6 – STRING ROUTINE – This will move strings using the stack.

  • On entry, the stack should have the count/source address and DE should have the destination address.
29C6
POP HL
Load HL with the value of the return address to the stack.
29C7
EX (SP),HL
Exchange the value of the return address in HL with the string’s VARPTR to the stack.


29C8 – STRING MOVE ROUTINE
On entry HL points to the string control block for the string to be moved, and DE contains the destination address. All registers are used. The string length and address are not moved. String control blocks have the format: X=String Length; ADDR = String Address.

29C8
LD A,(HL)
Load register A with the string’s length at the location of the string’s VARPTR in HL.
29C9
INC HL
Bump the value of the string’s VARPTR in HL.
29CA
LD C,(HL)
Load register C with the LSB of the string’s address at the location of the string’s VARPTR in HL.
29CB
INC HL
Bump the value of the string’s VARPTR in HL.
29CC
LD B,(HL)
Load register B with the MSB of the string’s address at the location of the string’s VARPTR in HL.
29CD
LD L,A
Load register L with the string’s length in register A.
29CE
INC L
Bump the value of the string’s length in register L.
29CF
DEC L
Decrement the value of the string’s length in register L.
29D0
RET Z
Return if all of the characters in the string have been moved.

29D1
LD A,(BC)
Load register A with the character at the location of the string pointer in BC.
29D2
LD (DE),A
Save the character in register A at the location of the string storage pointer in DE.
29D3
INC BC
Bump the value of the string pointer in BC.
29D4
INC DE
Bump the value of the string storage pointer in DE.
29D5-29D6
Loop until the string has been completely moved.


29D7-29F4 – STRING ROUTINE

  • This routine is a contination of VAL, FRE, and PRINT processing. A jump to here would include the need to get a string’s VARPTR and put it in HL.
29D7-29D9
GOSUB to 0AF4H to make sure that the current result in REG l is a string.

29DA-29DC
LD HL,(4121H)
Load HL with the string’s VARPTR in REG 1.
29DD
EX DE,HL
Load DE with the value of the string’s VARPTR in HL.
29DE-29E0
Check to see if the string is the last entry in the temporary string work area.
29E1
EX DE,HL
Load HL with the value of the string’s VARPTR in DE.
29E2
RET NZ
Return if the string isn’t the last entry in the temporary string work area.

29E3
PUSH DE
Save the value of the string’s VARPTR in DE to the stack.
29E4
LD D,B
Load register D with the MSB of the string’s address in register B.
29E5
LD E,C
Load register E with the LSB of the string’s address in register C.
29E6
DEC DE
Decrement the value of the string’s address in DE.
29E7
LD C,(HL)
Load register C with the string’s length at the location of the string’s VARPTR in HL.
29E8-29EA
LD HL,(40D6H)
Load HL with the next available location in string space pointer.
Note: 40D6H-40D7H holds Next available location in string space pointer.
29EB
RST 18H
We need to see if the current string is the last one defined in the string area by seeing if the string’s address in DE is the same as the next available location in string space pointer in HL, so we call the COMPARE DE:HL 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.
29EC-29ED
Jump forward to 29F3H if the string’s address in DE isn’t the same as the next available location in string space pointer in HL.
29EE
LD B,A
If is the last one defined then we need to update the current string pointer so first we load register B with the value in register A.
29EF
ADD HL,BC
Add the length of the string in BC to the next available location in string space pointer in HL.
29E0-29F2
LD (40D6H),HL
Save the adjusted next available location in string space pointer in HL.
Note: 40D6H-40D7H holds Next available location in string space pointer.
29F3
POP HL
Get the string’s VARPTR from the stack and put it in HL.
29F4
RET
Return.


29F5-2A02 – STRING ROUTINE

29F5-29F7
LD HL,(40B3H)
Load HL with the temporary string work area pointer.
Note: 40B3H-40B4H holds Next available location in the temporary string work area pointer.
29F8
DEC HL
Decrement the value of the temporary string work area pointer in HL which backs up two words.
29F9
LD B,(HL)
Load register B with the MSB of the string’s address at the location of the temporary string work area pointer in HL.
29FA
DEC HL
Decrement the value of the temporary string work area pointer in HL.
29FB
LD C,(HL)
Load register C with the LSB of the string’s address at the location of the temporary string work area pointer in HL.
29FC
DEC HL
Decrement the value of the temporary string work area pointer in HL.
29FD
RST 18H
Now we need to check to see if the string’s VARPTR in DE matches the temporary string work area pointer in HL, so we call the COMPARE DE:HL 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.
29FE
RET NZ
Return if the string’s VARPTR in DE doesn’t match the temporary string work area pointer in HL.

29FF-2A01
LD (40B3H),HL
Save the value of the temporary string work area pointer in HL.
Note: 40B3H-40B4H holds Next available location in the temporary string work area pointer.
2A02
RET
Return.


2A03-2A0E – LEVEL II BASIC LEN ROUTINE


2A03-2A05
LD BC,27F8H
Load BC with the return address of 27F8H.
2A06
Save the return address of 27F8H (in BC) to the stack.
2A07-2A09
GOSUB to 29D7H to get the string’s VARPTR and put it in HL.
2A0A
XOR A
Zero register A.
2A0B
LD D,A
Zero register D.
2A0C
LD A,(HL)
Load register A with the string’s length at the location of the string’s VARPTR in HL.
2A0D
OR A
Set the flags according to the string’s length in register A.
2A0E
RET
Return.


2A0F-2A1E – LEVEL II BASIC ASC ROUTINE


2A0F-2A11
LD BC,27F8H
Load BC with the return address of 27F8H.
2A12
Save the return address of 27F8H (in BC) to the stack.
2A13-2A15
GOSUB to 2A07H (which itself is a GOSUB to 29D7H) to get string’s VARPTR into HL and the string’s length into register A.
2A16-2A18
Display a ?FC ERROR if the string’s length in register A is equal to zero.
2A19
INC HL
Bump the value of the string’s VARPTR in HL.
2A1A
LD E,(HL)
Load register E with the LSB of the string’s address at the location of the string’s VARPTR in HL.
2A1B
INC HL
Bump the value of the string’s VARPTR in HL.
2A1C
LD D,(HL)
Load register D with the MSB of the string’s address at the location of the string’s VARPTR in HL.
2A1D
LD A,(DE)
Load register A with the first character at the location of the string pointer in DE.
2A1E
RET
Return.


2A1F-2A2E – LEVEL II BASIC CHR$ ROUTINE

2A1F-2A20
LD A,01H
Load register A with the length of the string to be created.
2A21-2A23
GOSUB to 2857H to save the string’s length in register A and value and set up the string’s address.
2A24-2A26
GOSUB to 2B1FH to evaluate the expression at the location of the current BASIC program pointer in HL and return with the integer result in DE.
2A27-2A29
LD HL,(40D4H)
Load HL with the temporary string’s address.
2A2A
LD (HL),E
Save the character in register E at the location of the string pointer in HL.
2A2B
POP BC
Clean up the stack.
2A2C-2A2E
Jump to 2884H.


2A2F-2A60 – LEVEL II BASIC STRING$ ROUTINE

2A2F
RST 10H
We have the STRING$ command, but now we need the next character so we call a RST 10H to 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.
2A30-2A31
RST 08H
28
Since the character at the location of the current BASIC program pointer in HL must be a (, call the COMPARE SYMBOL routine at RST 08H.

NOTE: The RST 08H routine compares 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 the next execution address (i.e, the RST 08H instruction + 2) with the next symbol in the A Register 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).
2A32-2A34
This will get the string length required (which we will call “N”) via a GOSUB to 2B1CH to evaluate the expression at the location of the current BASIC program pointer in HL and return with the integer result in DE.
2A34
DEC HL
Backspace the code string. This is a Z-80 trick because this code was part of the above call instruction.
2A35
PUSH DE
Save the string’s length (“N”) (currently in DE) to the stack.
2A36-2A37
RST 08
2C
Now we have STRING$(nnn so the next character needs to be a ,. To test for the character at the location of the current BASIC program pointer in HL being a ,, call the COMPARE SYMBOL routine which compares 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 A register 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).
2A38-2A3A
Now we have STRING$(xxx, and an expression so GOSUB to 2337H to evaluate the expression at the location of the current BASIC program pointer in HL and return with the result in REG 1.
2A3B-2A3C
RST 08H
29
Now we have STRING$(nnn,X. Since the character at the location of the current BASIC program pointer in HL must be a ), call the COMPARE SYMBOL routine at RST 08H.

NOTE: The RST 08H routine compares 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 the next execution address (i.e, the RST 08H instruction + 2) with the next symbol in the A Register 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).
2A3D
EX (SP),HL
We are now done with getting STRING$(nnn,X). Next we must exchange the value of the current BASIC program pointer in HL with the string’s length (“N”) in the stack.
2A3E
PUSH HL
Save the string’s length (“N”) in HL to the stack so that we can test it to make sure it is an integer.
2A3F
RST 20H
We need to check the value of the current data 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
  • and Double Precision is NZ/NC/P/E and A is 5.
2A40-2A41
If that test shows “N” is a a STRING, jump to down to 2A47H.
2A42-2A44
We now know that “N” is at least a number, so we GOSUB to 2B1FH to convert the current result in REG 1 to an integer and return with the 8-bit result in register A.
2A45-2A46
Skip the next instruction (which would load the string address and 1st character) by jumping to 2A4AH.
2A47-2A49
Go get the first character in the string and return with it in register A. This is the character that will be repeated.
2A4A
POP DE
Get the “N” from the stack and put it in DE.
2A4B
PUSH AF
Save the character for the string (held in register A) to the stack.
2A4C
PUSH AF
and then save it to the stack again.
2A4D
LD A,E
Load register A with “N” (held in register E).
2A4E-2A4F
GOSUB to 2857H to allocate N bytes in the temporary string work area .
2A51
LD E,A
Load register E with “N” (held in register A).
2A52
POP AF
Get the character for the string (“X”) from the stack and put it in register A.
2A53
INC E
To set the status flags we need to increase and then decrease E. First, bump the value of the string’s length in register E …
2A54
DEC E
… and then decrement the string’s length in register E.
2A55-2A56
If “N” was zero (so that the string is now complete), jump back to 2A2BH.
2A57-2A59
LD HL,(40D4H)
If we are here, we have not finished building the STRING$ string so now we load HL with the string’s address and get ready to loop.
2A5A
LD (HL),A
Save the character in register A (“X”) at the location of the string pointer in HL.
2A5B
INC HL
Bump the value of the string pointer in HL.
2A5C
DEC E
Decrement the string’s length in register E.
2A5D-2A5E
Loop back to 2A5AH to keep filling (HL) until the string of X’s has been completed.
2A5F-2A60
Jump back to 2A2BH.


2A61-2A90 – LEVEL II BASIC LEFT$( ROUTINE – On entry, HL=address of LEFT$$, the stack = string address, stack+1 = n, and DE = code string address.

2A61-2A63
Go check the syntax. The character at the location of the current BASIC program pointer in HL must be a ).
2A64
XOR A
Zero register A.
2A65
EX (SP),HL
Exchange the value of the current BASIC program pointer in HL with the string’s VARPTR to the stack.
2A66
LD C,A
Zero register C.
2A67-2A68
3E E5
Z-80 Trick. By adding a 3E at 2A67, it masks out 2A68H if passing through by making the Z-80 think the instruction is LD A,0E5H.
2A68
LD H,A
Load register H with the value in register A.
2A69
PUSH HL
Save the value of the string’s VARPTR in HL to the stack.
2A6A
LD A,(HL)
Load register A with the string’s length at the location of the string’s VARPTR in HL.
2A6B
CP B
Check to see if the new string’s length in register B is greater than the string’s length in register A.

2A6C-2A6D
Jump to 2A70H if the new string’s length in register B is greater than the string’s length in register A.
2A6E
LD A,B
Load register A with the new string’s length in register B.
2A6F-2A71
11 0E 00
Z-80 Trick. This is a LD DE,000EH which is irrelevant and only executed if continuing through. If, however, one was to jump to 2A70H instead, a proper opcode would occur.
2A70-2A7l
LD C,00H
Zero register C.
2A72
PUSH BC
Save the string’s length in BC to the stack.
2A73-2A75
Go see if there is enough string space for the new string.
2A76
POP BC
Get the new string’s length from the stack and put it in BC.
2A77
POP HL
Get the string’s VARPTR from the stack and put it in HL.
2A78
PUSH HL
Save the string’s VARPTR in HL to the stack.
2A79
INC HL
Bump the value of the string’s VARPTR in HL.
2A7A
LD B,(HL)
Load register B with the LSB of the string’s address at the location of the string’s VARPTR in HL.
2A7B
INC HL
Bump the value of the string’s VARPTR in HL.
2A7C
LD H,(HL)
Load register H with the MSB of the string’s address at the location of the string’s VARPTR in HL.
2A7D
LD L,B
Load register L with the LSB of the string’s address in register B.
2A7E-2A7F
LD B,00H
Zero register B.
2A80
ADD HL,BC
Add the string’s length in BC to the string’s address in HL.
2A81
LD B,H
Load register B with the MSB of the string’s ending address in register H.
2A82
LD C,L
Load register C with the LSB of the string’s ending address in register L.
2A83-2A85
Go save the string’s length (held in A) and the string’s starting address (held in DE).
2A86
LD L,A
Load register L with the string’s length (i.e., the number of characters to move) held in register A.
2A87-2A89
Go move L characers frm BC to DE.
2A8A
POP DE
Clean up the stack.
2A8B-2A8D
Go update the temporary string work area.
2A8E-2A90
Jump to 2884H.


2A91-2A99 – LEVEL II BASIC RIGHT$ ROUTINE

2A91-2A93
Go check the syntax. The character at the location of the current BASIC program pointer in HL must be a ).
2A94
POP DE
Get the string’s VARPTR from the stack and put it in DE.
2A95
PUSH DE
Save the string’s VARPTR in DE to the stack.
2A96
LD A,(DE)
Load register A with the string’s length (held at the location of the string’s VARPTR in DE).
2A97
SUB B
Subtract the new string’s length in register B from the string’s length in register A to isolate the number of bytes.
2A98-2A99
Jump to the LEFT$( code.


2A9A-2AC4 – LEVEL II BASIC MID$ ROUTINE

2A9A
EX DE,HL
Load HL with the value of the current BASIC program pointer (held in DE).
2A9B
LD A,(HL)
Load register A with the terminal character, currently held at the location of the current BASIC program pointer in HL.
2A9C-2A9E
GOSUB to 2AE2H to get the string’s position in register B and the string’s VARPTR in DE.
2A9F
INC B
We need to set the status flags to correspond to the position value so we first bump the value of the string’s position in register B …
2AA0
DEC B
… and then we decrement the value of the string’s position in register B.
2AA1-2AAJ
If the starting position (held in B) is 0, display ?FC ERROR.
2AA4
PUSH BC
Save the value of the string’s starting position (held in register B) to the stack.
2AA5-2AA6
LD E,0FFH
Load register E with the default string’s length of 256 in case no number of bytes are given.
2AA7-2AA8
CP 29H
More syntax checking. Here we need to test for a ) at the location of the current BASIC program pointer.
2AA9-2AAA
Jump to 2AB0H if the character at the location of the current BASIC program pointer in register A is a ).
2AAB-2AAC
RST 08H
2C
If it wasn’t a ), it had best be a , so we need to test the character at the location of the current BASIC program pointer in HL by calling the COMPARE SYMBOL routine at RST 08H.

NOTE: The RST 08H routine compares 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 the next execution address (i.e, the RST 08H instruction + 2) with the next symbol in the A Register 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).
2AAD-2AAF
Go evaluate the expression at the location of the current BASIC program pointer in HL and return with the integer result in DE. Now the byte count is in DE as an integer.
2ABO-2AB1
RST 08H
29
Since the character at the location of the current BASIC program pointer in HL must be a ), call the COMPARE SYMBOL routine at RST 08H.

NOTE: The RST 08H routine compares 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 the next execution address (i.e, the RST 08H instruction + 2) with the next symbol in the A Register 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).
2AB2
POP AF
Get the value of the string’starting s position from the stack and put it in register A.
2AB3
EX (SP),HL
Exchange the value of the current BASIC program pointer in HL with the value of the string’s VARPTR to the stack.

2AB4-2AB6
LD BC,2A69H
Load BC with 2A69H as the return address (which is in the LEFT$ routine).
2AB7
PUSH BC
Save the return address in BC to the stack.
2AB8
DEC A
Decrement the value of the string’s position in register A so that we have a starting position minus 1.
2AB9
CP (HL)
Compare the string’s length at the location of the string’s VARPTR in HL with the value of the string’s position in register A.
2ABA-2ABB
LD B,00H
Zero register B.
2ABC
RET NC
Return if the string’s position in register A is greater than the string’s length at the location of the string’s VARPTR in HL.

2ABD
LD C,A
Load register C with the string’s position in register A.
2ABE
LD A,(HL)
Load register A with the string’s length at the location of the string’s VARPTR in HL.
2ABF
SUB C
Subtract the value of the string’s position in register C from the string’s length in register A.
2AC0
CP E
Compare the new string’s length in register E with the adjusted string’s length in register A.
2AC1
LD B,A
Load register B with the adjusted string’s length in register A.
2AC2
Return to 2A69H if the new string’s length in register E is greater than the string’s length in register A.

2AC3
LD B,E
Load register B with the new string’s length in register E.
2AC4
Return to 2A69H.


2AC5-2ADE – LEVEL II BASIC VAL ROUTINE

2AC5-2AC7
Go get the string’s length in register A and the string’s VARPTR in HL.
2AC8-2ACA
Jump to 27F8H if the string’s length in register A is equal to zero.
2ACB
LD E,A
Load register E with the string’s length at the location of the string’s VARPTR in HL.
2ACC
INC HL
Bump the value of the string’s VARPTR in HL.
2ACD
LD A,(HL)
Load register A with the LSB of the string’s address at the location of the string’s VARPTR in HL.
2ACE
INC HL
Bump the value of the string’s VARPTR in HL.
2ACF
LD H,(HL)
Load register H with the MSB of the string’s address at the location of the string’s VARPTR in HL.
2ADO
LD L,A
Load register L with the LSB of the string’s address in register A.
2AD1
PUSH HL
Save the value of the string’s address in HL to the stack.
2AD2
ADD HL,DE
Add the string’s length in DE to the string’s address in HL.
2AD3
LD B,(HL)
Load register B with the last character of the string at the location of the string pointer in HL.
2AD4
LD (HL),D
Save the zero in register D at the location of the string pointer in HL.
2AD5
EX (SP),HL
Exchange the string’s ending address in HL with the string’s address to the stack.
2AD6
PUSH BC
Save the last character of the string in register B to the stack.
2AD7
LD A,(HL)
Load register A with the character at the location of the string pointer in HL.
2AD8-2ADA
Call the ASCII TO DOUBLE routine at 0E65H (which converts the ASCII string pointed to by HL to its double precision equivalent; with output left in REG 1).
2ADB
POP BC
Get the last character of the string from the stack and put it in register B.
2ADC
POP HL
Get the string’s ending address from the stack and put it in HL.
2ADD
LD (HL),B
Save the character in register B at the location of the string pointer in HL.
2ADE
RET
Return.


2ADF-2A6 – STRING ROUTINE

  • This is called by LEFT$, MID$, and RIGHT$ to test for the ending “)” character. On entry, the stack has the string address, byte count, and return address. On exit the stack has the string address, DE and B each have the byte count.
2ADF
EX DE,HL
Load HL with the value of the current BASIC program pointer in DE.
2AE0-2AE1
RST 08H
29
Since the character at the location of the current BASIC program pointer in HL must be a ), call the COMPARE SYMBOL routine at RST 08H.

NOTE: The RST 08H routine compares 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 the next execution address (i.e, the RST 08H instruction + 2) with the next symbol in the A Register 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).
2AE2
POP BC
Get the return address from the stack and put it in BC.
2AE3
POP DE
Get the number of bytes to isolate from the string (from the stack) and put it in DE.
2AE4
PUSH BC
Save the return address in BC to the stack.
2AE5
LD B,E
Load register B with the number of bytes in register E.
2AE6
RET
Return.


2AE7H- AEE – DISK ROUTINE

2AE7-2AE8
CP 7AH
Check to see if the character at the location of the current BASIC program pointer in register A is equal to 7AH (which is a lower case z).
2AE9-2AEB
Display a ?SN ERROR message if the character at the location of the current BASIC program pointer in register A isn’t equal to 7AH.
2AEC-2AEE
Jump to the DOS link at 41D9H to let disk BASIC handle TABMID$.


2AEF-2AF7 – LEVEL II BASIC INP ROUTINE

2AEF-2AF1
Go evaluate the expression at the location of the current BASIC program pointer in HL and return with the port number in register A.
2AF2-2AF4
LD (4094H),A
Save the value of the port number (from register A) into 4094H.
2AF5-2AF7
Go get the value from the port, execute an IN xx instruction, and return to the execution driver.
Note: 4093H-4095H holds INP routine.


2AF8-2B00 – LEVEL II BASIC OUT ROUTINE

2AF8-2AFA
Go evaluate the expression at the location of the current BASIC program pointer in HL and return with the port number saved in memory.
2AFB-2AFD
Go evaluate the expression at the location of the current BASIC program pointer in HL and return with value to send to the port in register A.
2AFE-2B00
Go send the value in register A, execute an OUT xx instruction to the port, and return.
Note: 4096H-4098H holds OUT routine.


2B01-2B0D – EVALUATE EXPRESSION ROUTINE – This evaluates an expression and leaves the result in DE as an integer.

2B01
RST 10H
We need the next character in the BASIC program so 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.
2B02-2B04
Go evaluate the expression at the location of the current BASIC program pointer in HL and return with the result in REG 1.


2B05 – This routine takes the value from the ACC, converts it to an integer value and places the result in the DE register pair. The Z flag will be set if the result in DE is smaller than or equal to 255 (FFH). (DE = INT (ACC)).

2B05
PUSH HL
Save the value of the current BASIC program pointer in HL to the stack.
2B06-2B08
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).
2B09
EX DE,HL
Load DE with the integer result in HL.
2B0A
POP HL
Get the value of the current BASIC program pointer from the stack and put it in HL.
2B0B
LD A,D
Load register A with the MSB of the integer result in register D.
2B0C
OR A
Test the value of the MSB in register A.
2B0D
RET
Return.


2B0E-2Bl6 – EVALUATE EXPRESSION ROUTINE – OUT continues here

2B0E-2Bl0
GOSUB to 2B1CH to evaluate the expression at the location of the current BASIC program pointer in HL and return with the 8-bit value in register A.
2Bll-2Bl3
LD (4094H),A
Save the 8-bit value in register A in the DOS address of 4094H.
2Bl4-2Bl6
LD (4097H),A
Save the 8-bit value in register A in the DOS address of 4097H.


2Bl7-2BlA – CHECK SYNTAX ROUTINE – This checks to see if the next character is a and contnues on to 2B1CH if it is, and errors out if it isn’t.

2B17-2B18
RST 08H
2E
Since the character at the location of the current BASIC program pointer in HL must be a “,”, call the COMPARE SYMBOL routine at RST 08H.

NOTE: The RST 08H routine compares 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 the next execution address (i.e, the RST 08H instruction + 2) with the next symbol in the A Register 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).
2B19-2B1A
Jump forward to 2B1CH.


2BlB-2B28 – EVALUATE EXPRESSION ROUTINE – This is called by PRINT TAB.

2B1B
RST 10H
We need the next character in the BASIC program so 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.


2B1C – This routine converts a numeric ASCII string pointed to by the HL into a hexadecimal value and places the result in the A register. If the result is larger than 255 (FFH) then an FC ERROR (Illegal function call) will be generated. After execution the HL will point to the delimiter. If the delimiter is a zero byte or a colon (3AH) then the Z flag will be set. Any other delimiter will cause the Z flag to be reset.

2B1C-2B1E
GOSUB to 2337H to evaluate the expression at the location of the current BASIC program pointer in HL and return with the result in REG l.
2B1F-2B21
GOSUB to 2B05H to convert the result in REG 1 to an integer and return with the integer result in DE.
2B22-2B24
If the result is greater than 255, display a ?FC ERROR message.
2B25
DEC HL
Decrement the value of the current BASIC program pointer in HL.
2B26
RST 10H
We need the next character in the BASIC program so 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.
2B27
LD A,E
Load register A with the 8-bit result in register E.
2B28
RET
Return.


2B29-2B2D – LEVEL II BASIC LLIST ROUTINE

  • This routine sets the output device flag to PRINTER and then flows through to the LIST command.
2B29-2B2A
LD A,01H
Load register A with the printer output device code.
2B2B-2B2D
LD (409CH),A
Save the value in register A as the current output device flag.
Note: 409CH holds the current output device flag: -1=cassette, 0=video and 1=printer.

2B2E-2B74 – LEVEL II BASIC LIST ROUTINE.

  • On entry the stack has the return address, then the first basic line number to be listed, then the last basic line number to be listed.
2B2E
POP BC
Get the return address from the stack and put it in BC.
2B2F-2B31
Go evaluate the range of line numbers given at the location of the current BASIC program pointer in HL.
2B32
PUSH BC
Save the address of the first BASIC line (held in BC) to the stack.
2B33-2B35
LD HL,FFFFH
Load HL with a -1. This is because the below loop starts with a INC HL, so as to turn the first line number into 0.
2B36-2B38
LD (40A2H),HL
Save the value in HL as the current BASIC line number.
  • Note: 40A2H-40A3H holds the current BASIC line number.
2B39
POP HL
Get the address of the first BASIC line to be listed (from the stack) and put it in HL.
2B3A
POP DE
Get the value of the last BASIC line number to be listed (from the stack) and put it in DE.
2B3B
LD C,(HL)
Load register C with the LSB of the next BASIC line pointer at the location of the memory pointer in HL.
2B3C
INC HL
Bump the value of the memory pointer in HL.
2B3D
LD B,(HL)
Load register B with the MSB of the next BASIC line pointer at the location of the memory pointer in HL.
2B3E
INC HL
Bump the value of the memory pointer in HL.
2B3F
LD A,B
Load register A with the MSB of the next BASIC line pointer in register B.
2B40
OR C
Combine the LSB of the next BASIC line pointer in register C with the MSB of the next BASIC line pointer in register A. This will let us test for the end of the BASIC program.
2B4l-2B43
Jump to 1A19H if this is the end of the BASIC program.
2B44-2B46
Go call the DOS link at 41DFH.
In NEWDOS 2.1, this is called from LIST processing.
2B47-2B49
Go scan the keyboard to see if the BREAK key or the shift-@ key was pressed.
2B4A
PUSH BC
Save the address of the next BASIC line in BC to the stack.
2B4B
LD C,(HL)
Load register C with the LSB of the BASIC line number at the location of the memory pointer in HL.
2B4C
INC HL
Bump the value of the memory pointer in HL.
2B4D
LD B,(HL)
Load register B with the MSB of the BASIC line number at the location of the memory pointer in HL.
2B4E
INC HL
Bump the value of the memory pointer in HL.
2B4F
PUSH BC
Save the BASIC line number in BC to the stack.
2B50
EX (SP),HL
Exchange the value of the memory pointer in HL with the value of the BASIC line number to the stack.
2B51
EX DE,HL
Exchange the value of the BASIC line number in HL with the value of the last BASIC line number in DE.
2B52
RST 18H
Now we need to compare the BASIC line number in DE with the last BASIC line number in HL, so we call the COMPARE DE:HL 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.
2B53
POP BC
Get the value of the memory pointer from the stack and put it in BC.
2B54-2B56
Jump to 1A18H if the BASIC line number in DE is greater than the last BASIC line number in HL.
2B57
EX (SP),HL
Exchange the value of the last BASIC line number in HL with the address of the next BASIC line to the stack.
2B58
PUSH HL
Save the address of the next BASIC line in HL to the stack.
2B59
PUSH BC
Save the memory pointer in BC to the stack.
2B5A
EX DE,HL
Load HL with the BASIC line number in DE.
2B5B-2B5D
LD (40ECH),HL
Save the BASIC line number in HL.
Note: 40ECH-40EDH holds EDIT line number.
2B5E-2B60
Call the HL TO ASCII routine at 0FAFH (which converts the value in the HL (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.
2B61-2B62
LD A,20H
Load register A with a space.
2B63
POP HL
Get the value of the memory pointer from the stack and put it in HL.
2B64-2B66
Go send the space in register A to the current output device.
2B67-2B69
GOSUB to 2B7EH move the BASIC line at the location of the memory pointer in HL into the input buffer and untokenize the BASIC line.
2B6A-2B6C
LD HL,(40A7H)
Load HL with the starting address of the input buffer.
Note: 40A7H-40A8H holds the input Buffer pointer.
2B6D-2B6F
Since we need to send the BASIC line in the input buffer to the current output device we call the PRINT MESSAGE routine at 2B75H which writes string pointed to by HL to the current output device.
2B70-2B72
Go send a carriage return to the current output device.
2B73-2B74
Loop back to 2B33H until the listing is complete.


2B75-2B7D – DISPLAY MESSAGE ROUTINE

  • This is the PRINT MESSAGE routine which writes string pointed to by HL to the current output device. String must be terminated by a byte of zeros. This call is different from 28A7H because it does not use the literal string pool area, but it does use the same display routine and it takes the same DOS Exit at 41C1H. Uses all registers. This routine can be called without loading the BASIC utility, if a C9H (RET) is stored in 41ClH.

This routine outputs a string to device indicated by device type flag stored at 409CH. String must end with zero byte. On entry, HL registers must point to address of start of string. Calls routine at 032AH.

2B75
LD A,(HL)
Load register A with the character at the location of the memory pointer in HL.
2B76
OR A
Check to see if the character in register A is an end of the string character (00H).
2B77
RET Z
Return if the character in register A is an end of the string character.

2B78-2B7A
Go send the character in register A to the current output device.
2B7B
INC HL
Bump the value of the memory pointer in HL.
2B7C-2B7D
Loop back to 2B75H until all of the characters have been sent to the current output device.


2B7E-2BC5 – UNTOKENIZE ROUTINE

  • This routine is called by LIST and EDIT. It moves the line pointed to by HL to the input buffer area and then expands each token into the appropriate key word.
2B7E
PUSH HL
Save the BASIC line pointer in HL to the stack.
2B7F-2B81
LD HL,(40A7H)
Load HL with the starting address of the input buffer.
Note: 40A7H-40A8H holds the input Buffer pointer.
2B82
LD B,H
Load register B with the MSB of the input buffer pointer in register H.
2B83
LD C,L
Load register C with the LSB of the input buffer pointer in register L.
2B84
POP HL
Get the value of the BASIC line pointer from the stack and put it in HL.
*2B85-2B87
JUMP to 069AH to clear A and all flags, load the data flag (at 409FH) with 0, load D with 255 (a buffer), and JUMP to 2B8DH.
Difference between M1 and M3 ROMs: This change is to the LIST command. JP 069AH in the Model III replaces LD D,0FFH followed by JR 2B8CH in the Model I.
*2B88
NOP
No Operation
2B89
INC BC
Bump the value of the input buffer pointer in BC.
2B8A
DEC D
Decrement the character count in register D.
2B8B
RET Z
Return if 256 characters have been moved into the input buffer.

*2B8C
INC HL
Move one byte forward in the text.
Difference between M1 and M3 ROMs: Another change to LIST. In the Model I three instructions occupied this area: LD A,(HL); OR A; INC HL. In the Model III the INC HL instruction is moved to the beginning of the three.

*2B8D
LD A,(HL)
Load register A with the character at the location of the BASIC line pointer in HL.
*2B8D
OR A
Set the status flags to enable us to check to see if the character in register A is an end of the BASIC line character.
2B8F
LD (BC),A
Save the character at the location of the input buffer pointer (held in register A) to the memory location held by BC.
2B90
RET Z
Return if the character in register A is an end of the BASIC line character.

*2B91-2B93
Jump to 302DH, which JUMPS to 377B.

Difference between M1 and M3 ROMs: The final change to LIST – a JP P,2B89H instruction in the Model I is changed to a JP 302DH instruction in the Model III.


2B94-2B95
CP FBH
Check to see if the character in register A is a token.
2B96-2B97
Jump forward to 2BA0H if the character in register A isn’t a token.
2B98
DEC BC
The next bunch of opcodes is to backspace the expanded buffer pointer by 4 and then adjust the count of characters in the buffer. First, decrement the value of the input buffer pointer in BC.
2B99
DEC BC
Decrement the value of the input buffer pointer in BC.
2B9A
DEC BC
Decrement the value of the input buffer pointer in BC.
2B9B
DEC BC
Decrement the value of the input buffer pointer in BC.
2B9C
INC D
Bump the value of the character counter in register D.
2B9D
INC D
Bump the value of the character counter in register D.
2B9E
INC D
Bump the value of the character counter in register D.
2B9F
INC D
Bump the value of the character counter in register D.
2BA0-2BA1
CP 95H
Check to see if the character in register A is an ELSE token.
2BA2-2BA4
If it was an ELSE we need to backspace the expanded buffer pointer so … go back to 0B24H to decrement the value of the input buffer pointer if the character in register A is an ELSE token.
2BA5-2BA6
SUB 7FH
Subtract 7F to get the number of the entry we are looking for in token list.
2BA7
PUSH HL
Save the value of the BASIC line pointer in HL to the stack.
2BA8
LD E,A
Load register E with the character in register A.
2BA9-2BAB
LD HL,1650H
Load HL with the starting address of the reserved words list.
2BAC
LD A,(HL)
Load register A with the character at the location of the reserved words list pointer in HL.
2BAD
OR A
Test the value of the character in register A.
2BAE
INC HL
Bump the value of the reserved words list pointer in HL.
2BAF-2BB1
Jump back to 2BACH if the character at the location of the reserved words pointer in register A doesn’t have bit 7 set.
2BB2
DEC E
Decrement the value of the token in register E.
2BB3-2BB4
Jump back to 2BACH if this isn’t the reserved word for the token.
2BB5-2BB6
AND 7FH
Reset bit 7 of the character in register A by ANDing it against 0111 1111.
2BB7
LD (BC),A
Save the character in register A at the location of the input buffer pointer in BC.
2BB8
INC BC
Bump the value of the input buffer pointer in BC.
2BB9
DEC D
Decrement the value of the character counter in register D.
2BBA-2BBC
Jump back to 28D8H if the maximum number of characters have been put into the input buffer.
2BBD
LD A,(HL)
Load register A with the character at the location of the reserved words pointer in HL.
2BBE
INC HL
Bump the reserved words pointer in HL.
2BBF
OR A
Test the value of the character in register A.
2BC0-2BC2
Jump back to 2BB7H if bit 7 of the character in register A isn’t set.
2BC3
POP HL
Get the value of the BASIC line pointer from the stack and put it in HL.
2BC4-2BC5
Jump back to 2B8CH.
2BC6-2BF4
LEVEL II BASIC DELETE ROUTINE
2BC6-2BC8
GOSUB to 1B10H to evaluate the line numbers at the location of the current BASIC program pointer in HL.
2BC9
POP DE
Get the value of the last BASIC line number to be deleted (in binary) from the stack and put it in DE.
2BCA
PUSH BC
Save the address of the first BASIC line to be deleted in BC to the stack.
2BCB
PUSH BC
Save the address of the first BASIC line to be deleted in BC to the stack AGAIN!.
2BCC-2BCE
GOSUB to 1B2CH to the SEARCH FOR LINE NUMBER routine which looks for the line number specified in DE so as to get the address of the last line to be deleted.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.

2BCF-2BD0
Goto 2BD6H to show a ?FC ERROR if the SEARCH FOR LINE NUMBER routine returns a NC, that means that the line searched for (in this case, the last line to be deleted) does not exist; and if that’s the case, jump to 2BDH6.
2BD1
LD D,H
Load register D with the MSB of the last BASIC line’s address in register H.
2BD2
LD E,L
Load register E with the LSB of the last BASIC line’s address in register L.
2BD3
EX (SP),HL
Exchange the last BASIC line’s address in HL with the first BASIC line’s address to the stack.
2BD4
PUSH HL
Save the first BASIC line’s address in HL to the stack.
2BD5
RST 18H
Now we need to check to see if the first BASIC line’s address in HL is greater than or equal to the last BASIC line’s address in DE, so we call the COMPARE DE:HL 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.
2BD6-2BD8
Display a ?FC ERROR message if the first BASIC lines address in HL is greater than or equal to the last BASIC line’s address in DE.
2BD9-2BDB
LD HL,1929H
Load HL with the starting address of the BASIC READY message.
2BDC-2BDE
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).
2BDF
POP BC
Get the first BASIC line’s address from the stack and put it in BC.
2BE0-2BE2
LD HL,1AE8H
Load HL with the return address.
2BE3
EX (SP),HL
Exchange the value of the return address in HL with the value of the last BASIC line’s address to the stack.
2BE4
EX DE,HL
Load DE with the last BASIC line’s address in HL.
2BE5-2BE7
LD HL,(40F9H)
Load HL with the end of the BASIC program pointer.
  • Note: 40F9H-40FAH holds the starting address of the simple variable storage area.
2BE8
LD A,(DE)
Load register A with the character at the location of the memory pointer in DE.
2BE9
LD (BC),A
Save the character in register A at the location of the memory pointer in BC.
2BEA
INC BC
Bump the value of the memory pointer in BC.
2BEB
INC DE
Bump the value of the memory pointer in DE.
2BEC
RST 18H
Now we need to check to see if the memory pointer in DE equals the end of the BASIC program pointer in HL, so we call the COMPARE DE:HL 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.
2BED-2BEE
Loop back to 2BE8H until the memory pointer in DE equals the end of the BASIC program pointer in HL.
2BD3
EX (SP),HL
Exchange the last BASIC line’s address in HL with the first BASIC line’s address to the stack.
2BD4
PUSH HL
Save the first BASIC line’s address in HL to the stack.
2BD5
RST 18H
Now we need to check to see if the first BASIC line’s address in HL is greater than or equal to the last BASIC line’s address in DE, so we call the COMPARE DE:HL 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.
2BD6-2BD8
Display a ?FC ERROR if the first BASIC lines address in HL is greater than or equal to the last BASIC line’s address in DE.
2BD9-2BDB
LD HL,1929H
Load HL with the starting address of the BASIC READY message.
2BDC-2BDE
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).
2BDF
POP BC
Get the first BASIC line’s address from the stack and put it in BC.
2BE0-2BE2
LD HL,1AE8H
Load HL with the return address.
2BE3
EX (SP),HL
Exchange the value of the return address in HL with the value of the last BASIC line’s address to the stack.
2BE4
EX DE,HL
Load DE with the last BASIC line’s address in HL.
2BE5-2BE7
LD HL,(40F9H)
Load HL with the end of the BASIC program pointer.
  • Note: 40F9H-40FAH holds the starting address of the simple variable storage area.
2BE8
LD A,(DE)
Load register A with the character at the location of the memory pointer in DE.
2BE9
LD (BC),A
Save the character in register A at the location of the memory pointer in BC.
2BEA
INC BC
Bump the value of the memory pointer in BC.
2BEB
INC DE
Bump the value of the memory pointer in DE.
2BEC
RST 18H
Now we need to check to see if the memory pointer in DE equals the end of the BASIC program pointer in HL, so we call the COMPARE DE:HL 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.
2BED-2BEE
Loop until the memory pointer in DE equals the end of the BASIC program pointer in HL.
2BEF
LD H,B
Load register H with the MSB of the memory pointer in register B.
2BF0
LD L,C
Load register L with the LSB of the memory pointer in register C.
2BF1-2BF3
LD (40F9H),HL
Save the value in HL as the new end of the BASIC program pointer.
  • Note: 40F9H-40FAH holds the starting address of the simple variable storage area.
2BF4
RET
Return.


2BF5-2C1E – LEVEL II BASIC CSAVE ROUTINE

2BF5-2BF7
Calls the WRITE LEADER routine at 0284H (which writes a Level II leader on the cassette unit set in register A).
2BF8
2BFAH Go evaluate the rest of the CSAVE expression at the location of the current BASIC program pointer in HL and return with the result in REG l.
2BFB
PUSH HL
Save the value of the current BASIC program pointer in HL to the stack so we can get it back at the end of the routine.
2BFC-2BFE
Go get the starting address of the filename into DE.
2BFF-2C00
LD A,D3H
Load register A with the filename header byte (=D3H which is a “S” with the sign bit on).
2C01-2C03
the WRITE ONE BYTE TO CASSETTE routine at 0264H (which writes the byte in the A register to the cassette drive selected in the A register), which in this case the filename header byte.
2C04-2C06
Go write the filename header byte in register A twice more.
2C07
LD A,(DE)
Load register A with the first character of the filename at the location of the filename pointer in DE.
2C08-2C0A
the WRITE ONE BYTE TO CASSETTE routine at 0264H (which writes the byte in the A register to the cassette drive selected in the A register), which in this case is the filename.
2C0B-2C0D
LD HL,(40A4H)
Load 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).
2C0E
EX DE,HL
Load DE with the start of the BASIC program pointer in HL.
2C0F-2C11
LD HL,(40F9H)
Load HL with the end of the BASIC program pointer.
  • Note: 40F9H-40FAH holds the starting address of the simple variable storage area.
2C12
LD A,(DE)
We are going to loop from DE (start of program) to HL (end of program) now. Load register A with the character at the location of the memory pointer in DE.
2C13
INC DE
Bump the value of the memory pointer in DE.
2C14-2C16
the WRITE ONE BYTE TO CASSETTE routine at 0264H (which writes the byte in the A register to the cassette drive selected in the A register).
2C17
RST 18H
Now we need to check to see if the memory pointer in DE is equal to the end of the BASIC program pointer in HL, so we call the COMPARE DE:HL 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.
2C18-2C19
Loop back to 2C12H until the memory pointer in DE is equal to the end of the BASIC program pointer in HL.
2C1A-2C1C
All done! GOSUB 01F8H to turn the cassette recorder off.
2C1D
POP HL
Get the value of the current BASIC program pointer from the stack and put it in HL.
2C1E
RET
Return.


2C1F-2CA4 – LEVEL II BASIC CLOAD ROUTINE

Difference between M1 and M3 ROMs:Another change that originated in the “new” ROM Model I modified the CLOAD command (changed the order of portions of the CLOAD routine, disallowed CLOAD from cassette drive #2, etc.).

2C1F
SUB 0B2H
Test for CLOAD?
2C21
Jump to 2C25H if it is CLOAD?
2C23
XOR A
Signal CLOAD (not CLOAD?)

2C24
LD BC,232FH
CPL A=-1 if CLOAD?, 0000 if CLOAD
2C27
PUSH AF
Increment HL to the filname of the CLOAD/CLOAD? flag
2C28
LD A,(HL)
Set the next element from the code string, which should be the filename
2C29
OR A
Set status flags
2C2A
If it is the EOL, jump to 2C33H
2C2C
Call 2337H to get the filename.
2C2F
Call 2A13H to get the address of the filename into DE
2C32
LD A,(DE)
Get the filename
2C33
LD L,A
Move the filename into Register L
2C34
POP AF
Restore the CLOAD/CLOAD? flag
2C35
OR A
Set the status register according to that flag
2C36
LD H,A
H will now hold CLOAD/CLOAD? flag, and L will hold the filename
2C37
LD (4121H),HL
Put the flag and filename into REG 1.
2C3A
If the flag is a CLOAD, call the NEW routine at 1B4DH.
2C3D
LD HL,0000H
Cause the drive to be selected
2C40
Call 2093H to get the leader and sync byte from the cassette.
2C43
LD HL,(4121H)
Restore the CLOAD/CLOAD? flag and filename
2C46
EX DE,HL
Load DE with the CLOAD/CLOAD? flag and load the filename into HL.
2C47-2C48
LD B,03H
Load register B with the number of bytes for the filename header to match against (which is 3 … 3 S’s with the sign bit on).
2C49-2C4B
Calls the READ ONE BYTE FROM CASSETTE routine at 0235H (which reads one byte from the cassette drive specified in register A, and returns the byte in register A).
2C4C-2C4D
SUB 0D3H
Check to see if the character in register A is a filename header byte.
2C4E-2C4F
Loop if the character in register A isn’t a filename header byte.
2C50-2C51
Loop back to 2C49H until three filename header bytes (3 S’s with the sign bit on) have been read.
2C52-2C54
Now that the header is out of the way, let’s start working on the filename. GOSUB to 0235H to the READ ONE BYTE FROM CASSETTE (which reads one byte from the cassette drive specified in register A, and returns the byte in register A).
2C55
INC E
We need to test to see if a filename was even given so we have to increase and decrease E to set flags … Bump the value of the filename in register E.
2C56
DEC E
Decrement the value of the filename in register E.
2C57-2C58
Jump to 2C5CH if no filename was specified.
2C59
CP E
If we are here, then the user has supplied a filename which is held in Register E AND we have the first byte from the tape in Register A, so we need to compare the filename specified in register E with the character in register A.


2CA5 – “BCD” message string.

2C5A-2C5B
Jump to 2C93H (to skip to the end of that file) if the filename specified in register E doesn’t match the byte read from tape in register A.
2C5C-2C5E
LD HL,(40A4H)
If we are here, the filename on tape matches the filename given so lets start loading. Load 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).

This loop is going to read a byte, compare it to the next byte in the program memory, jump away if it doesn’t match AND CLOAD? was chosen, write (or overwrite) that byte to memory, check for a zero, and loop back if no zero was found.

2C5F-2C60
LD B,03H
Load register B with the number of zeros to look for to stop the load (which is 3).
2C61-2C63
Calls the READ ONE BYTE FROM CASSETTE routine at 0235H (which reads one byte from the cassette drive specified in register A, and returns the byte in register A).
2C64
LD E,A
Load register E with the character in register A.
2C65
SUB (HL)
Compare the character we just read from the tape (held in register A) with the character at the location of the memory pointer in HL by subtracting them.
2C66
AND D
Combine the subtracted result in register A with the value of the CLOAD/CLOAD? flag in register D.
2C67-2C68
Jump to 2C8AH if CLOAD? was selected but the bytes don’t match.
2C69
LD (HL),E
At this point either CLOAD? was selected and the bytes match, or CLOAD was selected. Either way, save the character we read from the tape (held in register E) to the location of the memory pointer in HL.
2C6A-2C6C
Go check for an ?OM ERROR.
2C6D
LD A,(HL)
Load register A with the character at the location of the memory pointer in HL.
2C6E
OR A
Check to see if the byte just read in register A is equal to zero.
2C6F
INC HL
Bump the value of the memory pointer in HL.
2C70-2C71
Loop if the byte in register A isn’t equal to zero (meaning that it isn’t end of program or end of statement).
2C72-2C74
Call the BLINK ASTERISK routine at 022CH which alternatively displays and clears an asterisk in the upper right hand corner of the video display.
2C75-2C76
Do that loop until three zeros in a row have been read from the cassette recorder.
2C77-2C79
LD (40F9H),HL
By this point, HL will have been incremented all the way through the program. Save the value of the memory pointer in HL as the new end of the BASIC program pointer.
  • Note: 40F9H-40FAH holds the starting address of the simple variable storage area.
*2C7A-2C7C
GOSUB to 01F8H to turn off the tape.
Difference between M1 and M3 ROMs: Also part of CLOAD, this change turns off the tape before printing READY on the video display. In the Model I, the code from 2C7AH – 2C82H consisted of the instructions LD HL,1929H; CALL 28A7H, CALL 01F8H. In the Model III the CALL to 01F8H has been moved to the beginning of these instructions.
*2C7D-2C7F
LD HL,1929H
Load HL with the starting address of the BASIC READY message.
*2C80-2C82
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).
2C83-2C85
LD HL,(40A4H)
Load 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).
2C86
PUSH HL
Save the start of the BASIC program pointer in HL to the stack.
2C87-2C89
Jump to 1AE8H to reinitialize the BASIC interpreter and continue.
*2C8A-2C8C
GOSUB to 31BDH to reset the cassette I/O.
Difference between M1 and M3 ROMs: This is part of the CLOAD? routine used when a bad byte has been read from the tape. In the Model I, a LD HL, 2CA5H instruction is found here (loads HL with the starting address of the “BAD” message), while the Model III uses a CALL 31BDH instruction, which does some housekeeping in addition to pointing HL to the “BAD” message.
2C8D-2C8F
We need to display the BAD 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).
2C90-2C92
Jump to 1AE8H to reinitialize the BASIC interpreter and continue.
2C93-2C95
LD (3C3EH),A
Go display the filename on the video display.
2C96-2C97
LD B,03H
Load register B with the number of zeros to be found to stop the search.
2C98-2C9A
Calls the READ ONE BYTE FROM CASSETTE routine at 0235H (which reads one byte from the cassette drive specified in register A, and returns the byte in register A).
2C9B
OR A
Check to see if the character in register A is equal to zero.
2C9C-2C9D
Loop if the character in register A isn’t equal to zero.
2C9E-2C9F
Loop until three zeros in a row have been read from the cassette recorder.
2CA0-2CA2
Calls the READ CASSETTE LEADER routine at 0296 (which reads from the cassette recorder selected in register A until the end-of-leader marker of A5H is found; and flashes the cursor while doing this).
2CA3-2CA4
Jump back to 2C47H.


2CA5-2CA9 – MESSAGE STORAGE LOCATION

2CA5-2CA9
“BAD”
The BAD message is stored here.


2CAA-2CB0 – LEVEL II BASIC PEEK ROUTINE – On entry, REG 1 to have the peek location, and on exit Reg 1 to have the peeked value.

2CAA-2CAC
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).
2CAD
LD A,(HL)
Load register A with the value at the location of the memory pointer in HL.
2CAE-2CB0
Go save the 8-bit value in register A as the current result in REG 1.


2CB1-2CBC – LEVEL II BASIC POKE ROUTINE

2CB1-2CB3
Go evaluate the expression at the location of the current BASIC program pointer in HL and return with the integer result in DE.
2CB4
PUSH DE
Save the address the user wants to POKE to (held in DE) to the stack.
2CB5-2CB6
RST 08H
2E
Since the character at the location of the current BASIC program pointer in HL must be a ,, call the COMPARE SYMBOL routine at RST 08H.

NOTE: The RST 08H routine compares 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 the next execution address (i.e, the RST 08H instruction + 2) with the next symbol in the A Register 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).
2CB7-2CB9
GOSUB to 2B1CH to evaluate the expression at the location of the current BASIC program pointer in HL and return with the 8-bit value in register A.
2CBA
POP DE
Get the address the user wants to POKE to from the stack and put it in DE.
2CBB
LD (DE),A
Save the value the user wanted to poke (held in register A) in the location that the user wants to POKE to (held in DE).
2CBC
RET
Return.


2CBD-2E52 – LEVEL II BASIC USING ROUTINE

2CBD-2CBF
Go evaluate the string expression at the location of the current BASIC program pointer in HL.
2CC0-2CC2
Go make sure the expression that was just evaluated was a string.
2CC3-2CC4
RST 08H
3B
Since the character at the location of the current BASIC program pointer in HL must be a “;”, call the COMPARE SYMBOL routine at RST 08H.

NOTE: The RST 08H routine compares 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 the next execution address (i.e, the RST 08H instruction + 2) with the next symbol in the A Register 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).
2CC5
EX DE,HL
Load DE with the value of the current BASIC program pointer in HL.
2CC6-2CC8
LD HL,(4121H)
Load HL with the USING string’s VARPTR.
2CC9-2CCA
Jump down to 2CD3H to continue.
2CCB-2CCD
LD A,(40DEH)
Load register A with the value of the READ/INPUT flag.
Note: 40DEH holds READ flag.
2CCE
OR A
Check to see if the READ/INPUT flag in register A indicates INPUT.
2CCF-2CD0
Jump down to 2CDDH if the READ/INPUT flag in register A indicates INPUT.
2CD1
POP DE
Restore the current BASIC program pointer (from the stack) into DE.
2CD2
EX DE,HL
Load HL with the value of the current BASIC program pointer in DE. D will wind up being the length of the string
2CD3
PUSH HL
Save the USING string’s VARPTR in HL to the stack.
2CD4
XOR A
Zero register A.
2CD5-2CD7
LD (40DEH),A
Clear the READ/INPUT flag.
Note: 40DEH holds READ flag.
2CD8
CP D
Check to see if the value in D is equal to zero (by checking it against A which was XOR’d to 0 above).
2CD9
PUSH AF
Save the value in AF (the difference) to the stack.
2CDA
PUSH DE
Save the value in DE (the address of the next input symbol from the code string) to the stack.
2CDB
LD B,(HL)
Load register B with the USING string’s length at the location of the USING string’s VARPTR in HL.
2CDC
OR B
Check to see if the USING string’s length in register B is equal to zero.
2CDD-2CDF
Display a ?FC ERROR if the USING string’s length in register B is equal to zero.
2CE0
INC HL
Bump the value of the USING string’s VARPTR in HL.
2CE1
LD C,(HL)
Load register C with the LSB of the USING string’s address at the location of the USING string’s VARPTR in HL.
2CE2
INC HL
Bump the value of the USING string’s VARPTR in HL.
2CE3
LD H,(HL)
Load register H with the MSB of the USING string’s address at the location of the USING string’s VARPTR in HL.
2CE4
LD L,C
Load register L with the LSB of the USING string’s address in register C.
2CE5-2CE6
Jump down to 2D03H to analyze the field description.
2CE7
LD E,B
Load register E with the USING string’s length in register B.
2CE8
PUSH HL
Save the value of the current USING string pointer in HL.
2CE9-2CEA
LD C,02H
Load register C with the number of %’s substring length.
2CEB
LD A,(HL)
Load register A with the character at the location of the USING string pointer in HL.
2CEC
INC HL
Bump the value of the USING string pointer in HL.
2CED-2CEE
CP 25H
Check to see if the character in register A is a %.
2CEF-2CF1
Jump down to 2E17H if the character in register A is a %.
2CF2-2CF3
CP 20H
Check to see if the character in register A is a space.
2CF4-2CF5
Jump down a few opcodes to 2CF9H if the character in register A isn’t a space.
2CF6
INC C
Bump the % substring length in register C.
2CF7-2CF8
Decrement the USING string’s length in register B.
2CF9
POP HL
At this point we have either exhausted the input or found a non-blank character. In either case … get the value of the USING string pointer from the stack and put it in HL.
2CFA
LD B,E
Load register B with the USING string’s length.
2CFB-2CFC
LD A,25H
Load register A with a %.
2CFD-2CFF
Go print a + after printing a single % if necessary.
2D00-2D02
Go print the character in register A.
2D03
XOR A
Zero register A and clear the flags.
2D04
LD E,A
Zero register E.
2D05
LD D,A
Zero register D.
2D06-2D08
Go print a leading + if necessary.
2D09
LD D,A
Zero register D.
2D0A
LD A,(HL)
Load register A with the character (i.e., the field description) at the location of the USING string pointer in HL.
2D0B
INC HL
Bump the value of the USING string pointer in HL.
2D0C-2D0D
CP 21H
Check to see if the character in register A is a !.
2D0E-2D10
Jump if the character in register A is a !.
2D11-2D12
CP 23H
Check to see if the character in register A is a #.
2D13-2D14
Jump if the character in register A is a #.
2D15
DEC B
Decrement the value of the string’s length in register B.
2D16-2D18
Jump if this is the end of the USING string.
2D19-2D1A
CP 2BH
Check to see if the character in register A is a +.
2D1B-2D1C
LD A,08H
Set the flag in register A to force a leading +.
2D1D-2D1E
Jump if the character in register A was a +.
2D1F
DEC HL
Decrement the value of the USING string pointer in HL.
2D20
LD A,(HL)
Load register A with the character at the location of the USING string pointer in HL.
2D21
INC HL
Bump the value of the USING string pointer in HL.
2D22-2D23
CP 2EH
Check to see if the character in register A is a ..
2D24-2D25
Jump if the character in register A is a ..
2D26-2D27
CP 25H
Check to see if the character in register A is a %.
2D28-2D29
Jump if the character in register A is a %.
2D2A
CP (HL)
Compare the character in register A with the character at the location of the USING string pointer in HL.
2D2B-2D2C
Jump if the character in register A isn’t equal to the character at the location of the USING string pointer in HL.
2D2D-2D2E
CP 24H
Check to see if the character in register A is a $.
2D2F-2D30
Jump if the character in register A is a $.
2D31-2D32
CP 2AH
Check to see if the character in register A is a *.
2D33-2D34
Jump if the character in register A isn’t a *.
2D35
LD A,B
Load register A with the USING string’s length in register B.
2D36-2D37
CP 02H
Check to see if the USING string’s length in register A is at least two.
2D38
INC HL
Bump the value of the USING string pointer in HL.

2D39-2D3A
Jump to 2D3EH if the USING string’s length in register A isn’t at least two.
2D3B
LD A,(HL)
Load register A with the character at the location of the USING string pointer in HL.
2D3C-2D3D
CP 24H
Check to see if the character in register A is a string.
2D3E-2D3F
LD A,20H
Set the ** edit flag in register A.
2D40-2D41
Jump if the character in register A isn’t a $.
2D42
DEC B
Decrement the value of the USING string’s length in register.
2D43
INC E
Bump the number of characters to the left of the decimal point in register E.
2D44-2D45
FE AF
Z-80 Trick to skip over a XOR A if passing through by processing it as a CP AFH.
2D45
XOR A
This is $ processing for PRINT USING.
2D46-2D47
ADD A,10H
Mask the value of the edit flag in register A for leading $‘s.
2D48
INC HL
Bump the value of the USING string pointer in HL.
2D49
INC E
Bump the number of characters to the left of the decimal point in register E.
2D4A
ADD A,D
Combine the value of the edit flag in register D with the value of the edit flag in register A.
2D4B
LD D,A
Load register D with the value of the edit flag in register A.
2D4C
INC E
Bump the number of characters to the left of the decimal point in register E.
2D4D-2D4E
LD C,00H
Zero the number of characters to the right of the decimal point in register C.
2D4F
DEC B
Decrement the value of the string’s length in register B.
2D50-2D51
Jump if this is the end of the string.
2D52
LD A,(HL)
Load register A with the character at the location of the USING string pointer in HL.
2D53
INC HL
Bump the value of the USING string pointer in HL.
2D54-2D55
CP 2EH
Check to see if the character in register A is a ..
2D56-2D57
Jump if the character in register A is a ..
2D58-2D59
CP 23H
Check to see if the character in register A is a #.
2D5A-2D
5BH Jump if the character in register A is a #.
2D5C-2D5D
CP 2CH
Check to see if the character in register A is a ,.
2D5E-2D5F
Jump if the character in register A isn’t a ,.
2D60
LD A,D
Load register A with the value of the edit flag in register D.
2D61-2D62
OR 40H
Mask the edit flag in register A for ,.
2D63
LD D,A
Load register D with the value of the edit flag in register A.
2D64-2D65
Jump to 2D4CH.
2D66
LD A,(HL)
Load register A with the character at the location of the USING string pointer in HL.
2D67-2D68
CP 23H
Check to see if the character in register A is a #.
2D69-2D6A
LD A,2EH
Load register A with a decimal point.
2D6B-2D6C
Jump if the character in register A wasn’t a #.
2D6D-2D6E
LD C,01H
Load register C with the number of characters to the right of the decimal point.
2D6F
INC HL
Bump the value of the USING string pointer in HL.
2D70
INC C
Bump the number of characters to the right of the decimal point in register C.
2D71
DEC B
Decrement the value of the string’s length in register B.
2D72-2D73
Jump if this is the end of the string.
2D74
LD A,(HL)
Load register A with the character at the location of the USING string pointer in HL.
2D75
INC HL
Bump the value of the USING string pointer in HL.
2D76-2D77
CP 23H
Check to see if the character in register A is a #.
2D78-2D79
Jump if the character in register A is a #.
2D7A
PUSH DE
Save the value of the edit flag and the count of the characters to the left of the decimal point in DE to the stack.
2D7B-2D7D
LD DE,2D97H
Load DE with the return address.
2D7E
PUSH DE
Save the value of the return address in DE to the stack.
2D7F
LD D,H
Load register D with the MSB of the USING string pointer m register H.
2D80
LD E,L
Load register E with the LSB of the USING string pointer in register L.
2D81-2D82
CP 5BH
Check to see if the character in register A is an up arrow.
2D83
RET NZ
Return if the character in register A isn’t an up arrow.

2D84
CP (HL)
Check to see if the character at the location of the USING string pointer in HL is an up arrow.
2D85
RET NZ
Return to 2D97 if the character at the location of the USING string pointer in HL isn’t an up arrow (meaning we do not have a [[ format).

2D86
INC HL
Bump the value of the USING string pointer in HL.
2D87
CP (HL)
Check to see if there is a third up arrow at the location of the USING string pointer in HL.
2D88
RET NZ
Return to 2D97 if the character at the location of the USING string pointer in HL isn’t an up arrow (meaning we do not have a [[[ format).

2D89
INC HL
Bump the value of the USING string pointer in HL.
2D8A
CP (HL)
Check to see if the character at the location of the USING string pointer in HL is a fourth up arrow.
2D8B
RET NZ
Return to 2D97 if the character at the location of the USING string pointer in HL isn’t an up arrow (meaning we do not have a [[[[ format).

2D8C
INC HL
Bump the value of the USING string pointer in HL. If we are here we have a #.##[[[[ format.
2D8D
LD A,B
Load register A with the value of the USING string’s length in register B.
2D8E-2D8F
SUB 04H
Check to see if there are at least 4 characters left in the USING string.
2D90
RET C
Return to 2D97 if there aren’t at least four characters left in the USING string.

2D91
POP DE
If there are at least 4 characters left, then clean up the stack.
2D92
POP DE
Get the edit flag and the count of the characters to the left of the decimal point from the stack and put it in DE.
2D93
LD B,A
Load register B with the USING string’s length in register A.
2D94
INC D
Set the exponential notation flag in register D.
2D95
INC HL
Bump the value of the USING string pointer in HL.
2D96
CA
Z-80 Trick! By putting the CA opcode here, the next 2 bytes are ignored if passing through, but remain in effect if jumped to.
2D97
EX DE,HL
(Ignored if passing through) Load HL with the value of the USING string pointer in DE.
2D98
POP DE
(Ignored if passing through) Get the edit flag and the count of the characters to the left of the decimal point from the stack and put it in DE.
2D99
LD A,D
Load register A with the value of the edit flag in register D.
2D9A
DEC HL
Decrement the value of the USING string pointer in HL.
2D9B
INC E
Bump the number of characters to the left of the decimal point in register E.
2D9C-2D9D
AND 08H
Check to see if the sign flag is set in register A.
2D9E-2D9F
Jump to 2DB5H if the sign flag has already been processed.
2DA0
DEC E
Decrement the number of characters to the left of the decimal point in register E.
2DA1
LD A,B
Load register A with the USING string’s length in register B.
2DA2
OR A
Check to see if this is the end of the string.
2DA3-2DA4
Jump to 2DB5H if this is the end of the string.
2DA5
LD A,(HL)
Load register A with the character at the location of the USING string pointer in HL.
2DA6-2DA7
SUB 2DH
Check to see if the character in register A is a – .
2DA8-2DA9
Jump to 2DB0H if the character in register A is a – .
2DAA-2DAB
CP 0FEH
Check to see if the character in register A is a +.
2DAC-2DAD
Jump to 2DB5H if the character in register A isn’t a +.
2DAE-2DAF
LD A,08H
Set the edit flag for a + character.
2DB0-2DB1
ADD A,04H
Set the edit flag for a – character.
2DB2
ADD A,D
Combine the value of the edit flag in register D with the value of the edit flag in register A.
2DB3
LD D,A
Load register D with the value of the edit flag in register A.
2DB4
DEC B
Decrement the value of the USING string’s length in register B.
2DB5
POP HL
Get the value of the current BASIC program pointer from the stack and put it in HL.
2DB6
POP AF
Load register A with the character at the location of the current BASIC program pointer in HL.
2DB7-2DB8
Jump if this is the end of the BASIC statement.
2DB9
PUSH BC
Save the count of the characters to the right of the decimal point and the USING string’s length in BC to the stack.
2DBA
PUSH DE
Save the edit flag and the number of characters to the left of the decimal point in DE to the stack.
2DBB-2DBD
Go evaluate the expression at the location of the current BASIC program pointer and return with the result in REG 1.
2DBE
POP DE
Get the edit flag and the number of characters to the left of the decimal point from the stack and put it in DE.
2DBF
POP BC
Get the number of characters to the right of the decimal point and the USING string’s length from the stack and put it in BC.
2DC0
PUSH BC
Save the number of characters to the right of the decimal point and the USING string’s length m BC to the stack.
2DC1
PUSH HL
Save the value of the current BASIC program pointer in HL to the stack.
2DC2
LD B,E
Load register B with the number of characters to the left of the decimal point in register E.
2DC3
LD A,B
Load register A with the number of characters to the left of the decimal point in register B.
2DC4
ADD A,C
Add the number of characters to the right of the decimal point in register C to the number of characters to the left of the decimal point in register A.
2DC5-2DC6
CP 19H
Check to see if the total number of characters in register A is greater than 24.
2DC7-2DC9
Display a FC ERROR message if the total number of characters in register A is greater than 24.
2DCA
LD A,D
Load register A with the value of the edit flag in register D.
2DCB-2DCC
OR 80H
Set the edit flag in register A.
2DCD-2DCF
Call the FLOATING TO ASCII routine at 0FBEH (whcih converts a single or double precision number in REG 1 to its ASCII equivalent which will be stored at the buffer pointed to by HL using the format codes in the A, B, and C registers.
2DD0-2DD2
We need to display the ASCII string, 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).
2DD3
POP HL
Get the value of the current BASIC program pointer from the stack and put it in HL.
2DD4
DEC HL
Decrement the value of the current BASIC program pointer in HL.
2DD5
RST 10H
We need the next character in the BASIC program so 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.
2DD6
SCF
Set the Carry flag.
2DD7-2DD8
Jump if the character at the location of the current BASIC program pointer in register A is an end of the BASIC statement character.
2DD9-2DDB
LD (40DEH),A
Save the character at the location of the current BASIC program pointer in register A.
Note: 40DEH holds READ flag.
2DDC-2DDD
CP 3BH
Check to see if the character at the location of the current BASIC program pointer in register A is a semicolon.
2DDE-2DDF
Jump if the character at the location of the current BASIC program pointer in register A is a semicolon.
2DE0-2DE1
CP 2CH
Check to see if the character at the location of the current BASIC program pointer in register A is a comma.
2DE2-2DE4
Go to the Level II BASIC error routine and display an SN ERROR message if the character at the location of the current BASIC program pointer in register A isn’t a comma.
2DE5
RST 10H
We need the next character in the BASIC program so 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.
2DE6
POP BC
Get the USING string’s length from the stack and put it in register B.
2DE7
EX DE,HL
Load DE with the value of the current BASIC program pointer in HL.
2DE8
POP HL
Get the USING string’s VARPTR from the stack and put it in HL.
2DE9
PUSH HL
Save the USING string’s VARPTR in HL to the stack.
2DEA
PUSH AF
Save the character at the location of the current BASIC program pointer in register A to the stack.
2DEB
PUSH DE
Save the value of the current BASIC program pointer in DE to the stack.
2DEC
LD A,(HL)
Load register A with the USING string’s length at the location of the USING string’s VARPTR in HL.
2DED
SUB B
Compare the USING string’s length in register B with the USING string’s length in register A.
2DEE
INC HL
Bump the value of the USING string’s VARPTR in HL.
2DEF
LD C,(HL)
Load register C with the LSB of the USING string’s address at the location of the USING string’s VARPTR in HL.
2DF0
INC HL
Bump the value of the USING string’s VARPTR in HL.
2DF1
LD H,(HL)
Load register H with the MSB of the USING string’s address at the location of the USING string’s VARPTR in HL.
2DF2
LD L,C
Load register L with the LSB of the USING string’s address in register C.
2DF3-2DF4
LD D,00H
Zero register D.
2DF5
LD E,A
Load register E with the USING string’s offset in register A.
2DF6
ADD HL,DE
Add the USING string’s offset in DE to the USING string’s address in HL.
2DF7
LD A,B
Load register A with the USING string’s length in register B.
2DF8
OR A
Check to see if this is the end of the USING string.
2DF9-2DFB
Jump to 2D03H if this isn’t the end of the USING string.
2DFC-2DFD
Jump to 2E04H if this is the end of the USING string.
2DFE-2E00
GOSUB to 2E49H print a + if necessary.
2E01-2E03
Go send the character in register A to the current output device.
2E04
POP HL
Get the value of the current BASIC program pointer from the stack and put it in HL.
2E05
POP AF
Get the character at the location of the current BASIC program pointer from the stack and put it in register A.
2E06-2E08
Jump back to 2CCBH if this isn’t the end of the BASIC statement.

2E09-2E0B
GOSUB to 20FEH to send a carriage return to the current output device if necessary.
2E0C
EX (SP),HL
Exchange the value of the current BASIC program pointer in HL with the value of the USING string’s VARPTR to the stack.
2E0D-2E0F
Go get the USING string’s address in DE.
2E10
POP HL
Get the value of the current BASIC program pointer from the stack and put it in HL.
2E11-2E13
Return to 2169H.

2E14-2E15
LD C,01H
Continue processing a ! in the USING format by loading register C with the number of characters to be printed.
2E16-2E17
3E F1
Z-80 Trick. By putting a 3E in front of the F1 (which is POP AF, to clear the stack) that POP AF gets skipped if flowing down in the code.
2E17
POP AF
(Skipped if passing down) Clear the stack.
2E18
DEC B
Decrement the value of the string’s length in register B.
2E19-2E1B
Go print a + if register D is not zero.
2E1C
POP HL
Get the value of the current BASIC program pointer from the stack and put it in HL.
2E1D
POP AF
Get the character at the location of the current BASIC program pointer from the stack and put it in register A.
2E1E-2E1F
Jump back to 2E09H if the character at the location of the current BASIC program pointer in register A is an end of the BASIC statement character.
2E20
PUSH BC
Save the USING string’s length and the number of characters to be printed in BC to the stack.
2E21-2E23
Go evaluate the expression at the location of the current BASIC program pointer in HL and return with the result in REG 1
2E24-2E26
Go make sure the current result in REG 1 is a string.
2E27
POP BC
Get the USING string’s length and the number of characters to be printed from the stack and put it in BC.
2E28
PUSH BC
Save the USING string’s length and the number of characters to be printed in BC to the stack.
2E29
PUSH HL
Save the value of the current BASIC program pointer in HL to the stack.
2E2A-2E2C
LD HL,(4121H)
Load HL with the string’s VARPTR in REG 1.
2E2D
LD B,C
Load register B with the number of characters to be printed in register C.
2E2E-2E2F
LD C,00H
Zero register C.
2E30
PUSH BC
Save the length of the string to be printed in register B to the stack.
2E31-2E33
Go evaluate the string to be printed.
2E34-2E36
Go send the string to the current output device.
2E37-2E39
LD HL,(4121H)
Load HL with the string’s VARPTR in REG 1.
2E3A
POP AF
Get the length of the string to be printed from the stack and put it in register A.
2E3B
SUB (HL)
Subtract the string’s length at the location of the string’s VARPTR in HL from the length of the string to be printed in register A.
2EJC
LD B,A
Load register B with the number of spaces to be printed in register A.
2EJD-2EJE
LD A,20H
Load register A with a space.
2E3F
INC B
Bump the number of spaces in register B.

This loop will print all the spaces needed and then jump to 2DD3H.

2E40
Decrement the number of spaces in register B.
2E41-2E43
Jump back to 2DD3H if all of the spaces have been printed.
2E44-2E46
Go send a space to the current output device.
2E47-2E48
Jump back to 2E40H.
2E49
PUSH AF
Save the value in register A to the stack.
2E4A
LD A,D
Load register A with the value in register D.
2E4B
OR A
Check to see if register A is equal to zero.
2E4C-2E4D
LD A,2BH
Load register A with a +.
2E4E-2E50
Go send a + to the current output device if register D is non-zero.
2E51
POP AF
Get the value from the stack and put it in register A.
2E52
RET
Return.


2E53-2FFA – LEVEL II BASIC EDIT ROUTINE

2E53-2E55
LD (409AH),A
Reset the error flag.
Note: 409AH holds the RESUME flag.
2E56-2E58
LD HL,(40EAH)
Load HL with the line number where the error occurred.
Note: 40EAH-40EBH holds the line number with error.
2E59
OR H
OR register A with the MSB of the error line number in register H.
2E5A
AND L
Combine the LSB of the error line number in register L with the MSB of the error line number in register A. It will be FFH if execution had not begun.
2E5B
INC A
Bump the combined value of the error line number in register A. If execution had not begin, this will turn A from FFH into 00H
2E5C
EX DE,HL
Load DE with the line number with the error (held in HL).
2E5D
RET Z
If there was no line number, return if Level II BASIC.

2E5E-2E5F
Jump to 2E64H.

Now that the above code is out of the way (it was the code which would enter EDIT if there was an error in a line number), let us actually process the EDIT command.

2E60-2E62
Get the first line number by calling 1E4F – returns in in DE.
2E63
RET NZ
If the zero flag got set, there was no line number, so return.

2E64
POP HL
Clean up the stack.
2E65
EX DE,HL
Load HL with the line number to be edited in DE.
2E66-2E68
LD (40ECH),HL
Save the value of the line number to be edited (in HL) to the memory location that cares about such things.
Note: 40ECH-40EDH holds EDIT line number.
2E69
EX DE,HL
Load DE with the line number to be edited in HL.
2E6A-2E6C
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.
2E6D-2E6F
If the BASIC line number doesn’t exist, display a ?UL ERROR.
2E70
LD H,B
At this point, the line number has been found. Load register H with the MSB of the memory pointer in register B.
2E71
LD L,C
Load register L with the LSB of the memory pointer in register C.
2E72
INC HL
Bump the value of the memory pointer in HL.
2E73
INC HL
Bump the value of the memory pointer in HL.
2E74
LD C,(HL)
Load register C with the LSB of the BASIC line number at the location of the memory pointer in HL.
2E75
INC HL
Bump the value of the memory pointer in HL.
2E76
LD B,(HL)
Load register B with the MSB of the BASIC line number at the location of the memory pointer in HL.
2E77
INC HL
Bump the value of the memory pointer in HL.
2E78
PUSH BC
Save the value of the BASIC line number in BC to the stack.
2E79-2E7B
Go move the BASIC line we are working on into the input buffer and expand it.
2E7C
POP HL
Get the value of the BASIC line number from the stack and put it in HL.
2E7D
PUSH HL
Save the value of the BASIC line number in HL to the stack.
2E7E-2E80
Convert the line number to ASCII and print it out by calling the HL TO ASCII routine at 0FAFH (which converts the value in the HL (assumed to be an integer) to ASCII and display it at the current cursor position on the video screen).
2E81-2E82
LD A,20H
Load register A with a space.
2E83-2E85
Go display the space in register A.
2E86-2E88
LD HL,(40A7H)
Load HL with the starting address of the expended version of the current line from the input buffer.
Note: 40A7H-40A8H holds the input Buffer pointer.
2E89-2E8A
LD A,0EH
Load register A with the “turn on the cursor” character.
2E8B-2E8D
Go turn on the cursor.
2E8E
PUSH HL
Save the value of the input buffer pointer (in HL) to the stack.
2E8F-2E90
LD C,FFH
Load register C with the number of characters examined so far with FFH because the next line is going to INC it by 1 to make it 0.
2E91
INC C
Bump the number of characters examined so far in register C.
2E92
LD A,(HL)
Load register A with the character at the location of the input buffer pointer in HL.
2E93
OR A
Check to see if the character in register A is an end of the BASIC line character.
2E94
INC HL
Bump the value of the input buffer pointer in HL.
2E95-2E96
Loop back to 2E91H until the end of the BASIC line has been found.
2E97
POP HL
At this point, C will be the maximum number of characters in the line at issue. Put the start of the expended buffer into HL.
2E98
LD B,A
Zero register B. B will ultimately contain the count of characters inserted.
2E99-2E9A
LD D,00H
Zero register D.
2E9B-2E9D
Go scan the keyboard.
2D9E-2E9F
SUB 30H
We need to test to see if the character was alphabetic or alphanumeric so we subtract 30H from it.

2EA0-2EA1
Jump down to 2EB0H if the character in register A is alphabetic.
2EA2-2EA3
CP 0AH
Check to see if the character is register A is numeric.

2EA4-2EA5
Jump to 2EB0H if the character in register A isn’t numeric.
2EA6
LD E,A
Load register E with the binary value of the character in register A.
2EA7
LD A,D
Load register A with the value in register D.
2EA8
RLCA
Multiply the value in register A by two (so now A has multiplied by 2).
2EA9
RLCA
Multiply the value in register A by two (so now A has multiplied by 4).
2EAA
ADD A,D
Add the value in register D to the value in register A (so now A has multiplied by 5).
2EAB
RLCA
Multiply the value in register A by two (so now A has multiplied by 10).
2EAC
ADD A,E
Add the value in register E to the value in register A.
2EAD
LD D,A
Load register D with the value in register A.
2EAE-2EAF
Loop until a nonnumeric character is pressed.
2EB0
PUSH HL
Save the value of the input buffer pointer in HL to the stack.
2EB1-2EB3
LD HL,2E99H
Load HL with the return address of 2E99H.
2EB4
EX (SP),HL
Exchange the value of the return address in HL with the value of the input buffer pointer to the stack.
2EB5
DEC D
We need to test if the command was preceded by a number so we need to set the flags by first … decrementing the numeric value in register D …
2EB6
INC D
… and then incrementing the numeric value in register D.
2EB7-2EB9
Jump to 2EBBH if a numeric value preceded the command (i.e., register D isn’t equal to zero).
2EBA
INC D
Load register D with a one.
2EBB-2EBC
CP 0D8H
Check to see if the character in register A is a backspace character.
2EBD-2EBF
Jump if the character in register A is a backspace character.
2EC0-2EC1
CP 0DDH
Check to see if the character in register A is a carriage return.
2EC2-2EC4
Jump if the character in register A is a carriage return.
2EC5-2EC6
CP 0F0H
Check to see if the character in register A is a space.
2EC7-2EC8
Jump if the character in register A is a space.
2EC9-2ECA
CP 31H
Check to see if the character in register A is lowercase.

2ECB-2ECC
Jump if the character in register A isn’t lowercase.
2ECD-2ECE
SUB 20H
Convert the lowercase character in register A to uppercase.
2ECF-2ED0
CP 21H
Check to see if the character in register A is a Q.
2ED1-2ED3
Jump if the character in register A is a Q.
2ED4-2ED5
CP 1CH
Check to see if the character in register A is an L.
2ED6-2ED7
Jump if the character in register A is an L.
2ED9-2EDA
CP 23H
Check to see if the character in register A is an S.
2EDB-2EDC
Jump if the character in register A is an S.
2EDD-2EDE
CP 19H
Check to see if the character in register A is an I.
2EDF-2EE1
Jump if the character in register A is an I.
2EE2-2EE3
CP 14H
Check to see if the character in register A is a D.
2EE4-2EE6
Jump if the character in register A is a D.
2EE7-2EE8
CP 13H
Check to see if the character in register A is a C.
2EE9-2EEB
Jump if the character in register A is a C.
2EEC-2EED
CP 15H
Check to see if the character in register A is an E.
2EEE-2EF0
Jump if the character in register A is an E.
2EF1-2EF2
CP 28H
Check to see if the character in register A is an X.
2EF3-2EF5
Jump if the character in register A is an X.
2EF6-2EF7
CP 1BH
Check to see if the character in register A is a K.
2EF8-2EF9
Jump if the character in register A is a K.
2EFA-2EFB
CP 18H
Check to see if the character in register A is an H.
2EFC-2EFE
Jump if the character in register A is an H.
2EFF-2F00
CP 11H
Check to see if the character in register A is an A.
2F01
RET NZ
Return if the character in register A isn’t an A.


2F02 – EDIT Command – Cancel and Restore Logic.


2F02
POP BC
Clean up the stack.
2F03
POP DE
Get the BASIC line number from the stack and put it in DE.
2F04-2F06
Go print a carriage return on the video display if necessary.
2F07-2F09
Jump back to 2E65H to re-enter the EDIT routine.


2F0A – This routine prints a string of text to the display, printer or tape. it uses 032AH to do this. HL must point to the first character of the string. (409CH must be set before calling this routine, see 32AH). String must be delimited with a zero byte.
Note: 409CH holds the current output device flag: -1=cassette, 0=video and 1=printer.

2F0A
LD A,(HL)
Load register A with the character at the location of the input buffer pointer in HL.
2F0B
OR A
Check to see if the character in register A is an end of the BASIC line character.
2F0C
RET Z
Return if the character in register A is an end of the BASIC line character.

2F0D
INC B
Bump the character position in register B.
2F0E-2F10
Go display the character in register A.
2F11
INC HL
Bump the value of the input buffer pointer in HL.
2F12
DEC D
Decrement the number of times to perform the operation in register D.
2F13-2F14
Loop until done.
2F15
RET
Return.


2F16 – EDIT Command – KILL Logic.

2F16
PUSH HL
Save the value of the input buffer pointer in HL to the stack.
2F17-2F19
LD HL,2F5FH
Load HL with the return address of 2F5FH (which will print the final !).
2F1A
EX (SP),HL
Exchange the value of the return address in HL with the value of the input buffer pointer to the stack.
2F1B
SCF
Set the KILL/SEARCH flag for KILL since CARRY flag signals KILL.
2F1C
PUSH AF
Save the KILL/SEARCH flag to the stack.
2F1D-2F1F
Go scan the keyboard for the character to locate.
2F20
LD E,A
Load register E with the character to locate in register A.
2F21
POP AF
Get the KILL/SEARCH flag from the stack.
2F22
PUSH AF
Save the KILL/SEARCH flag to the stack.

2F23-2F25
If KILL (because the CARRY flag was set) then GOSUB to 2F5FH to print a !.
2F26
LD A,(HL)
Load register A with the character at the location of the input buffer pointer in HL.
2F27
OR A
Check to see if the character in register A is an end of the BASIC line character.
2F28-2F2A
Jump down to 2F3EH if the character in register A is an end of the BASIC line character.
2F2B-2F2D
Go display the character in register A.
2F2E
POP AF
Get the KILL/SEARCH flag from the stack.
2F2F
PUSH AF
Save the KILL/SEARCH flag to the stack.

2F30-2F32
If the CARRY flag is set, that means we are in KILL mode so GOSUB to 2FA1H to delete the character from the input buffer.

2F33-2F34
Jump to 2F37H if KILL.
2F35
INC HL
If we are here, it must be SEARCH! So bump to the next character.
2F36
INC B
Bump the value of the character position counter in register B.
2F37
LD A,(HL)
Regardless of whether we are SEARCH or KILL, load register A with the character at the location of the current input buffer pointer in HL.
2F38
CP E
Check to see if the character in register A is the same as the character to be located in register E.
2F39-2F3A
Loop back to 2F26H until the character to be located is found.
2F3B
DEC D
Decrement the number of times to perform the operation in register D.
2F3C-2F3D
Loop until done.
2F3E
POP AF
Get the KILL/SEARCH flag from the stack.
2F3F
RET
Return.


2F40 – EDIT Command – LIST Logic.

2F40-2F42
Since we need to display the line being edited we call the PRINT MESSAGE routine at 2B75H which writes string pointed to by HL to the current output device..
2F43-2F45
Go display a carriage return if necessary.
2F46
POP BC
Get the BASIC line number from the stack and put it in BC.
2F47-2F49
Jump to 2E7CH (to print the current line number and await the next EDIT command).


2F4A – EDIT Command – DELETE Logic.

2F4A
LD A,(HL)
Load register A with the character at the location of the input buffer pointer in HL.
2F4B
OR A
Check to see if the character in register A is an end of the BASIC line character.
2F5C
RET Z
Return if the character in register A is an end of the BASIC line character.

2F4D-2F4E
LD A,21H
Load register A with an !.
2F4F-2F51
Go display the ! in register A.
2F52
LD A,(HL)
Load register A with the character at the location of the input buffer pointer in HL.
2F53
OR A
Check to see if the character in register A is an end of the BASIC line character.
2F54-2F5B
Jump to 2F5FH if the character in register A is an end of the BASIC line character.
2F56-2F58
Go display the character in register A.
2F59-2F5B
Go delete the character from the input buffer.
2F5C
DEC D
Decrement the number of times to perform the operation in register D.
2F5D-2F5E
Loop until done.
2F5F-2F60
LD A,21H
Load register A with an !.
2F61-2F63
Go display the ! in register A.
2F64
RET
Return.


2F65 – EDIT Command – CHANGE Logic.

2F65
LD A,(HL)
Load register A with the character at the location of the input buffer pointer in HL.
2F66
OR A
Check to see if the character in register A is an end of the BASIC line character.
2F67
RET Z
Return if the character in register A is an end of the BASIC line character.

2F68-2F6A
Go get the character to put in the input buffer from the keyboard.
2F6B
LD (HL),A
Save the character in register A at the memory location of the input buffer pointer in HL.
2F6C-2F6E
Go display the character in register A.
2F6F
INC HL
Bump the value of the input buffer pointer in HL.
2F70
INC B
Bump the character position in register B.
2F71
DEC D
Decrement the number of times to perform the operation in register D.
2F72-2F73
Loop until done.
2F74
RET
Return.


2F75 – EDIT Command – HACK/INSERT Logic.

2F75-2F76
LD (HL),00H
Zero the location of the input buffer pointer in HL.
2F77
LD C,B
Load register C with the character position in register B.
2F78-2F79
LD D,0FFH
Load register D with the number of times to perform the operation.
2F7A-2F7C
GOSUB to 2F0AH to display the register BASIC line if necessary.
2F7D-2F7F
Go get the character to be inserted from the keyboard.
2F80
OR A
Check to see if a key was pressed.
2F81-2F83
Loop back to 2F7DH until a key is pressed.
2F84-2F85
CP 08H
Check to see if the character in register A is a backspace character.
2F86-2F87
Jump to 2F92H if the character in register A is a backspace character.
2F88-2F89
CP 0DH
Check to see if the character in register A is a carriage return.
2F8A-2F8C
Jump to 2FE0H if the character in register A is a carriage return.
2F8D-2F8E
CP 1BH
Check to see if the character in register A is a shift up arrow.
2F8F
RET Z
Return if the character in register A is shift up arrow.

2F90-2F91
Jump to 2FB0H to ass the new character to the current line.


2F92 – EDIT Command – BACKSPACE CURSOR Logic.

2F92-2F93
LD A,08H
Load register A with a backspace the cursor character.
2F94
DEC B
Decrement the character position in register B.
2F95
INC B
Bump the character position in register B.
2F96-2F97
Jump forward to 2FB7H if this is the first character of the BASIC line.
2F98-2F9A
Go backspace the cursor on the video display.
2F9B
DEC HL
Decrement the value of the input buffer pointer in HL.
2F9C
DEC B
Decrement the character position in register B.
2F9D-2F9F
LD DE,2F7DH
Load DE with a return address of 2F7DH.
2FA0
PUSH DE
Save the value of the return address in DE to the stack.
2FA1
PUSH HL
Save the value of the input buffer pointer in HL to the stack.
2FA2
DEC C
Decrement the character position in register C.
2FA3
LD A,(HL)
Load register A with the character at the location of the input buffer pointer in HL.
2FA4
OR A
Check to see if the character in register A is an end of the BASIC line character.
2FA5
SCF
Set the Carry flag to signal that the character was deleted.
2FA6-2FA8
Jump to 0890H if the character in register A is an end of the BASIC line character.
2FA9
INC HL
Bump the value of the input buffer pointer in HL.
2FAA
LD A,(HL)
Load register A with the character at the location of the input buffer pointer in HL.
2FAB
DEC HL
Decrement the value of the input buffer pointer in HL.
2FAC
LD (HL),A
Save the character in register A at the location of the current input buffer pointer in HL.
2FAD
INC HL
Bump the value of the input buffer pointer in HL.
2FAE-2FAF
Loop back to 2FA3H until the line has been moved down.


2FB0 – EDIT Command – ADD A CHARACTER Logic.

2FB0
PUSH AF
Save the character to be inserted in register A to the stack.
2FB1
LD A,C
Load register A with the number of characters in the input buffer in register C.
2FB2-2FB3
CP FFH
Check for the maximum BASIC line length.

2FB4-2FB5
Jump forward to 2FB9H if the maximum BASIC line length hasn’t been reached.
2FB6
POP AF
Get the character to be inserted from the stack and put it in register A.
2FB7-2FB8
Jump back to 2F7DH.
2FB9
SUB B
Subtract the character position in register B from the number of characters in the input buffer in register A. This should give the current byte position.
2FBA
INC C
Bump the number of characters in the input buffer in register C.
2FBB
INC B
Bump the character position in register B.
2FBC
PUSH BC
Save the character position and the number of characters in the input buffer in BC to the stack.
2FBD
EX DE,HL
Load DE with the input buffer pointer in HL.
2FBE
LD L,A
Load register L with the character count in register A.
2FBF-2FC0
LD H,00H
Zero register H.
2FC1
ADD HL,DE
Add the value of the input buffer pointer in DE to the character count in HL.
2FC2
LD B,H
Load register B with the MSB of the end of the BASIC line pointer in register H.
2FC3
LD C,L
Load register C with the LSB of the end of the BASIC line pointer in register L.
2FC4
INC HL
Bump the value of the end of the BASIC line pointer in HL.
2FC5-2FC7
Go move the BASIC line up one character.
2FC8
POP BC
Get the character position and the number of characters in the input buffer from the stack and put it in BC.
2FC9
POP AF
Get the character to be inserted from the stack and put it in register A.
2FCA
LD (HL),A
Save the character in register A at the location of the current input buffer pointer in HL.
2FCB-2FCD
Go display the character in register A.
2FCE
INC HL
Bump the value of the input buffer pointer in HL.
2FCF-2FD1
Jump back to 2F7DH.


2FD2 – EDIT Command – BACKSPACE Logic.

2FD2
LD A,B
Load register A with the number of times to backspace in register B.
2FD3
OR A
Check to see if this is the start of the BASIC line.
2FD4
RET Z
Return if this is the start of the BASIC line.

2FD5
DEC B
Decrement the character position in register B.
2FD6
DEC HL
Decrement the value of the input buffer pointer in HL.
2FD7-2FD8
LD A,08H
Load register A with a backspace the cursor character.
2FD9-2FDB
Go backspace the cursor on the video display.
2FDC
DEC D
Decrement the number of times to perform the operation in register D.
2FDD-2FDE
Loop until done.
2FDF
RET
Return.

2FE0-2FE2
Since we need to display the rest of the BASIC line, we call the PRINT MESSAGE routine at 2B75H which writes string pointed to by HL to the current output device..
2FE3-2FES
Go display a carriage return if necessary.
2FE6
POP BC
Clean up the stack.
2FE7
POP DE
Get the BASIC line number (in binary) from the stack and put it in DE.
2FE8
LD A,D
Load register A with the MSB of the BASIC line number in register D.
2FE9
AND E
Combine the LSB of the BASIC line number in register E with the MSB of the BASIC line number in register A.
2FEA
INC A
Bump the combined BASIC line number in register A.
2FEB-2FED
LD HL,(40A7H)
Load HL with the starting address of the input buffer.
Note: 40A7H-40A8H holds the input Buffer pointer.
2FEE
DEC HL
Decrement the value of the input buffer pointer in HL.
2FEF
RET Z
Return if this is the Level II BASIC command mode.

2FF0
SCF
Set the Carry flag to signal a BASIC program statement.
2FF1
INC HL
Bump the value of the input buffer pointer in HL.
2FF2
PUSH AF
Save the command mode flag in AF to the stack.
2FF3-2FF5
Jump to the Level II BASIC READY routine.


2FF6 – EDIT Command – QUIT Logic.

2FF6
POP BC
Clean up the stack.
2FF7
POP DE
Get the BASIC line number from the stack and put it in DE.
2FF8-2FFA
Jump to the Level II BASIC READY routine.
2FFB-2FFF
DEC3C344B2
Garbage Code.