Model III ROM Explained – Part 2


This page covers 1001H-2002H of the Model III ROM. The ONLY difference between the Model I v1.3 ROM and the Model III ROM in this entire range is located at 1B5DH-1B5FH. On the Model I, that address loaded HL with the contents of memory location 40A4H, the start of data. On the Model III, that adress is a GOSUB to unprotect the screen and load HL with the start of data.


There is no difference between the early Model III ROM and the later Model III ROM in this range. The Model 4 ROM is also identical to the Model III ROM in this range.

1001-1002
Jump if leading * aren’t to be included in the ASCII string.
1003
LD A,B
Load register A with the character at the location of the input buffer pointer in register B.
1004
CP C
Check to see if the character at the location of the input buffer pointer in register A is a space.
1005-1006
LD C,2AH
Load register C with an * character.
1007-1008
Skip the next opcode (which loads B with a *, if the character at the location of the input buffer pointer in register A isn’t a space.
1009
LD B,C
Load register B with the * character in register C.
l00A
LD (HL),C
Save the * character in register C at the location of the input buffer pointer in register pair HL.
100B
RST 10H
Since we need to bump the current input buffer pointer in register pair HL until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:
  • The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
  • Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
  • The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
  • The string must be terminated by a byte of zeros.
100C-100D
Jump down to 1022H if the character at the location of the input buffer pointer in register pair HL is the end of the input buffer character (00H).
100E-100F
CP 45H
Check to see if the character at the location of the input buffer pointer in register A is an E.
1010-1011
Jump down to 1022H if the character at the location of the input buffer pointer in register A is an E.
1012-1013
CP 44H
Check to see if the character at the location of the input buffer pointer in register A is a D.
1014-1015
Jump down to 1022H if the character at the location of the input buffer pointer in register A is a D.
1016-1017
CP 30H
Check to see if the character at the location of the input buffer pointer in register A is a 0.
1018-1019
Jump back to 100AH if the character at the location of the input buffer pointer in register A is a 0.
101A-101B
CP 2CH
Check to see if the character at the location of the input buffer pointer in register A is a ,.
101C-101D
Jump back to 100AH if the character at the location of the input buffer pointer in register A is a ,.
101E-101F
CP 2EH
Check to see if the character at the location of the input buffer pointer in register A is a ..
1020-1021
Jump down to 1025H if the character at the location of the input buffer pointer in register A isn’t a ..
1022
DEC HL
Now we know we have an E, D, 0, ,, or . so we need to backspace it out by decrementing the value of the input buffer pointer in register pair HL.
1023-1024
LD (HL),”0″
Save a zero character (0) at the location of the input buffer pointer in register pair HL.
1025
LD A,E
Load register A with the value of the edit flag in register E.
1026-1027
AND 10H
MASK A against 10H (Binary: 0001 0000) to leave only Bit 5 so as to check to see if a $ is to be included in the ASCII string.
1028-1029
Skip the next 2 instructions (which put in a $) if a $ isn’t to be included in the ASCII string.
102A
DEC HL
Need to add a $, so first we decrement the value of the input buffer pointer in register pair HL …
102B-102C
LD (HL),24H
… and then put a $ there.
102D
LD A,E
Load register A with the value of the input flag in register E.
102E-102F
AND 04H
Check to see if the sign is to follow the ASCII string.
1030
RET NZ
Return if the sign isn’t to follow the ASCII string.
1031
DEC HL
Decrement the value of the input buffer pointer in register pair HL.
1032
LD (HL),B
Save the character in register B at the location of the input buffer pointer in register pair HL.
1033
RET
Return.

This routine initializes the input buffer for an ASCII conversion. It is called by the FLOATING to ASCII Conversion Routine (at 0FBEH) and by the BINARY to ASCII Conversion Routine (at 0FAFH).

1034-1036
LD (40D8H),A
Save the value of the edit flag (stored at 40D8H) in register A.

NOTE: 40D8H-40D9H holds the temporary storage location.
1037-1039
LD HL,4130H
Load register pair HL with the starting address of the input buffer (which is 4130H).

NOTE: 4130H-4149H holds Internal print buffer.
103A-103B
LD (HL),20H
Save a space at the location of the input buffer pointer in register pair HL.
103C
RET
Return.

This routine gets called by the FLOATING to ASCII Conversion Routine (0FBEH-0FC0H) if the value being converted is either Single Precision or Double Precision.

103D-103E
CP 05H
Set the CARRY FLAG according to whether the current value in REG 1 is single precision or double precision (Carry set if double precision).
103F
PUSH HL
Save the value in register pair HL to the stack.
1040-1041
SBC A,00H
Adjust the value of the number type in register A. It will be 04H if SINGLE PRECISION and it will be 08H if DOUBLE precision.
1042
RLA
Multiply the value of the number type in register A by two, so now A will be 08H if SINGLE precision and 0AH if DOUBLE precision.
1043
LD D,A
Load register D with the adjusted value of the number type in register A.
1044
INC D
Bump the value of the number type in register D (so D will be 09H if SINGLE precision and 0BH if DOUBLE precision).
1045-1047
GOSUB to 1201H to scale the current value in REG 1 to be 99,999 <= X <= 999,999. Returns wihth A being the number of times the DOUBLE precision value was scaled up or down.
1048-104A
LD BC,0300H
Load register pair BC with 300H (Decimal: 768).
104B
ADD A,D
Add the value in register D to the value in register A.
104C-104E
Jump to 1057H if the number of digits in register A is too large (i.e., if scaled down more than 9 or 11 places).
104F
INC D
Bump the value in register D (so D will be 0AH if SINGLE precision or 0CH if DOUBLE precision).
1050
CP D
Check to see if the number of digits in register A is equal to the value in register D (meaning that the number wasn’t scaled at all).

NOTE: Results from a CP:
  • Z: A and * are the same
  • NZ: A and * are NOT the same
  • C: A < *
  • NC: A => *
1051-1052
If the number was scaled up or down (meaning that A and D are the same or A is greater than D), jump to 1057H.
1053
INC A
Now we know the number was scaled, so we must bump the number of digits in register A so that it holds the number of digits in the value.
1054
LD B,A
Load register B with the number of digits in the value (stored in register A).
1055-1056
LD A,02H
Load register A with a two because the next step (which is a common code jump point) will force the exponent to be zero.
1057-1058
SUB A,02H
Compute the exponent value (which will be a zero if we were passing through).
1059
POP HL
Get the value from the stack (the Program Buffer) and put it in register pair HL.
105A
PUSH AF
Save the exponent value (currently in register pair AF) to the stack.
105B-105D
Go put a comma or decimal point in the input buffer if necessary.
105E-105F
LD (HL),”0″
Save a 0 character at the location of the input buffer pointer in register pair HL.
1060-1062
If there was no scaling, GOSUB to 09C9H to bump the value of the input buffer pointer in register pair HL if necessary.
1063-1065
Go convert the binary value in REG 1 to ASCII, the result being stored in the input buffer pointer.
1066
DEC HL
Backspace the last character by decrementing the value of the input buffer pointer in register pair HL.
1067
LD A,(HL)
Load register A with the value at the location of the input buffer pointer in register pair HL (which is the previous character).
1068-1069
CP 30H
Check to see if the value in register A is a 0 (which is 30H).
106A-106B
Loop until the character at the location of the input buffer pointer in register pair HL is not a zero character.
106C-106D
CP “.”
Check to see if the character at the location of the input buffer pointer in register A is a ..

NOTE: Results from a CP:
  • Z: A and * are the same
  • NZ: A and * are NOT the same
  • C: A < *
  • NC: A => *
106E-1070
If its NOT a decimal point, GOSUB to bump the value of the input buffer pointer in register pair HL.
1071
POP AF
Get the value from the stack (i.e., the exponent) and put it in register pair HL.
1072-10731
If the exponent is zero, jump to 1093H.
1074
PUSH AF
Save the exponent (stored in AF) back to the stack.
1075
RST 20H
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register according to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • Double Precision is NZ/NC/P/E and A is 5.
1076-1077
LD A,22H
Load register A with the starting value for a D or E character.
1078
ADC A,A
Multiply the value of the character in register A by two and add in the value of the CARRY FLAG from the number type flag test. This will result with A it being a D if the value is SINGLE precision and an E if the value is DOUBLE precision.
1079
LD (HL),A
Save the exponent designation (the D or E in register A) at the location of the input buffer pointer in register pair HL.
107A
INC HL
Bump the value of the input buffer pointer in register pair HL, which is the first position of the exponent in the buffer.
107B
POP AF
Get the value of the exponent from the stack and put it in register A.
107C-107D
LD (HL),2BH
Save a + (=2BH) at the location of the input buffer pointer in register pair HL.
107E-1080
Skip the next 3 instructions (by jumping to 1085H) if the exponent is positive.
1081-1082
LD (HL),2DH
Save a (which is 2DH) at the location of the input buffer pointer in register pair HL.
1083
CPL
Convert the negative exponent to positive by reversing the value of the exponent in register A and …
1084
INC A
… bumping the value of the exponent in register A.
1085-1086
LD B,2FH
At this point, the exponent is positive. Next step is to load register B with a 0 minus one (which is a /).
1087
INC B
Bump the value of the ASCII character in register B (so now it is an 0). This is the start of a 3 Opcode routine to divide by 10 using compound subtraction.
1088-1089
SUB A,0AH
Subtract ten from the value of the exponent in register A.
108A-108B
Loop until the value of the exponent in register A is less than ten. B holds the quotient (e.g., the number of times the subtraction had to occur to get to a remainder less than 10).
108C-108D
ADD A,3AH
Since A is holding the remainder of the ‘divide-by-10’ routine above, add 3AH to it so that it will be an ASCII digit.
108E
INC HL
Bump the value of the input buffer pointer in register pair HL.
108F
LD (HL),B
Save the ASCII character in register B (which is the first digit of the exponent in ASCII) at the location of the input buffer pointer in register pair HL.
1090
INC HL
Bump the value of the input buffer pointer in register pair HL.
1091
LD (HL),A
Save the value of the ASCII character in register A (which is the second digit of the exponent in ASCII) at the location of the input buffer pointer in register pair HL.
1092
INC HL
Bump the value of the input buffer pointer in register pair HL.
1093-1094
LD (HL),00H
Save an end of the ASCII string character (designated as 00H) at the location of the input buffer pointer in register pair HL.
1095
EX DE,HL
Load register pair DE with the ending address of the input buffer pointer.
1096-1098
LD HL,4130H
Load register pair HL with the starting address of the input buffer pointer.

NOTE: 4130H-4149H holds Internal print buffer.
1099
RET
Return.
109A
INC HL
Bump the value of the input buffer pointer in register pair HL.
109B
PUSH BC
Save the value in register pair BC to the stack (currently B has the number of #‘s before the current vale of the input buffer pointer and C has the number of #’s after).
109C-109D
CP 04H
Check to see if the current number type in REG 1 is single or double precision. Results:
  • If A=04H it sets the ZERO FLAG
  • If A<04H then the CARRY FLAG will be set
  • If A>=04H then the NO CARRY FLAG will be set
109E
LD A,D
Load register A with the value of the edit flag in register D.
109F-10A1
Jump to 1109H if the current value in REG 1 is either single precision or double precision (i.e., A>=04H since 4=Single precision and 8=Double precision
10A2
RRA
Rotate A right one bit to put the value of the exponential notation flag into the CARRY FLAG.
10A3-10A5
JUMP to 11A3H if exponential notation is requested.
Alternative interpretation is Jump to 11A3H if the variable is a string; which will leave us now with only an integer value.

10A6 – This is where the PRINT USING routine will edit for INTEGER values.

10A6-10A8
LD BC,0603H
Load register pair BC with a default value of 0603H (so that Register B has the number of leading digits of 6 and Register C has the comma counter of 3).
10A9-10AB
Go check to see if commas are requested. If no comma is requested, set Register C to zero.
10AC
POP DE
Get the value from the stack and put it in register pair DE. This will put the number of #’s to the left of the decimal point into D.
10AD
LD A,D
Load register A with the number of digits requested to the left of the decimal point in register D.
10AE-10AF
SUB A,05H
Since the maximim number of digits allowed for an integer to the left of the decimal point is 5, subtract 5 from the number of digits to the left of the decimal point requested.
10B0-10B2
Go put leading zeros into the input buffer if the number of digits to the left of the decimal point requested is greater than the number of digits to the left of the decimal point for the maximum length of an integer value (meaning, the POSITIVE flag has been set).
10B3-10B5
Call the INTEGER TO ASCII routine at 1232F (which converts the integer in REG 1 to ASCII and stores the ASCII string in the buffer pointed to in HL).
10B6
LD A,E
Load register A with the number of digits to the right of the decimal point requested (which is stored in register E).
10B7
OR A
Check to see if there are any digits to the right of the decimal point requested and set the status flags accordingly.
10B8-10BA
Go decrement the value of the input buffer pointer in register pair HL if there are no digits to the right of the decimal point requested.
10BB
DEC A
Decrement the number of digits to the right of the decimal point in register A. This tests to see if no count was given.
10BC-10BE
If the POSITIVE flag is set, gosub to 1269H to add trailing zeros to the ASCII string if necessary.
10BF
PUSH HL
Save the current input buffer pointer (stored in register pair HL) to the stack.
10C0-10C2
Go edit the ASCII string in the input buffer.
10C3
POP HL
Get the saved input buffer pointer value from the stack and put it in register pair HL.
10C4-10C5
Jump to 10C8H if the sign follows the ASCII string.
10C6
LD (HL),B
So now we know a sign does not follow the value so we save the character in register B (which should be a space) at the location of the input buffer pointer in register pair HL.
10C7
INC HL
Bump the value of the input buffer pointer in register pair HL
10C8-10C9
LD (HL),00H
Terminate the buffer by saving an end of the ASCII string character (=00H) at the location of the input buffer pointer in register pair HL.
10CA-10CC
LD HL,412FH
Load register pair HL with the starting address of the input buffer pointer (which is 412FH) minus 1 (because the first instruction of the following common code is add 1 to HL).
10CD
INC HL
Bump the value of the input buffer pointer in register pair HL.
10CE-10D0
LD A,(40F3H)
Load register A with the LSB of the address of the decimal point for the ASCII string.

NOTE: 40F3H-40F4H holds the temporary storage location.
10D1
SUB A,L
Subtract the LSB of the input buffer pointer address in register L from the value in register A.
10D2
SUB A,D
Subtract the number of digits to the left of the decimal point in register D from the adjusted value in register A.
10D3
RET Z
Return if the input buffer pointer in register pair HL points to the start of the ASCII string.
10D4
LD A,(HL)
So now we know we are not at the start of the field, so we fetch the character at the location of the input buffer pointer in register pair HL into Register A.
10D5-10D6
CP 20H
Check to see if the character at the location of the input buffer pointer in register A is a space (which is a blank).
10D7-10D8
Jump back to 10CDH if the character at the location of the input buffer pointer in register pair HL is a space so that we keep looking until we are either at the start of the field, or a “+”, “-“, or “$” is found.
10D9-10DA
CP “*”
Check to see if the character at the location of the input buffer pointer in register A is a *.
10DD
DEC HL
Since we want to ignore “*”‘s decrement the value of the input buffer pointer in register pair HL so it will get re-tested.
10DE
PUSH HL
Save the value of the input buffer pointer in register pair HL to the stack.
10DF
PUSH AF
Save the value in register pair AF (which is the current character) to the stack.
10E0-10E2
LD BC,10DFH
Load register pair BC with the return address for use in case we have a , a +, or a $.
10E3
PUSH BC
Save the return address in register pair BC to the stack.
10E4
RST 10H
Since we need to bump the current input buffer pointer in register pair HL until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:
  • The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
  • Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
  • The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
  • The string must be terminated by a byte of zeros.
10E5-10E6
CP “-“
Check to see if the character at the location of the input buffer pointer in register A is a .
10E7
RET Z
Return (to 10DFH) if the character at the location of the input buffer pointer in register A is a .
10E8-10E9
CP “+”
Check to see if the character at the location of the input buffer pointer in register A is a +.
10EA
RET Z
Return (to 10DFH) if the character at the location of the input buffer pointer in register A is a +.
10EB-10EC
CP “$”
Check to see if the character at the location of the input buffer pointer in register A is a $.
10ED
RET Z
Return (to 10DFH) if the character at the location of the input buffer pointer in register A is a $.
10EE
POP BC
We don’t need a shortcut to jump to 10DFH anymore, so let’s get the real return address from the stack and put it in register pair BC.
10EF-10F0
CP “0”
Check to see if the character at the location of the input buffer pointer in register A is a 0.
10F1-10F2
Jump to 1102H if the character at the location of the input buffer pointer in register A isn’t a 0.
10F3
INC HL
Bump the value of the input buffer pointer in register pair HL so that we skip to the next character.
10F4
RST 10H
Since we need to bump the current input buffer pointer in register pair HL until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:
  • The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
  • Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
  • The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
  • The string must be terminated by a byte of zeros.
10F5-10F6
Jump to 1102H if the character at the location of the input buffer pointer in register A isn’t a numeric character.
10F7
DEC HL
Decrement the value of the input buffer pointer in register pair HL to backspace to the last character examined.
10F8
01 2B 77
Z-80 Trick! The byte at this memory location, 01H, is there to turn the real instruction that follows in 10F9H into a harmless LD BC,xxxx. This way, if you are processing straight down in order, it skips the next command at 10F9H (in this case a DEC HL) because it wasn’t a command, it was a hex number to be loaded into BC! Instead, if you jump to 10F9H, you skip this byte and it is an DEC HL.
10F9
DEC HL
Decrement the value of the input buffer pointer in register pair HL (we needed that Z-80 trick to avoid a double backspace in passing through).
10FA
LD (HL),A
Save the character in register A at the location of the input buffer pointer in register pair HL.
10FB
POP AF
Get the value from the stack and put it in register pair AF.
10FC-10FD
Loop until the end of the field is reached (by finding a 00H).
10FE
POP BC
Clear the stack.
10FF-1101
Jump back to 10CEH to restart the scan.
1102
POP AF
Restore the character at the start of the field from the stack and put it in register pair AF.
1103-1104
Loop until the beginning of the field is found.
1105
POP HL
Get the starting address of the field from the stack and put it in register pair HL.
1106-1107
LD (HL),25H
Save a % character at the location of the input buffer pointer in register pair HL (which is the starting address).
1108
RET
Return.

1109 – This is where the PRINT USING routine will edit for FLOATING POINT values.

1109
PUSH HL
Save the current input buffer pointer in register pair HL to the stack.
110A
RRA
Rotate A right one bit, with Bit 0 going to the CARRY FLAG. This will allow us to test bit 0 of the edit flags to see if exponential notation is requested by the edit flag in register A.
110B-110D
Jump to 11AAH if exponential notation is requested by the edit flag in register A on a floating point number.
110E-110F
Jump to 1124H if the current value in REG 1 is single precision.
1110-1112
LD DE,1384H
Load register pair DE with the address of the DOUBLE PRECISION value to be compared to the current value in REG 1. Register pair DE points to a double precision constant equal to 1el6.
1113-1115
Go compare the double precision constant pointed to by register pair DE (which is 1el6) to the double precision value in REG 1.
1116-1117
LD D,10H
Load register D with the maximum length of a double precision value (which is 16).
1118-111A
Jump to 1132H if the double precision value in REG 1 is less than or equal to 1el6.
111B
POP HL
So now we know the double precision value in REG 1 exceeds 1×10^16. Get the current input buffer pointer from the stack and put it in register pair HL.
111C
POP BC
Get the value from the stack and put it in register pair BC, resulting in B containing the number of #‘s before and C containing the number of #‘s after.
111D-111F
Go convert the double precision value in REG 1 to an ASCII string. The goal is to reenter the edit routine until the double precision value is less than 1×10^16.
1120
DEC HL
Decrement the input buffer pointer in register pair HL to get it back to the current position.
1121-1122
LD (HL),”%”
Save a % character at the location of the input buffer pointer in register pair HL.
1123
RET
Return.

1124H – Continuation point if the current value in REG 1 is single precision.

1124-1126
LD BC,B60EH
Load register pair BC with the exponent and the MSB of a single precision constant.
1127-1129
LD DE,1BCAH
Load register pair DE with the NMSB and the LSB of a single precision constant. Register pairs BC and DE now hold a single precision constant equal to 1×10^16.
112A-112C
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=00H if REG 1 = BCDE
  • A=01H if REG 1>BCDE; and
  • A=FFH if REG 1<BCDE.
112D-112F
Jump back to 111BH if the the POSITIVE flag is set (meaning the single precision value in REG 1 is greater than 1×10^16).
1130-1131
LD D,06H
Now we know that the SINGLE precision value in REG 1 is less than 1×10^16. Load register D with the maximum length of a single precision value (which is 6).
1132-1134
Go check the sign of the value in REG 1.
1135-1137
GOSUB to 1201H to adjust the current value of REG 1 so that the single precision value is 99,999 < X < 999,999. On the return from that GOSUB, A will equal the number of times the value was scaled up or down as a + or -.
1138
POP HL
Get the origin of the ASCII buffer from the stack and put it in register pair HL.
1139
POP BC
Get the value from the stack and put it in register pair BC, resulting in B containing the number of #‘s before and C containing the number of #‘s after.
113A-113C
JUMP forward to 1157H if the value in REG 1 had to be scaled up (multiplied by 10) to get it in range.
113D
PUSH BC
Save the value in register pair BC (B was the number of #‘s before and C is the number of #‘s after) to the stack.
113E
LD E,A
Load register E with the number of times the current value in REG 1 was divided.
113F
LD A,B
Load register A with the number of digits before the decimal point requested.
1140
SUB A,D
Subtract the maximum length for the current number type in register D (which is 6) from the number of digits requested in register A.
1141
SUB A,E
Subtract the number of times the current value in REG 1 was divided in register E from the adjusted value in register A.
1142-1144
If the POSITIVE flag is set, gosub to 1269H to put leading zeros into the input buffer if necessary.
1145-1147
GOSUB to 127DH to figure the comma count and the position of the decimal point.
1148-114A
GOSUB to 12A4H to convert the integer portion of the current value in REG 1 to an ASCII string.
114B
OR E
Check to see if there are any trailing zeros needed by testing the number of times the value was scaled.
114C-114E
Go put trailing zeros into the input buffer if necessary.
114F
OR E
Check to see if commas or the decimal point is needed.
1150-1152
Go put commas and the decimal point into the input buffer if necessary.
1153
POP DE
Get the edit counts value from the stack and put it in register pair DE.
1154-1156
Jump to 10B6H to convert the fractional portion fo the number to ASCII.

1157H – Subroutine if REG 1 Needs to be Scaled Up (Multiplied by 10) To Get It In Range

1157
LD E,A
Load register E with the number of times the current value in REG 1 was scaled (multiplied by 10).
1158
LD A,C
Load register A with the number of digits requested to the right of the decimal point.
1159
OR A
Check to see if any digits to the right of the decimal point was requested.
115A-115C
Go decrement the number of digits requested to the right of the decimal point if necessary.
115D
ADD A,E
Add the number of times the current value was multiplied in register E to the number of digits to the right of the decimal point requested in register A.
115E-1160
Jump if the value in REG 1 must be scaled down.
1161
XOR A
Zero register A and indicate that there is on scaling down needed.
1162
PUSH BC
Save the value in register pair BC (B was the number of #‘s before and C is the number of #‘s after) to the stack.
1163
PUSH AF
Save the value in register pair AF (the scale count) to the stack.
1164-1166
GOSUB to 0F18H to divide the value in REG 1 by ten, A times, if necessary.
1167-1169
Loop until the value in REG 1 is properly adjusted. When this is done, A will hold the number of times it was divided by 10.
116A
POP BC
Get the original scale count from the stack and put it in register pair BC.
116B
LD A,E
Load register A with the number of times the value in REG 1 was multiplied in register E.
116C
SUB A,B
Subtract the value in register B from the value in register A.
116D
POP BC
Get the before/after value from the stack and put it in register pair BC.
116E
LD E,A
Load register E with the adjusted scale factor value in register A.
116F
ADD A,D
Add the length of the maximum size for the current value in register D to the adjusted scale factor value in register A. This will set the sign flag.
1170
LD A,B
Load register A with the number of #‘s before (stored in B).
1171-1173
Jump to 117FH if there are no digits to the left of the decimal point.
1174
SUB A,D
We now know there are leading digits so, subtract the maximum length for the current value in register D (6 for SINGLE precision and 10 for DOUBLE precision) from the adjusted value in register A.
1175
SUB A,E
Then, subtract the adjusted scale value in register E from the adjusted value in register A.
1176-1178
If that subtraction leads to a positive number, go put leading zeros into the input buffer.
1179
PUSH BC
Save the value in register pair BC (B was the number of #‘s before and C is the number of #‘s after) to the stack.
117A-117C
GOSUB to set up BC for decimal point and comma counters.
117D-117E
Jump to 1190H to edit the numbers before the decimal point.

117FH – Continuation Routine (From 1171H) if there are no digits to the left of the decimal point.

117F-1181
Go put leading zeros into the input buffer if necessary.
1182
LD A,C
Load Register A with the number of bytes requested to the right of the decimal point (in register C) because C is about to get wiped.
1183-1185
GOSUB to 1294H to put a decimal point into the input buffer.
1186
LD C,A
Reload register C with the number of digits requested to the right of the decimal point in register A.
1187
XOR A
Zero Register A.
1188
SUB A,D
Subtract the maximum length for the current value in register D from the value in register A.
1189
SUB A,E
Subtract the value in register E from the adjusted value in register A.
118A-118C
GOSUB to 1269H to put that many zeroes into the input buffer (if necessary).
118D
PUSH BC
Save the value in register pair BC (B was the number of #‘s before and C is the number of #‘s after) to the stack.
118E
LD B,A
Load register B with the value in register A (which is 0).
118F
LD C,A
Load register C with the value in register A (which is 0).

1190H – Continuation Routine (From 117DH) to edit the numbers before the decimal point.

1190-1192
GOSUB to 12A4H to convert the integer portion of the SINGLE precision value in REG 1 to an ASCII string.
1193
POP BC
Get the number of #‘s before and number of #‘s after and put it back in register pair BC.
1194
OR C
Check to see if there are any digits to the right of the decimal point requested and set the status accordingly.
1195-1196
Jump to 119AH if there are digits to the right of the decimal point requested.
1197-1199
LD HL,(40F3H)
Now we know that there are no digits to the right of the decimal point. Load register pair HL with the position of the decimal point (which is stored in 40F3H).

NOTE: 40F3H-40F4H holds the temporary storage location.
119A
ADD A,E
Add the value in register E to the value in register A to get the number of digits before the decimal point.
119B
DEC A
Decrement the adjusted value in register A.
119C-119E
If dropping A by 1 still results in a positive number, GOSUB 1269H to put that number of zeros into the input buffer.
119F
LD D,B
Load register D with the number of digits to the left of the decimal point requested (from Register B).
11A0-11A2
Jump to 10BFH to edit the ASCII value.
11A3
PUSH HL
Save the current position of the input buffer (in register pair HL) to the stack.
11A4
PUSH DE
Save the edit flags (in register pair BC) to the stack.
11A5-11A7
GOSUB 0ACCH to convert the integer value in REG 1 to a SINGLE precision value.
11A8
POP DE
Get the edit flags from the stack and put it in register pair DE.
11A9
XOR A
Zero register A, clear the status flags.
11AA-11AC
Slip the next 2 instructions to 11B0H (using a Z-80 trick) to skip the next instruction if the current value in REG 1 is SINGLE precision.
11AD-11AE
LD E,10H
Load register E with the maximum length of a double precision value (which is 16).
11AFH
01 + LD E,06H
or
LD BC, 1E06H
Z-80 Trick! By putting a 01 here, the opcode becomes a 3 byte opcode, turning 01 1E 06 into LD BC, 1E06H. This would corrupt BC, but otherwise would then make the next instruction 11B2H, skipping the next instruction of LD E,06H because, well, it doesn’t exist!

11B0H – Continuation Routine (From 11AAH) if the current value in REG 1 is SINGLE precision.

11B0-11B1
LD E,06H
Load register E with the maximum length of a single precision value (which is 6).
11B2-11B4
GOSUB 0955H to check the sign for the current value in REG 1.
11B5
SCF
Set the CARRY FLAG (to force a jump at 11F3 on the first pass).
11B6-11B8
GOSUB to 1201H to scale the current value in REG 1 if its nonzero.
11B9
POP HL
Get the input buffer position from the stack and put it in register pair HL.
11BA
POP BC
Get the number of #‘s before and the number of #‘s after from the stack and put it in register pair BC.
11BB
PUSH AF
Save the decimal point and the flag for test at 11F3H in register pair AF to the stack.
11BC
LD A,C
Load register A with the number of digits to the right of the decimal point requested (stored in register C).
11BD
OR A
Set the status so we can see if there are any digits to the right of the decimal point requested through a zero register.
11BE
PUSH AF
Save the original trailing digit count (in register pair AF) to the stack.
11BF-11C1
If the trail count is not zero, then GOSUB to 0F16H to decrement the number of digits requested to the right of the decimal point in register A.
11C2
ADD A,B
Add the number of digits requested for the left of the decimal point in register B to the number of digits requested to the right of the decimal point in register A.
11C3
LD C,A
Load register C with the total digit count (held in register A).
11C4
LD A,D
Load register A with the value of the edit flag in register D.
11C5-11C6
AND 04H
Check to see if the sign follows the ASCII string.
11C7-11C8
CP 01H
Set the CARRY FLAG according to the sign following the ASCII string test (it will be No Carry if a sign follows).
11C9
SBC A,A
Adjust register A so that it will reflect the sign following the ASCII string test (A will be 0 if there is no sign, and FEH otherwise).
11CA
LD D,A
Load register D with the edit flag (from register A).
11CB
ADD A,C
Add the value in register C to the value in register A so as to adjust the count of the digits to print if a sign follows.
11CC
LD C,A
Load register C with the adjusted value in register A.
11CD
SUB A,E
Subtract the value in register E from the adjusted value in register A so that A will now contain the number of times to divide by 10.
11CE
PUSH AF
Save the divisor count (from register pair AF) to the stack.
11CF
PUSH BC
Save the character count (from register pair BC) to the stack.
11D0-11D2
GOSUB to 0F18H to divide the current value in REG 1 by ten, Register A number of times.
11D3-11D5
Loop back 1 instruction (divide by 10) until the division has been completed.
11D6
POP BC
Get the counter of the #‘s from the stack and put it in register pair BC.
11D7
POP AF
Get the division count from the stack and put it in register pair AF.
11D8
PUSH BC
Save the value in Register Pair BC to the STACK.
11D9
PUSH AF
Save the value in register pair AF to the stack.
11DA-11DC
Skip the next instruction (i.e., jump to 11DEH) if there are any trailing zeroes.
11DD
XOR A
Zero register A and all status flags.
11DE
CPL
Make the trailing zero count posivite by inverting the value in register A.
11DF
INC A
Bump the value in register A so that it will be positive.
11E0
ADD A,B
Add the number of digits requested to the left of the decimal point in register B to the adjusted value in register A.
11E1
INC A
Bump the adjusted value in register A.
11E2
ADD A,D
Add the value of the maximum length for the current number type in register D (6 for single precision, 16 fo double precision) to the adjusted value in register A.
11E3
LD B,A
Copy Register A into Register B so that B holds the number of digits before the decimal point.
11E4-11E5
LD C,00H
Load register C with zero (so that there are no commas).
11E6-11E8
GOSUB to 12A4H to convert the current value in REG 1 to an ASCII string.
11E9
POP AF
Get the number of #’s before from the stack and put it in register pair AF.
11EA-11EC
GOSUB 1271H to put zeros into the trailing input buffer.
11ED
POP BC
Get the number of #’s before and the number of #‘s after from the stack and put it in register pair BC.
11EE
POP AF
Get the count of numbers before the decimal point from the stack and put it in register pair AF.
11EF-11F1
GOSUB to 092FH to decrement the input buffer pointer in register pair HL if there are none.
11F2
POP AF
Get the first time flag from the stack and put it in register pair AF.
11F3-11F4
Jump to 11F8H (to add the exponent) if the CARRY FLAG was set during the first pass.
11F5
ADD A,E
Add the value in register E to the value in register A.
11F6
SUB A,B
Subtract the number of digits to the left of the decimal point requested in register B from the adjusted value in register A.
11F7
SUB A,D
Subtract the value in register D from the value in register A to get the size of the exponent.
11F8
PUSH BC
Save the value in Register Pair BC to the STACK.
11F9-11FB
GOSUB to 1074H to figure the value of the exponent for the current value in REG 1
11FC
EX DE,HL
Load register pair HL with the value of the input buffer pointer in register pair DE.
11FD
POP DE
Get the value from the stack and put it in register pair DE. Clear the stack.
11FE-1200
Jump to 10BFH to edit the ASCII value.

1201 – Test the magnitude of SP and DP numbers, and clear the times the value was scaled.

  • Scales so that the number lies between 99,999 and 999,999.
  • On exit, A = +(times value divided) or A=-(times value multiplied).
1201
PUSH DE
Save the value in register pair DE to the stack.
1202
XOR A
Zero register A and all the flags.
1203
PUSH AF
Save the value in register pair AF to the stack.
1204
RST 20H
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register according to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • Double Precision is NZ/NC/P/E and A is 5.
1205-1207
If that test shows we have a SINGLE PRECISION number (through getting a Parity-Odd flag), jump to 1222H.
1208-120A
LD A,(4124H)
At this point we know we have a DOUBLE precision value. Load register A with the value of the exponent for the double precision value in REG 1.
120B-120C
CP 91H
Check to see if the double precision value in REG 1 uses more than 16 bits of precision for the integer portion of the double precision value.

NOTE: Results from a CP:
  • Z: A and * are the same
  • NZ: A and * are NOT the same
  • C: A < *
  • NC: A => *
120D-120F
Jump to 1222H if the double precision value in REG 1 uses more than 16 bits of precision for its integer portion.
1210-1212
LD DE,1364H
Load register pair DE with the starting address for the double precision constant equal to 5.5x10e2.
1213-1215
LD HL,4127H
Load register pair HL with the starting address for REG2.

NOTE: 4127H-412EH holds REG 2.
1216-1218
GOSUB to 09D3H to move the double precision constant of 5.5x10e2 into REG2.
1219-121B
GOSUB to 0DA1H to call the DOUBLE PRECISION MULTIPLY routine at 0DA1H (which multiplies the double precision value in REG 1 by the value in REG 2. The product is left in REG 1).
121C
POP AF
Get the number of times the DOUBLE precision value was multiplied to scale it up from the stack and put it in register pair AF.
121D-121E
SUB A,0AH
Subtract ten from the value in register A.
121F
PUSH AF
Save the value in register pair AF to the stack.
1220-1221
Jump to 1208H so as to loop until the integer portion exceeds 2e16.
1222-1224
GOSUB to 124FH to compare the current value in REG 1 to 999999.5.
1225
RST 20H
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register according to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • Double Precision is NZ/NC/P/E and A is 5.
1226-1228
In ROM 1.2 this is a big bug fix. Now if the shows we do NOT have a STRING, jump to 1233H
1229-122B
LD BC,9143H
Load register pair BC with the exponent and the MSB of a single precision constant.
122C-122E
LD DE,4FF9H
Load register pair DE with the NMSB and the LSB of a single precision constant. Register pairs BC and DE are now equal to a single precision constant of 99,999.945.
122F-1231
GOSUB to 0A0CH to 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=00H if REG 1 = BCDE
  • A=01H if REG 1>BCDE; and
  • A=FFH if REG 1<BCDE.
1232-1233
Jump down two instructions to 123AH to test the results of the comparison.
1233-1235
LD DE,136CH
Load register pair DE with the starting address of a double precision constant equal to 9.9921El4.
1236-1238
Go compare the double precision constant pointed to by register pair DE to the double precision value in REG 1.
1239-123B
Jump to 124CH if the current value in REG 1 is greater than the constant compared to it (more than 5 digits in integer or less than 17 digits in DOUBLE precision).
123C
POP AF
Get the value of the scaled counter from the stack and put it in register pair AF.
123D-123F
GOSUB to 0F0BH to multiply the current value in REG 1 by ten.
1240
PUSH AF
Save the value in register pair AF to the stack. A is the negative of the number of times the value was multiplied.
1241-1242
Jump to 1225H to loop until it is between 999,999 and 99,999.
1243
POP AF
Get the scaled count from the stack and put it in Register A.
1244-1246
GOSUB to 0F18H to divide the current value in REG 1 by ten.
1247
PUSH AF
Save the value in register pair AF to the stack. A is the count of the number of times it was divided.
1248-124A
GOSUB to 124FH to loop until the value in REG 1 is < 999,999.
124B
POP AF
Get the value from the stack and put it in register pair AF. A = + times divided or – times multiplied.
Difference between M1 and M3 ROMs: This change first appeared in the “new” ROMs for the Model I. The order of two instructions (OR A and POP DE) have been reversed for no apparent reason.
124C
POP DE
Get the value from the stack and put it in register pair DE.
124D
OR A
In ROM v1.2 sets the status flags. This also realigns the memory addresses from changes to v1.2 ROM.
124E
RET
Return.
124F
RST 20H
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register according to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • Double Precision is NZ/NC/P/E and A is 5.
1250-1252
If that test shows we have a DOUBLE PRECISION number, jump to 125EH.
1253-1255
LD BC,9474H
Now that we know we have a single precision number, load register pair BC with the exponent and the MSB of a single precision constant.
1256-1258
LD DE,23F8H
Load register pair DE with the NMSB and the LSB of a single precision constant. Register pairs BC and DE are now equal to a single precision constant of 999,999.5.
1259-125B
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=00H if REG 1 = BCDE
  • A=01H if REG 1>BCDE; and
  • A=FFH if REG 1<BCDE.
125C-125D
Jump to 1264H to test the result of the comparison.
125E-1260
LD DE,1374H
Load register pair DE with the starting address of a double precision constant equal to 1El6H.
1261-1263
GOSUB to 0A49H to compare the double precision constant pointed to by register pair DE to the double precision value in REG 1.
1264
Get the return address from the stack and put it in register pair HL so we can go to 1244H.
1265-1267
In ROM v1.2 the ROM addresses had moved 1 byte.
1268
JP (HL)
Jump to the caller (which was POPed from the stack).

This routine puts leading zeroes into the input buffer

1269
OR A
Check to see if the value in register A is equal to zero.
126A
RET Z
Return if the value in register A is equal to zero.
126B
DEC A
Decrement the value in register A to show that an ASCII zero was moved to the print buffer.
126C-126D
LD (HL),”0″
Save a 0 at the location of the input buffer pointer in register pair HL.
126E
INC HL
Bump the input buffer pointer in register pair HL.
126F-1270
Jump back to 126AH until the number in Register A of ASCII zeroes were moved.
1271-1272
Jump to 1277H if not done adding trailing zeroes.
1273
RET Z
Return if done adding trailing zeroes.
1274-1276
GOSUB to 1291H to put decimal point and commas into the input buffer.
1277-1278
LD (HL),”0″
Save a zero character at the location of the input buffer pointer in register pair HL.
1279
INC HL
Bump the input buffer pointer in register pair HL.
127A
DEC A
Decrement the counter of trailing zeroes to add in register A.
127B-127C
Jump back up to 1273H to RET.

127DH – Subroutine to set up BC for decimal point and comma counters. On entry: Register D holds the number of digits to print, Register E holds the count of the times the value was scaled up or down.

127D
LD A,E
Load register A with the value in register E so that A holds the count of the times the value was scaled up or down.
127E
ADD A,D
Add the number of digits to print (from Register D) to the value in register A.
127F
INC A
Bump the adjusted value in register A so now A holds the number of digits before the decimal point.
1280
LD B,A
Load register B with the leading digit count (from register A).
1281
INC A
Bump the value in register A so not A holds the leading digits + 2.
1282-1283
SUB A,03H
Subtract three from the adjusted value in register A which, when combined with the next instruction as a loop, divides modulo 3.
1284-1285
Loop back 1 instruction until the value in register A is -1, -2, or -3.
1286-1287
ADD A,05H
Add 5 to A to get a positive remainder. This will give 4, 3, or 2 as the comma count.
1288
LD C,A
Load register C with the comma count in register A.
1289-128B
LD A,(40D8H)
Load register A with the value of the edit flag (stored at 40D8H).

NOTE: 40D8H-40D9H holds the temporary storage location.
128C-128D
AND 40H
Mask the EDIT FLAG against 40H (Binary: 0100 0000) to isolate bit 6 (the comma bit) in the edit flag word to see if commas are requested.
128E
RET NZ
Return with Register C = Comma count if commas are requested.
128F
LD C,A
Zero the comma counter in register C.
1290
RET
Return.

1291H – Subroutine to count the leading digits before the decimal point.

1291
DEC B
Decrement the decimal point counter in register B to see if the zero flag sets or not.
1292-1293
Jump to 129CH if the decimal point position hasn’t been reached.
1294-1295
LD (HL),”.”
Save a . at the location of the input buffer pointer in register pair HL.
1296-1298
LD (40F3H),HL
Save the address of the decimal point position (which is held in 40F3H) in register pair HL.

NOTE: 40F3H-40F4H holds the temporary storage location.
1299
INC HL
Bump the input buffer pointer in register pair H to the first character of the fractional part of a numberL.
129A
LD C,B
Zero the comma/decimal counter in register C (because B is zero since the above jump didn’t fire) to stop any more decimal points and commas.
129B
RET
Return.

129CH – Continuation Routine (from 1292H) if the decimal point position hasn’t been reached.

129C
DEC C
Decrement the decimal/comma counter in register C.
129D
RET NZ
Return if this location is not the end of a 3 character group (and so it doesn’t need a comma).
129E-129F
LD (HL),”,”
If didn’t jump out, then we need a comma here so put a comma at the location of the input buffer pointer in register pair HL.
12A0
INC HL
Bump the input buffer pointer (to account for the new comma) in register pair HL.
12A1-12A2
LD C,03H
Reset the comma counter by setting it to 3.
12A3
RET
Return.

12A4 – Routine to Convert the INTEGER porton of a DOUBLE precision value to its ASCII equivalent.

12A4
PUSH DE
Save the edit flags (stored in register pair DE) to the stack.
12A5
RST 20H
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register according to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • Double Precision is NZ/NC/P/E and A is 5.
12A6-12A8
If we have a single precision number (PO Flag Set), JUMP to 12EAH to convert a SINGLE precision number into its INTEGER equivalent.
12A9
PUSH BC
Now that we know we have a DOUBLE PRECISION number, save leading digit count/comma count (in register pair BC) to the stack.
12AA
PUSH HL
Save the input buffer address (in register pair HL) to the stack.
12AB-12AD
GOSUB to 09FCH to mmove the double precision value in REG 1 to REG2.
12AE-12B0
LD HL,137CH
Load register pair HL with the starting address of a double precision constant equal to 0.5.
12B1-12B3
GOSUB to 09F7H to move the double precision value pointed to by register pair HL to REG 1.
12B4-12B6
GOSUB to 0C77H – DOUBLE PRECISION ADD function (which adds the double precision value in REG 2 to the value in REG 1 (which is the constant 0.5). Result is left in REG 1).
12B7
XOR A
Zero register A and clear the status flags.
12B8-12BA
GOSUB to 0B7BH to adjust the double precision result in REG 1.
12BB
POP HL
Get the input buffer address from the stack and put it in register pair HL.
12BC
POP BC
Get the counters from the stack and put it in register pair BC.
12BD-12BF
LD DE,138CH
Load register pair DE with the starting address of a series of double precision constants (i.e., a table of powers of 10 from 1.0x10E15 – 1.0x10E6) for the binary to ASCII conversion.
12C0-12C1
LD A,0AH
Load register A with the number of times to divide the double precision value in REG 1 by a power of 10.
12C2-12C4
GOSUB to 1291H to add a decimal point or comma (as applicable) into the input buffer if necessary.
12C5
PUSH BC
Save the count of digits before the decimal point and the count of digts after the decimal point (stored in register pair BC) to the stack.
12C6
PUSH AF
Save the division count (stored in register pair AF) to the stack.
12C7
PUSH HL
Save the current input buffer address (stored in register pair HL) to the stack.
12C8
PUSH DE
Save the address of the power table (stored in register pair DE) to the stack.
12C9-12CA
LD B,2FH
Load register B (which will be the quotient in ASCII for each division) with the ASCII value for a zero character minus one.
12CB
INC B
Bump the ASCII value for the digit in register B so as to start with ASCII “0”.
12CC
POP HL
Get the address of the power table (i.e., the divisor) from the stack and put it in register pair HL and …
12CD
PUSH HL
… put it right back into the stack so that it can be restored during the loop.
12CE-12D0
GOSUB to 0D48H to subtract the double precision value pointed to by register pair HL from the double precision value in REG l. This is to divide the current integer value by of a power of 10 starting at 10e15 working its way down to 10e6 in a loop until the remainder is less than the current power).
12D1-12D2
Jump back to do another subtraction and keep looping until the CARRY FLAG gets set by the subtraction (meaning that the remainder is now less than the current power).
12D3
POP HL
Get the address of the power table from the stack and put it in register pair HL.
12D4-12D6
GOSUB to 0D36H to add the double precision value pointed to by register pair HL (which is the table of powers of 10) to the double precision remainder in REG 1 to make it a positive value. Return with the correct remainder in REG 1.
12D7
EX DE,HL
Load register pair DE with the starting address for the current power of 10 (stored in register pair HL).
12D8
POP HL
Get the current input buffer address from the stack and put it in register pair HL.
12D9
LD (HL),B
Save the ASCII value for the digit in register B at the location of the input buffer pointer (stored in register pair HL).
12DA
INC HL
Bump the input buffer pointer in register pair HL since we have just put a digit there.
12DB
POP AF
Get the status flags from the stack and put it in register pair AF so that we can test for 10 times.
12DC
POP BC
Get the counts of digits before/after the decimal point value from the stack and put it in register pair BC.
12DD
DEC A
Decrement the counter value in register A (we are going to loop 10 times).
12DE-12DF
Loop 10 times until the ASCII string has been figured.
12E0
PUSH BC
Save the the counts of digits before/after the decimal point value (stored in register pair BC) to the stack.
12E1
PUSH HL
Save the current input buffer pointer (stored in register pair HL) to the stack.
12E2-12E4
LD HL,411DH
Load register pair HL with the starting address for REG 1 (which holds the last half of the DOUBLE prevision value)
Note: 411DH-4124H holds REG l.
12E5-12E7
Call 09B1H (which moves a SINGLE PRECISION number pointed to by HL to REG 1).
12E8-12E9
Jump to 12F6H to convert that last half to ASCII.

12EAH – This routine is to convert a SINGLE precision value to an INTEGER.

  • Divide the integer equivalent by 100,000 and 10,000. Use the code at 1335H to convert the last 1000 to ASCII.
12EA
PUSH BC
Save the leading digit count/comma count (in register pair BC) to the stack.
12EB
PUSH HL
Save the current input buffer pointer (stored in register pair HL) to the stack.
12EC-12EE
GOSUB to 0708H to add a single precision value of 0.5 to the single precision value in REG 1. The result is stored in BC/DE.
12EF
INC A
Bump the MSB.
12F0-12F2
GOSUB to 0AFBH to convert the positive single precision value in REG 1 to an integer. The result is stored in BC/DE.
12F3-12F5
GOSUB to 09B4H (which moves the SINGLE PRECISION value in DC/DE [which is the integer portion of the original single precision value] into REG 1).
12F6
POP HL
Get the current input buffer pointer value from the stack and put it in register pair HL.
12F7
POP BC
Get the leading digit count/comma count value from the stack and put it in register pair BC.
12F8
XOR A
Zero register A.
12F9-12FB
LD DE,13D2H
Load register pair DE with the starting address for a series of integer values (in this case, 100,000).
12FC
CCF
Complement the CARRY FLAG. This is the first time switch for the division loop of 12FC-1327H.
12FD-12FF
GOSUB to 1291H to put a decimal point or a comma into the input buffer if necessary .
1300
PUSH BC
Save the counts of digits before/after the decimal point value (stored in register pair BC) to the stack.
1301
PUSH AF
Save the CARRY FLAG for the count of the number of times through this loop (stored in register pair AF) to the stack.
1302
PUSH HL
Save the current input buffer pointer value (stored in register pair HL) to the stack.
1303
PUSH DE
Save the division table address (stored in register pair DE) to the stack.
1304-1306
GOSUB to 09BFH (which loads the SINGLE PRECISION value in REG 1 into register pair BC/DE).
1307
POP HL
Get the division table address (the integer value for 100,000) from the stack and put it in register pair HL.
1308-1309
LD B,2FH
Load register B with the ASCII value for a zero character minus one.

130AH – This routine divides the integer portion of the current value by 100,000 using compound subtraction. The quotient is kept in Register B as an ASCII value.

130A
INC B
Bump the ASCII value from the digit in register B to increase the ASCII value from 0 and upward.
130B
LD A,E
Load register A with the LSB of the single precision value in register E.
130C
SUB (HL)
Subtract the value at the location of the memory pointer in register pair HL (the LSB of 100,000) from the value of the LSB of the single precision value in register A.
130D
LD E,A
Load register E with the adjusted LSB of the single precision value in register A.
130E
INC HL
Bump the value of the memory pointer in register pair HL to the next digit of 100,000.
130F
LD A,D
Load register A with the NMSB of the single precision value in register D.
1310
SBC A,(HL)
Subtract the value at the location of the memory pointer in register pair HL (the middle byte of 100,000) from the value of the NMSB of the single precision value in register A.
1311
LD D,A
Load register D with the adjusted NMSB of the single precision value in register A.
1312
INC HL
Bump the value of the memory pointer in register pair HL to the MSB of 100,000.
1313
LD A,C
Load register A with the MSB of the single precision value in register C.
1314
SBC A,(HL)
Subtract the value at the location of the memory pointer in register pair HL from the value of the MSB of 100,000 (a single precision value in register A).
1315
LD C,A
Load register C with the adjusted MSB of the single precision value in register A.
1316
DEC HL
Decrement the value of the memory pointer in register pair HL to the NMSB of 100,000.
1317
DEC HL
Decrement the value of the memory pointer in register pair HL again, now to the LSB of 100,000.
1318-1319
Loop until the ASCII value for the digit under 100,000 has been figured.
131A-131C
We need to add 100,000 to C/DE and make it positive so we GOSUB to 07B7H to add the value at the location of the memory pointer in register pair HL to the value in register pairs BC and DE.
131D
INC HL
Bump the value of the memory pointer in register pair HL to now point to the 10,000 constant.
131E-1320
Save the remainder as a current value by GOSUB to 09B4H (which moves the SINGLE PRECISION value in DC/DE into REG 1).
1321
EX DE,HL
Load register pair DE with the address of the next value to divide the current value in REG 1 by (which is the constant of 10,000).
1322
POP HL
Get the value of the memory pointer from the stack and put it in register pair HL.
1323
LD (HL),B
Save the ASCII value for the digit in register B at the location of the input buffer pointer in register pair HL.
1324
INC HL
Bump the value of the input buffer pointer in register pair HL.
1325
POP AF
Get the CARRY FLAG from the stack and put it in register pair AF.
1326
POP BC
Get the value from the stack and put it in register pair BC so it can be saved later.
1327-1328
If the CARRY FLAG is set, then reset it and loop the dividing by 10,000 until the integer portion is found.
1329
INC DE
If we fall through to here, we have divided the integer part of the single precision variable by 100,000 and then by 10,000 with the remainder being positive and saved as the current value. With this we bump the value of the memory pointer in register pair DE.
132A
INC DE
and again bump the value of the memory pointer in register pair DE, so now DE points to the constant 1,000.
132B-132C
LD A,04H
Load register A with the number of digits for the ASCII string to be figured.
132D-132E
Jump down to 1335H to convert the remainder to 4 ASCII digits.

132FH – This routine will convert an INTEGER to ASCII.

132F
PUSH DE
Save the edit flags (stored in register pair DE) to the stack.
1330-1332
LD DE,13D8H
Load register pair DE with the starting address of the descending powers of 10 starting at 10,000.
1333-1334
LD A,05H
Load register A with the number of digits for the ASCII string to be built (i.e., 5).

1335H – This routine will convert the last x (based on A) digits of an INTEGER to ASCII.

1335-1337
Go put a decimal point or a comma into the input buffer if necessary.
1338
PUSH BC
Save the counts of digits before/after the decimal point value (stored in register pair BC) to the stack.
1339
PUSH AF
Save the number of digits counter (stored in register A) to the stack.
133A
PUSH HL
Save the address of the power table (stored in register pair HL) to the stack.
133B
EX DE,HL
Load register pair HL with the starting address of the descending powers of 10 starting at 10,000 (stored in register pair DE).
133C
LD C,(HL)
Load register C with the LSB for the power of 10 stored in register pair HL.
133D
INC HL
Bump the value of the memory pointer in register pair HL to be the MDB of the power of 10.
133E
LD B,(HL)
Load register B with the MSB for the integer value at the location of the memory pointer in register pair HL.
133F
PUSH BC
Save the integer value of the power of 10 in register pair BC to the stack.
1340
INC HL
Bump the value of the memory pointer in register pair HL to the next value in the power of 10 table.
1341
EX (SP),HL
Exchange the memory pointer of the next power of 10 (stored in register pair HL) with the value in the stack, and vice versa.
1342
EX DE,HL
Load register pair DE with the current value from the stack (stored in register pair HL).
1343-1345
LD HL,(4121H)
Load register pair HL with the integer value in REG 1.
1346-1347
LD B,2FH
Since we are about to start a loop which starts with an INC, compensate by loading register B with the ASCII value for a zero character minus one.

1348 – This loop divides the current value by a power of 10 starting at 10,000 and working down to 10. The remainder frome ach division is added to the division and the sum becomes the dividend for the next division until done. The quotient is +2FH (which is the ASCII equivalent of a quotient).

1348
INC B
Bump the ASCII value for the digit in register B (so it starts at 0 and moves up each loop).
1349
LD A,L
Load register A with the LSB of the integer value in register L.
134A
SUB E
Subtract the value of the LSB of the integer value in register E from the value of the LSB of the integer value in register A.
134B
LD L,A
Load register L with the adjusted value of the LSB of the integer value in register A.
134C
LD A,H
Load register A with the value of the MSB of the integer value in register H.
134D
SBC A,D
Subtract the MSB of the integer value in register D from the value of the MSB of the integer value in register A.
134E
LD H,A
Load register H with the adjusted value of the MSB of the integer value in register A.
134F-1350
Loop back to 1348H until the CARRY FLAG is triggered because the quotient (stored in HL) is less than the current power of 10.
1351
ADD HL,DE
Add the remainder (stored as an integer in register pair DE) to the quotient (stored in register pair HL as an integer).
1352-1354
LD (4121H),HL
Save the integer remainder (stored in register pair HL) in REG 1.
1355
POP DE
Get the address of the next power of 10 from the stack and put it in register pair DE.
1356
POP HL
Get the memory pointer for the output buffer from the stack and put it in register pair HL.
1357
LD (HL),B
Save the ASCII value for the digit (from register B that tracked the number of divisions) to the location of the output buffer pointer (stored in register pair HL).
1358
INC HL
Bump the value of the input buffer pointer in register pair HL since we just filled that spot with an ASCII value.
1359
POP AF
Get the number of digits to convert from the stack and put it in A.
135A
POP BC
Get the counts of digits before/after the decimal point value from the stack and put it into register pair BC.
135B
DEC A
Decrement the value of the counter in register A (which is a countdown from 5).
135C-135D
If the counter of the number of digits (from 5) is still not zero, jump back to 1335H until all of the digits have been figured.
135E-1360
So now all the digits have been calculated in ASCII, so GOSUB 1291H to put a decimal point or comma into the input buffer if necessary.
1361
LD (HL),A
Save a zero (the value in register A which hit zero when the loop from 5 finished) to the input buffer, pointed to by register pair HL.
1362
POP DE
Get the value from the stack (which was whatever value was in DE when this routine started) and put it in register pair DE.
1363
RET
Return.

1364-136B – DOUBLE PRECISION CONSTANT STORAGE LOCATION

1364-136BH
00 00 00 00 F9 02 15 A2
A double precision constant equal to 1E10 (or 10 x 10E9)is stored here.

136C-1373 – DOUBLE PRECISION CONSTANT STORAGE LOCATION

136C-1373H
FD FF 9F 31 A9 5F 63 B2
A double precision constant equal to 9.9921E14 (or 1 x 10e15) is stored here.

1374-137B – DOUBLE PRECISION CONSTANT STORAGE LOCATION

1374-137BH
FE FF 03 BF C9 1B 0E B6
A double precision constant equal to 1×10^16 is stored here.

137C-1383 – DOUBLE PRECISION CONSTANT STORAGE LOCATION

137C-1383H
00 00 00 00 00 00 00 80
A double precision constant equal to 0.5 is stored here.
BYTE SAVING NOTE: Referencing 1380H, which is half-way through this double precision value of .5, results in a single precision value of 0.5.

1384-138B – DOUBLE PRECISION CONSTANT STORAGE LOCATION

1384-138BH
00 00 04 BF C9 1B 0E B6
A double precision constant equal to 1×10^16 is stored here.
138A-138DH
0E B5 00 80
BYTE SAVING NOTE: A double precision constant equal to .502778.

138C-13D1 – DOUBLE PRECISION INTEGER CONSTANT STORAGE LOCATION

138C-1392H
00 80 C6 A5 7E 8D 03
1 x 10e15.
1393-1399H
00 40 7A 10 F3 5A 00
1 x 10e14.
139A-13A0H
00 A0 72 4E 18 09 00
1 x 10e13.
13A1-13A7H
00 10 A5 D5 E8 00 00
1 x 10e12.
13A1-13A7H
00 10 A5 D5 E8 00 00
1 x 10e12.
13A8-13AEH
00 E8 76 48 17 00 00
1 x 10e11 (which is 100,000,000,000).
13AF-13B5H
00 E4 0B 54 02 00 00
1 x 10e10 (which is 10,000,000,000).
13B6-13BCH
00 CA 9A 3B 00 00 00
1 x 10e09 (which is 1,000,000,000).
13BD-13C3H
00 E1 F4 05 00 00 00
1 x 10e08 (which is 100,000,000).
13C4-13CAH
80 96 98 00 00 00 00
1 x 10e07 (which is 10,000,000).
13CB-13D1H
40 42 0F 00 00 00 00
1 x 10e06 (which is 1,000,000).

13D2H-13D9H – SINGLE PRECISION INTEGER CONSTANT STORAGE LOCATION

13D2-13D4H
A0 86 01
1 x 10e04 (which is 100,000).
13D5-13D7H
10 27 00
1 x 10e03 (which is 10,000).
13D8-13D9H
E8 03
1 x 10e02 (which is 1,000).
13DA-13DBH
E8 03
1 x 10e01 (which is 100).
13DEH
10
1 x 10e00 (which is 10).
13DF
Nothing.

13E1-13E6 – LEVEL II BASIC MATH ROUTINE

13E1
NOP
Do nothing.
13E2-13E4
LD HL,0982H
Load register pair HL with 0982H.

NOTE: 0982H is the address of the routine for conversion of floating point numbers from negative to positive.
13E5
EX (SP),HL
Exchange the value of that routines jump address to the stack with the value of the return address in register pair HL.
13E6
JP (HL)
Jump to the address in register pair HL, which is basically a return to caller.

13E7-13F1 – LEVEL II BASIC SQUARE ROOT ROUTINE – SQR(n) routine.

  • Single-precision values only should be used. (REG 1 = SQR(REG 1)).
    Computes the square root of any value in REG 1. The root is left in REG 1 as a single precision value.
  • NOTE: To use a ROM call to find the square root of a nonnegative single precision numbers, store the number in 4121H-4124H and then CALL 13E7H. The result (in single precision format) is in 4121H-4124Hin approximately 48 milliseconds. NOTE: A fatal error (returning control to the Level II monitor) occurs if the input number is negative.
13E7-13F1
GOSUB 09A4 which moves the SINGLE PRECISION value in REG 1 to the stack (stored in LSB/MSB/Exponent order).
13EA-13EC
LD HL,1380H
Load register pair HL with the starting address of a single precision constant equal to 0.5 (which will be the exponent).
13ED-13EF
GOSUB 09B1H (which moves a SINGLE PRECISION number pointed to by HL to REG 1).
13F0-13F1
Jump to the EXP(n) routine at 13F5H (which will be using a .5 exponent to do the square root) skipping 13F2H since the exponent is already single precision.

13F2-1478 LEVEL II BASIC X to the Y Power (X^Y) ROUTINE

  • A call to 13F2H raises the single precision value which has been saved to the stack to the power specified in REG 1. The result will be returned in REG 1. The method of computation is e ** (y ln x).
13F2-13F4
Make sure that the exponent is single precision by GOSUB to 0AB1H which is the CONVERT TO SINGLE PRECISION routine at 0AB1H (which converts the contents of REG 1 from integer or double precision into single precision).
13F5
POP BC
Get the MSB of the single precision value from the stack and put it in register pair BC.
13F6
POP DE
Get the NMSB and the LSB of the single precision value from the stack and put it in register pair DE.
  • NOTE: To use a ROM call to raise a single precision number (the base) to a single precision power (the exponent), store the base (single precision) in registers BCDE, and store the exponent (also single precision) in 4121H-4124H and then CALL 13F7H. The result (in single precision format) is in 4121H-4124H and in approximately 50 milliseconds.
13F7-13F9
GOSUB 0955H to check the sign for the single precision value in REG 1 (the exponent).
13FA
LD A,B
Load register A with the MSB of the number to be raised (stored as a single precision value in register B).
13FB-13FC
Jump to the EXP(n) routine at 1439H if the exponent (the single precision value in REG 1) is equal to zero.
13FD-13FF
Skip the next 2 opcodes (which check to see if zero is involved) if the exponent (the single precision value in REG 1) is positive.
1400
OR A
Check to see if the value to be raised (i.e., the single precision value in register pairs BC and DE) is equal to zero.
1401-1403
Display a ?/0 ERROR message if the single precision value in REG 1 is negative and the single precision value in register pairs BC and DE is equal to zero.
/0 ERROR entry point.
1404
OR A
ANOTHER check to see if the value to be raised (i.e., the single precision value in register pairs BC and DE) is equal to zero.
1405-1407
Jump to 0779H if the value to be raised (i.e., the single precision value in register pairs BC and DE) is equal to zero.
1408
PUSH DE
At this point we know that none of the values are zero, and we are raising the number to a positive power. Save the value to be raised (the NMSB and the LSB of the single precision value in register pair DE) to the stack.
1409
PUSH BC
Save the exponent and the MSB of the single precision value in register pair BC to the stack.
140A
LD A,C
Load register A with the value of the MSB of the single precision value to be raised (which is stored in register C).
140B-140C
OR 7FH
Test the sign of the based by turning on bits 0-6 of the MSB of the single precision value (0111 1111) in register A.
140D-140F
Load the exponent (the power) into BC/DE by GOSUB to 09BF which loads the SINGLE PRECISION value in REG 1 (the exponent) into register pair BC/DE.
1410-1412
Jump down to 1421H if the base (the single precision value to the stack) is positive.
1413
PUSH DE
Save the NMSB and the LSB of the exponent (the single precision value in register pair DE) to the stack.
1414
PUSH BC
Save the exponent and the LSB of the single precision value in register pair BC to the stack.
1415-1417
GOSUB to 0B40H to figure the integer portion of the exponent (i.e., the single precision value in REG 1) into A with the truncated floating point portion into REG 1.
1418
POP BC
Restore the exponent and the MSB of the single precision value from the stack and put it in register pair BC.
1419
POP DE
Restore the NMSB and the LSB of the single precision value from the stack and put it in register pair DE.
141A
PUSH AF
Save the integer portion of the exponent (i.e., the value in register pair AF) to the stack.
141B-141D
Compare the original exponent to the truncated one by GOSUB to 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=00H if REG 1 = BCDE
  • A=01H if REG 1>BCDE; and
  • A=FFH if REG 1<BCDE.
141E
POP HL
Get the exponent as an integer from the stack and put it in register H.
141F
LD A,H
Load register A with the exponent as an integer (as stored in register H).
1420
RRA
If the exponent (as an integer) is odd, set the CARRY FLAG.
1421
POP HL
Get the original exponent from the stack and put it in register pair HL.
1422-1424
LD (4123H),HL
Save the value of the original exponent and the MSB of the single precision value (stored in register pair HL) in REG 1.
1425
POP HL
Get the rest of the exponent from the stack and put it in register pair HL.
1426-1428
LD (4121H),HL
Save the rest of the exponent (i.e., as stored in register pair HL as the NMSB and the LSB of the single precision value) in REG 1.
1429-142B
If the CARRY FLAG is set (i.e. the exponent is odd and the base is negative) GOSUB to 13E2H.
142C-142E
If the exponent is an integer and the base is negative, GOSUB to 0983H to invert the value of the exponent.
142F
PUSH DE
Save the NMSB and the LSB of the exponent (i.e., the single precision value in register pair DE) to the stack.
1430
PUSH BC
Save the MSB of the exponent (i.e., the single precision value in register pair BC) to the stack.
1431-1433
CALL the LOG(N) routine at 0809H (which computes the natural log (base E) of the single precision value in REG 1. The result is returned as a single precision value in REG 1. Can give an ILLEGAL FUNCTION CALL erro if a negative base is raised to a power with a fraction).
1434
POP BC
Get the exponent and the MSB of the single precision value from the stack and put it in register pair BC.
1435
POP DE
Get the NMSB and the LSB of the single precision from the stack and put it in register pair DE.
1436-1438
We need to multiply the ln(value) * the exponent so we have to GOSUB to 0847H to SINGLE PRECISION MULTIPLY routine (which multiplies the current value in REG 1 by the value in (BC/DE). The product is left in REG 1.

1439 – EXP routine. Single-precision only. (REG 1 = EXP(REG1)).

  • A call to 1439H raises E (natural base) to the value in REG 1 which must be a single precision value. The result will be returned in REG 1 as a single precision number.
  • NOTE: To use a ROM call to find EXP(X), where X is a single precision variable, store the value of X in 4121H-4124H and then CALL 1439H. The result (in single precision format) is in 4121H-4124Hin approximately 28 milliseconds. NOTE: A fatal error occurs if the result is as large as 2 to the power of 127.
1439-143BH
“EXP”
Call 09A4 to move the SINGLE PRECISION value in REG 1 (the exponent) to the stack (stored in LSB/MSB/Exponent order).
143C-143E
LD BC,8138H
Load register pair BC with the exponent and MSB of a single precision constant.
143F-1441
LD DE,AA3BH
Load register pair DE with the NMSB and the LSB of a single precision constant. Register pairs BC and DE are now equal to a single precision constant of 1.442695 (which is approximately 2 + ln 2).
1442-1444
We need to multiply the exponent value by 2 ln 2 so we call the SINGLE PRECISION MULTIPLY routine at 0847H (which multiplies the current value in REG 1 by the value in (BC/DE). The product is left in REG 1.
1445-1447
LD A,(4124H)
Load register A with the result of the math just done (i.e., which was multiplying the exponent value by 2 ln 2) which was stored in REG 1.
1448-1449
CP 88H
Check to see if the integer portion of the single precision value in REG 1 uses more than 7 bits of precision by comparing it against a mask of 1000 1000.
144A-144C
Jump to 0931H if the single precision value in REG 1 uses more than 7 bits of precision for its integer portion.
144D-144F
So now that we know the integer portion is less than 8 bits, we need to get the integer and put it into Register A by GOSUB to 0B40H to get the integer portion of the value in REG 1 and return with it in register A.
1450-1451
ADD A,80H
Adjust the value in register A by masking it against 80H (Binary: 1000 0000).
1452-1453
ADD A,02H
Adjust the value in register A by adding 2 more (Binary: 1000 0010).
1454-1456
If (exponent * 2 ln 2) is => 126 (meaning when 2 was added it it, it overflowed with a 128), jump to 0931H.
1457
PUSH AF
Save the integer value (+82H) (as stored in register pair AF) to the stack.
1458-145A
LD HL,07F8H
Load register pair HL with a single precision constant equal to 1.0 (as found at 1458H).
145B-145D
Go add the single precision constant 1.0 (as pointed to by register pair HL) to the current value in REG 1 which is EXP * 2 ln 2.
145E-1460
Need to multiply that by ln 2, so GOSUB to 0841H to multiply (1 + [EXP * 2 ln 2]) (as stored in REG 1) by 0.693147.
1461
POP AF
Get the integerized value of EXP * 2 ln 2 (as stored in the stack) and put it in register pair AF.
1462
POP BC
Get the original exponent into BC/DE in 2 steps fist get the exponent and the MSB of the single precision value from the stack and put it in register pair BC …
1463
POP DE
and then get the NMSB and the LSB of the single precision value from the stack and put it in register pair DE.
1464
PUSH AF
Save the integerized EXP * 2 ln 2 (stored in register pair AF) to the stack.
1465-1467
Now we need to subtract the original exponent from the integerized exponent so we GOSUB to 0713H which is the SINGLE PRECISION SUBTRACT routine (which subtracts the single precision value in BC/DE from the single precision value in REG 1. The difference is left in REG 1).
1468-146A
To force that difference to be a positive number we GOSUB to 0982H which makes the current single precision value in REG 1 positive.
146B-146D
LD HL,1479H
Load register pair HL with the starting address for a series of 8 coefficients.
146E-1470
GOSUB to 14A9H to do that series of computations.
1471-1473
LD DE,0000H
We need to load the integerized equivalent of EXP * 2 lnt 2 into BC/DE so first we load register pair DE with zero …
1474
POP BC
… and then get the value from the stack and put it in register pair BC.
1475
LD C,D
Load register C with zero (since Register D was filled with a zero in 1471H).
1476-1478
We need to multiply by the sum from the series and return so we jump to 0847H which is the the SINGLE PRECISION MULTIPLY routine at 0847H (which multiplies the current value in REG 1 by the value in (BC/DE). The product is left in REG 1.

1479-1499 – SINGLE PRECISION CONSTANT STORAGE LOCATION
This represents 1/6, -1/5, 1/4, -1/3, 1/2, -1, and 1

1479H
09
The number of single precision constants (9) which follow are stored here.
147A-147DH
40 2E 94 74
A single precision constant equal to -0.00014171607 (-1.413165 * 10e-4) is stored here.
147E-1481H
70 4F 2E 77
A single precision constant equal to 0.00132988204 (1.32988 * 10e-3, roughly -1/6) is stored here.
1482-1485H
6E 02 88 7A
A single precision constant equal to -0.00830136052 (-8.30136 * 10e-3, roughly -1/5) is stored here.
1486-1489H
E7 A0 2A 7C
A single precision constant equal to 0.04165735095 (roughly 1/4) is stored here.
148A-148DH
50 AA AA 7E
A single precision constant equal to -0.16666531543 (roughly -1/3) is stored here.
148E-1491H
FF FF 7F 7F
A single precision constant equal to 0.49999996981 (roughly 1/2) is stored here.
1492-1495H
00 00 80 81
A single precision constant equal to -1.0 is stored here.
1496-1499H
00 00 00 81
A single precision constant equal to 1.0 is stored here.

149A-14C8 – LEVEL II BASIC MATH ROUTINE

  • This is a general purpose summation routine which computes the series SUM ((((x^2 * c0+c1)x^2 +c2)x^2 + … cN)x for I=0 to N when entered at 149AH If entered at 14A9H the series changes to SUM ((((x*c0+c1)x*c2)x+c3)x+…cN. On entry, the x is held in BC/DE and HL points to a list containing the number of terms followed by the coefficients.
149A-149C
GOSUB to 09A4 to which move the SINGLE PRECISION value in REG 1 to the stack (stored in LSB/MSB/Exponent order).
149D-149F
LD DE,0C32H
Load register pair DE with the return address of 0C32H.

NOTE: 0C32H pops BC and DE and then JUMPs to JP 0847H.
14A0
PUSH DE
Save DE to the STACK.
14A1
PUSH HL
Save the memory pointer of list containing the number of terms followed by the coefficients (as stored in register pair HL) to the stack.
14A2-14A4
GOSUB to 09BFH which loads the SINGLE PRECISION value in REG 1 into register pair BC/DE.
14A5-14A7
Since REG 1 and BC/DE now hold the same number, you can square that by a GOSUB to 0847H which is the SINGLE PRECISION MULTIPLY routine (which multiplies the current value in REG 1 by the value in (BC/DE). The product is left in REG 1).
14A8
POP HL
Restore the address of the coefficient from the stack and put it in register pair HL.
14A9-14AB
We need to move either x or x**2 (depending on the routine entry point) to the stack so we GOSUB to 09A4 which moves the SINGLE PRECISION value in REG 1 to the stack (stored in LSB/MSB/Exponent order).
14AC
LD A,(HL)
Load register A with the number of values to be figured at the location of the memory pointer in register pair HL.
14AD
INC HL
Bump the value of the memory pointer in register pair HL so that it points to the next coefficient.
14AE-14B0
Now load the coefficient (stored in HL) and move it to REG 1 by GOSUB to 09B1H (which moves a SINGLE PRECISION number pointed to by HL to REG 1).
14B1H
06 F1
Z-80 Trick! See the general explanation at 10F8H.
14B2
Get the count of coefficients left (from the stack) and put it in register A.
14B3-14B4
POP BC
POP DE
Get the value of x from the stack and put it in register pair BC/DE.
14B5
DEC A
Count 1 of the terms as computed by decrementing the counter in register A.
14B6
RET Z
If that decrement results in a zero (meaning the series of computations has been completed) return out of the subroutine.
14B7-14B8
PUSH DE
PUSH BC
Save the NMSB and the LSB of x from DE to the stack and save the MSB of x from BC to the stack.
14B9
PUSH AF
Save counter of remaining terms to compute (stored in register A) to the stack.
14BA
PUSH HL
Save the value of the memory pointer to the next coefficient (stored in register pair HL) to the stack.
14BB-14BD
Compute C(I)*x by GOSUB to 0847H which is the SINGLE PRECISION MULTIPLY routine (which multiplies the current value in REG 1 by the value in (BC/DE). The product is left in REG 1.
14BE
POP HL
Restore the coefficient table address (from the stack) to register pair HL.
14BF-14C1
Get the next coefficient from HL into BC/DE by GOSUB to 09C2H (which loads a SINGLE PRECISION value pointed to by register pair HL into register pairs BC and DE).
14C2
PUSH HL
Save the next coefficient (stored in register pair HL) to the stack.
14C3-14C5
Compute C(I)*x+C(I+1) by GOSUB to 0716H which is the SINGLE PRECISION ADD routine (which adds the single precision value in (BC/DE) to the single precision value in REG 1. The sum is left in REG 1).
14C6
POP HL
Restore the coefficient table address (from the stack) to register pair HL.
14C7-14C8
Jump back to 14B2H to continue the series. REG 1 contains the current term.

14C9-1540 – LEVEL II BASIC RND(n). Generates a single-precisions random number between 0 and 1, or 1 and n depending on the parameter passed in REG 1, The random value is returned in REG 1 as an integer with the mode flag set. The parameter passed will determine the range of the random number returned. A parameter of 0 will return an interger between 0 and 1. A parameter greater than 0 will have any fraction portion truncated and will cause a value between 1 and the integer portion of the parameter to be returned.

14C9-14CBH
“RNDM”
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).
  • NOTE: To run a RND(J) function via a ROM call just The RND(J) function (with J a nonzero integer) load the value of J into the HL register pair. Then CALL 14CCH and then CALL 0A7FH. The result (in integer format) is in 4121H-4122H and in HL in approximately 5.7 milliseconds. The input variable J must have a value between 1 and 32767, inclusive, or an FC error will occur.
14CC
LD A,H
Load register A with the value of the MSB for the integer value in register H.
14CD
OR A
Check to see if the integer value in register pair HL is negative.
14CE-14D0
Display a ?FC ERROR message if the integer value in register pair HL is negative.
14D1
OR L
To test for HL=0, the opcode pair of LD A,H / OR L is a simplest way. Only if both H and L are zero, will A be zero.
14D2-14D4
If it is zero, we don’t need the rest of the below which functions to generate RND(n) so we just jump to 14F0H (which generates RND(0)) if the integer value in register pair HL is equal to zero (meaning the call was for RND(0)).
14D5
PUSH HL
Since it wasn’t zero, we need to save the n of RND(n) (as stored in register pair HL) to the stack.
14D6-14D8
GOSUB to 14F0H (which generates RND(0)) and return with the single precision result in REG 1.
14D9-14DB
Load the random number into BC/DE by a GOSUB to 09BFH which loads the SINGLE PRECISION value in REG 1 into register pair BC/DE.
14DC
EX DE,HL
Load register pair HL with the NMSB and the LSB of the single precision value in register pair DE.
14DD
EX (SP),HL
Exchange the integer value to the stack with NMSB and the LSB of the single precision value in register pair HL. At this point, the random number is in the stack and the n (of RND(n)) is stored in register pair HL.
14DE
PUSH BC
Save the RND(0) value to the stack.
14DF-14E1
Convert the original x of RND(x) to single precision by GOSUB to 0ACFH which converts the integer value in register pair HL to single precision and return with the result in REG 1.
14E2-14E3
POP BC
POP DE
Restore the RND(0) value from the stack and put it into register pair BC/DE.
14E4-14E6
Multiply the RND(0) value (currently in BC/DE) by the n of RND(n) (currently in REG 1) by GOSUB to 0847H which is the SINGLE PRECISION MULTIPLY routine (which multiplies the current value in REG 1 by the value in (BC/DE). The product is left in REG 1.
14E7-14E9
LD HL,07F8H
Load register pair HL with the starting address of a single precision constant equal to 1.0.
14EA-14EC
Increase the random number by one by GOSUB to 070BH which adds the single precision constant pointed to by register pair HL (which is 1.0) to the single precision value in REG 1 (which is the random number). Return with the single precision result in REG 1
14ED-14EF
With the random number now in REG 1, jump to 0B40H (which will convert it to an integer and RETurn to the subroutine caller).

14F0H – This routine calculates RND(0).

  • NOTE: To run a RND(0) function via a ROM call just CALL 14F0H. No input variable is necessary. The result (in single precision format) is in 4121H-4124H in approximately 2.4 milliseconds.
14F0-14F2
LD HL,4090H
Load register pair HL with the starting address for a table used for figuring random numbers.

NOTE: 4090H holds the random number seed 2
14F3
PUSH HL
Save the starting address for a table used for figuring random numbers (stored in HL) to the stack.
14F4-14F6
LD DE,0000H
Load register pair DE with zero (which will be the NMLSB and LSB of the starting value).
14F7
LD C,E
Load register C with zero (C will be the MSB of the starting value).
14F8-14F9
LD H,03H
Load register H with the counter value for the loop (which will be 3).
14FA-14FB
LD L,08H
Load register L with a counter value of 8.
14FC
EX DE,HL
Exchange the counters in register pair HL with the NMSB and the LSB of the random number in register pair DE.
14FD
ADD HL,HL
Multiply the NMSB and the LSB of the random number in register pair HL by two.
14FE
EX DE,HL
Exchange the NMSB and the LSB of the random number in register pair HL with the counters in register pair DE.
14FF
LD A,C
Load register A with the MSB of the random number in register C.
1500
RLA
Multiply the MSB of the random number in register A by two.
1501
LD C,A
Load register C with the adjusted MSB of the random number in register A.
1502
EX (SP),HL
Exchange the counter values in register pair HL with the value of the memory pointer to the stack.
1503
LD A,(HL)
Load register A with the table value (held at the location of the memory pointer in register pair HL).
1504
RLCA
Multiply the value in register A by two.
1505
LD (HL),A
Save the doubled value (stored in register A) at the location of the memory pointer in register pair HL.
1506
EX (SP),HL
Exchange the memory pointer in register pair HL with the counter values to the stack.
1507-1509
Jump forward to 1516H if the table value hasn’t overflowed.
150A
PUSH HL
If we are here, the table value overflowed so we need to save the counter values in register pair HL to the stack.
150B-150D
LD HL,(40AAH)
Load register pair HL with the NMSB and the LSB of the random number seed.

NOTE: 40AAH-40ADH holds the random number seed.
150E
ADD HL,DE
Add the NMSB and the LSB of the random number in register pair DE to the NMSB and the LSB of the random number seed in register pair HL.
150F
EX DE,HL
Load register pair DE with the adjusted NMSB and LSB of the random number in register pair HL.
1510-1512
LD A,(40ACH)
Load register A with the MSB of the random number seed.
1513
ADC A,C
Add the MSB of the random number in register C to the MSB of the random number seed in register A.
1514
LD C,A
Load register C with the adjusted MSB of the random number in register A.
1515
POP HL
Get the counter values from the stack and put it in register pair HL.
1516
DEC L
Decrement the loop counter in register L.
1517-1519
Loop back to 14FCH until the above has been done eight times.
151A
EX (SP),HL
Exchange the counter values in register pair HL with the memory pointer of the table value to the stack.
151B
INC HL
Bump to the next table value.
151C
EX (SP),HL
Exchange the value of the table value in register pair HL with the counter value to the stack.
151D
DEC H
Decrement the counter value of the outer loop (in register H).
151E-1520
Loop back to 14FAH three times until the random number has been figured.
1521
POP HL
Clear the flag table address from the stack. The fact that it is going into HL is not important.
1522-1524
LD HL,B065H
Load register pair HL with the value to reseed the random number seed.
1525
ADD HL,DE
Add the seed (from register pair HL) to the NMSB and the LSB of the random number in register pair DE.
1526-1528
LD (40AAH),HL
Save the adjusted value in register pair HL as the NMSB and the LSB of the random number seed.

NOTE: 40AAH-40ADH holds the random number seed.
1529-152B
Go set the current number type to single precision.
152C-152D
LD A,05H
Load register A with a 5.
152E
ADC A,C
Add 5 (the value held in A) and the MSB of the random number in register C.
152F-1531
LD (40ACH),A
Save the adjusted value in register A as the MSB of the random number seed.
1532
EX DE,HL
Swap DE and HL so as to move the NMSB and LSB to DE so that we will have a BC/DE pair for the random number.
1533-1534
LD B,80H
Load register B with a value for the sign flag and the exponent (Binary: 1000 0000).
1535-1537
LD HL,4125H
Load register pair HL with the address for the sign value storage location.

NOTE: 4125H-4126H is used by floating point routines.
1538
LD (HL),B
Save the sign result (1000 0000) in register B at the location of the memory pointer in register pair HL.
1539
DEC HL
Decrement to exponent (held in register pair HL).
153A
LD (HL),B
Set the exponent to (1000 0000) so that the value will be < 1.
153B
LD C,A
Load register C with the value of the MSB for the single precision random number in register A.
153C-153D
LD B,00H
Zero the value of the exponent in register B.
153E-1540
Jump to 0765H which will normalize the value and then jump to 14D9H unless RND(0) was called in which case return to caller.

1541-1546 – LEVEL II BASIC COS

  • COS routine. Single-precision only.(REG 1 = COS(REG 1)).
    A call to 1541H computes the cosine for an angle given in radians. The angle must be a floating point value in REG 1; the cosine will be returned in REG 1 as a floating point value.
  • NOTE: To use a ROM call to find COS(X), where X is a single precision variable (in radians), store the value of X in 4121H-4124H and then CALL 1541H. The result (in single precision format) is in 4121H-4124Hin approximately 25 milliseconds.
1541-1543H
“COSN”
LD HL,158BH
Load register pair HL with the starting address of a single precision constant equal to 1.57079637029 (which is pi / 2).
1544-1546
GOSUB to 070BH to add 1.57079637029 (stored in HL) to the single precision value in REG 1 and then pass through to the SIN() routine which is next.

1547-158A – LEVEL II BASIC SIN

  • SIN(n) routine. Single-precision only.(REG 1 = SIN(REG 1)).
  • A call to 1549H returns the sine as a single precision value in REG 1. The sine must be given in radians in REG 1.
  • The actual calculation routine is:
    1. Assume X <= 360 degrees.
    2. Recompute x as x=x/360 so that x=< 1.
    3. If x <= 90 degrees go to step 7.
    4. If x <= 180 degrees then x=0.5-x and then go to step 7.
    5. If x <= 270 degrees then x=0.5-x.
    6. Recompute x as x=x-1.0.
    7. Compute SIN using the power series.
  • NOTE: To use a ROM call to find SIN(X), where X is a single precision variable, store the value of X in 4121H-4124H and then CALL 1547H. The result (in single precision format) is in 4121H-4124Hin approximately 25 milliseconds. NOTE: The argument (X) must be in radians.
1547-1549H
“SINE”
Call 09A4 which moves the SINGLE PRECISION value in REG 1 (the x in a SIN(x) call) to the stack (stored in LSB/MSB/Exponent order).
154A-154C
LD BC,8349H
Load register pair BC with the exponent and the MSB of a single precision constant.
154D-154F
LD DE,0FDBH
Load register pair DE with the NMSB and the LSB of a single precision constant. Register pairs BC and DE now hold a single precision constant equal to 6.2831855 (which is pi * 2).
1550-1552
Move 2 x pi value (held in DC/BE) into REG 1 by GOSUB to 09B4H (which moves the SINGLE PRECISION value in DC/DE into REG 1).
1553-1554
POP BC
POP DE
Put the x from a SIN(x) call into BC/DE.
1555-1557
To divide the x from a SIN(x) call (held in BC/DE) by pi*2 (held in REG 1) we must GOSUB 80A2H to divide the single precision value in register pairs BC and DE by the single precision value in REG 1. Return with the single precision result in REG 1.
1558-155A
Move that value (x / 2*pi) from REG 1 to the stack by GOSUB to 09A4H which moves the SINGLE PRECISION value in REG 1 to the stack (stored in LSB/MSB/Exponent order).
155B-155D
Go figure the integer portion for the single precision value in REG 1 by calling 0B40H. We need to do this so we can isolate the remainder.
155EH,155F
POP BC
POP DE
Put the quotient and remainder of x/2*pi into BC/DE.
1560-1562
To get the remainder we need to subtract the integer portion from the full portion so we GOSUB 0713H (the SINGLE PRECISION SUBTRACT routine) to subtract the single precision value in BC/DE (the entire result) from the single precision value in REG 1 (the integer part of the result). The difference is left in REG 1).
1563-1565
LD HL,158FH
Load register pair HL with the starting address of a single precision constant equal to 0.25.
1566-1568
Next in calculating a SIN we would need to subtract .25 (held in HL) from the fractional part (held in REG 1) so as to see if it is <= to 90 degrees. To do this we GOSUB 0710H to subtract the single precision value in REG 1 from the single precision constant pointed to by register pair HL. Return with the result in REG 1.
1569-156B
Go check the sign of the result of that (.25 – fractional part) subtraction which is held in REG 1.
156C
SCF
Set the CARRY FLAG.
156D-156F
Jump to 1577H if the single precision value in REG 1 is positive (meaning it is < than 90 degrees).
1570-1572
If we are here, it is => 90 degrees, so we need to add .5 to the single precision value in REG 1. Return with the result in REG 1
1573-1575
Go check the sign for the single precision value in REG 1 which basically checks to see if it is > 0.75 (meaning < 270 degrees).
1576
OR A
Test the value of the sign test in register A.
1577
PUSH AF
Save the sign indicator (+ or -1) in register pair AF to the stack.
1578-157A
If it is positive, make it negative by GOSUB to 0982H.
157B-157D
LD HL,158FH
Load register pair HL with the starting address of a single precision constant equal to 0.25.
157E-1580
Add .25 (stored in HL) to the current value in REG 1 by GOSUB to 070BH (result is saved in REG 1).
1581
POP AF
Get the sign reversal flag from the stack and put it in register pair AF.
1582-1584
Set the sign of the x term according to the quadrant by GOSUB to 0982H if if the CARRY FLAG wasn’t set from above.
1585-1587
LD HL,1593H
Load register pair HL with 1593H (which is the starting address for a series of single precision values for a set of computations).
1588-158A
JUMP to 149AH to compute the series and then RETURN.

158BH-15A7H – SINGLE PRECISION CONSTANT STORAGE LOCATION

158B-158EH
DB 0F 49 81
A single precision constant equal to 1.57079637029 is stored here.
158F-1592H
00 00 00 7F
A single precision constant equal to 0.25 is stored here.
1593H
05H
The number of single precision constants (05) which follows is stored here. These are the coefficients used in the power series to compute SIN(x).
1594-1597H
BAH D7H 1EH 86H
A single precision constant equal to 39.7106704708 is stored here.
1598-159BH
64H 26H 99H 87H
A single precision constant equal to -76.5749816893 is stored here.
159C-159FH
58H 34H 23H 87H
A single precision constant equal to 81.6022338865 is stored here.
15A0-15A3H
E0H 6DH A5H 86H
A single precision constant equal to -41.3416748045 is stored here.
15A4-15A7H
DAH 0FH 49H 83H
A single precision constant equal to 6.28318500497 is stored here.

15A8-15BC – LEVEL II BASIC TAN ROUTINE – “TAN”
TAN(n)

  • Single-precision only.(REG 1 = TAN(REG 1)).
    A call to 15A8H computes the tangent of an angle in radians. The angle must be specified as a single precision value in REG 1. The tangent will be left in REG 1.
    Uses the fact that TAN(x) = SIN(x) / COS(x)
  • NOTE: To use a ROM call to find TAN(X), where X is a single precision variable (in radians), store the value of X in 4121H-4124H and then CALL 15A8H. The result (in single precision format) is in 4121H-4124Hin approximately 54 milliseconds. NOTE: A fatal error occurs if the result is as large as 2 to the power of 127, which will be the case if the value of X is sufficiently close to any odd multiple of pi/2 radians.
15A8-15AA
Call 09A4 which moves the SINGLE PRECISION value in REG 1 to the stack (stored in LSB/MSB/Exponent order).
15AB-15AD
Call the SIN(n) routine at 1547H (which returns the sine as a single precision value in REG 1. The sine must be given in radians in REG 1.
15AEH,15AF
POP BC
POP HL
Get the original exponent and value from the stack and put it in register pair BC/HL.
15B0-15B2
Call 09A4 which moves the SIN(x) single precision value (stored in REG) 1 to the stack (stored in LSB/MSB/Exponent order).
15B3
EX DE,HL
Load register pair DE with the NMSB and the LSB of the single precision value in register pair HL.
15B4-15B6H 
Call 09B4H (which moves the original value in BC/DE into REG 1).
15B7-15B9
Call the COSINE routine at 1541H (which computes the cosine for an angle given in radians. The angle must be a floating point value; the cosine will be returned in REG 1 as a floating point value.
15BA-15BC
Jump to 08A0H to compute SIN(n) / COS(n) and return the value as TAN(n).

15BD-15E2 – LEVEL II BASIC ATN ROUTINE – “ATAN”
ATN(n) routine.

  • Single-precision only.(REG 1 = ATN(REG 1)).
    A call to 15BD returns the angle in radians, for the floating point tangent value in REG 1. The angle will be left as a single precision value in REG 1.
    The method of computation used in this routine is:
    1. Test the sign of the tangent to see if a negative angle is in the 2nd or 4th quadrant. Set the flag to force the result to positive on exit. If the value is negative, invert the sign.
    2. Test magnitude of tangent. If it is < 1 go to step 3. Otherwise, compute its reciprocal and put the return address on the stack that will calculate pi/2 – series value.
    3. Evaluate the series: (((x^2*c0+c1) x^2+c2) … c8)x
    4. If the flag from step 1 is not set, then invert the sign of the series result.
    5. If the original value is < 1 then return to the caller. Otherwise, compute pi/2-value from step 4 and then return.
  • NOTE: To use a ROM call to find ATN(X), where X is a single precision variable, store the value of X in 4121H-4124H and then CALL 15BDH. The result (in single precision format, in radians) is in 4121H-4124Hin approximately 27 milliseconds.
15BD-15BF
Go check the sign of the single precision value in REG 1
15C0-15C2
If the single precision value in REG 1 is negative then GOSUB to 13E2H to return address of 0982H to the stack pointer.
15C3-15C5
Go convert the negative number in REG 1 to positive if necessary.
15C6-15C8
LD A,(4124H)
Load register A with the exponent of the tangent (which is a single precision value in REG 1).
15C9-15CA
CP 81H
Check to see if the the exponent of the tangent (which is a single precision value in REG 1) is less than one by comparing it against 81H (Binary: 1000 0001). Results:
  • If A=”1″ it sets the ZERO FLAG.
  • If A<“1” then the CARRY FLAG will be set
  • If A>=”1″ then the NO CARRY FLAG will be set.
15CB-15CC
Jump to forward to 15D9H if A<“1”.
15CD-15CF
LD BC,8100H
Load register pair BC with an exponent and a MSB for a single precision value. This also sets C to 00H.
15D0
LD D,C
Zero the NMSB of the single precision value in register D.
15D1
LD E,C
Zero the LSB of the single precision value in register E.
15D2-15D4
GOSUB 082AH to get the reciprocal of the tangent. This routine divides the single precision value in REG 1 into the single precision constant in register pairs BC and DE.
15D5-15D7
LD HL,0710H
Load register pair HL with a return address of 0710H (which is the subtract routine to be called once the series is calculated).
15D8
PUSH HL
Save the value of the return address in register pair HL to the stack.
15D9-15DB
LD HL,15E3H
Load register pair HL with the starting address for a series of single precision numbers for a set of computations.
15DC-15DE
GOSUB to 149AH to do the set of computations.
15DF-15E1
LD HL,158BH
Load register pair HL with the starting address of a single precision constant equal to 1.57079637029 (which is pi/2).
15E2
RET
Return. The return address was set to 0710H above, which will then subtract the last term from pi/2 and then return.

15E3-1607 – SINGLE PRECISION CONSTANTS STORAGE LOCATION

15E3H
09H
The number of single precision constants (9) which follows is stored here
15E4-15E7H
4A D7 3B 78
A single precision constant equal to 0.00286622549 is stored here.
15E8-15EBH
02 6E 84 7B
A single precision constant equal to -0.01616573699 is stored here.
15EC-15EFH
FE C1 2F 7C
A single precision constant equal to 0.04290961441 is stored here.
15F0-15F3H
74 31 9A 3D
A single precision constant equal to 0.07528963666 is stored here.
15F4-15F7H
84 3D 5A 7D
A single precision constant equal to 0.10656264407 is stored here.
15F8-15FBH
C8 7F 91 7E
A single precision constant equal to -0.14208900905 is stored here.
15FC-15FFH
E4 BB 4C 7E
A single precision constant equal to 0.19993549561 is stored here.
1600-1603H
6C AA AA 7F
A single precision constant equal to -0.33333146561 is stored here.
1604-1607H
00 00 00 01
A single precision constant equal to 1.0 is stored here.

1608-18C8 – LIST OF BASIC RESERVED WORDS, TOKENS, AND ENTRY LOCATIONS AS FOLLOWS:

ABS
D9
0977
|
AND
D2
25FD
|
ASC
F6
2A0F
ATN
E4
15BD
|
AUTO
B7
2008
|
CDBL
Fl
0ADB
CHR$(
F7
2A1F
|
CINT
EF
0A7F
|
CLEAR
B8
1E7A
CLOAD
B9
2C1F
|
CLOSE
A6
4185
|
CLS
84
01C9
CMD
85
4173
|
CONT
B3
1DE4
|
COS
El
1541
CSAVE
BA
2BF5
|
CSNG
F0
0ABl
|
CVD
E8
415E
CVI
E6
4152
|
CVS
E7
4158
|
DATA
88
1F05
DEF
DD
415B
|
DEFDBL
9B
1E09
|
DEFINT
99
1E03
DEFSNG
9A
1E06
|
DEFSTR
98
lE00
|
DELETE
B6
2BC6
DIM
8A
2608
|
EDIT
9D
2E60
|
ELSE
95
1F07
END
80
lDAE
|
EOF
E9
4161
|
ERL
C2
24DD
ERR
C3
24CF
|
ERROR
9E
1FF4
|
EXP
E0
1439
FIELD
A3
417C
|
FIX
F2
0B26
|
FN
BE
4155
FOR
81
1CA1
|
FRE
DA
27D4
|
GET
A4
4174
GOSUB
91
1EB1
|
GOTO
5D
1EC2
|
IF
8F
2039
INKEY$
C9
019D
|
INP
DB
2AEF
|
INPUT
89
219A
INSTR
C5
419D
|
INT
D8
0B37
|
KILL
AA
4191
LEFT$
F8
2A61
|
LEN
F3
2A03
|
LET
8C
1F21
LINE
9C
41A3
|
LIST
B4
2B2E
|
LLIST
B5
2B29
LOAD
A7
4188
|
LOC
EA
4164
|
LOF
EB
4167
LOG
DF
0809
|
LPRINT
AF
2067
|
LSET
AB
4197
MEM
C8
27C9
|
MERGE
A8
418B
|
MID$
FA
2A9A
MKD$
EE
4170
|
NAME
A9
418E
|
NEW
BB
1849
NEXT
87
22B6
|
NOT
CB
25C4
|
ON
A1
1FC6
OPEN
A2
4179
|
OR
D3
25F7
|
OUT
AO
2AFB
PEEK
E5
2CAA
|
POINT
C6
0132
|
POKE
B1
2CB1
POS
DC
27F5
|
PRINT
B2
206F
|
PUT
A5
4182
RANDOM
86
01D3
|
READ
8B
21EF
|
REM
93
1F07
RESET
82
0138
|
RESTORE
90
1D91
|
RESUME
9F
lFAF
RETURN
92
lEDE
|
RIGHT$
F9
2A91
|
RND
DE
14C9
RSET
AC
419A
|
RUN
8E
1EA3
|
SAVE
AD
41A0
SET
83
0135
|
SGN
D7
098A
|
SIN
E2
1547
SQR
CD
13E7
|
STEP
cc
2B01
|
STOP
94
1DA9
STR$
F4
2836
|
STRING$
C4
2A2F
|
SYSTEM
AE
02B2
TAB(
BC
2137
|
TAN
E3
15A8
|
THEN
CA
���
TIME$
C7
4176
|
TO
BD
���
|
TROFF
97
1DF8
TRON
96
1DF8
|
USING
BF
2CBD
|
USR
C1
27FE
VAL
FF
2AC5
|
VARPTR
C0
24EB
|
+
CD
249F
CE
2532
|
*
CF
���
|
/
D0
���
?
D1
���
|
>
D4
���
|
=
D5
���
<
D6
���
|
&
26
���
|
FB
3A93

18C9-18F6 – STORAGE LOCATION FOR LEVEL II BASIC ERROR MESSAGES

00
NEXT without FOR
02
Syntax Error
04
RETURN without GOSUB
06
Out of DATA
08
Illegal Function Call
10
Overflow
12
Out of Memory
14
Underfined line number
16
Subscript out of Range
18
Redimensioned Array
20
Division by zero
22
Illegal direct operation
24
Type mismatch
26
Out of string space
28
String too long
30
String formula too complex
32
Can’t continue
34
No RESUME
36
RESUME without error
38
Unprintable error
40
Missing operand
42
Bad file data
44
Disk BASIC command

18F7-1904 – STORAGE LOCATION FOR THE SINGLE PRECISION DIVISION ROUTINE
This code is moved from 18F7-191DH to 4080H-40A5H during non-disk initial setup.

18F7
SUB 00H
Subtract the LSB
18F9
LD L,A
Restore the value to L
18FA
LD A,H
Get the middle byte
18FB
SBC A,00H
Subtract the middle byte
18FD
LD H,A
Move the difference to H
18FE
LD A,B
Get the MSB
18FF
SBC A,00H
Subtract the MSB
1901
LD B,A
Move it back to A
1902
LD A,00H
Clear A
1904
RET
RETurn.

1905-191C – STORAGE LOCATION FOR VALUES PLACED IN RAM UPON INITIALIZATION.

  • This code is moved to 408E during non-disk initial setup.
1918H
X
Difference between M1 and M3 ROMs: 1917H – 1918H contains 434CH in the Model I, 444CH in the Model III. This value is loaded to 40A0H (the start of string space pointer) during power-up.
191CH
X
Difference between M1 and M3 ROMs: 191BH – 191CH contains 42E9H in the Model I, 43E9H in the Model III. This value is loaded to 40A4H (the start of BASIC program pointer) during power-up.

191DH-1935H – MESSAGE STORAGE LOCATION

191D-1923H
“Error”
The Level II BASIC ERROR message is stored here.
1924-1928H
“in”
The Level II BASIC IN message is stored here.
1929-192FH
“READY”
The Level II BASIC READY message is stored here.
1930-1935H
“Break”
The Level II BASIC BREAK message is stored here.

1936-1954 – SCAN STACK ROUTINE

  • This routine is called with DE as the address of the NEXT index. It scans the stack backwards looking for a FOR push. If one is found, it gets the address of the index and compares with the DE that was in place when this routine was called. If it is equal, then it exits with A=0 and HL=Address of the variable. If it is not equal it will keep scanning until no FOR push is found and then exit with A<>0.
1936-1938
LD HL,0004H
Load register pair HL with 4 so that we can backspace.
1939
ADD HL,SP
Add the 4 (held in HL) to the current value of the stack pointer. HL will hold the current stack pointer, the stack point will bump forward 4.
193A
LD A,(HL)
Load register A with the value held at the current stack point MINUS 4.
193B
INC HL
Bump the value of the memory pointer in register pair HL so as to backspace one more byte in case a FOR token is located.
193C-193D
CP 81H
Check to see if the value in register A (which is the current stack pointer – 4) is a FOR token.
193E
RET NZ
Return if the value in register A isn’t a FOR token. This returns with A being non-zero because there was no FOR push.
193F
LD C,(HL)
Load register C with the LSB of the FOR‘s variable address.
1940
INC HL
Bump the value of the memory pointer in register pair HL so as to backspace the current stack pointer by yet another byte.
1941
LD B,(HL)
Load register B with the MSB of the FOR‘s variable address.
1942
INC HL
Bump the value of the memory pointer in register pair HL so now HL will be the address of the FOR variable on the stack.
1943
PUSH HL
Save the value in register pair HL (which is the address of the FOR variable) to the stack.
1944
LD L,C
Load register L with the LSB of the FOR variable’s address in register C.
1945
LD H,B
Load register H with the MSB of the FOR variable’s address in register B.
1946
LD A,D
Load register A with the MSB of the variable address in register D. This sets up fto test the user specified variable address.
1947
OR E
Check to see if the variable address in register pair DE is equal to zero.
1948
EX DE,HL
Exchange the variable address in register pair HL with the variable address in register pair DE so that DE will now hold the address of the FOR variable from the stack.
1949-194A
Skip the next 2 opcodes if the variable address in register pair DE was equal to zero.
194B
EX DE,HL
Exchange the variable address in register pair HL with the variable address in register pair DE so that HL will now have the address of the FOR variable from the stack.
194C
RST 18H
This routine was entered with DE being the address of the NEXT index, so we need to compare that against the index from the stack. To do this, we RST 18 to see if the variable address in HL is the same as in DE, so we call the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as:
  • HL<DE: CARRY SET
  • HL>DE: NO CARRY
  • HL><DE: NZ
  • HL=DE: Z
194D-194F
LD BC,000EH
Load register pair BC with the value to backspace to next FOR token (which is 10).
1950
POP HL
Get the memory pointer from the stack of the sign of the increment flag and put it in register pair HL.
1951
RET Z
Return if the FOR block matched the NEXT index block.
1952
ADD HL,BC
If it didn’t match, execute that 10 byte stepback in BC for the next possible FOR push.
1953-1954
Keep looking until the appropriate FOR block has been located.

1955-1962 – DATA MOVEMENT ROUTINE

  • This routine moves a variable into another area specified by the caller. On entry BC is set as the end address of the list to move (which is the upper limit); DE is set as the start address of the list to move; and HL is the end of the area to move it to.
1955-1957
GOSUB to 196CH to make sure there’s enough room in memory for the string area.
1958
PUSH BC
Save the end address of the list to move (stored in BC) to the stack.
1959
EX (SP),HL
Save the end address of the list to move (stored in the stack now) to register pair HL.
195A
POP BC
Get the end address of the move from the stack and put it in register pair BC.
195B
RST 18H
Now we need to check to see if the memory pointer in HL is the same as the memory pointer in DE (to see if the move is finished), so we call the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as:
  • HL<DE: CARRY SET
  • HL>DE: NO CARRY
  • HL><DE: NZ
  • HL=DE: Z
195C
LD A,(HL)
Get a byte from the source list and put it in register A.
195D
LD (BC),A
Save the byte into wherever BC is pointing.
195E
RET Z
Return if finished with the move (i.e., the memory pointer in register pair HL is the same as the value of the memory pointer in register pair DE).
195F
DEC BC
Decrement the source address (in register pair BC).
1960
DEC HL
Decrement the destination address (in register pair HL).
1961-1962
Loop until the list was moved.

1963-197D – MEMORY CHECK ROUTINE – Computes the amount of space between HL and the end of memory at FFC6H.

1963
PUSH HL
Save the value in register pair HL to the stack.
1964-1966
LD HL,(40FDH)
Load register pair HL with the starting address of free memory (which is stored at 40FDH).

NOTE: 40FDH-40FEH holds the pointer to the starting address of free memory.
1967-1968
LD B,00H
Load register B with zero.
1969
ADD HL,BC
Add 2 times the number of bytes required to start of free area (held in register pair BC) to the value in register pair HL.
196A
ADD HL,BC
Add the value in register pair BC to the value in register pair HL leaving HL to now contain the end of the free area.
196B-196C
3EH E5H
Z-80 Trick! See the general explanation at 10F8H.
196C
Save the new free area pointer (which is the start) to the stack.
196D-196E
LD A,C6H
Load register A with C6H (which is the the LSB of FFC6H; the top of memory).
196F
SUB L
Subtract the LSB of the value of the new memory pointer in register L from the value in register A.
1970
LD L,A
Load register L with the adjusted value in register A (i.e., the free memory pointer resulting from subtracting the new starting address).
1971-1972
LD A,FFH
Load register A with the MSB of the top of memory.
1973
SBC A,H
Subtract the MSB of the new memory pointer in register H from the value in register A. If the free space list exceeds FFC6 then the CARRY FLAG gets set, meaning memory overflowed.
1974-1975
If the CARRY FLAG is set, display a ?OM ERROR since we are out of memory.
1976
LD H,A
Next we need to determine if the free space list has overflowed the stack area so first we load register H with the adjusted value in register A.
1977
ADD HL,SP
Add the value of the stack pointer to the adjusted value in register pair HL.
1978
POP HL
Get the value from the stack and put it in register pair HL.
1979
RET C
If the CARRY FLAG is set, then we have no overflow – so we better RETURN because the next step is an OM error processor.

197A-197B – OM ERROR entry point.

197A-197B
LD E,0CH
Load register E with the ?OM ERROR.
197C-197D
Display an ?OM ERROR message.

197E-1AF7 – LEVEL II BASIC COMMAND MODE

197E-1980
LD HL,(40A2H)
Load register pair HL with the value of the current BASIC line number.

NOTE: 40A2H-40A3H holds the current BASIC line number.
1981
LD A,H
Load register A with the MSB of the current BASIC line number in register H.
1982
AND L
Combine the LSB of the current BASIC line number in register L with the MSB of the current line number in register A.
1983
INC A
Bump the value of the combined BASIC line number in register A. If the current line is FFFFH then we have not started execution of a BASIC program yet (meaning we are still in the inputting phase).
1984-1985
Jump to 198EH if Level II BASIC is still in the command mode (rather than being in execution mode).
1986-1988
LD A,(40F2H)
Load register A with contents of 40F2H.

NOTE: 40F2H holds the error flag.
1989
OR A
Check to see if the error flag is set.
198A-198B
LD E,22H
Load register E with a ?NR ERROR code.
198C-198D
Jump to 19A2H if the error flag is set (meaning there was no RESUME address).
198E-1990
Otherwise, jump to 1DC1H (the READY routine) because there was an error in the input phase.
1991-1993
LD HL,(40DAH)
Load register pair HL with the DATA line number (which is stored at 16602).

NOTE: 40DAH-40DBH holds DATA line number.
1994-1996
LD (40A2H),HL
Save the DATA line number in register pair HL.

NOTE: 40A2H-40A3H holds the current BASIC line number.
1997-1998
LD E,02H
Load register E with a ?SN ERROR code.
SN ERROR entry point.
199A-199B
LD E,14H
Load register E with a 14H which is the ?/0 ERROR code.
199C-199E
LD BC,001EH
Load register BC with a ?NF ERROR code.
?NF ERROR entry point.
199F-19A1
LD BC,241EH
Load register BC with a ?RW ERROR code.
?RW ERROR entry point.
19A2-19A4
LD HL,(40A2H)
Load register pair HL with the value of the current BASIC line number which has the error.

NOTE: 40A2H-40A3H holds the current BASIC line number.
19A5-19A7
LD (40EAH),HL
Save the value of the current BASIC line number with the error in register pair HL.

NOTE: 40EAH-40EBH holds the line number with error.
19A8-19AA
LD (40ECH),HL
Save the value of the current BASIC line number with the error in register pair HL.

NOTE: 40ECH-40EDH holds EDIT line number.
19AB-19AD
LD BC,19B4H
Load register pair BC with the return address of 19B4H which is the continuation address after a reinitialization.
19AE-19B0
LD HL,(40E8H)
Load register pair HL with the value of the stack pointer (which is stored at 40E8H).

NOTE: 40E8H-40E9H holds Stack pointer pointer.
19B1-19B3
Jump to 1B9AH to reinitialize the system variables.
19B4
Get the value from the stack and put it in register pair BC, which should be 0000H.
19B5
LD A,E
Load register A with the value of the error code in register E.
19B6
LD C,E
Load register C with the value of the error code in register E.
19B7-19B9
LD (409AH),A
Save the value of the error code (from in register A) into 409AH.

NOTE: 409AH holds the RESUME flag.
19BA-19BC
LD HL,(40E6H)
Load register pair HL with the value of the current BASIC program pointer (which is stored in 40E6H) (i.e., the address of the last byte executed in the current line).

NOTE: 40E6H-40E7H holds the temporary storage location.
19BD-19BF
LD (40EEH),HL
Save the value of the current BASIC program pointer (which is stored in 40EEH) in register pair HL.

NOTE: 40EEH-40EFH is used by RESUME.
19C0
EX DE,HL
Load register pair DE with the value of the current BASIC program pointer in register pair HL.
19C1-19C3
LD HL,(40EAH)
Load register pair HL with the value of the last number line executed (which is stored in 16618).

NOTE: 40EAH-40EBH holds the line number with error.
19C4-19C5
LD A,H
AND L
The easiest way to test a 2 Byte Register is to AND the MSB and LSB together, as the only way to get 1111 would be if both the LSB and MSB were 1111. Here, HL las the last line number executed.
19C6
INC A
Bump the value of the combined current BASIC line number. This will test to against FFFFH which would mean we are still in the input phase.
19C7-19C8
Jump to 19D0H if Level II BASIC is in the command mode (meaning the line number was FFFFH, which then flipped to zero on the prior INC command).
19C9-19CB
LD (40F5H),HL
Save the value of the current BASIC line number in register pair HL to (40F5H).

NOTE: 40F5H-40F6H holds the last line number executed.
19CC
EX DE,HL
Load register pair HL with the value of the current BASIC program pointer in register pair DE.
19CD-19CF
LD (40F7H),HL
Save the value of the current BASIC program pointer (which is stored in 16631) in register pair HL.

NOTE: 40F7H-40F8H holds the last byte executed.
19D0-19D2
LD HL,(40F0H)
Load register pair HL with memory contents held at (40F0H).

NOTE: 40F0H-40F1H holds the ON ERROR adress.
19D3
LD A,H
Load register A with the MSB of the ON ERROR address in register H.
19D4
OR L
Combine the LSB of the ON ERROR address in register L with the MSB of the ON ERROR address in register A.
19D5
EX DE,HL
Load register pair DE with the ON ERROR address in register pair HL.
19D6-19D8
LD HL,40F2H
Load register pair HL with the address of the error flag (which is 40F2H).

NOTE: 40F2H holds the error flag.
19D9-19DA
Jump to 19E3H (to error out) if there isn’t an ON ERROR address.
19DB
AND (HL)
Combine the value of the error flag at the location of the memory pointer in register pair HL with the combined value of the ON ERROR address in register A.
19DC-19DD
Jump to 19E3H (to error out) if register A is non zero (meaning that there was no ON ERROR address).
19DE
DEC (HL)
Decrement the value of the error flag at the location of the memory pointer in register pair HL so that RESUME will work.
19DF
EX DE,HL
Load register pair HL with the ON ERROR address in register pair DE.
19E0-19E2
Jump to 1D36H to make that happen.
19E3
XOR A
Zero register A.
19E4
LD (HL),A
Clear the error override flag by save a zero (from register A) as the current error flag at the location of the memory pointer in register pair HL..
19E5
LD E,C
Load register E with the value of the error code in register C.
19E6-19E8
We need to position the video to the next line, so go display a carriage return on the video display if necessary.
19E9-19EB
LD HL,18C9H
Load register pair HL with the starting address for the table of error messages.
19EC-19EE
CALL 41A6H
Go to the DOS link at 41A6H (whcih would load and execute BASIC error messages as supplied by DOS).

NOTE: 41A6H-41E4H holds DOS links.
In NEWDOS 2.1, this would be a call to load a DISK BASIC error, with Register E holding the error number.
19EF
LD D,A
Since we are non-DOS, we continue by loading register D with zero.
19F0-19F1
LD A,3FH
Load register A with a “?” (which is ASCII code 3FH).
19F2-19F4
GOSUB to 032AH to display the question mark in register A.
19F5
ADD HL,DE
Add the value of the error code in register pair DE to the starting address of the table of error messages in register pair HL.
19F6
LD A,(HL)
Load register A with the first character of the error message at the location of the table pointer in register pair HL.
19F7-19F9
GOSUB to 032AH to display the first character of the error message in register A.
19FA
RST 10H
Error codes are 2 characters so we need to set the second character of the error in register A, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:
  • The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
  • Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
  • The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
  • The string must be terminated by a byte of zeros.
19FB-19FD
GOSUB to 032AH to display the second character of the error message in register A.
19FE-1A00
LD HL,191DH
Load register pair HL with 191DH which is the starting address of the READY message.
1A01
PUSH HL
Save the starting address of the READY message (held in HL) to the stack.
1A02-1A04
LD HL,(40EAH)
Load register pair HL with the value of the current BASIC line number (i.e., the statement causing the error).

NOTE: 40EAH-40EBH holds the line number with error.
1A05
EX (SP),HL
Exchange the value of the current BASIC line number in register pair HL with the starting address of the Level II BASIC ERROR message to the stack.
1A06-1A08
We need to display the Level II BASIC ERROR message so we call the WRITE MESSAGE routine at 28A7H.
NOTE:
  • The routine at 28A7 displays the message pointed to by HL on current system output device (usually video).
  • The string to be displayed must be terminated by a byte of machine zeros or a carriage return code 0D.
  • If terminated with a carriage return, control is returned to the caller after taking the DOS exit at 41D0H (JP 5B99H).
1A09
POP HL
Get the value of the BASIC line number with the error from the stack and put it in register pair HL.
1A0A-1A0C
LD DE,FFFEH
Load register pair DE with FFFEH.

This basically reserves the line number 65534 as a trigger for the next few steps.
1A0D
RST 18H
Now we need to compare the BASIC line number causing the error (held in HL) with FFFEH (held in DE) so as to see if we are in the initialization routine, so we call the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as:
  • HL<DE: CARRY SET
  • HL>DE: NO CARRY
  • HL><DE: NZ
  • HL=DE: Z
1A0E-1A10
Jump to 0674H if we are in the initialization routine because the error line number was FFFEH.
1A11
LD A,H
We need to see if were in command mode, which is signalled by CURRENT LINE NUMBER of 0. The first step is to load register A with the MSB of the current BASIC line number in register H.
1A12
AND L
Combine the LSB of the current BASIC line number in register L with the MSB of the current BASIC line number in register A.
1A13
INC A
Bump the combined value of the current BASIC line number in register A to test to see if the line number is 00H (meaning command mode).
1A14-1A16
GOSUB to 0FA7H to display the current BASIC line number in register pair HL if Level II BASIC isn’t in the command mode.
1A17H
3E C1
Z-80 Trick! See the general explanation at 10F8H.
1A18
Get the value from the stack and put it in register pair BC.

1A19 – “$READY” – Jump to Model II BASIC “READY”
To exit from a machine-language program into BASIC’s immediate mode, jump (not call) to $READY.

1A19-1A1BH
“READY”
Go set the current output device to the video display.
Re-entry into BASIC command mode entry point. (see 6CCH also).
1A1C-1A1E
CALL 41ACH
Go call the DOS link at 41ACH.
In NEWDOS 2.1, this is the start of BASIC just before BASIC shows the READY prompt.
1A1F-1A21
Go turn off the cassette recorder.
1A22-1A24
Go display a carriage return if necessary.
1A25-1A27
LD HL,1929H
Load register pair HL with the starting address of the Level II BASIC READY message.
1A28-1A2A
We need to display the Level II BASIC READY message, so we call the WRITE MESSAGE routine at 28A7H.
NOTE:
  • The routine at 28A7 displays the message pointed to by HL on current system output device (usually video).
  • The string to be displayed must be terminated by a byte of machine zeros or a carriage return code 0D.
  • If terminated with a carriage return, control is returned to the caller after taking the DOS exit at 41D0H (JP 5B99H).
1A2B-1A2D
LD A,(409AH)
Load register A with the value of the current error code.

NOTE: 409AH holds the RESUME flag.
1A2E-1A2F
SUB 02H
Check to see if the current error code is a ?SN ERROR code by subtracting 2 from the error code, resulting in a zero if its a SN ERROR and any other number if it isn’t..
1A30-1A32
GOSUB to 2E53H to the EDIT mode if the current error code is a SN ERROR code.

1A33 – Many routines jump here as the start of the Level II BASIC interpreter.

  • If the jump here was from an AUTO call, (40E4H) will have the increment number, (40E1H) will be 0 if no AUTO and non-zero if AUTO, and (40E2H) will have the starting line number.
1A33-1A35
LD HL,FFFFH
Load register pair HL with the command mode line number of FFFFH.

NOTE: FFFFH is the command mode line number.
1A36-1A38
LD (40A2H),HL
Save the line number in register pair HL as the current BASIC line number.

NOTE: 40A2H-40A3H holds the current BASIC line number.
1A39-1A3B
LD A,(40E1H)
Load register A with the value of the AUTO flag. It will be zero if not in AUTO, and anything else if in AUTO.
1A3C
OR A
Check to see if in the AUTO mode.
1A3D-1A3E
Jump to 1A76H if not in the AUTO mode.
1A3F-1A41
LD HL,(40E2H)
We are in AUTO mode so load register pair HL with the current AUTO line number.

NOTE: 40E2H-40E3H holds Current BASIC line number.
1A42
PUSH HL
Save the current AUTO line number (stored in register pair HL) to the stack.
1A43-1A45
GOSUB to 0FAFH to call the HL TO ASCII routine at 0FAFH (which converts the value in the HL register pair (assumed to be an integer) to ASCII and display it at the current cursor position on the video screen) to display the AUTO line number.
1A46
POP DE
Get the current AUTO line number from the stack and put it in register pair DE.
1A47
PUSH DE
Save the current AUTO line number in register pair DE to the stack.
1A48-1A4A
Call the SEARCH FOR LINE NUMBER routine at 1B2CH which looks for the line number specified in DE. Returns C/Z with the line found in BC, NC/Z with line number is too large and HL/BC having the next available location, or NC/NZ with line number not found, and BC has the first available one after that.
1A4B-1A4C
LD A,”*”
Load register A with a * (which will be code for a matching line number).
1A4D-1A4E
If the call to 1B2CH shows a matching line number was found in the BASIC program (by returning a C), skip the next instruction so that register A keeps the “*”.
1A4F-1A50
LD A,20H
If we are here, then there was no matching line number so we need to change the next character from a “*” (which is loaded into register A which but is not applicable) to a space.
1A51-1A53
Go display the character in register A on the video display (which will be a “*” if a matching line number was found).
1A54-1A56
GOSUB to 0361H to get input into the buffer.
1A57
POP DE
Get the current line number from the stack and put it in register pair DE.
1A58-1A59
Skip the next 3 opcodes if the BREAK key wasn’t pressed.
1A5A
XOR A
The BREAK key was pressed so we need to zero register A to clear the AUTO increment flag.
1A5B-1A5D
LD (40E1H),A
Save the value in register A as the current AUTO flag (to turn off AUTO).

NOTE: 40E1H will hold 0 if no AUTO and non-zero if AUTO.
1A5E-1A5F
Jump to the normal command mode “READY” routine at 1A19H.

If we are here, then the BREAK key was not pressed.

1A60-1A62
LD HL,(40E4H)
Load register pair HL with the value of the AUTO increment.

NOTE: 40E4H-40E5H holds the AUTO increment number.
1A63
ADD HL,DE
Since we didn’t BREAK out of the routine we need to keep processing the AUTO so we add the value of the AUTO line number in register pair DE with the AUTO increment value in register pair HL.
1A64-1A65
If that addition to the next AUTO line number causes an overflow (by triggering the CARRY FLAG), jump to 1A5AH which is the same as if the BREAK key was hit.
1A66
PUSH DE
Save the current AUTO line number in register pair DE to the stack.
1A67-1A69
LD DE,FFF9H
Load register pair DE with the maximum BASIC line number of FFF9H (=65529).

There is an explanation at 1E5AH as to why 65529 is the highest possible line number (vs 65535 which would make more sense).
1A6A
RST 18H
Now we need to compare the adjusted AUTO line number (in HL) with the maximum BASIC line number (in DE), so we call the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as:
  • HL<DE: CARRY SET
  • HL>DE: NO CARRY
  • HL><DE: NZ
  • HL=DE: Z
1A6B
POP DE
Get the current AUTO line number from the stack and put it in register pair DE.
1A6C-1A6D
If the adjusted AUTO line number in register pair HL is too large, jump to 1A5AH which is the same as if the BREAK key was hit.
1A6E-1A70
LD (40E2H),HL
Save the adjusted AUTO line number in register pair HL as the current AUTO line number.

NOTE: 40E2H-40E3H holds Current BASIC line number.
1A71-1A72
OR FFH
Load register A with the AUTO flag value.
1A73-1A75
Jump to the EDIT routine to save the current BASIC line.
1A76-1A77
LD A,3EH
Load register A with a > (the prompt that follows READY)
1A78-1A7A
Go display the Level II BASIC prompt in register A on the video display.
1A7B-1A7D
GOSUB to 0361H to accept input. HL will hold the buffer address for that input.
1A7E-1A80
Jump to 1A33H if the BREAK key was pressed.
1A81
RST 10H
Since we need to bump the current input buffer pointer in register pair HL until it points to the first character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:
  • The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
  • Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
  • The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
  • The string must be terminated by a byte of zeros.
1A82
INC A
Bump the value of the character in register A. This sets the status flags but saves the CARRY FLAG.
1A83
DEC A
Decrement the value of the character in register A so we can test for an end of statement.
1A84-1A86
JUMP to 1A33H if we have an end of statement.
1A87
PUSH AF
Save the value in register pair AF to the stack (including the CARRY FLAG).
1A88-1A8A
Call the ASCII TO INTEGER routine at 1E5AH.
NOTE:
  • The routine at 1E5A converts the ASCII string pointed to by HL to an integer deposited into DE. If the routine finds a non-numerica character, the conversion is stopped

1A8BH – This little looping routine is to clear any trailing blanks between the line number and the statement.

1A8B
DEC HL
Decrement the value of the input buffer pointer in register pair HL.
1A8C
LD A,(HL)
Load register A with the value of the character at the location of the input buffer pointer in register pair HL.
1A8D-1A8E
CP 20H
Check to see if the character at the location of the input buffer pointer in register A is a space.
1A8F-1A90
Loop back to 1A8BH if the character at the location of the input buffer pointer in register A is a space.
1A91
INC HL
Bump the value of the input buffer pointer in register pair HL so that it points to the first character following a line number.
1A92
LD A,(HL)
Load register A with that character.
1A93-1A94
CP 20H
Check to see if the character at the location of the input buffer pointer in register A is a space.
1A95-1A97
If it is a space then skip it by a GOSUB to 09C9H which bumps the value of the input buffer pointer in register pair HL if necessary.
1A98
PUSH DE
Save the BASIC line number in register pair DE (which was converted from ASCII to an integer in 1A88H through a call to 1E5AH) to the stack.
1A99-1A9B
Tokenize the input via a GOSUB to 1BC0H. BC will equal the length of the encoded statement when its done.
1A9C
POP DE
Get the value of the BASIC line number (which is an integer) from the stack.
1A9D
POP AF
Get the CARRY FLAG (from the 1A81H character fetch) and put it in register pair AF.
1A9E-1AA0
LD (40E6H),HL
Save the input buffer pointer in register pair HL.

NOTE: 40E6H-40E7H holds the temporary storage location.
1AA1-1AA3
CALL 41B2H
Go call the DOS line at 4182H.
In NEWDOS 2.1, this is the input scanner after tokenizing the current statement.
1AA4-1AA6
Jump to 1D5AH if there wasn’t a line number with the input (meaning it was a direct statement or a system command).
1AA7
PUSH DE
Save the BASIC line number (as an integer stored in register pair DE) to the stack.
1AA8
PUSH BC
Save the length of the tokenized input (stored in register pair BC) to the stack.
1AA9
XOR A
Zero register A.
1AAA-1AAC
LD (40DDH),A
Save the value in register A (which is a 00H) as the input flag.

NOTE: 40DDH holds INPUT flag.
1AAD
RST 10H
Since we need find the first token, we have to bump the current input buffer pointer in register pair HL until it points to the next character by calling the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:
  • The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
  • Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
  • The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
  • The string must be terminated by a byte of zeros.
1AAE
OR A
Set the flags.
1AAF
PUSH AF
Save the status flag to the stack.
1AB0
EX DE,HL
Load register pair HL with the integer value of the BASIC line number (held in register pair DE).
1AB1-1AB3
LD (40ECH),HL
Save the integer value of the line number (held in register pair HL) to 40ECH.

NOTE: 40ECH-40EDH holds EDIT line number.
1AB4
EX DE,HL
Exchange the value of the input buffer pointer in register pair DE with the integer value of the BASIC line number in register pair HL. This will fill DE with the line number for the search routine in the next instruction.
1AB5-1AB7
Call the SEARCH FOR LINE NUMBER routine at 1B2CH which looks for the line number specified in DE. Returns C/Z with the line found in BC, NC/Z with line number is too large and HL/BC having the next available location, or NC/NZ with line number not found, and BC has the first available one after that.
1AB8
PUSH BC
Save the address of the line number in the BASIC program (if it exists) in register pair BC to the stack.
1AB9-1ABB
If there wasn’t a matching line number in the BASIC program, GOSUB to 2BE4H to move the closest line number up in memory to make room for another line.
1ABC
POP DE
Get the integer address of the BASIC line number from the stack and put it in register pair DE.
1ABD
POP AF
Restore the status from the 1AADH token scan into register pair AF.
1ABE
PUSH DE
Save the integer address of the BASIC line number to the stack.
1ABF-1AC0
Jump to 1AE8H if there was a matching line number in the BASIC program; otherwise we move on and a new line has to be added as follows.
1AC1
POP DE
Get the address of the BASIC line number from the stack and put it in register pair DE.
1AC2-1AC4
LD HL,(40F9H)
Load register pair HL with the end of the BASIC program pointer.
  • Note: 40F9H-40FAH holds the starting address of the simple variable storage area.
1AC5
EX (SP),HL
Exchange the length of the tokenized input to the stack with the end of the BASIC program pointer in register pair HL.
1AC6
POP BC
Get the end of the BASIC program pointer from the stack and put it in register pair BC.
1AC7
ADD HL,BC
Add the end of the BASIC program pointer in register pair BC to the value of the length of the tokenized input in register pair HL.
1AC8
PUSH HL
Save the adjusted end of the BASIC program pointer in register pair HL to the stack.
1AC9-1ACB
Go check to see if there is enough room in memory for the new BASIC line by GOSUB to 1955H.
1ACC
POP HL
Get the new end of the BASIC program pointer from the stack and put it in register pair HL.
1ACD-1ACF
LD (40F9H),HL
Save the new end of the BASIC program pointer in register pair HL.
  • Note: 40F9H-40FAH holds the starting address of the simple variable storage area.
1AD0
EX DE,HL
Load register pair HL with the address of the BASIC line.
1AD1
LD (HL),H
Save the MSB of the address of the BASIC line in register H.
1AD2
POP DE
Get the value of the BASIC line number from the stack and put it in register pair DE.
1AD3
PUSH HL
Save the value of the memory pointer in register pair HL to the stack.
1AD4
INC HL
Bump the value of the memory pointer in register pair HL (which bumps it to the LSB of the line number entry).
1AD5
INC HL
Bump the value of the memory pointer in register pair HL (which bumps it to the MSB of the line number entry).
1AD6
LD (HL),E
Save the LSB of the BASIC line number in register E at the location of the memory pointer in register pair HL.
1AD7
INC HL
Bump the value of the memory pointer in register pair HL.
1AD8
LD (HL),D
Save the MSB of the BASIC line number in register D at the location of the memory pointer in register pair HL. At this point DE should have the binary value for the new line number.
1AD9
INC HL
Bump the value of the BASIC line number in register pair HL.
1ADA
EX DE,HL
Load register pair DE with first data byte address following the line number (held in register pair HL).
1ADB-1ADD
LD HL,(40A7H)
Load register pair HL with the value of the tokenized input pointer
Note: 40A7H-40A8H holds Input Buffer pointer.
1ADE
EX DE,HL
Exchange the value of the memory pointer in register pair DE with the value of the tokenized input pointer in register pair HL.
1ADF
DEC DE
Decrement the value of the tokenized input buffer pointer in register pair DE.
1AE0
DEC DE
Decrement the value of the tokenized input buffer pointer in register pair DE.
1AE1
LD A,(DE)
Load register A with the value at the location of the tokenized input buffer pointer in register pair DE.
1AE2
LD (HL),A
Save the value in register A at the location of the memory pointer in register pair HL.
1AE3
INC HL
Bump the store address (held in register pair HL).
1AE4
INC DE
Bump the fetch address (held in register pair DE).
1AE5
OR A
Check to see if the character in register A is an end of the line character.
1AE6-1AE7
Loop until the whole of the new BASIC line has been stored in memory.
1AE8
POP DE
Get the address of the line in the program table from the stack and put it in register pair DE.
1AE9-1AEB
Go update line pointers for all lines following the new line.
1AEC-1AEE
CALL 41B5H
Go call the DOS link at 41B5H.
In NEWDOS 2.1, this is the input scanner after updating the PST (Program Statement Table).
1AEF-1AF1
Update all the BASIC line pointers.
1AF2-1AF4
CALL 41B8H
Go call the DOS link at 41B8H.
In NEWDOS 2.1, this is the input scanner after reinitializing BASIC
1AF5-1AF7
Go get the input again.

1AF8-1B0F – LINE POINTERS ROUTINE

  • This routine fixes the line pointers in a BASIC program. This is useful, for instance for a renumber program which has to move BASIC program lines from one location in memory to an other, which means that the line pointers would no longer be valid. This routine will fix them. Registers A, HL and DE are used.
1AF8
LD HL,(40A4H)
Load register pair HL with the start of the BASIC program pointer (called the PST).
  • Note: 40A4H-40A5H holds the starting address of BASIC program text also known as the PROGRAM STATEMENT TABLE (PST).
1AFB
EX DE,HL
Move the PST address to DE.
1AFC
LD H,D
Load register H with the MSB of the memory pointer in register D.
1AFD
LD L,E
Load register L with the LSB of the memory pointer in register E.
1AFE
LD A,(HL)
Load register A with the value at the location of the memory pointer in register pair HL.
1AFF
INC HL
Bump the value of the memory pointer in register pair HL.
1B00
OR (HL)
Since the first 2 bytes of each line contains the address of the next line, a 0000H would signify the end byte. With this, check to see if the character at the location of the memory pointer in register pair HL is an end of the BASIC program character.
1B01
RET Z
Return if done.
1B02
INC HL
Since HL is the ‘beginning of statment pointer’, we need to skip over the 3rd and 4th bytes, so bump the value of the memory pointer in register pair HL.
1B03
INC HL
Bump the value of the memory pointer in register pair HL.
1B04
INC HL
Bump the value of the memory pointer in register pair HL.
1B05
XOR A
Zero register A and clear the flags.
1B06
CP (HL)
Check to see if the character at the location of the memory pointer in register HL is an end of the BASIC line character.
1B07
INC HL
Bump the value of the memory pointer in register pair HL.
1B08
Loop until the end of the BASIC line character is found.
1B0A
EX DE,HL
Exchange the starting address of the current BASIC line in register pair DE with the starting address of the next BASIC line in register pair HL.
1B0B
LD (HL),E
Save the LSB of the next BASIC line’s starting address in register E at the location of the memory pointer in register pair HL.
1B0C
INC HL
Bump the value of the memory pointer in register pair HL.
1B0D
LD (HL),D
Save the MSB of the next BASIC line’s starting address in register D at the location of the memory pointer in register pair HL.
1B0E-1B0F
Loop until the end of the program has been found.

1B10-1B48 – EVALUATE LINE NUMBERS

  • This is called by LIST and DELETE. It converts the starting and ending linbers (X-Y) to binary and saves the ending line number on the stack. Then the code locates the program table address for the starting line. The routine leaves the address of the starting line in BC and the ending line number in the stack.
1B10-1B12
LD DE,0000H
Load register pair DE (which will be the line counter) with zero.
1B13
PUSH DE
Save the value in register pair DE to the stack.
1B14-1B15
Jump to 1B1FH if there aren’t any line numbers to be evaluated.
1B16
POP DE
Get the value from the stack and put it in register pair DE (which will be the line number).
1B17-1B19
Go evaluate the line number at the location of the current BASIC program pointer in register pair HL and return with the line number’s binary value in register pair DE.
1B1A
PUSH DE
Save the first line number’s value (stored in register pair DE) to the stack.
1B1B-1B1C
Jump if there isn’t a second line number to be evaluated given (i.e, LIST 3000-).
1B1D-1B1E
RST 08H
CEH
If we are here, there is a second line number. That that would have to be preceded by a at the location of the current BASIC program pointer in register pair HL, call the COMPARE SYMBOL routine which comparess the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call. If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the Aregister and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase).
1B1F-1B21
LD DE,FFFAH
Load register pair DE with the default second line number of FFAFH.
1B22-1B24
Go evaluate the second line number at the location of the current BASIC program pointer in register pair HL and return with the line number’s binary value in register pair DE. Will return with Z flag set if it was a number.
1B25-1B27
Go to the Level II BASIC error routine and display a SN ERROR message if the data which followed the token wasn’t a line number.
1B28
EX DE,HL
Load register pair HL with the value of the second line number in register pair DE and load register pair DE with the value of the current BASIC program pointer in register pair HL.
1B29
POP DE
Get the value of the first line number from the stack and put it in register pair DE.
1B2A
EX (SP),HL
Exchange the return address to the stack with the value of the second line number in register pair HL.
1B2B
PUSH HL
Save the value of the return address in register pair HL to the stack so we can properly exit later.

1B2C – This routine searches a BASIC program for a BASIC line with a line number matching the value in the DE register pair.

To use this routine, the required line number must be placed in the DE register pair. When a match is found, this routine sets the CARRY FLAG; the BC register pair points to the start of the required line, and the HL register points to the start of the next line. HL, AF and BC are used.

This is the the SEARCH FOR LINE NUMBER routine at 1B2C, which searches the Program Statement Table (PST) for a BASIC statement with the line number specified in the DE register pair. All registers are used. The exit conditions are:

C/Z=Line Found and BC is the starting address of the line in the PST and HL is the address following;

NC/Z=Line not found or too large and HL/BC will have the address of the next available PST location; and

NC/NZ=Line not found and BC=Address of the first line number greater than the one specified and HL will be the address of the following line.


1B2C
LD HL,(40A4H)
Load register pair HL with the value of the start of the BASIC program pointer.
  • Note: 40A4H-40A5H holds the starting address of BASIC program text also known as the PROGRAM STATEMENT TABLE (PST).
1B2F
LD B,H
Load register B with the value of the MSB of the memory pointer in register H.
1B30
LD C,L
Load register C with the LSB of the memory pointer in register L. Now BC will hold the address of the current line in the PST.
1B31
LD A,(HL)
Load register A with the LSB of the address of the next line (held in register pair HL).
1B32
INC HL
Bump the value of the memory pointer in register pair HL to the MSB of the address of the next line.
1B33
OR (HL)
Combine the value at the location of the memory pointer in register pair HL with the value in register A and set the status flags.
1B34
DEC HL
Restore HL to the start of the current line.
1B35
RET Z
Return if this is the end of PST (=the end of the BASIC program).
1B36
INC HL
It’s not the end so we need HL to point the line number for the current line which means it must advance by 2. Bump the value of the memory pointer in register pair HL.
1B37
INC HL
Bump the value of the memory pointer in register pair HL.
1B38
LD A,(HL)
Load register A with the LSB of the current BASIC line number at the location of the memory pointer in register pair HL.
1B39
INC HL
Bump the value of the memory pointer in register pair HL to point to the MSB of the current BASIC line number.
1B3A
LD H,(HL)
Load register H with the MSB of the current BASIC line number at the location of the memory pointer in register pair HL.
1B3B
LD L,A
Load register L with the LSB of the current BASIC line number in register A.
1B3C
RST 18H
Now we need to compare the value of the current BASIC line number in HL and the first line number (in DE), so we call the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as:
  • HL<DE: CARRY SET
  • HL>DE: NO CARRY
  • HL><DE: NZ
  • HL=DE: Z
1B3D
LD H,B
Load register H with the MSB of the memory pointer in register B.
1B3E
LD L,C
Load register L with the LSB of the memory pointer in register C.
1B3F
LD A,(HL)
Load register A with the value at the location of the memory pointer in register pair HL.
1B40
INC HL
Bump the value of the memory pointer in register pair HL.
1B41
LD H,(HL)
Load register H with the MSB of the next BASIC line pointer at the location of the memory pointer in register pair HL.
1B42
LD L,A
Load register L with the LSB of the next BASIC line pointer in register A to form the address of the next line in HL.
1B43
CCF
Complement the value of the CARRY FLAG. The carry will be set if the current line number is < the value in DE. This will clear the CARRY FLAG.
1B44
RET Z
Return if the first line number in register pair DE is the same as the current BASIC line number. The line numbers match, so exit C, Z, BC=address of the current line, and HL=address of the next line.

If we are here, then we have no match.

1B45
CCF
Complement (reverse) the CARRY FLAG.
1B46
RET NC
If the first line number in register pair DE is less than the current BASIC line number. BC will be the address of the current line and HL will be the address of the next line.
1B47
Loop until the location of the line number has been found in the BASIC program.

1B49-1B5C – LEVEL II BASIC NEW ROUTINE

1B49
RET NZ
Go to the Level II BASIC error routine and display a ?SN ERROR message if there is any input following the NEW token.
1B4A-1B4C
Call the CLEAR SCREEN routine at 01C9 (which cleans the screen, changes to 64 characters, and homes the screen).
1B4D
LD HL,(40A4H)
Load register pair HL with the start of the PST (the start of the BASIC program).
  • Note: 40A4H-40A5H holds the starting address of BASIC program text also known as the PROGRAM STATEMENT TABLE (PST).
1B50
GOSUB to the TROFF routine at 1DF8H (which just loads A with a zero for TROFF, and puts that 0 into 411BH).
1B53
LD (40E1H),A
Reset the AUTO flag by putting a zero (which is in A due to the GOSUB to the TROFF statement in the above instruction) into 40E1H.
1B56
LD (HL),A
We need to initialize the PST, and the way to do that is to zero the first two bytes so … save a zero at the location of the memory pointer in register pair HL.
1B57
INC HL
… bump the value of the memory pointer in register pair HL …
1B58
LD (HL),A
… and save a zero at the location of the memory pointer in register pair HL.
1B59
INC HL
Bump the value of the memory pointer in register pair HL.
1B5A
LD (40F9H),HL
Save the value in register pair HL at 40F9H to initialize the start of the variable list table as the end of the PST.
  • Note: 40F9H-40FAH holds the starting address of the simple variable storage area.

1B5D-1BB2 – LEVEL II BASIC RUN ROUTINE

Differences between M1 and M3 ROMs: The locations 1B5DH – 1B5FH are part of the RUN, NEW, EDIT, etc. commands; in the Model I these three bytes contain a LD HL,(40A4H) instruction (resets HL to point to the start of the BASIC program). In the Model III, this has been replaced by a CALL 046BH instruction, which unprotects the video display in addition to resetting HL to the start of the BASIC program.

  • This routine does a lot of variable resets and other things that are common to NEW as well, so NEW just does the special NEW stuff and than passes right through to here to reset the rest.
  • To use a ROM call to RUN a BASIC program, starting with its first line, execute the following instructions:
    LD HL,1D1EH
    PUSH HL
    JP 1B5DH
    The ability to RUN a BASIC program from an assembly language program is valuable for linking the two programs.
*1B5D-1B5F
GOSUB to 046BH to unprotect the screen and point HL to the start of data.
1B60
DEC HL
Decrement the value in register pair HL to backspace.
1B61-1B63
LD (40DFH),HL
Save the adjusted value in register pair HL into 40DFH.

NOTE: 40DFH-40E0H is used by DOS.
1B64-1B65
LD B,1AH
Load register B with the number of variable names to be initialized (which is 26).
1B66-1B68
LD HL,4101H
Load register pair HL with the starting address of the variable declaration table (which is 4101H).

NOTE: 4101H-411AH holds Variable Declaration Table.
1B69-1B6A
LD (HL),04H
Set the variable at the location of the memory pointer in register pair HL to a single precision variable.
1B6B
INC HL
Bump the value of the memory pointer in register pair HL to the next variable.
1B6C-1B6D
Loop until all 26 variables have been set to single precision.
1B6E
XOR A
Zero register A.
1B6F-1B71
LD (40F2H),A
Save the value in register A (which is a zero) as the current value of the RESUME flag to say that there is no error for RESUME to handle.

NOTE: 40F2H holds the error flag.
1B72
LD L,A
Zero register L.
1B73
LD H,A
Zero register H.
1B74-1B76
LD (40F0H),HL
Save a zero (held in register pair HL) as the current ON ERROR address.

NOTE: 40F0H-40F1H is used by ON ERROR.
1B77-1B79
LD (40F7H),HL
Save a zero (held in register pair HL) as the current BREAK, STOP, or END address.

NOTE: 40F7H-40F8H holds the last byte executed.
1B7A-1B7C
LD HL,(40B1H)
Load register pair HL with the top of the memory pointer held in 40B1H.

NOTE: 40B1H-40B2H holds MEMORY SIZE? pointer.
1B7D-1B7F
LD (40D6H),HL
Save the top of memory pointer (held in register pair HL) as the next available address in the string space pointer.

NOTE: 40D6H-40D7H holds Next available location in string space pointer.
1B80-1B82
Go do a RESTORE (which will mess with DE and HL).
1B83-1B85
LD HL,(40F9H)
Load register pair HL with the end of the BASIC program pointer.
  • Note: 40F9H-40FAH holds the starting address of the simple variable storage area.
1B86-1B88
LD (40FBH),HL
Save the value in register pair HL as the new simple variables pointer.
  • Note: 40FBH-40FCH holds the starting address of the BASIC array variable storage area.
1B89-1B8B
LD (40FDH),HL
Save the value in register pair HL as the new array variables pointer.

NOTE: 40FDH-40FEH holds the pointer to the starting address of free memory.
1B8C-1B8E
CALL 41BBH
Go call the DOS line at 41BBH.
In NEWDOS 2.1 this initializes BASIC for a new routine.

1B8FH – Inside the RUN routine – Initialize the Level II BASIC variables and pointers

1B8F
POP BC
Get the return address from the stack because we are about to change the stack pointer.
1B90-1B92
LD HL,(40A0H)
Load register pair HL with the start of string space pointer.
  • Note: 40A0H-40A1H holds the start of string space pointer.
1B93
DEC HL
Decrement the value of the memory pointer in register pair HL.
1B94
DEC HL
Decrement the value of the memory pointer in register pair HL (so now HL has the sart of the string space pointer – 2).
1B95-1B97
LD (40E8H),HL
Save the string space pointer – 2 (in register pair HL) as the stack pointer
Note: 40E8H-40E9H holds Stack pointer pointer.
1B98
INC HL
Bump the value of the memory pointer in register pair HL.
1B99
INC HL
Bump the value of the memory pointer in register pair HL so it is back to being the start of the string space pointer.
1B9A
LD SP,HL
Load the stack pointer with the start of the string space pointer (held in register pair HL).
1B9B-1B9D
LD HL,40B5H
Load register pair HL with the start of the string work area (which is 40B5H).

NOTE: 40B5H-40D2H holds Temporary string work area.
1B9E-1BA0
LD (40B3H),HL
Save the value in register pair HL as the next available location in the string work area pointer.

NOTE: 40B3H-40B4H holds Next available location in the temporary string work area pointer.
1BA1-1BA3
GOSUB 038BH to set the current output device to the video display.
1BA4-1BA6
Go turn off the cassette recorder.
1BA7
XOR A
Zero register A.
1BA8
LD H,A
Zero register H.
1BA9
LD L,A
Zero register L.
1BAA-1BAC
LD (40DCH),A
Clear the FOR statement flag.

NOTE: 40DCH holds FOR flag.
1BAD
PUSH HL
Save the value in register pair HL (which is RUN) to the stack.
1BAE
PUSH BC
Save the value in register pair BC (which is the address to continue executing code) to the stack.
1BAF-1BB1
LD HL,(40DFH)
Load register pair HL with the current value of the BASIC program pointer.

NOTE: 40DFH-40E0H holds Used by DOS.
1BB2
RET
Return.

1BB3-1BBF – KEYBOARD INPUT ROUTINE

  • This is the last of the general purpose input routines. This routine functions identically to the 361H routine with the exception that it prints a “?” on the screen (like INPUT does with BASIC) before allowing input from the keyboard.
  • To use a ROM call to display “?” on the video screen at the current cursor position (Non-DOS Systems Only), and then to input a string of up to 240 characters, execute CALL 1BB3H. The input string will be in consecutive memory locations starting at the address contained in 40A7H-40A8H, with a zero byte at the end. The HL register pair will contain an address one less than the starting address of the stored input.
1BB3-1BB4H
“INPUT”
LD A,3FH
Load register A with a ?.
1BB5-1BB7
Go display the ? (stored in register A) on the video display.
1BB8-1BB9
LD A,20H
Load register A with a space.
1BBA-1BBC
Go display the space in register A on the video display.
1BBD-1BBF
Jump to the keyboard input routine at 0361H.

1BC0-1C8F – TOKENIZE INPUT ROUTINE

1BC0
XOR A
Zero register A.
1BC1-1BC3
LD (40B0H),A
Save the value in register A as the current value of the tokenization flag.

NOTE: 40B0H holds the temporary storage location.
1BC1-1BC3
LD (409FH),A
Save the value in register A into the DATA FLAG held in 409FH.

NOTE: Bit 0 HIGH means inside a quote. Bit 1 HIGH means inside a DATA. Bit 2 HIGH means inside a REM.

NOTE: In the original Model III ROM, this byte was placed into 40B0H which was just a temporary storage location.
1BC4
LD C,A
Zero register C.
1BC5
EX DE,HL
Load register pair DE with the address of the first character after the line number (as stored in register pair HL).
1BC6-1BC8
LD HL,(40A7H)
Load register pair HL with the starting address of the input buffer.

NOTE: 40A7H-40A8H holds Input Buffer pointer.
1BC9
DEC HL
We need to backspace twice so … decrement the value of the input buffer pointer in register pair HL.
1BCA
DEC HL
… and again decrement the value of the input buffer pointer in register pair HL.
1BCB
EX DE,HL
Exchange the string address – 2 from HL into DE, and the current input string address from DE into HL.
1BCC
LD A,(HL)
Load register A with the character at the current input string address (in register pair HL).
1BCD-1BCE
CP 20H
Check to see if the character in register A is a space.
1BCF-1BD1
Jump to 1C5BH if the character in register A is a .
1BD2
LD B,A
Load register B with the value of the character in register A.
1BD3-1BD4
CP 22H
Check to see if the character in register A is a .
1BD5-1BD7
Jump to 1C77H if the character in register A is a . 1C77H will move the entire field between the quotes into the a code string.
1BD8
OR A
Check to see if the character in register A is an end of the input character and set the status flags.
1BD9-1BDB
Jump to 1C7DH if the character in register A is an end of the input character.
1BDC-1BDE
LD A,(40B0H)
Load register A with the value of the tokenization flag for DATA.

NOTE: 40B0H holds the temporary storage location.
1BDC-1BDE
LD A,(409FH)
Load register A with the value of the DATA FLAG.

NOTE: Bit 0 HIGH means inside a quote. Bit 1 HIGH means inside a DATA. Bit 2 HIGH means inside a REM.

NOTE: In the original Model III ROM, this byte was read from 40B0H which was just a temporary storage location.
1BDF
OR A
Check to see if a DATA statement is being processed.
1BE0
LD A,(HL)
Load register A with the value of the next character.
1BE1-1BE3
Jump to 1C5BH if a DATA statement is being processed.
1BE4-1BE5
CP 3FH
Check to see if the character in register A is a ? (meaning a PRINT statement).
1BE6-1BE7
LD A,B2H
Load register A with a PRINT token of B2H.
1BE8-1BEA
Jump to 1C5BH if the character at the location of the input buffer pointer in register pair HL is a ?. This will replace the ? with PRINT.
1BEB
LD A,(HL)
Re-fetch the current character (from the memory location of the input buffer pointer in register pair HL) and put it into Register A.
1BEC-1BED
CP 30H
Check to see if the character in register A is less than a zero character (alpha numeric).

NOTE: Results from a CP:
  • Z: A and * are the same
  • NZ: A and * are NOT the same
  • C: A < *
  • NC: A => *
1BEE-1BEF
Jump to 1BF5H if the character in register A is less than a zero character, meaning it is not a digit or letter.
1BF0-1BF1
CP 3CH
Check to see if the character in register A is less than < character (which is a test to see if it is 0-9, :, ;, <, constant or special character.

NOTE: Results from a CP:
  • Z: A and * are the same
  • NZ: A and * are NOT the same
  • C: A < *
  • NC: A => *
1BF2-1BF4
Jump to 1C5BH if the character in register A is 0-9, :, ;, <, constant or special character.
1BF5
PUSH DE
Save the value of the input buffer pointer in register pair DE to the stack.
1BF6-1BF8
LD DE,164FH
Load register pair DE with the starting address of the reserved words list.
1BF9
PUSH BC
Save the value in Register Pair BC to the STACK.
1BFA-1BFC
LD BC,1C3DH
Load register pair BC with the return address after matching the reserved word list.
1BFD
PUSH BC
Save the return address in register pair BC to the stack .
1BFE-1BFF
LD B,7FH
Load register B with the initial reserved words counter.
1C00
LD A,(HL)
Load register A with the character at the location of the input buffer pointer in register pair HL.
1C01-1C02
CP 61H
Check to see if the character in register A is lower�case.

NOTE: Results from a CP:
  • Z: A and * are the same
  • NZ: A and * are NOT the same
  • C: A < *
  • NC: A => *
1C03-1C04
Jump to 1C0CH if the character in register A isn’t lowercase.
1C05-1C06
CP 7BH
Check to see if the character in register A is lower�case.
1C07-1C08
Jump down 2 instructions to 1C0CH if the character in register A isn’t lowercase.
1C09-1C0A
AND 5FH
Make the lowercase character in register A upper�case.
1C0B
LD (HL),A
Save the adjusted character in register A at the location of the input buffer pointer in register pair HL.
1C0C
LD C,(HL)
Load register C with the character at the location of the input buffer pointer in register pair HL.
1C0D
EX DE,HL
Exchange the input buffer pointer in register pair HL with the reserved words list pointer in register pair DE.
1C0E
INC HL
Bump the value of the reserved words list pointer to the next reserved word and put that in register pair HL.
1C0F
OR (HL)
Check to see if bit 7 of the character at the location of the reserved words list pointer in register pair HL is set.
1C10-1C12
Jump to 1C0EH if the character at the location of the reserved words list pointer in register pair HL doesn’t have bit 7 set.
1C13
INC B
Bump the value of the reserved words counter in register B.
1C14
LD A,(HL)
Load register A with the character at the location of the reserved words list pointer in register pair HL.
1C15-1C16
AND 7FH
Reset bit 7 (the sign bit) of the character in register A.
1C17
RET Z
Return if this is the end of the reserved words list.
1C18
CP C
Check to see if the character in register C is the same as the character at the location of the reserved words list pointer in register A.
1C19-1C1A
Jump to 1C0EH if the characters don’t match.
1C1B
EX DE,HL
Exchange the value of the reserved words list pointer in register pair HL with the value of the input buffer pointer in register pair DE.
1C1C
PUSH HL
Save the starting address of the current symbol (stored register pair HL) to the stack.
1C1D
INC DE
Bump the value of the reserved words list pointer in register pair DE.
1C1E
LD A,(DE)
Load register A with the character at the location of the reserved words list pointer in register pair DE.
1C1F
OR A
Check to see if bit 7 of the character in register A is set.
1C20-1C22
Jump to 1C39H if we have the control element (i.e., bit 7 of the character in register A is set).
1C23
LD C,A
Load register C with the character in register A.
1C24
LD A,B
Load register A with the value of the reserved words counter in register B.
1C25-1C26
CP 8DH
Check to see if the current reserved word being checked is GOTO.
1C27-1C28
Jump to 1C2BH if the current reserved word being checked isn’t GOTO.
1C29
RST 10H
Since we need to skip spaces we need to bump the current input buffer pointer in register pair HL until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:
  • The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
  • Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
  • The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
  • The string must be terminated by a byte of zeros.
1C2A
DEC HL
Decrement the value of the input buffer pointer in register pair HL.
1C2B
INC HL
Bump the value of the input buffer pointer in register pair HL to point to the next character.
1C2C
LD A,(HL)
Load register A with the next element from the string input (i.e., the character at the location of the input buffer pointer in register pair HL).
1C2D-1C2E
CP 61H
Check to see if the character in register A is lower-case. Results:
  • If A=61H it sets the ZERO FLAG
  • If A<61H then the CARRY FLAG will be set
  • if A>=61H then the NO CARRY FLAG will be set.
If A is a not lower case then C will be set.
1C2F-1C30
Jump to 1C33H if the character in register A isn’t lowercase.
1C31-1C32
AND 5FH
Mask A against 5FH (Binary: 0101 1111) to turn off bits 5 and 7 (which locks A to be between 00H and 7FH).
1C33
CP C
Check to see if the character in register A (the input element) matches the character in register C (the syntax element).
1C34-1C35
Jump back to 1C1DH if the character in the input matches the reserved words character.
1C36
POP HL
If we didn’t just jump away, we need to restart the scan from the last point in the syntax list (which is stored in the stack) and put it into HL.
1C37-1C38
Jump back to 1C0CH.
1C39
LD C,B
Load register C with the value of the reserved words counter in register B.
1C3A
Get the value from the stack and put it in register pair AF (which is just disposing of the HL push from 1C1CH).
1C3B
EX DE,HL
Exchange the current string with the syntax tree address for the string.
1C3C
RET
Return.
1C3D
EX DE,HL
Exchange the reserved words list pointer in register pair HL with the input buffer pointer in register pair DE.
1C3E
LD A,C
Load register A with the value of the reserved words counter in register C.
1C3F
POP BC
Get the value from the stack and put it in register pair BC (basically to clear the return address from the stack).
1C40
POP DE
Get the input buffer pointer -2 from the stack and put it in register pair DE.
1C41
EX DE,HL
Exchange the input buffer pointer in register pair HL with the input buffer pointer in register pair DE. HL will be the buffer origin – 2 and DE will be the current string address.
1C42-1C43
CP 95H
Check to see if the token in register A is an ELSE token.
1C44-1C45
LD (HL),3AH
Save a colon at the location of the input buffer pointer -2 in register pair HL.
1C46-1C47
Jump to 1C4AH if the token in register A isn’t an ELSE token.
1C48
INC C
Bump the value of the counter in register C (which is tracking the token buffer).
1C49
INC HL
Bump the value of the input buffer pointer in register pair HL (which is the token buffer).
1C4A-1C4B
CP 0FBH
Check to see if the token in register A is a REM token.
1C4C-1C4D
Jump to 1C5AH if the token in register A isn’t a REM token.
1C4E-1C4F
LD (HL),3AH
Save a “:” at the memory location of the input buffer pointer in register pair HL.
1C50
INC HL
Bump the value of the input buffer pointer in register pair HL (because we just inserted a :).
1C51-1C52
LD B,93H
Load register B with a REM token.
1C53
LD (HL),B
Save the REM token in register B at the memory location of the input buffer pointer in register pair HL.
1C54
INC HL
Bump the value of the input buffer pointer in register pair HL (because we just inserted a REM token).
1C55
EX DE,HL
Exchange the value of the input buffer pointer in register pair HL with the value of the input buffer pointer in register pair DE.
1C56
INC C
Bump the value of the counter in register C.
1C57
INC C
Bump the value of the counter in register C.
1C58-1C59
Jump to 1C77H to move the comment to the token buffer.
1C5A
EX DE,HL
Exchange the value of the input buffer pointer in register pair HL with the value of the input buffer pointer in register pair DE.
1C5B
INC HL
Bump the value of the input buffer pointer in register pair HL.
1C5C
LD (DE),A
Save the value of the token in register A at the location of the input buffer pointer in register pair DE.
1C5D
INC DE
Bump the value of the input buffer pointer in register pair DE.
1C5E
INC C
Bump the value of the counter in register C (which is the index/counter for the next syntax element).
1C5F-1C60
SUB 3AH
Check to see if the character in register A is a : to flag a multi-statement line.
1C61-1C62
Jump to 1C67H if the character in register A is a colon and we have a multi-statement line.
1C63-1C64
CP 4EH
Check to see if the token in register A is a DATA token.
1C65-1C66
Jump to 1C6AH if the token in register A is NOT a DATA token.
1C67-1C69
LD (40B0H),A
Save the value in register A as the tokenization flag for DATA.

NOTE: 40B0H holds the temporary storage location.
1C67-1C69
LD (409FH),A
Save the value in register A into the DATA FLAG held in 409FH.

NOTE: Bit 0 HIGH means inside a quote. Bit 1 HIGH means inside a DATA. Bit 2 HIGH means inside a REM.

NOTE: In the original Model III ROM, this byte was placed into 40B0H which was just a temporary storage location.
1C6A-1C6B
SUB 59H
Check to see if the token in register A is a REM token.
1C6C-1C6E
Jump to 1BCCH if the token in register A isn’t a REM token.
1C6F
LD B,A
Load register B with a zero.
1C70
LD A,(HL)
Load register A with the character at the location of the input buffer pointer in register pair HL.
1C71
OR A
Check to see if the character in register A is an end of the input character.
1C72-1C73
Jump out of this loop to 1C7DH if the character in register A is an end of the input character.
1C74
CP B
Check to see if the character in register B matches the character in register A.
1C75-1C76
Jump to 1C5BH if the character in register B matches the character in register A.
1C77
INC HL
Bump the value of the input buffer pointer in register pair HL.
1C78
LD (DE),A
Save the character in register A at the location of the input buffer pointer in register pair DE.
1C79
INC C
Bump the value of the counter in register C.
1C7A
INC DE
Bump the value of the input buffer pointer in register pair DE.
1C7B-1C7C
Loop until a ‘end of statement’ or a ending quote is found.

Still Inside the TOKENIZE INPUT ROUTINE – This routine is called if the character in register A is an end of the input character.

1C7D-1C7F
LD HL,0005H
Load register pair HL with a five.
1C80
LD B,H
Load register B with zero.
1C81
ADD HL,BC
Add 5 to the length of the token buffer so far.
1C82
LD B,H
Load register B with the MSB of the value in register H.
1C83
LD C,L
Load register C with the LSB of the value in register L.
1C84-1C86
LD HL,(40A7H)
Load register pair HL with the start address of the input buffer.

NOTE: 40A7H-40A8H holds the pointer to the start of the Input Buffer.
1C87
DEC HL
Decrement the value of the input buffer pointer in register pair HL.
1C88
DEC HL
Decrement the value of the input buffer pointer in register pair HL.
1C89
DEC HL
Decrement the value of the input buffer pointer in register pair HL.
1C8A
LD (DE),A
Zero the location of the input buffer pointer in register pair DE.
1C8B
INC DE
Bump the value of the input buffer pointer in register pair DE.
1C8C
LD (DE),A
Zero the location of the input buffer pointer in register pair DE.
1C8D
INC DE
Bump the value of the input buffer pointer in register pair DE.
1C8E
LD (DE),A
Zero the location of the input buffer pointer in register pair DE.
1C8F
RET
Return.

1C90-1C95 – RST 0018H CODE
The RST 18H code is located here. (Unsigned compare (HL-DE)).

This is the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as:

  • HL<DE: CARRY SET
  • HL>DE: NO CARRY
  • HL><DE: NZ
  • HL=DE: Z
1C90H
“CHLDE”
LD A,H
Load register A with the MSB of the value in register H.
1C91
SUB D
Subtract the value of the MSB of the value in register D from the MSB of the value in register A.
1C92
RET NZ
Return if the MSB of the value in register D doesn’t equal the MSB of the value in register H.
1C93
LD A,L
Load register A with the LSB of the value in register L.
1C94
SUB E
Subtract the LSB of the value in register E from the LSB of the value in register A.
1C95
RET
Return.

1C96-1CA0 – RST 0008H CODE

  • The RST 8H code is located here.
    This is the COMPARE SYMBOL routine which comparess the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call. If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the Aregister and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase).
1C96
LD A,(HL)
Load register A with the character at the location of the current BASIC program pointer in register pair HL.
1C97
EX (SP),HL
Save the return address of the routine by exchanging the value of the current BASIC program pointer in register pair HL with the value of the return address to the stack.
1C98
CP (HL)
Check to see if the character at the location following the RST 08H call (stored in register pair HL) is the same as the character in register A.
1C99
INC HL
Bump the value of the return address in register pair HL.
1C9A
EX (SP),HL
Restore the return address (meaning the RST 08H plus 1 byte plus 1 byte) to the stack pointer.
1C9B-1C9D
Jump to the RST 0010H code if the characters match.
1C9E-1C90
If they don’t match, jump to the ?SN ERROR routine.

1CA1-1D1D – Level II BASIC FOR ROUTINE

1CA1-1CA2
LD A,64H
Load register A with the value for the FOR flag.
1CA3-1CA5
LD (40DCH),A
Save the value in register A as the current value of the FOR flag.

NOTE: 40DCH holds FOR flag.
1CA6-1CA8
Go evaluate the N=M portion of the expression.
1CA9
EX (SP),HL
Exchange the value of the current BASIC program pointer in register pair HL with the value to the stack.
1CAA-1CAC
GOSUB to 1936H to check to see if there is a FOR statement to the stack already using the same variable name (called the index).
1CAD
POP DE
Get the current BASIC program pointer from the stack (which should be the TO token and put it in register pair DE.
1CAE-1CAF
If there isn’t a matching FOR statement to the stack, skip the next 4 instructions (which are preparing for a NEXT WITHOUT FOR error) and jump to 1CB5H. If one is found, on exit HL will equal the starting address of the FOR push.
1CB0
ADD HL,BC
Add the value in register pair BC (which is the offset to the end of the stack frame) to the value in register pair HL. After this addition, we should be pointing to the end of the first FOR frame push.
1CB1
LD SP,HL
Reset the stack pointer to end of the first FOR frame push. This also frees up the stack space and prepares for a NF error.
1CB2-1CB4
LD (40E8H),HL
Save the value in register pair HL as the stack pointer, get ready for a NF error.

NOTE: 40E8H-40E9H holds Stack pointer pointer.
1CB5
EX DE,HL
Exchange the value of the current BASIC program pointer in register pair DE with the value of the stack pointer address in register pair HL.
1CB6-1CB7
LD C,08H
Load register C with the 1/2 the amount of space needed.
1CB8-1CBA
Go check to see if there is enough memory (i.e., 16 bytes) left by calling 1963H (which is the MEMORY CHECK ROUTINE).
1CBB
PUSH HL
Save the value of the current BASIC program pointer (which is the code string address before the TO) in register pair HL to the stack.
1CBC-1CBE
Keep scanning the current BASIC program (pointer is in register pair HL) until it points to the end of the BASIC statement.
1CBF
EX (SP),HL
Exchange the adjusted value of the current BASIC program pointer in register pair HL with the value of the current BASIC program pointer to the stack.
1CC0
PUSH HL
Save the value of the current BASIC program pointer in register pair HL to the stack. This should be pointing to the TO token.
1CC1-1CC3
LD HL,(40A2H)
Load register pair HL with the value (in binary) of the current BASIC line number.

NOTE: 40A2H-40A3H holds the current BASIC line number.
1CC4
EX (SP),HL
Exchange the value of the current BASIC line number in register pair HL with the value of the current BASIC program pointer to the stack.
1CC5-1CC6
RST 08H
BDH
Since the character at the location of the current BASIC program pointer in register pair HL must be TO token (BDH) so call the COMPARE SYMBOL routine which comparess the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call. If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the Aregister and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase).
1CC7
RST 20H
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register according to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • Double Precision is NZ/NC/P/E and A is 5.
1CC8-1CCA
If that test shows we have a STRING, go to the Level II BASIC error routine and display a TM ERROR message.
1CCB-1CCD
If that test shows we have a DOUBLE PRECISION number, go display a ?TM ERROR message.
1CCE
PUSH AF
We have an integer, so let’s keep going and save the value in register pair AF (the type flags) to the stack.
lCCFH-lCDl
Go evaluate the expression at the location of the current BASIC program pointer in register pair HL (which should be the TO side) and return with the result in REG 1.
1CD2
POP AF
Restore the index type flags from the from the stack and put it in register pair AF.
1CD3
PUSH HL
Save the value of the current BASIC program pointer (which is the code string after the TO pointer) in register pair HL to the stack.
1CD4-1CD6
Jump if the current number type is single precision.
1CD7-1CD9
Call the CONVERT TO INTEGER routine at 0A7FH (where the contents of REG 1 are converted from single or double precision to integer and deposited into HL).
1CDA
EX (SP),HL
Exchange the integer value in register pair HL (the current TO value) with the value of the current BASIC program pointer to the stack.
1CDB-1CCD
LD DE,0001H
Load register pair DE with a default STEP value of 1.
1CDE
LD A,(HL)
Load register A with the character at the location of the current BASIC program pointer in register pair HL.
1CDF-1CE0
CP CCH
Check to see if the character in register A is CCH which is the STEP token.
1CE1-1CE3
So now we have a STEP token so we have to get the step value into DE. To do this, GOSUB to 2B01H to evaluate the expression at the location of the current BASIC program pointer in register pair HL and return with the integer value in register pair DE if the character in register A is a STEP token.
1CE4
PUSH DE
Save the STEP index value (in register pair DE) to the stack.
1CE5
PUSH HL
Save the current BASIC program pointer (in register pair HL) to the stack.
1CE6
EX DE,HL
Exchange the STEP value (from DE) with the value of the current BASIC program pointer (in register pair HL). Now HL will have the value so the next call can test its size.
1CE7-1CE9
GOSUB to 099EH to get the sign of the STEP value into A. It will be A=+1 if positive and A=-1 if negative.
1CEA-1CEB
Jump down to 1D0EH to skip the convert to single precision code which follows.
1CEC-1CEE
Need the TO value to be integer so GOSUB to the CONVERT TO SINGLE PRECISION routine at 0AB1H (which converts the contents of REG 1 from integer or double precision into single precision).
1CEF-1CF1
Call 09BF which loads the SINGLE PRECISION value in REG 1 (the TO value in integer) into register pair BC/DE.
1CF2
POP HL
Get the value of the current BASIC program pointer from the stack (which should be the end of the TO expression) and put it in register pair HL.
1CF3H,1CF4
PUSH BC
PUSH DE
Save all 4 bytes of the TO value to the stack.
1CF5-1CF7
LD BC,8100H
Load register pair BC with the exponent and the MSB for a single precision constant.
1CF8
LD D,C
Zero the NMSB for the single precision constant in register D.
1CF9
LD E,D
Zero the LSB for the single precision constant in register E. Register pairs BC and DE now hold a single precision constant equal to one.
1CFA
LD A,(HL)
Load register A with the character at the location of the current BASIC program pointer in register pair HL.
1CFB-1CFC
CP CCH
Check to see if the character in register A is a STEP token.
1CFD-1CFE
LD A,01H
Load register A with the default STEP value (in this case, 1).
1CFF-1D00
Skip over the next unstructions by jumping down to 1D0FH if the character at the location of the current BASIC program pointer in register A isn’t a STEP token.
1D01-1D03
Go evaluate the expression at the location of the current BASIC program pointer (which is the STEP instruction and return with the result in REG 1
1D04
PUSH HL
Save the value of the current BASIC program pointer in register pair HL to the stack.
1D05-1D07
Convert the STEP value to single precision by calling the CONVERT TO SINGLE PRECISION routine at 0AB1H (which converts the contents of REG 1 from integer or double precision into single precision).
1D08-1D0A
Load the STEP value into BC/DE by calling 09BF which loads the SINGLE PRECISION value in REG 1 into register pair BC/DE.
1D0B-1D0D
Go get the sign for the STEP value (held in REG 1) into register A. A will be +1 if positive, and -1 if negative.
1D0E
POP HL
Get the value of the current BASIC program pointer from the stack and put it in register pair HL.
1D0F
PUSH BC
Save the exponent and the NMSB for the single precision value in register pair BC to the stack.
1D10
PUSH DE
Save the NMSB and the LSB for the single precision value in register pair DE to the stack.
1D11
LD C,A
Load register C with the sign value for the STEP value in register A.
1D12
RST 20H
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register according to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • Double Precision is NZ/NC/P/E and A is 5.
1D13
LD B,A
Load register B with type-adjusted and sign value of the number type flag test in register A.
1D14
PUSH BC
Save the type-adjusted and sign value in register pair BC to the stack.
1D15
PUSH HL
Save the value of the current BASIC program pointer in register pair HL to the stack.
1D16-1D18
LD HL,(40DFH)
Load register B with a FOR x=y token.

NOTE: 40DFH-40E0H holds Used by DOS.
1D19
EX (SP),HL
Put the code address string into HL and put the address of the x variable into the stack.
1D1A-1D1B
LD B,81H
Load register B with the FOR token.
1D1C
PUSH BC
Save the FOR and token and the sign of the STEP increment BC to the stack.
1D1D
INC SP
Bump the value of the stack pointer to leave a one byte gap. By continuing onward, we will wind up continuing the execution of the code string.

1D1E-1D77 – LEVEL II BASIC INTERPRETER

1D1E-1D20
GOSUB to 0358H to check to see if a key has been pressed.
1D21
OR A
Set the flags to test for what key was pressed.
1D22-1D24
GOSUB to 1DA0H if the key pressed was a SHIFT-@. This will save the address of the last byte executed in the current line.
1D25-1D27
LD (40E6H),HL
Save the value of the current BASIC program pointer.

NOTE: 40E6H-40E7H holds the temporary storage location.
1D28-1D2B
LD (40E8H),SP
Save the value of the stack pointer.

NOTE: 40E8H-40E9H holds Stack pointer pointer.
1D2C
LD A,(HL)
Load register A with the value at the location of the current BASIC program pointer in register pair HL.
1D2D-1D2E
CP 3AH
Check to see if the character in register A is a :.
1D2F-1D30
If the character is a :, jump to 1D5AH since that means this is a brand new statement on this line.
1D31
OR A
There wasn’t a colon, so the only valid thing we can find now is an END OF LINE character. This will check to see if the character in register A is an end of the BASIC line character.
1D32-1D34
Go to the Level II BASIC error routine and display a ?SN ERROR message if the character in register A isn’t an end of the BASIC line character.
1D35
INC HL
So now we know that we have another line number to check, so bump the value of the current BASIC program pointer in register pair HL.
1D36
LD A,(HL)
Load register A with the LSB of the next BASIC line pointer at the location of the current BASIC program pointer in register pair HL.
1D37
INC HL
Bump the value of the current BASIC program pointer in register pair HL.
1D38
OR (HL)
Check to see if the next BASIC line pointer is equal to zero.
1D39-1D3B
Jump to 197EH if this is the end of the BASIC program.
1D3C
INC HL
If we are here, it was not the end of the BASIC program so we need to bump the value of the current BASIC program pointer in register pair HL.
1D3D
LD E,(HL)
Load register E with the LSB of the BASIC line number at the location of the current BASIC program pointer in register pair HL.
1D3E
INC HL
Bump the value of the current BASIC program pointer in register pair HL.
1D3F
LD D,(HL)
Load register D with the MSB of the BASIC line number at the location of the current BASIC program pointer in register pair HL.
1D40
EX DE,HL
Exchange the value of the BASIC line number in register pair DE with the value of the current BASIC program pointer in register pair HL.
1D41-1D43
LD (40A2H),HL
Save the value of the BASIC line number in register pair HL.

NOTE: 40A2H-40A3H holds the current BASIC line number.

1D44 – Honor a TRON by showing the line number if it is in effect.

1D44-1D46
LD A,(411BH)
Before we move on, we need to honor a TRON, if its in effect so first we load register A with the value of the TRON flag.

NOTE: 411BH holds the TRON/TROFF flag.
1D47
OR A
Check for TRON.
1D48-1D49
Jump out of this routine to 1D59H if TROFF.
1D4A
PUSH DE
If we are here, we have to process the code to show the “<nnnn>” of a TRON. First, save the value of the current BASIC program pointer in register pair DE to the stack.
1D4B-1D4C
LD A,3CH
Load register A with a <.
1D4D-1D4F
Go display the < that preceeds the line number in TRON output
1D50-1D52
Call the HL TO ASCII routine at 0FAFH (which converts the value in the HL register pair (assumed to be an integer) to ASCII and display it at the current cursor position on the video screen) to display the current BASIC line number.
1D53-1D54
LD A,3EH
Load register A with a >
1D55-1D57
Go display the > that follows the line number in TRON output
1D58
POP DE
Get the value of the current BASIC program pointer from the stack and put it in register pair DE.

1D59 – Done with the TRON, so let us continue.

1D59
EX DE,HL
Load register pair HL with the value of the current BASIC program pointer in register pair DE.
RST 10H
We need to get the next token. We bump the current input buffer pointer in register pair HL until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:
  • The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
  • Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
  • The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
  • The string must be terminated by a byte of zeros.
1D5B-1D5D
LD DE,1D1EH
Load register pair DE with the return address to go to after executing one verb.
1D5E
PUSH DE
Save that return address in register pair DE to the stack.
1D5F
Return (back to 1D1EH) if the character at the location of the current BASIC program pointer (in register pair HL) is an end of the BASIC line character.
1D60-1D61
SUB 80H
Check to see if the character at the location of the current BASIC program pointer in register A is a token. This is accomplished because tokens range from 80H-FBH so this would give an index of the current token.
1D62-1D64
Jump to 1F21H if the character in register A isn’t a BASIC token.
1D65-1D66
CP 3CH
Check to see if the token in register A is below the TAB( token.
1D67-1D69
Jump out of here to 2AE7H if the token in register A is greater than or equal to a TAB( token, meaning TAB( to MID$(.
1D6A
RLCA
Multiply the token value in register A by two. This doubles the remainder of the routine address offset.
1D6B
LD C,A
Load the adjusted token value in register C from register A.
1D6C-1D6D
LD B,00H
Load register B with zero so that BC now holds “00” and (2 x the token).
1D6E
EX DE,HL
Load register pair DE with the value of the current BASIC program pointer in register pair HL.
1D6F-1D71
LD HL,1822H
Load register pair HL with the list of BASIC execution addresses.
1D72
ADD HL,BC
Add the value of the token offset in register pair BC to the starting address of the list of BASIC execution addresses in register pair HL.
1D73
LD C,(HL)
Load register C with the LSB of the execution address at the location of the memory pointer in register pair HL.
1D74
INC HL
Bump the value of the memory pointer in register pair HL.
1D75
LD B,(HL)
Load register B with the MSB of the execution address at the location of the memory pointer in register pair HL.
1D76
PUSH BC
Save the value of the execution address in register pair BC to the stack.
1D77
EX DE,HL
Load register pair HL with the value of the current BASIC program pointer in register pair DE (i.e., restore the code string address).

1D78-1D90 – RST 0010H CODE

  • The RST 10H code is located here. This is the EXAMINE NEXT SYMBOL routine which loads the next character from the string pointed to by the HL register set into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric. Blanks and control codes 09 and OB are ignored causing the following character to be loaded and tested. The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one. The string must be terminated by a byte of zeros).
1D78H
“FETCH”
INC HL
Bump the value of the current BASIC program pointer in register pair HL to the next character.
1D79
LD A,(HL)
Load register A with the value of the character at the location of the current BASIC program pointer in register pair HL.
1D7A-1D7B
CP 3AH
Check to see if the character at the location of the current BASIC program pointer in register A is greater than or equal to a :. Results:
  • If A=: it sets the ZERO FLAG
  • If A<: then the CARRY FLAG will be set
  • if A>=: then the NO CARRY FLAG will be set.
1D7C
RET NC
Return if the character at the location of the current BASIC program pointer in register A is greater than or equal to a : (meaning :, ;, <Y, Z.
1D7D-1D7E
CP 20H
Check to see if the character at the location of the current BASIC program pointer in register A is a space.
1D7F-1D81
Loop if the character at the location of the current BASIC program pointer in register A is a space.
1D82-1D83
CP 0BH
Check to see if the character at the location of the current BASIC program pointer in register A is greater than or equal to 0BH (meaning it is not a control code). Results:
  • If A=0BH it sets the ZERO FLAG
  • If A<0BH then the CARRY FLAG will be set
  • if A>=0BH then the NO CARRY FLAG will be set.
1D84-1D85
Jump if the character at the location of the current BASIC program pointer in register A if greater than or equal to 0BH.
1D86-1D87
CP 09H
Check to see if the character at the location of the current BASIC program pointer in register A is greater than or equal to 09H (meaning a horizontal tab). Results:
  • If A=09H it sets the ZERO FLAG
  • If A<09H then the CARRY FLAG will be set
  • if A>=09H then the NO CARRY FLAG will be set.
1D88-1D8A
Loop back up to get the next character if if the character at the location of the current BASIC program pointer in register A is greater than or equal to 09H.
1D8B-1D8C
CP 30H
Check to see if the character at the location of the current BASIC program pointer in register A is greater than or equal to a 0. Results:
  • If A=0 it sets the ZERO FLAG
  • If A<0 then the CARRY FLAG will be set
  • if A>=0 then the NO CARRY FLAG will be set.
1D8D
CCF
Complement (invert) the CARRY FLAG so that it will set the CARRY FLAG if that ascii character is numeric (i..e, greater than or equal to 30H).
1D8E
INC A
Clear the CARRY FLAG if it is not numeric (i.e., it is less than 30).
1D8F
DEC A
Set the status flags (except for the CARRY FLAG) according to the character at hand.
1D90
RET
Return.

1D91-1D9A – LEVEL II BASIC RESTORE ROUTINE

1D91
EX DE,HL
Save the contents of HL by loading its contents into DE.
1D92-1D94
LD HL,(40A4H)
Load register pair HL with the start of the BASIC program pointer.
  • Note: 40A4H-40A5H holds the starting address of BASIC program text also known as the PROGRAM STATEMENT TABLE (PST).
1D95
DEC HL
Backspace from the start of the BASIC program pointer.
1D96-1D98
LD (40FFH),HL
Save the start of the program pointer -1 into 40FFH.

NOTE: 40FFH-4100H holds READ pointer.
1D99
EX DE,HL
Restore the HL from being held in DE.
1D9A
RET
Return.

1D9B-1DAD – SCAN KEYBOARD ROUTINE

1D9B-1D9D
GOSUB to 0358H to scan the keyboard.
1D9E
OR A
Set the flags (to see if a key was pressed).
1D9F
RET Z
Return if a key wasn’t pressed.

1DA0H – Inside the SCAN KEYBOARD ROUTINE – This will process a SHIFT + @ (Pause) Keypress

1DA0-1DA1
CP 60H
Check to see if the key pressed in register A is a SHIFT + @.
1DA2-1DA4
If you got a SHIFT + @ we now need to honor that by waiting for yet another key to be pressed.
1DA5-1DA7
LD (4099H),A
Save the key pressed in register A as the value of the last key pressed.

NOTE: 4099H holds the Last key pressed.
1DA8
DEC A
Check to see if the BREAK key was pressed.

1DA9H-1DADH – Inside the SCAN KEYBOARD ROUTINE – This will process a STOP.

1DA9
RET NZ
Return if the BREAK key wasn’t pressed.
This is the STOP entry point.
1DAA
INC A
Readjust the value of the key pressed in register A.
1DAB-1DAD
Jump into the applicable portion of the code that processes END.

1DAE-1DE3 – LEVEL II BASIC END ROUTINE

1DAE
RET NZ
Return and display a ?SN ERROR message if there is anything following the END token.
1DAF
PUSH AF
Save the value in register pair AF to the stack.
1DB0-1DB2
CALL Z,41BBH
If this is a DOS system, then call the DOS link at 41BBH instead of continuing here.
1DB3
POP AF
Restore the END status to the A register.
1DB4-1DB6
LD (40E6H),HL
Save the value of the current BASIC program pointer in register pair HL.

NOTE: 40E6H-40E7H holds the temporary storage location.
1DB7-1DB9
LD HL,40B5H
Load register pair HL with the starting address of the temporary string work area.

NOTE: 40B5H-40D2H holds Temporary string work area.
1DBA-1DBC
LD (40B3H),HL
Save the value in register pair HL as the new temporary string work area pointer.

NOTE: 40B3H-40B4H holds Next available location in the temporary string work area pointer.
1DBD-1DBFH
21 F6 FF
Z-80 space saving trick
1DBE-1DBF
OR FFH
Set the flags.
1DC0
POP BC
Get the value from the stack and put it in register pair BC. This clears out the stack.
1DC1-1DC3
LD HL,(40A2H)
Load register pair HL with the value of the current BASIC line number in binary.

NOTE: 40A2H-40A3H holds the current BASIC line number.
1DC4
PUSH HL
Save the value of the current BASIC line number (in binary) in register pair HL to the stack.
1DC5
PUSH AF
Save the value in register pair AF to the stack. A will be 0 if it is an END and A will be a 1 if it is a STOP.
1DC6
LD A,L
These 3 instructions test to see if we are in command mode by testing for an uninitialized line (meaning a line number of FFFF). First, load register A with the LSB of the current BASIC line number in register L.
1DC7
AND H
Combine the MSB of the current BASIC line number in register H with the LSB of the current BASIC line number in register A.
1DC8
INC A
Bump the combined value of the current BASIC line number in register A.
1DC9-1DCA
Increasing FFFF by 1 would flip the Z flag on, meaning there was no line number. If there was no line number, skip the nex 3 instructions and go to 1D44H.
1DCB-1DCD
LD (40F5H),HL
If we are here, we have a line number so save the line number we ended on in register pair HL.

NOTE: 40F5H-40F6H holds the last line number executed.
1DCE-1DD0
LD HL,(40E6H)
Load register pair HL with the value of the current BASIC program pointer .

NOTE: 40E6H-40E7H holds the temporary storage location.
1DD1-1DD3
LD (40F7H),HL
Save the value of the current BASIC program pointer in register pair HL.

NOTE: 40F7H-40F8H holds the last byte executed.
1DD4-1DD6
Go set the current output device to the video display.
1DD7-1DD9
Go display a carriage return if necessary.
1DDA
POP AF
Restore A so we can see if this is an END (where A=0) or a STOP (where A=1).
1DDB-1DDD
LD HL,1930H
Load register pair HL with the starting address of the BREAK message.
1DDE-1DE0
Jump to 1A06H if it was a BREAK or a STOP that halted program execution.
1DE1-1DE3
At this point it was either due to an END statement or an error while in command mode so jump to 1A18H (note: This uses a Z-80 trick as 1A18H is in the middle of a 2 Opcode instruction starting at 1A17H).

1DE4-1DF6 – LEVEL II BASIC CONT ROUTINE.

1DE4-1DE6
LD HL,(40F7H)
Load register pair HL with the value of the continuation address.

NOTE: 40F7H-40F8H holds the last byte executed.
1DE7-1DE8
LD A,H
OR L
Test HL for 0. The easiest way to test a 2 byte register for zero is to load the MSB into A and then OR it with the LSB. if the MSB was 0 and the LSB was 0, then A will be 0.
1DE9-1DEA
LD E,20H
Load register E with a ?CN ERROR code.
1DEB-1DED
If HL was zero, then a CONT isn’t possible, so JUMP to 19A2H to display a ?CN ERROR.
1DEE
EX DE,HL
If we are here, there was a valid return line number, so load register pair DE with the value of the continuation line number in register pair HL.
1DEF-1DF1
LD HL,(40F5H)
Load HL with the value of the last BASIC line number executed.

NOTE: 40F5H-40F6H holds the last line number executed.
1DF2-1DF4
LD (40A2H),HL
Save the last line number executed in register pair HL (which had the error) as the current BASIC line number.

NOTE: 40A2H-40A3H holds the current BASIC line number.
1DF5
EX DE,HL
Swap so that HL will be the address of the continuation line.
1DF6
RET
Return (continue running but from the CONT line number).

1DF7H-1DFCH – TRON and TROFF Routine

1DF7H – TRON Entry Point (Set A with AFH)

1DF7-1DF8
LD A,AFH
Load register A with AFH (Decimal: 175), which is the value for TRON when placed into 411BH.

1DF8H – TROFF Entry Point (Set A with 00H)

1DF8
XOR A
Z-80 trick. This command is only visible if jumped to. This zeros register A.

1DF9-1DFC – COMMON CODE SHARED BY TRON AND TROFF – Put A into (411BH)

1DF9-1DFB
LD (411BH),A
Save the value in register A as the current value of the TRON/TROFF flag.

NOTE: 411BH holds the TRON/TROFF flag. 0=off (TROFF), 175=on (TRON)
1DFC
RET
RETURN.

1DFD-1DFF – DISK ROUTINE NOT USED BY LEVEL II BASIC.

1DFD
POP AF
1DFE
POP HL
1DFF
RET

1E00H-1E3CH – DEFxxx Routine

1E00-1E02 – INSIDE THE DEFxxx ROUTINE – DEFSTR Entry Point

1E00-1E01
LD E,03H
Load register E with the DEFSTR string number type flag (03H).
1E02H
32 1B 41
Z-80 Trick! See the general explanation at 10F8H.

1E03H-1E05H – INSIDE THE DEFxxx ROUTINE – DEFINT Entry Point

1E03-1E04
LD E,02H
Load register E with the DEFINT integer number type flag (02H).
1E05H
011 1E 04
Z-80 Trick! See the general explanation at 10F8H.

1E06H-1E08H – INSIDE THE DEFxxx ROUTINE – DEFSNG Entry Point

1E06-1E07
LD E,04H
Load register E with the DEFSNG single precision number type flag (04H).
1E08H
011 E0 08
Z-80 Trick! See the general explanation at 10F8H.

1E09-1E0AH – INSIDE THE DEFxxx ROUTINE – DEFDBL Entry Point

1E09-1E0A
LD E,08H
Load register E with the DEFDBL double precision number type flag (08H).

1E0BH-1E3CH – INSIDE THE DEFxxx ROUTINE – Common code shared by all the above – All of those can either have a for a range of values or be separated by ,. This code needs to figure out the variables that followed the DEF??? instruction and then set the variable type (which is currently sitting in Register E) in the variable table.

1E0B-1E0D
GOSUB to 1E3DH to check the value at memory location (HL), which would be the current BASIC program pointer, to see if it is a letter. If its not, CARRY is set. If it is, CARRY is clear.
1E0E-1E10
LD BC,1997H
Load register pair BC with a return address which will return to the ?SN ERROR routine.
1E11
PUSH BC
Save the ?SN ERROR address (in register pair BC) to the stack.
1E12
RET C
Return if the character at the location of the current BASIC program pointer in register A isn’t alphabetic (meaning that DEF??? wasn’t followed by a letter).
1E13-1E14
SUB 41H
Subtract 41H from the letter’s value in register A so that it will be in the range of 0-25.
1E15
LD C,A
Load register C with the adjusted value in register A.
1E16
LD B,A
Load register B with the adjusted value in register A.
1E17
RST 10H
Since we now need bump the value of the current BASIC program pointer until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:
  • The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
  • Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
  • The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
  • The string must be terminated by a byte of zeros.
1E18-1E19
CP CEH
Check to see if the character at the location of the current BASIC program pointer in register A is a .
1E1A-1E1B
If it’s not a we know this isn’t a range, so jump to 1E25H because we don’t need to get any more variables.
1E1C
RST 10H
If we are here, then we know the DEF??? has a range, so we need another character. We bump the value of the current BASIC program pointer until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:
  • The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
  • Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
  • The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
  • The string must be terminated by a byte of zeros.
1E1D-1E1F
GOSUB to 1E3DH to check the value at memory location (HL), which would be the current BASIC program pointer, to see if it is a letter. If its not, CARRY is set. If it is, CARRY is clear.
1E20
RET C
Return if the character at the location of the current BASIC program pointer in register A isn’t alphabetic.
1E21-1E22
SUB 41H
Subtract 41H from the letter’s value in register A so that it will be in the range of 0-25.
1E23
LD B,A
Load register B with the adjusted value in register A.
1E24
RST 10H
Since we now need bump the value of the current BASIC program pointer until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:
  • The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
  • Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
  • The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
  • The string must be terminated by a byte of zeros.
1E25
LD A,B
Load register A with the value of the second letter in register B.
1E26
SUB C
Subtract the value of the first letter in register C from the value of the second letter in Register A.
1E27
RET C
If the CARRY FLAG is set (meaning that varible names are not in ascending order … the one in Register C is earlier than the one in Register A), return (to a syntax error).
1E28
INC A
Bump the value in register A so that it holds the number of variable names to be changed.
1E29
EX (SP),HL
Clear the error address and save the current code string address.
1E2A-1E2C
LD HL,4101H
Load register pair HL with 4101H which is the starting address of the variable declaration table.

NOTE: 4101H-411AH holds Variable Declaration Table.
1E2D-1E2E
LD B,00H
Load register B with zero.
1E2F
ADD HL,BC
Find the next entry in the type table by adding the value of the first letter in register pair BC to the value of the starting address of the variable declaration table in register pair HL.
1E30
LD (HL),E
E was set on entry to string, integer, single precision, or double precision as applicable. Save the number type flag in register E at the location of the memory pointer in register pair HL.
1E31
INC HL
Bump the value of the memory pointer in register pair HL.
1E32
DEC A
Decrement the count of the number of variables to be changed in register A.
1E33-1E34
Loop until all of the variables in the DEFxxx range have been changed.
1E35
POP HL
Restore the code string pointer into register pair HL.
1E36
LD A,(HL)
Load A with the character at the location of the current BASIC program pointer in register pair HL.
1E37-1E38
CP 2CH
Check to see if the character at the location of the current BASIC program pointer in register A is a ,.
1E39
RET NZ
Return if the character at the location of the current BASIC program pointer in register A isn’t a ,.
1E3A
RST 10H
Since we now need bump the value of the current BASIC program pointer until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:
  • The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
  • Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
  • The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
  • The string must be terminated by a byte of zeros.
1E3B-1E3C
Loop until done with all the variables.

1E3D-1E44 – EXAMINE VARIABLE – See if the value pointed to at the memory location (HL) is an ASCII letter. C Flag is set for yes, NC Flag for no.

1E3D
LD A,(HL)
Load register A with the character at the location of the current BASIC program pointer in register pair HL.
1E3E-1E3F
CP 41H
Check to see if the character at the location of the current BASIC program pointer in register A is less than an A. Results:
  • If A=A it sets the ZERO FLAG
  • If A<A then the CARRY FLAG will be set
  • If A>=A then the NO CARRY FLAG will be set
1E40
RET C
Return if the character at the location of the current BASIC program pointer in register A is less than an A.
1E41-1E42
CP 5BH
Check to see if the character at the location of the current BASIC program pointer in register A is greater than a Z. Results:
  • If A=Z it sets the ZERO FLAG
  • If A<Z then the CARRY FLAG will be set
  • If A>=Z then the NO CARRY FLAG will be set
1E43
CCF
Complement the value of the CARRY FLAG. On exit this routine will have the CARRY FLAG set if the character at the location of the current BASIC program pointer in register A isn’t alphabetic and will have the CARRY FLAG cleared if the character at the location of the current BASIC program pointer in register A is alphabetic.
1E44
RET
Return.

1E45-1E4E – EXAMINE VARIABLE

  • This is called when evaluating a subscript for a variable reference. It will evaluate if the value is positive or negative.
1E45
RST 10H
Get the next symbol from the input. Bump the value of the current BASIC program pointer until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:
  • The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
  • Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
  • The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
  • The string must be terminated by a byte of zeros.
1E46-1E48
GOSUB to 2B02H to evaluate the expression at the current location of the BASIC program pointer in register pair HL and return with the integer result in register pair DE.
1E49
RET P
Return if the integer result in register pair DE is positive. If it is negative, flow down to the ?FC ERROR.

1E4A – FC ERROR entry point.

1E4A-1E4B
LD E,08H
Load register E with an ?FC ERROR code.
1E4C-1E4E
Display a ?FC ERROR message. If this is from a pass through, the error wll show if the integer result in register pair DE is negative.

1E4F-1E79 – ASCII TO BINARY

1E4F
LD A,(HL)
Load register A with the character at the location of the current BASIC program (which is pointed to by register pair HL).
1E50-1E51
CP 2EH
Check to see if the character at the location of the current BASIC program pointer in register A is a .. Results:
  • If A=. it sets the ZERO FLAG
  • If A<. then the CARRY FLAG will be set
  • If A>=. then the NO CARRY FLAG will be set
1E52
EX DE,HL
Load register pair DE with the value of the current BASIC program pointer in register pair HL.
1E53-1E55
LD HL,(40ECH)
Load register pair HL with the current BASIC line number.

NOTE: 40ECH-40EDH holds EDIT line number.
1E56
EX DE,HL
Exchange the value of the current BASIC program pointer in register pair DE with the current BASIC line number in register pair HL.
1E57-1E59
Jump to the RST 10H (EXAMINE NEXT SYMBOL) routine if the character at the location of the current BASIC program pointer in register A is a ..

1E5A – “DECBIN” – Converts numeric ASCII string pointed to by the HL register pair, to HEX and places the result in the DE register pair. After execution HL points to the delimiter and the A register contains the delimiter value. The Z flag is set if the delimiter equals 00 or 3A. Z is reset if any other delimiter is used. If there is no string at the location pointed to by HL the routine will return a MO ERROR (missing operand). If the result in the DE register pair exceeds FFFFH an OV ERROR (overflow) results.

1E5AH
DEC HL
Backspace HL (the current BASIC program pointer) to the current character.
1E5B-1E5D
LD DE,0000H
Load register pair DE with zero.
1E5E
RST 10H
Re-process that previous character through a RST 10H call.
NOTE:
  • The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
  • Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
  • The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
  • The string must be terminated by a byte of zeros.
1E5F
RET NC
Return if the character at the location of the current BASIC program pointer in register A isn’t numeric.
1E60
PUSH HL
Save the value of the current BASIC program pointer in register pair HL to the stack.
1E61
PUSH AF
Save the value in register pair AF (which is the digit plus flags resulting from the RST 10H call) to the stack.
1E62-1E64
LD HL,1998H
Load register pair HL with 6552.

Why 6552? Well, since the Z-80 has no multiply function, checking for any possible arbitrary number would require 4 branches for each step in the ‘add to itself until it hits * 10’ plus another 4 when adding the last digit. The TRS-80 ROM didn’t have that kind of room, nor the time to do all that, so they needed a cheat and that cheat was to let it go as high 65529. After all, 6552 + 1 more digit can NEVER exceed 65535, but 6553 + 1 digit sure can!

So with this trick, the ROM just needs to first check the number against 6552, which, when multiplied by 10, and adding one more digit, will never exceed 65529 (because 9 is the highest one number can go).

By using this trick, only 1 comparison is needed (is it greater or less than 6552) … at the cost of 4 usable line numbers/memory size setting in the 6553x range.

Wait, you say. 65535-65529 is 6 numbers, so why do you say 4. Well, another shortcut the ROM uses is that it assumes anything at line number 65535 is being entered in direct mode (i.e., no line number; just a command), so 65535 couldn’t be a line number. Similarly, in 1A09, 65534 is reserved to trigger the BASIC interpreter to jump to the initial powerup routine in the ROM (i.e., a reboot) so you couldn’t use that line number either.
1E65
RST 18H
Now we need to check to see if the integer value in DE is greater than 6552, so we call the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as:
  • HL<DE: CARRY SET
  • HL>DE: NO CARRY
  • HL><DE: NZ
  • HL=DE: Z
1E66-1E68
Go to the Level II BASIC error routine and display a SN ERROR message if the value in register pair DE is greater than 6552.
1E69
LD H,D
Load register H with the MSB of the integer total in register D.

This is so we can multiply HL (which should hold the number 6552) by 10.
1E6A
LD L,E
Load register L with the LSB of the integer total in register E.

This is so we can multiply HL (which should hold the number 6552) by 10.
1E6B
ADD HL,DE
Multiply the integer value in register pair HL by two.
1E6C
ADD HL,HL
Add HL to itself, which is the same as multiplying the integer value in register pair HL by two. The integer result in register pair HL is now equal to the integer value in register pair DE times four.
1E6D
ADD HL,DE
Add the integer value in register pair DE to the integer value in register pair HL. The integer result in register pair HL is now equal to the integer value in register pair DE times five.
1E6E
ADD HL,HL
Add HL to itself, which is the same as multiplying the integer value in register pair HL by two. The integer result in register pair HL is now equal to the integer value in register pair DE times ten. Now HL is 65520.
1E6F
POP AF
Put the last ASCII digit (from the stack) into AF.
1E70-1E71
SUB 30H
Convert the ASCII digit in register A to binary.
1E72
LD E,A
Load register E with the binary value of the character in register A.
1E73-1E74
LD D,00H
Load register D with zero so that DE will be 0000 through 0009 (the binary equivalent of the digit).
1E75
ADD HL,DE
Add the binary value of the character in register pair DE to the integer value in register pair HL

As noted above, adding in any digit can only result in HL going to 65529.
1E76
EX DE,HL
Swap DE and HL. This will have the effect of setting DE to be 10(base 10) * DE + A.
1E77
POP HL
Restore the pointer to the next digit (from the stack) into HL.
1E78-1E79
Loop until the ASCII to binary conversion has been completed.

1E7A-1EA0 – LEVEL II BASIC CLEAR ROUTINE. If Z FLAG is set, no number of bytes was provided (i.e., CLEAR instead of CLEAR 20).

1E7A-1E7C
Jump to 1B61H (which will set all 26 variables to single precision) if there isn’t a number of bytes specified to clear for string space.
1E7D-1D7F
GOSUB to 1E46H to evaluate the number of bytes to be reserved for string space and return with the integer result in register pair DE.
1E80
DEC HL
Decrement the current BASIC program pointer in register pair HL.
1E81
RST 10H
Evaluate the next instruction through a RST 10H call. This will bump the value of the current BASIC program pointer until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:
  • The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
  • Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
  • The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
  • The string must be terminated by a byte of zeros.
1E82
RET NZ
Return out of the routine if the character at the location of the current BASIC program pointer isn’t an end of the BASIC statement character.
1E83
PUSH HL
Save the value of the current BASIC program pointer in register pair HL to the stack.
1E84-1E86
LD HL,(40B1H)
Load the top of memory pointer into register pair HL.

NOTE: 40B1H-40B2H holds MEMORY SIZE? pointer.
1E87
LD A,L
Load register A with the LSB of the top of memory pointer in register L.
1E88
SUB E
Subtract the LSB of the number of bytes for string space in register E from the LSB of the top of memory pointer in register A.
1E89
LD E,A
Load register E with the LSB of the start of string space in register A.
1E8A
LD A,H
Load register A with the MSB of the top of memory pointer in register H.
1E8B
SBC A,D
Subtract the MSB of the number of bytes for string space in register D from the MSB of the top of memory pointer in register A.
1E8C
LD D,A
Load register D with the MSB of the start of string space pointer in register A.
1E8D-1E8F
If the CARRY FLAG was triggered there isn’t enough memory for the amount of string space specified, so go show a ?OM ERROR message.
1E90-1E92
LD HL,(40F9H)
Load register pair HL with the end of the BASIC program pointer.
  • Note: 40F9H-40FAH holds the starting address of the simple variable storage area.
1E93-1E95
LD BC,0028H
Load register pair BC with the least amount of space needed for BASIC program variables.
1E96
ADD HL,BC
Add the value in register pair BC to the end of BASIC program pointer in register pair HL.
1E97
RST 18H
Now we need to check to the adjusted end of the BASIC program pointer (in HL) with the start of the string space pointer (in DE), so we call the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as:
  • HL<DE: CARRY SET
  • HL>DE: NO CARRY
  • HL><DE: NZ
  • HL=DE: Z
1E98-1E9A
Display an ?OM ERROR message if the start of string space pointer in register pair DE is less than the adjusted end of the BASIC program pointer in register pair HL.
1E9B
EX DE,HL
Put the new start of the string area address into HL.
1E9C-1E9E
LD (40A0H),HL
Load the start of string space pointer with HL.
  • Note: 40A0H-40A1H holds the start of string space pointer.
1E9F
POP HL
Restore the code string pointer back into HL.
1EA0-1EA2
Jump to 1B61H.

1EA3-1EB0 – LEVEL II BASIC RUN ROUTINE. If Z FLAG is set, no line number was provided (i.e., RUN instead of RUN nnnn).

1EA3-1EA5
JUMP to 1B5DH if there isn’t a line number specified after the RUN token.
1EA6-1EA8
CALL 41C7H
GOSUB to 41C7H which is where the RUN nnnn code would be under DOS.

If we are here, then the command was RUN nnnn and we are in Cassette BASIC.

1EA9-1EAB
GOSUB to 1B61H to initialize the BASIC variables and pointers.
1EAC-1EAE
LD BC,1D1EH
Load register pair BC with the continuation addres in the execution driver.
1EAF-1EB0
Jump to 1EC1H to use the GOTO code to begin execution at the nnnn line.

1EB1-1EC1 – LEVEL II BASIC GOSUB ROUTINE
Can be used to execute the equivalent of a GOSUB statement from an assembly program. It allows a BASIC subroutine to be called from an assembly subroutine. After the BASIC subroutine executes, control returns to the next statement in the assembly program. All registers are used. On entry, the HL must contain an ASCII string with the starting line number of the subroutine.

1EB1-1EB2
LD C,03H
Load register B with the number of bytes needed for the GOSUB push.
1EB3-1EB5
Go make sure that there’s enough memory for the GOSUB push.
1EB6
POP BC
Get the return address from the stack and put it in register pair BC.
1EB7
PUSH HL
Save the value of the current BASIC program pointer in register pair HL to the stack.
1EB8
PUSH HL
Create a hole to be filled in later by once again saving the value of the current BASIC program pointer to the stack.
1EB9-1EBB
LD HL,(40A2H)
Load register pair HL with the value of the current BASIC line number in binary.

NOTE: 40A2H-40A3H holds the current BASIC line number.
1EBC
EX (SP),HL
Put the binary value for the current line number into the hole in the stack AND restore the code string pointer.
1EBD-1EBE
LD A,91H
Load register A with a GOSUB token.
1EBF
PUSH AF
Save the GOSUB marker (in register pair AF) to the stack.
1EC0
INC SP
Bump the value of the stack pointer.
1EC1
PUSH BC
Save the return address in register pair BC (which is to the GOTO code) to the stack.

1EC2-1EDD – LEVEL II BASIC GOTO ROUTINE. Register pair DE should hold the nnnn for the GOTO nnnn command.

1EC2-1EC4
We need to put the line number to branch to into DE so we GOSUB to the ASCII TO INTEGER routine at 1E5A.
NOTE:
  • The routine at 1E5A converts the ASCII string pointed to by HL to an integer deposited into DE. If the routine finds a non-numerica character, the conversion is stopped
1EC5-1EC7
GOSUB to 1F07H to bump the current BASIC program pointer in register pair HL until it points to the end of the current BASIC line.
1EC8
PUSH HL
Save the value of the current BASIC program pointer in register pair HL to the stack.
1EC9-1ECB
LD HL,(40A2H)
Load register pair HL with the binary equivalent of the last line number.

NOTE: 40A2H-40A3H holds the current BASIC line number.
1ECC
RST 18H
Now we need to compare the value of the current BASIC line number (in HL) with the value of the line number to branch to (in DE), so we call the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as:
  • HL<DE: CARRY SET
  • HL>DE: NO CARRY
  • HL><DE: NZ
  • HL=DE: Z
1ECD
POP HL
Get the value of the current BASIC program pointer from the stack and put it in register pair HL.
1ECE
INC HL
Bump the value of the current BASIC program pointer in register pair HL so as to restore the code string address. DE holds the line number specified.
1ECF-1ED1
If the line number to branch to (in register pair DE) is greater than the current BASIC line number then GOSUB to 1B2FH to find where the line number is located at a LATER location.
1ED2-1ED4
If the line number to branch to (in register pair DE) is less than the current BASIC line number, then go find where the line number is located by calling the SEARCH FOR LINE NUMBER routine at 1B2CH which looks for the line number specified in DE. Returns C/Z with the line found in BC, NC/Z with line number is too large and HL/BC having the next available location, or NC/NZ with line number not found, and BC has the first available one after that.
1ED5
LD H,B
Load register H with the MSB of the new BASIC program pointer in register B. BC is still holding the address of the requested line number.
1ED6
LD L,C
Load register L with the LSB of the new BASIC program pointer in register C.
1ED7
DEC HL
Decrement the value of the current BASIC program pointer in register pair HL to get to the start of the line.
1ED8
RET C
If a line number was found, RETURN from this routine to the execution driver (to start execution at the new line number).

Inside the GOTO ROUTINE – If we are here, the line number nnnn was not found, so error out.

1ED9-1EDA
LD E,0EH
Load register E with an ?UL ERROR code.
1EDB-1EDD
Since the line number wasn’t found, display a ?UL ERROR message.

1EDE-1E04 – LEVEL II BASIC RETURN ROUTINE

  • Returns control to the BASIC statement following the last GOSUB call. An assembly program called by a BASIC subroutine may wish to return directly to the orginal caller without returning through the subroutine entry point. This exit can be used for that return. The return address to the stack for the call to the assembly program must be cleared before returning via 1EDFH.
1EDE
RET NZ
Display a ?SN ERROR message if there is anything following the RETURN token.
1EDF-1EE0
LD D,FFH
Load register D with FFH (a dummy address for the search routine).
1EE1-1EE3
GOSUB to 1936H to backspace the stack pointer by four and return with the value at the location of the stack pointer in register A.
1EE4
LD SP,HL
Load the stack pointer with the new value in register pair HL.
1EE5-1EE7HS
LD (40E8H),HL
Save the stack pointer position in register pair HL.

NOTE: 40E8H-40E9H holds Stack pointer pointer.
1EE8-1EE9
CP 91H
Check to see if the value in register A is a GOSUB token.
1EEA-1EEB
LD E,04H
Load register E with a ?RG ERROR code.

1EEC – ?RG ERROR entry point.

1EEC-1EEE
Display a ?RG ERROR message if there isn’t a GOSUB push to the stack.
1EEF
POP HL
Get the binary value of the GOSUB line number from the stack and put it in register pair HL.
1EF0-1EF2
LD (40A2H),HL
Save the GOSUB line number in register pair HL as the current BASIC line number.

NOTE: 40A2H-40A3H holds the current BASIC line number.
1EF3
INC HL
Bump the value of the current BASIC line number in register pair HL.
1EF4
LD A,H
OR L
The way to test HL for 0 is to LOAD A,H and OR L, so A will be 0 only if BOTH H and L were 0. If HL=0 then HL was FFFFH and we have an overflow or a command mode.
1EF6-1EF7
Jump if Level II BASIC is in the command mode.
1EF8H-lEFA
LD A,(40DDH)
If we are here, we may have a one liner! Load register A with the command mode flag.

NOTE: 40DDH holds INPUT flag.
lEFB
OR A
Check for the command mode.
1EFC-1EFE
Jump to 1A18H if Level II BASIC is in the command mode.
1EFF-1F01
LD HL,1D1EH
Load register pair HL with the return address.
1F02
EX (SP),HL
Exchange the value of the current BASIC program pointer to the stack with the return address in register pair HL.
1F03H
3E E1
Z-80 Trick! See the general explanation at 10F8H.
1F04
Prepare to scan to the end of the GOSUB by restoring HL from the STACK.

1F05-1F20 – SCAN ROUTINE

  • This is also the DATA entry point.
1F05H
01
Z-80 Trick! See the general explanation at 10F8H.
1F06H
3A
Z-80 Trick! See the general explanation at 10F8H.
1F07-1F08
LD C,00H
Load register C with zero.
1F09-1F0A
LD B,00H
Load register B with zero.
1F0B
LD A,C
Load register A with the stop scan character in register C.
1F0C
LD C,B
Load register C with the stop scan character in register B.
1F0D
LD B,A
Load register B with the stop scan character in register A.
1F0E
LD A,(HL)
Load register A with the character at the location of the current BASIC program pointer in register pair HL.
1F0F
OR A
Check to see if the character at the location of the current BASIC program pointer in register A is an end of the BASIC line character.
1F10
RET Z
Return if the character at the location of the current BASIC program pointer in register A is an end of the BASIC line character.
1F11
CP B
Check to see if the character at the location of the current BASIC program pointer in register A is the same as the stop scan character in register B.
1F12
RET Z
Return if the character at the location of the current BASIC program pointer in register A is the same as the stop scan character in register B.
1F13
INC HL
Bump the value of the current BASIC program pointer in register pair HL.
1F14-1F15
CP 22H
Check to see if the character at the location of the current BASIC program pointer in register A is a .
1F16-1F17
Loop if the character at the location of the current BASIC program pointer in register A is a quote.
1F18-1F19
SUB 8FH
Check to see if the character at the location of the current BASIC program pointer in register A is a IF token.
1F1A-1F1B
Loop back to 1F0EH if the character at the location of the current BASIC program pointer in register A isn’t an IF token.
1F1C
CP B
Check to see if the character at the location of the current BASIC program pointer in register A is the same as the character in register B.
1F1D
ADC A,D
Add the value in register D to the value in register A.
1F1E
LD D,A
Load register D with the value in register A.
1F1F-1F20
Loop back to 1F0EH until scan is completed.

1F21-1F6B – LEVEL II BASIC LET ROUTINE

1F21-1F23
Call the FIND ADDRESS OF VARIABLE routine at 260DH which searches the Variable List Table for a variable name which matches the name in the string pointed to in HL, and return the address of that variable in DE (and if there is no variable, it creates it, zeroes it, and returns THAT location).
1F24-1F25
RST 08H
D5H
Test if the variable name is followed by a =. Since the character at the location of the current BASIC program pointer in register pair HL must be an EQUAL sign (D5) so call the COMPARE SYMBOL routine which comparess the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call. If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the Aregister and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase).
1F26
EX DE,HL
Exchange the address of the variable in register pair DE with the value of the current BASIC program pointer in register pair HL.
1F27-1F29
LD (40DFH),HL
Save the addres of the variable in register pair HL.

NOTE: 40DFH-40E0H holds Used by DOS.
1F2A
EX DE,HL
Exchange the value of the current BASIC program pointer in register pair DE with the address of the variable in register pair HL.
1F2B
PUSH DE
Save the address of the variable in register pair DE to the stack.
1F2C
RST 20H
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register according to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • Double Precision is NZ/NC/P/E and A is 5.
1F2D
PUSH AF
Save the value in register pair AF to the stack. A will be -1 for an integer, 0 for a string, 1 for single precision, and 5 for double precision.
1F2E-1F30
Go evaluate the expression at the location of the current BASIC program pointer in register pair HL and return with the result in REG 1.
1F31
POP AF
Get the value from the stack and put it in register pair AF.
1F32
EX (SP),HL
Exchange the address of the variable to the stack with the value of the current BASIC program pointer in register pair HL.
1F33-1F34
ADD A,03H
Adjust the value in register A so that it will hold the correct number type flag (i.e., A will be 2 for integer, 3 for string, 4 for single precision, and 8 for double precision).
1F35-1F37
Go to 2819H to convert the result in REG 1 to the same number type for the variable .
1F38-1F3A
Go save the result of the expression.
1F3B
PUSH HL
Save the address of the variable in register pair DE to the stack.
1F3C-1F3D
Jump if the result of the expression wasn’t a string.
1F3E-1F40
LD HL,(4121H)
Load register pair HL with the starting address of the string’s VARPTR in REG 1.
1F41
PUSH HL
Save the VARPTR for the string result in register pair HL to the stack.
1F42
INC HL
Bump the value of the VARPTR for the string result in register pair HL.
1F43
LD E,(HL)
Load register E with the LSB of the address for the string at the location of the VARPTR for the string in register pair HL.
1F44
INC HL
Bump the value of the VARPTR for the string result in register pair HL.
1F45
LD D,(HL)
Load register D with the MSB of the address for the string at the location of the VARPTR for the string in register pair HL.
1F46-1F48
LD HL,(40A4H)
Load register pair HL with the start of the BASIC program.
  • Note: 40A4H-40A5H holds the starting address of BASIC program text also known as the PROGRAM STATEMENT TABLE (PST).
1F49
RST 18H
Now we need to compare the start of the BASIC program area (in HL) with the address of the string result in DE, so we call the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as:
  • HL<DE: CARRY SET
  • HL>DE: NO CARRY
  • HL><DE: NZ
  • HL=DE: Z
1F4A-1F4B
Jump if the address of the string result in register pair DE is less than the start of the BASIC program area in register pair HL.
1F4C-1F4E
LD HL,(40A0H)
Load register pair HL with the start of the string space pointer.
  • Note: 40A0H-40A1H holds the start of string space pointer.
1F4F
RST 18H
Now we need to compare the start of the string space pointer (in HL) with the address of the string result in DE, so we call the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as:
  • HL<DE: CARRY SET
  • HL>DE: NO CARRY
  • HL><DE: NZ
  • HL=DE: Z
1F50
POP DE
Get the VARPTR for the string result from the stack and put it in register pair DE.
1F51-1F52
Jump if the address of the string result in register pair DE was less than the start of the string space pointer in register pair HL.
1F53-1F55
LD HL,(40F9H)
Load register pair HL with the simple variables pointer.
  • Note: 40F9H-40FAH holds the starting address of the simple variable storage area.
1F56
RST 18H
Now we need to compare the address of the VARPTR for the string result in register pair DE with the simple variables pointer in register pair HL, so we call the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as:
  • HL<DE: CARRY SET
  • HL>DE: NO CARRY
  • HL><DE: NZ
  • HL=DE: Z
1F57-1F58
Jump if the address of the VARPTR for the string result in register pair DE is less than the simple variables pointer in register pair HL.
1F59-1F5AH
3E D1
LD A,D1H
Z-80 Trick
1F5A
POP DE
Get the VARPTR for the string result from the stack and put it in register pair DE.
1F5B-1F5D
Go adjust the temporary string work area pointers.
1F5E
EX DE,HL
Exchange the VARPTR for the string in register pair DE with the string’s address in register pair HL.
1F5F-1F61
Go move the string into string space.
1F62-1F64
Go adjust the temporary string work area pointers.
1F65
EX (SP),HL
Exchange the address of the variable in register pair BL with the address of the variable to the stack.
1F66-1F68
Go move the result to its proper location in memory.
1F69
POP DE
Get the address of the variable from the stack and put it in register pair DE.
1F6A
POP HL
Get the value of the current BASIC program pointer from the stack and put it in register pair HL.
1F6B
RET
Return.

1F6C-1FAE – LEVEL II BASIC ERROR ON ROUTINE

1F6C-1F6D
CP 9EH
Check to see if the character at the location of the current BASIC program pointer in register A is an ERROR token (since this is supposed to be ON ERROR.
1F6E-1F6F
Jump down to 1F95H if the character at the location of the current BASIC program pointer in register A isn’t an ERROR token.
1F70
RST 10H
If we are here, we have ON ERROR but we do need to see what’s next. Since we now need bump the value of the current BASIC program pointer until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:
  • The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
  • Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
  • The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
  • The string must be terminated by a byte of zeros.
1F71-1F72
RST 08H
8DH
The next valid character at the location of the current BASIC program pointer in register pair HL must be a GOTO token (=8DH) so call the COMPARE SYMBOL routine which comparess the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call. If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the Aregister and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase).
1F73-1F75
Convert the next constant into binary (with the result in DE). To do this, call the ASCII TO INTEGER routine at 1E5A.
NOTE:
  • The routine at 1E5A converts the ASCII string pointed to by HL to an integer deposited into DE. If the routine finds a non-numerica character, the conversion is stopped
1F76
LD A,D
OR E
To test DE for zero, LOAD A,D and then OR E. A will be 0 only if BOTH D and E were 0
1F78-1F79
Jump to 1F83H if the line number in register pair DE is equal to zero.
1F7A-1F7C
Go find the location of the line number in register pair DE and return with the location of the line number in register pair BC.
1F7DH,1F7E
LD D,B
LD E,C
Put the line number from BC into DE
1F7F
POP HL
Get the value of the current BASIC program pointer from the stack and put it in register pair HL.
1F80-1F82
Display a ?UL ERROR message if the BASIC line doesn’t exist.
1F83
EX DE,HL
Exchange the location of the BASIC line in register pair DE with the value of the current BASIC pro gram pointer in register pair HL.
1F84-1F86
LD (40F0H),HL
Save the location of the BASIC line in register pair HL.

NOTE: 40F0H-40F1H is used by ON ERROR.
1F87
EX DE,HL
Exchange the value of the current BASIC program pointer in register pair DE with the location of the BASIC line in register pair HL.
1F88
RET C
RETURN out of this routine to the execution driver if it was not ON ERROR GOTO 0000.
1F89-1F8B
LD A,(40F2H)
Load register A with the value of the error flag.

NOTE: 40F2H holds the error flag.
1F8C
OR A
Check to see if the error flag is set.
1F8D
RET Z
RETURN out of this routine to the execution driver if the override flag is not set.
1F8E-1F90
LD A,(409AH)
Load register A with the error code.

NOTE: 409AH holds the RESUME flag.
1F91
LD E,A
Load register E with the value of the error code in register A.
1F92-1F94
Go to the Level II error routine and display the error message for the error code in register E.

1F95 – Still in the ON routine, but we know it isn’t ON ERROR. We now need to deal with the possibility that it was an ON n GOTO or ON n GOSUB.

1F95-1F97
First we need to get the n so go evaluate the expression at the location of the current BASIC program pointer and return with the result in register pair DE.
1F98
LD A,(HL)
Load register A with the next character (which should be a token) at the location of the current BASIC program pointer in register pair HL.
1F99
LD B,A
Save that token into register B.
1F9A-1F9B
CP 91H
Check to see if the character at the location of the current BASIC program pointer in register A is a GOSUB token.
1F9C-1F9D
Skip the next 2 opcodes if the character at the location of current BASIC program pointer in register A is a GOSUB token .
1F9E-1F9F
RST 08H
8DH
Now let’s test to see if the next character is the token for a GOTO, call the COMPARE SYMBOL routine which comparess the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call. If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the Aregister and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase).
1FA0
DEC HL
Decrement the value of the current BASIC program pointer in register pair HL to point to the GOTO token.
1FA1
LD C,E
Load register C with the LSB of the expression after the ON token in register E (i.e., the “n” from ON n GOTO).
1FA2
DEC C
Decrement the line number counter in register C.
1FA3
LD A,B
Load register A with the token in register B (which is either a GOSUB or GOTO token).
1FA4-1FA6
Jump to 1D60H if the line number has been found.
1FA7-1FA9
Evaluate the line number at the location of the current BASIC program pointer and return with the result in register pair DE.
1FAA-1FAB
CP 2CH
Check to see if the character at the location of the current BASIC program pointer in register A is a comma. If not, it is the ent of the statement.
1FAC
RET NZ
Return if the character at the location of the current BASIC program pointer in register A isn’t a ,.
1FAD-1FAE
Loop until the line number has been located.

1FAF-1FF3 – LEVEL II BASIC RESUME ROUTINE

1FAF-1FB1
LD DE,40F2H
Load register pair DE with the address of the Level II BASIC error flag.

NOTE: 40F2H holds the error flag.
1FB2
LD A,(DE)
Load register A with the error flag at the location of the memory pointer in register pair DE. It will be FF if there is an error, and a zero otherwise.
1FB3
OR A
Check for an error.
1FB4-1FB6
If there was no error, then display an ?RW ERROR message.
1FB7
INC A
Clear the error flag in register A.
1FB8-1FBA
LD (409AH),A
Save the new error flag in register A.

NOTE: 409AH holds the RESUME flag.
1FBB
LD (DE),A
Save the new error flag in register A at the location of the memory pointer in register pair DE.
1FBC
LD A,(HL)
Load register A with the character at the location of the current BASIC program pointer in register pair HL.
1FBD-1FBE
CP 87H
Check to see if the character at the location of the current BASIC program pointer in register A is a NEXT token.
1FBF-1FC0
Jump down to 1FCDH if the character at the location of the current BASIC program pointer in register A is a NEXT token (as in RESUME NEXT).
1FC1-1FC3
Get the binary equivalent of the line number into DE by calling the ASCII TO INTEGER routine at 1E5A.
NOTE:
  • The routine at 1E5A converts the ASCII string pointed to by HL to an integer deposited into DE. If the routine finds a non-numerica character, the conversion is stopped
1FC4
RET NZ
Return to the execution driver if there wasn’t a line number at the location of the current BASIC program pointer.
1FC5
LD A,D
OR E
To test DE against zero, LOAD A, D and OR E, so A will be 0 only if BOTH D and E are zero
1FC7-1FC9
Jump to the GOTO code at 1EC5H if the line number in register pair DE isn’t equal to zero (i.e., it was RESUME nnnn).
1FCA
INC A
Bump the value in register A so that it will indicate RESUME 0.
1FCB-1FCC
Jump to the RESUME 0 at 1FCFH.
1FCD
RST 10H
Since we now need bump the value of the current BASIC program pointer until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:
  • The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY FLAG if it is alphabetic, or sets it if is alphanumeric.
  • Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
  • The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
  • The string must be terminated by a byte of zeros.
1FCE
RET NZ
Return if this is the end of the BASIC statement.

1FCF – This is the RESUME 0 routine

1FCF-1FD1
LD HL,(40EEH)
Get the value of the current BASIC program pointer and put it in register pair HL.

NOTE: 40EEH-40EFH is used by RESUME.
1FD2
EX DE,HL
Load register pair DE with the value of the current BASIC program pointer in register pair HL.
1FD3-1FD5
LD HL,(40EAH)
Load register pair HL with the current BASIC line number.

NOTE: 40EAH-40EBH holds the line number with error.
1FD6-1FD8
LD (40A2H),HL
Save the value of the current BASIC line number in register pair HL. This is where we will resume execution.

NOTE: 40A2H-40A3H holds the current BASIC line number.
1FD9
EX DE,HL
Load register pair HL with the value of the current BASIC program pointer in register pair DE.
1FDA
RET NZ
Return to the execution driver if this is RESUME 0.
1FDB
LD A,(HL)
Get the character at the location of the current BASIC program pointer in register pair HL and put it in register A.
1FDC
OR A
Check the character at the location of the current BASIC program pointer in register A to see if its an end of the BASIC line character.
1FDD-1FDE
Jump forward to 1FE3H if the character at the location of the current BASIC program pointer in register A isn’t an end of the BASIC line character.
1FDF
INC HL
Bump the value of the current BASIC program pointer in register pair HL to skip over the zero byte terminator.
1FE0
INC HL
Bump the value of the current BASIC program pointer in register pair HL to skip over the LSB of the pointer to the next statement.
1FE1
INC HL
Bump the value of the current BASIC program pointer in register pair HL to skip over the MSB of the pointer to the next statement.
1FE2
INC HL
Bump the value of the current BASIC program pointer in register pair HL to skip over the LSB of the line number in binary for the line following the error.
1FE3
INC HL
Bump the value of the current BASIC program pointer in register pair HL to skip over the MSB of the line number in binary for the line following the error.
1FE4
LD A,D
Load register A with the MSB of the line number with the error in register D.
1FE5
AND E
Combine the LSB of the line number with the error in register E with the MSB of the line number with the error in register A. This begins the test for the end of program marker.
1FE6
INC A
Bump the combined value of the line number with the error in register A. This will finish the test of DE by turning the FFFFH into 0000H.
1FE7-1FE9
Jump to 1F05H if Level II BASIC isn’t in the command mode.
1FEA-1FEC
LD A,(40DDH)
Load register A with the command mode flag.

NOTE: 40DDH holds INPUT flag.
1FED
DEC A
Check to see if the command mode flag in register A is set.
1FEE-1FF0
Jump to 1DBEH if Level II BASIC is in the command mode.
1FF1-1FF3
Exit the routine by jumping to 1F05H.

1FF4H-2007 – LEVEL II BASIC ERROR ROUTINE – Evaluates n for ERROR n

1FF4-1FF6
Go evaluate the expression at the location of the current BASIC program pointer in register pair HL and return with the result in A.
1FF7
RET NZ
Return if this isn’t the end of the BASIC statement.
1FF8
OR A
Set up to check to see if the error number in register A is equal to zero.
1FF9-1FFB
Display an ?FC ERROR message if the error code in register A is equal to zero.
1FFC
DEC A
Subtract one from the error code in register A.
1FFD
ADD A,A
Multiply the error code in register A by two (so now A = 2(A-1)).
1FFE
LD E,A
Load register E with 2(A-1).
1FFF-2000
CP 2DH
Check to see if the error code in register A is less than 2DH. Results:
  • If A=2DH it sets the ZERO FLAG
  • If A<2DH then the CARRY FLAG will be set
  • if A>=2DH then the NO CARRY FLAG will be set.
2001-2002
Jump forward 1 instruction (i.e., skip the line that sets up for an error of ?UE ERROR) if the error code (in register A) is in range (i.e., less than 45).