Model I TRSDOS v2.3 BASIC/CMD Explained

This is a disassembly of TRSDOS v2.3’s BASIC/CMD File.

5200H
JUMP to 5C06H

5203H – Message Storage Area – Error Messages.

5203H
NOP
No Operation (Do Nothing)
5204H
DEFM ‘NEXT without FOR’
5214H
NOP
No Operation (Do Nothing)
5215H
DEFM ‘Syntax error’
5221H
NOP
No Operation (Do Nothing)
5222H
DEFM ‘RETURN without GOSUB’
5236H
NOP
No Operation (Do Nothing)
5237H
DEFM ‘Out of DATA’
5242H
NOP
No Operation (Do Nothing)
5243H
DEFM ‘Illegal function call’
5258H
NOP
No Operation (Do Nothing)
5259H
DEFM ‘Overflow’
5261H
NOP .
No Operation (Do Nothing)
5262H
DEFM ‘Out of memory’
526FH
NOP .
No Operation (Do Nothing)
5270H
DEFM ‘Undefined line number’
5285H
NOP .
No Operation (Do Nothing)
5286H
DEFM ‘Subscript out of range’
529CH
NOP .
No Operation (Do Nothing)
529DH
DEFM ‘Redimensioned array’
52B0H
NOP .
No Operation (Do Nothing)
52B1H
DEFM ‘Division by zero’
52C1H
NOP .
No Operation (Do Nothing)
52C2H
DEFM ‘Illegal direct’
52D0H
NOP .
No Operation (Do Nothing)
52D1H
DEFM ‘Type mismatch’
52DEH
NOP .
No Operation (Do Nothing)
52DFH
DEFM ‘Out of string space’
52F2H
NOP
No Operation (Do Nothing)
52F3H
DEFM ‘String too long’
5302H
NOP .
No Operation (Do Nothing)
5303H
DEFM ‘String formula too complex’
531DH
NOP .
No Operation (Do Nothing)
531EH
DEFM ‘Can’t continue’
532CH
NOP .
No Operation (Do Nothing)
532DH
DEFM ‘No RESUME’
5336H
NOP
No Operation (Do Nothing)
5337H
DEFM ‘RESUME without error’
534BH
NOP
No Operation (Do Nothing)
534CH
DEFM ‘Unprintable error’
535DH
NOP
No Operation (Do Nothing)
535EH
DEFM ‘Missing operand’
536DH
NOP
No Operation (Do Nothing)
536EH
DEFM ‘BAD FILE DATA’
537BH
NOP
No Operation (Do Nothing)
537CH
DEFM ‘DISK BASIC FEATURE’
538EH
NOP
No Operation (Do Nothing)
538FH
DEFM ‘Undefined user function’
53A6H
NOP
No Operation (Do Nothing)
53A7H
DEFM ‘FIELD overflow’
Error 51
53B5H
NOP
No Operation (Do Nothing)
53B6H
DEFM ‘Internal error’
Error 52
53C4H
NOP
No Operation (Do Nothing)
53C5H
DEFM ‘Bad file number’
Error 53
53D4H
NOP
No Operation (Do Nothing)
53D5H
DEFM ‘File not found’
Error 54
53E3H
NOP
No Operation (Do Nothing)
53E4H
DEFM ‘Bad file mode’
Error 55
53F1H
NOP
No Operation (Do Nothing)
53F2H
DEFM ‘File already open’
Error 56
5403H
NOP
No Operation (Do Nothing)
5404H
DEFB ‘?’
5405H
NOP
No Operation (Do Nothing)
5406H
DEFM ‘Disk I/O error’
5414H
NOP
No Operation (Do Nothing)
5415H
DEFM ‘File already exists’
5428H
NOP
No Operation (Do Nothing)
5429H
DEFB ‘?’
542AH
NOP
No Operation (Do Nothing)
542BH
DEFB ‘?’
542CH
NOP
No Operation (Do Nothing)
542DH
DEFM ‘Disk full’
Error 62
5436H
NOP
No Operation (Do Nothing)
5437H
DEFM ‘Input past end’
Error 63
5445H
NOP
No Operation (Do Nothing)
5446H
DEFM ‘Bad record number’
Error 64
5457H
NOP
No Operation (Do Nothing)
5458H
DEFM ‘Bad filename’
Error 65
5465H
NOP
No Operation (Do Nothing)
5466H
DEFM ‘Mode-mismatch’
5473H
NOP
No Operation (Do Nothing)
5474H
DEFM ‘Direct statement in file’
Error 67
548CH
NOP
No Operation (Do Nothing)
548DH
DEFM ‘Too many files’
Error 68
549BH
NOP
No Operation (Do Nothing)
549CH
DEFM ‘Disk write protected’
Error 69
54B0H
NOP
No Operation (Do Nothing)
54B1H
DEFM ‘File acess DENIED’
Error 70
54C2H
NOP
No Operation (Do Nothing)
54C3H
JUMP to 5F18H to process the CVI Command

54C6H – Process the FN Command.

54C6H
JUMP to 558EH

54C9H – CVS Command Jump Vector.

54C9H
JUMP to 5F1BH

54CCH – DEF Command Jump Vector.

54CCH
JUMP to 5655H

54CFH – CVD Command Jump Vector.

54CFH
JUMP to 5F1EH

54D2H – EOF Command Jump Vector.

54D2H
JUMP to 62B8H

54D5H – LOC Command Jump Vector.

54D5H
JUMP to 62FEH

54D8H – LOF Command Jump Vector.

54D8H
JUMP to 630FH

54DBH – MKI$ Command Jump Vector.

54DBH
JUMP to 5EFFH

54DEH – MKS$ Command Jump Vector.

54DEH
JUMP to 5F02H

54E1H – MKD$ Command Jump Vector.

54E1H
JUMP to 5F05H

54E4H – CMD Command Jump Vector.

54E4H
JUMP to 56CBH

54E7H – TIME$ Command Jump Vector.

54E7H
JUMP to 5745H

54EAH – OPEN Command Jump Vector.

54EAH
JUMP to 6434H

54EDH – FIELD Command Jump Vector.

54EDH
JUMP to 61AFH

54F0H – GET Command Jump Vector.

54F0H
JUMP to 6355H

54F3H – PUT Command Jump Vector.

54F3H
JUMP to 6354H

54F6H – CLOSE Command Jump Vector.

54F6H
JUMP to 6173H

54F9H – LOAD Command Jump Vector.

54F9H
JUMP to 606EH

54FCH – MERGE Command Jump Vector.

54FCH
JUMP to 6109H

54FFH – NAME Command Jump Vector.

54FFH
JUMP to 6544H

5502H – KILL Command Jump Vector.

5502H
JUMP to 6521H

5505H – & Command Jump Vector.

5505H
JUMP to 5913H

5508H – LSET Command Jump Vector.

5508H
JUMP to 620BH

550BH – RSET Command Jump Vector.

550BH
JUMP to 620AH

550EH – INSTR Command Jump Vector.

550EH
JUMP to 588BH

5511H – SAVE Command Jump Vector.

5511H
JUMP to 6148H

5514H – LINE Command Jump Vector.

5514H
JUMP to 5786H

5517H – Process BASIC errors routine.

5517H
JUMP to 57E6H

551AH – JUMP to a routine to determine what (n) was in a USR(n) call, and fetch the appropriate jump points and address of the variable in RAM

551AH
JUMP to 5679H

551DH – Vector to the routine to zero PTRFIL and close the open disk file

551DH
JUMP to 60EFH

5520H – Vector to the routine which sees if an input request is to be from a disk file

5520H
JUMP to 59EAH

5523H – Vector to the routine which dispatches a direct statement

5523H
JUMP to 6133H

5526H – Vector to the routine which prepares for insertion of a line

5526H
JUMP to 5BDFH

5529H – Routine when about to insert a line but after RUNC has executed

5529H
JUMP to 5BEEH

552CH – Vector to the routine to close ALL files

552CH
JUMP to 61A5H to CLOSE ALL FILES

552FH – Zeroes out PTRFIL and restore HL from the STACK

552FH
JUMP to 57B0H

5532H – Vector to the routine which outputs a character to a disk file

5532H
JUMP to 5A21H

5535H – Vector to the routine which processes LINE INPUT from disk

5535H
JUMP to 5A30H

5538H – – “LRUN”

5538H
JUMP to 6066H

553BH – Vector to see if a command was CASSETTE I/O or DISK I/O – “FILGTO”

553BH
JUMP to 56BFH

553EH – – “???????????”

553EH
JUMP to 5BFCH

5541H – – “???????????”

5541H
JUMP to 5BFBH

5544H – Vector to the routine which processes DISK I/O

5544H
JUMP to 5BC7H

5547H – Vector to the routine which checks to see if INPUT means “INPUT#n” command

5547H
JUMP to 57B8H

554AH – Vector to the routine which proceses a MID$()=”xxxx” command

554AH
JUMP to 5969H

554DH – Vector to the routine which sets to read a sequential item

554DH
JUMP to 5F35H

5550H – ?????? Something to do with the LIST command

5550H
JUMP to 57D0H

5553H – Vector to the routine which processes a Normal System Code to Return

5553H
JUMP to 5BB3H

5556H – Handler for user defined functions (DEF FN) – “PUSVAL”

Jumped to from 55BFH. On entry HL will point to the memory address for the variable in question
5556H
 ↳ “PUSVAL”
LD A,(40AFH)
LD A,(VALTYP)
Find out what type of value we are saving by fetching the VALTYP. It will contain a 2 for integer, 3 for string, 4 for single-precision, and 8 for double precision
The next few instructions set up the condition codes without affecting carry. 0=String and the PARITY FLAG will be set.
5559H
DEC A
DECrement the value stored in Register A by 1
555AH
DEC A
DECrement the value stored in Register A by 1
555BH
DEC A
DECrement the value stored in Register A by 1
555CH
OR A
Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
555DH
SCF
Turn the CARRY FLAG on
555EH
If the VALTYP was 3 (meaning STRING), then 3-3=0 and so the Z FLAG (Zero) will have been set, along with the CARRY flag from the SCF. JUMP to 55C2H to process a function for a string.
5561H
LD C,(HL)
Fetch the LSB of the variable we are dealing with and store it into Register C
5562H
INC HL
INCrement the value stored in Register Pair HL by 1 to now point to the MSB of the variable we are dealing with
5563H
LD B,(HL)
Fetch the MSB of the variable we are dealing with and store it into Register C
5564H
PUSH BC
Save the memory location for the variable (held in Register Pair BC) to the stack
5565H
If the S FLAG has been SET, then the data was an integer, so we are done in that case. JUMP to 557FH to skip over the REDO of HL, C, and B
If the S FLAG was not set, we are going to move to the next variable space.
5568H
INC HL
INCrement the value stored in Register Pair HL by 1
5569H
LD C,(HL)
Fetch the LSB of the memory address of the variable and store it into Register C
556AH
INC HL
INCrement the value stored in Register Pair HL by 1
556BH
LD B,(HL)
Fetch the MSB of the memory address of the variable and store it into Register B
556CH
PUSH BC
Save the memory address of the variable (held in Register Pair BC) to the stack. This should be FAC-1 and FAC
556DH
If the PO FLAG is set, then we had a single-precision number, so JUMP to 557FH to skip over the other REDO of HL, C, and B
If the PO FLAG was not set, we are going to move to the next variable space.
5570H
INC HL
INCrement the value stored in Register Pair HL by 1
5571H
If the C FLAG (Carry) has been set then the variable type we are dealing with has the value bytes as consecutive so leave HL as is by JUMPing to 5576H
If we’re here, then the variable is double precision, so we need to adjust HL to point to the DFACLO for that content
5573H
LD HL,411DH
LD HL,DFACLO
Let Register Pair HL equal 411DH which is the storage location for the Software Accumulator (SA)
At this point, (HL) is pointing to the variable, so we are going to push the 4 lowest order bytes of that variable to the stack.
5576H
 ↳ “PUSDVR”
LD C,(HL)
Fetch the LSB of the byte of the variable and store it into Register C
5577H
INC HL
INCrement the value stored in Register Pair HL by 1
5578H
LD B,(HL)
Fetch the MSB of the byte of the variable and store it into Register B
5579H
INC HL
INCrement the value stored in Register Pair HL by 1 to now point to the second set of bytes of the variable
557AH
PUSH BC
Save address pointed to first set of bytes of the variable to the stack
557BH
LD C,(HL)
Fetch the LSB of the second set of bytes of the variable and store it into Register C
557CH
INC HL
INCrement the value stored in Register Pair HL by 1. Note that this will leave HL pointing to the last value byte. This is required for all user-defined functions.
557DH
LD B,(HL)
Fetch the MSB of the second set of bytes of the variable and store it into Register B
557EH
PUSH BC
Save address pointed to by the second set of bytes of the variable to the stack
557FH
 ↳ “VPUSHD”
If the C FLAG (Carry) has been set, JUMP to 55CCH for user-defined functions. Otherwise, we are going to pass through for pre-existing functions
Otherwise pass through to the following which will get a pointer to an existing function name.
5582H
 ↳ “GETFNM”
RST 08H BEH
SYNCHK “FN”
Call RST 08H, which is the COMPARE SYMBOL routine which compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., BEH, which is the token for FN). 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
5584H
LD A,80H
We cannot permit an array to be here so let’s flag that prohibition by setting Register A to 80H …
5586H
LD (40DCH),A
LD (SUBFLG),A
… and storing that into SUBFLG. This will make sure that the “()” are not mistakenly taken to be an array.
5589H
OR (HL)
Merge in the contents of the RAM location pointed to by HL into Register A (currently 1000 0000) to turn the high bit on, thus indicating that this is a function.
558AH
LD B,A
Copy the first character of the function name into Register B
558BH
Now that we have set up the variables, JUMP to 2612H to really find the pointer. This is a shared routine with the routine which returns the address of a variable in memory or creates it if it is not found. In order to use this routine, HL must point to the variable name (ASCII). Then, after execution, HL will point to the character following the variable name and the location of the variable will be returned in the DE register pair. For integer, single or doubleprecision (VALTYPE=2, 4 or 8) the address returned in DE will be the same as for the VARPTR command under BASIC. (see Level II BASIC manual on VARPTR) For strings (VALTYPE=3) however the address returned in DE will point to the first of three bytes containing the string length and string address. NOTE: At this entry point, 40AEH needs to already be properly populated with the LOCATE or CREATE value flag and register B must already be populated with the first character of the variable name

558EH – Part of the FN Command – “FNDOER”

On Entry DE should be pointing to the address of the variable provided and HL to the next character in the BASIC instruction being processed
558EH
 ↳ “FNDOER”
GOSUB to 5582H to get a pointer to the function and allocate some space
5591H
LD A,(40AFH)
LD A,(VALTYP)
Fetch the VALTYP to find out what kind of function this is. It will contain a 2 for integer, 3 for string, 4 for single-precision, and 8 for double precision
5594H
OR A
Make sure the CARRY FLAG is off, so that when the values are POPped from the STACK and restored, we will know when to stop (which is when a VALTYP is popped off the stack with CARRY set to OFF)
5595H
PUSH AF
Save AF to preserve all this
5596H
LD (40F3H),HL
LD (TEMP2),HL
Store the text pointer (pointing PAST the function name) to TEMP2
5599H
EX DE,HL
EXchange DE and HL so that HL now points to the value of the function
559AH
LD A,(HL)
Fetch the LSB of the value of the function into Register A
559BH
INC HL
INCrement the value stored in Register Pair HL by 1 to point to the MSB of the value of the function
559CH
LD H,(HL)
Fetch the MSB of the value of the function into Register A
559DH
LD L,A
Copy the contents of Register A into Register L so that HL now points to the text pointer at the formal parameter list in the definition
559EH
OR H
OR Register H against Register A as a shortcut to see if HL is ZERO. If the Z FLAG is set, then the function was never defined
559FH
If the function wasn’t defined, then JUMP to 56BAH to error out with an “UNDEFINED FUNCTION” error
55A2H
LD A,(HL)
Now we need to check to see if there are any parameteres. Fetch the value held in the memory location pointed to by Register Pair HL and store it into Register A
55A3H
CP 28H
CP “(“
A parameter list MUST start with a “(” so let’s see if that’s the current character. NZ will be set it if isn’t. Note that we did a CP instead of a RST because the RST call will error out if the symbol isn’t there, and this is optional.
55A5H
If the character isn’t a “(” then we do not have a parameter list, so skip the parameter list code via a JUMP to 55F5H
55A8H
RST 10H
GETCHR
If the character was ( then let’s check the NEXT character via a call the EXAMINE NEXT SYMBOL routine at RST 10H. RST 10H bumps HL by 1 and then looks for the first non-space, non-chr$(9), and non-chr$(10) character pointed to by HL. If that character is a number (0-9), the C FLAG is set; otherwise the NC FLAG is set. Z will be set if the character is a 0 or a :. RST 10H exits with HL still pointing to the character it checked, the character it checked in Register A, and BC and DE are unaffected
55A9H
LD (40D8H),HL
LD (TEMP3),HL
Store the text pointer to the start of the parameter list into TEMP 3.
55ACH
JUMP to 55B0H to keep processing

55AEH – Continue processing the FN Command – “MORPUS”

55AEH
 ↳ “MORPUS”
RST 08H 2C
SYNCHK “,”
If we choose THIS jump point, then a “,” is mandatory, so do a SYNCHK to make sure the next character is a , via a call to RST 08H, which is the COMPARE SYMBOL routine. That routine compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., 2CH which is a ,). If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the A Register and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase
55B0H
 ↳ “FRSPRM”
LD C,04H
Let Register C equal 04H to permit double precision when CALLing to 1963H
55B2H
GOSUB to 1963H to make sure there are enough bytes (i.e., 4 bytes) of free RAM space between HL and FFC6. HL is preserved, so it will still point to the “x” character in “DEF FN(x”, which is the variable
55B5H
LD A,80H
We cannot permit an array to be here so let’s flag that prohibition by setting Register A to 80H …
55B7H
LD (40DCH),A
LD (SUBFLG),A
… and storing that into SUBFLG. This will prevent recursion when we do the PTRGET call.
55BAH
GOSUB to 260DH to get a pointer to the parameter into DE (and if there is no variable, it creates it, zeroes it, and returns THAT location)
55BDH
EX DE,HL
EXchange DE and HL so that the text pointer is now in DE and HL will point to the value to be saved on the stack
55BEH
SCF
Set the CARRY FLAG on to flag this as a USERDEFINED function when JUMPing into FRMEVL
55BFH
JUMP to 5556H to handle user defined functions. HL point to the memory address for the variable in question

55C2H – Continue processing the FN Command, for a STRING – “PUSSTR”

55C2H
 ↳ “PUSSTR”
FRMEVL does not allow strings to be processed through the PUSAVL routine, as that would imply that an arithmetic operator is being used on a string. So if NC FLAG is set, error out with a a TM ERROR
55C5H
PUSH DE
Save the text pointer to the STACK. Right now DE should be pointing to the character after the x in the BASIC command “DEF FN(x” being processed)
55C6H
EX DE,HL
EXchange DE and HL so that the pointer to the variable value is now in DE (as required by PUTTMP) and HL is the text pointer.
55C7H
We next need to set up a temporary memory area with the valeu of the string pointed to by (DE) so we GOSUB to 2888H to process the STRING present in the “DEF FN (x$)” command. The CALL issues a PUSH DE, loads HL with the next available location in the temporary string work area and claims it for the string being created, sets the VALTYP to 3 (string), allocates space in the temporary string area, make sure that there was not an error, POPs to HL, and loads register A with the character at the location of the current BASIC program pointer in HL. If there was an issue, a ?ST ERROR generates
55CAH
POP DE
Restore the text pointer into Register Paie DE
55CBH
XOR A
Make sure the Z FLAG is set because when that is the case, a string is always popped off as the end marker never has the Z FLAG set
55CCH
 ↳ “FINPUS”
PUSH HL
Save the pointer to the end of the value
55CDH
PUSH AF
Save the type of value it was and the associated flags
55CEH
EX DE,HL
EXchange DE and HL so that the text pointer is now in HL
55CFH
LD A,(HL)
Now we want to test to see if we are done with parameters. First, fetch next character from the text pointer and store it into Register A
55D0H
CP 29H
CP “)”
Compare the value held in Register A against a mandatory )). If Register A is anything other than a ), the NZ FLAG is set
55D2H
If the NZ FLAG (Not Zero) has been set, then there must be more paramters. Since we are not done, we LOOP BACK to the instruction that forces a check for a “,” as that would be the mandatory next character, so JUMP back to 55AEH to see if maybe that next character was a ,
55D4H
LD HL,(40F3H)
LD HL,(TEMP2)
Fetch the text pointer which is pointing just past the function name at the argument list and ut it into Register Pair HL
55D7H
RST 08H 28H
SYNCHK “(“
Let us now check to see if we are at the start of an argument list via a Call RST 08H, which is the COMPARE SYMBOL routine which compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., a (). 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
55D9H
PUSH HL
Save the callers text pointer to the stack.
55DAH
LD HL,(40D8H)
LD HL,(TEMP3)
Fetch pointer to the beginning of the parameter list into Register Pair HL
55DDH
 ↳ “ASGMOR”
Top of a loop to read in parameters. GOSUB to 260DH to search the list matches, returning the address of that variable in DE (and if there is no variable, it creates it, zeroes it, and returns THAT location)
55E0H
EX (SP),HL
EXchange (SP) and HL so that the text pointer into the parameter list is put onto the stack and the test pointer to the argument list is put into Register Pair HL
55E1H
GOSUB to 1F2BH to put a number into a variable
55E4H
LD A,(HL)
Now we want to see what comes after the argument formula. Fetch the value held in the memory location pointed to by Register Pair HL (i.e., the character after the argument formula) and store it into Register A
55E5H
CP 29H
CP “)”
Did we get a “)”, meaning that we are done processing arguments? If yes, set the Z FLAG
55E7H
If the next character was, in fact, a ), then the Z FLAG (Zero) will have been set, JUMP to the next routine at 55F0H to make sure the argument list also ended
55E9H
RST 08H 2C
SYNCHK “,”
If we didn’t get a “)” then we have more, and the next character BETTER be a ,, so check that via a call to RST 08H, which is the COMPARE SYMBOL routine. That routine compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., 2CH which is a ,). If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the A Register and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase
55EBH
EX (SP),HL
EXchange (SP) and HL so that the argument list text pointer is put into the stack, and the text pointer into the definition’s parameter list is now put into HL
55ECH
RST 08H 2C
SYNCHK “,”
We are now processing the paramter list, and need to make sure the next character THERE is a , via a call to RST 08H, which is the COMPARE SYMBOL routine. That routine compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., 2CH which is a ,). If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the A Register and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase
55EEH
LOOP BACK to 55DDH to keep binding the argument list and parameter list

55F0H – Continue processing the FN Command – “FINASG”

JUMPED here from 55E7H if a ) was found to be the next character in the command line being processed
55F0H
 ↳ “FINASG”
RST 10H
GETCHR
Skip to the next non-blank character via a call the EXAMINE NEXT SYMBOL routine at RST 10H. RST 10H bumps HL by 1 and then looks for the first non-space, non-chr$(9), and non-chr$(10) character pointed to by HL. If that character is a number (0-9), the C FLAG is set; otherwise the NC FLAG is set. Z will be set if the character is a 0 or a :. RST 10H exits with HL still pointing to the character it checked, the character it checked in Register A, and BC and DE are unaffected
55F1H
EX (SP),HL
EXchange (SP) and HL so that the argument’s text pointer is now on the stock and the parameter list text pointer is now in HL
55F2H
RST 08H 29
SYNCHK “)”
Test to see if we are at the end of the parameter list via a Call RST 08H against a ) character, which is the COMPARE SYMBOL routine which compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., )). If there is a match, control is returned to address of the RST 08 instruction + 2 with the next symbol in the A Register and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase
55F4H
LD A,D5H
Z-80 Trick. If passing through, this will simply set Register A to D5H and the next instruction, PUSH DE, will not be executed
55F5H
 ↳ “FINVLS”
PUSH DE
We are jumed here when there were no arguments or parameters. Save the text pointer of the caller (held in DE) to the stack.
55F6H
RST 08H D5
SYNCHK “=”
Make sure we have an EQUAL TOKEN (and then skip over it) via a call to RST 08H with a parameter of D5 (which is the token for “=”)
55F8H
GOSUB to 2337H to evaluate the definition forumla pointed to by HL and return with the result in ACCumulator. Evaluate BASIC string expression (may include constants, BASIC variables, BASIC functions, operators, etc.) and place result in ACCumulator. On entry, HL must point to first character of the string to be evaluated. On exit, HL will point to the string delimiter, which must be an acceptable BASIC expression terminator (such as a zero byte, a colon, a right parenthesis, etc.)
55FBH
DEC HL
Back up the pointer by 1 so it points just before the BASIC expression terminator. We do this to make sure the statement ended correctly instead of just with a random general terminator.
55FCH
RST 10H
GETCHR
Vet the terminator via a GOSUB to the EXAMINE NEXT SYMBOL routine at RST 10H. RST 10H bumps HL by 1 and then looks for the first non-space, non-chr$(9), and non-chr$(10) character pointed to by HL. If that character is a number (0-9), the C FLAG is set; otherwise the NC FLAG is set. Z will be set if the character is a 0 or a :. RST 10H exits with HL still pointing to the character it checked, the character it checked in Register A, and BC and DE are unaffected
55FDH
If the NZ FLAG as set, the throw a ?SN ERROR Via a JUMP to 1997H
At this point the DEF FN has been vetted and the syntax confirmed. We now need the original values of the parameters to be POPped off and restored
5600H
RST 20H
GETYPE
Where we store the result of the function depends entirely on what type of function it was. If it was a string function, for example, the result has to be stored in DSCTMP so that the parameter values for string can be fetched from the temporary storage locations. With this, we must check the data type with a call to RST 20H.
NOTE: The RST 20H routine determines the type of the current value in ACCumulator and returns a combination of STATUS flags and unique numeric values in the A Register according to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • and Double Precision is NZ/NC/P/E and A is 5.
5601H
If the character is a STRING, JUMP to 5632H to store the last temporary value into DSCTMP and check to see if the next available location in the string area is the same address as is stored in the ACCUMULATOR. If yes, JUMP to 5641H, otherwise 5603H
The function was not a string, so we continue here
5603H
 ↳ “MORRV2”
POP DE
Restore the text pointer from the caller into Register Pair DE
5604H
 ↳ “MORRVL”
POP AF
Restore the VALTYP and associated flags into Register Pair AF
5605H
If the Z FLAG (Zero) has been set, then we have a string, and need to restore STRING variables, which we do via a JUMP to 5646H
5607H
If the NC FLAG (No Carry) has been set, then we are already in a good place because we just popped off the the value type for the function itself so JUMP to 5625H to determine the variable type being created, put DE into HL, put 40D3H into DE, GOSUB to 2888H if the variable is a string, and the continue to 281AH
5609H
POP HL
Put the pointer to the end of the value into Register Pair HL
560AH
POP BC
Put the first part of the value into Register Pair BC
560BH
LD (HL),B
Now put the value back into RAM. First, store the value held in Register B into the memory location pointed to by Register Pair HL
560CH
DEC HL
DECrement the value stored in Register Pair HL by 1
560DH
LD (HL),C
Store the value held in Register C into the memory location pointed to by Register Pair HL
560EH
If the S FLAG has been SET, then the integers are done, so JUMP to 5604H
5611H
DEC HL
Integers are done, so now let’s deal with single precision! DECrement the value stored in Register Pair HL by 1
5612H
POP BC
Put the value held at the STACK into Register Pair BC
5613H
LD (HL),B
Store the value held in Register B into the memory location pointed to by Register Pair HL
5614H
DEC HL
DECrement the value stored in Register Pair HL by 1
5615H
LD (HL),C
Store the value held in Register C into the memory location pointed to by Register Pair HL
5616H
If the PO FLAG is set, then we are done with single precisions so JUMP to 5604H
5619H
DEC HL
If we’re here, then the only thing left is double precisions, so more of the same … DECrement the value stored in Register Pair HL by 1
561AH
POP BC
Put the value held at the STACK into Register Pair BC
561BH
LD (HL),B
Store the value held in Register B into the memory location pointed to by Register Pair HL
561CH
DEC HL
DECrement the value stored in Register Pair HL by 1
561DH
LD (HL),C
Store the value held in Register C into the memory location pointed to by Register Pair HL
561EH
DEC HL
DECrement the value stored in Register Pair HL by 1
561FH
POP BC
Put the value held at the STACK into Register Pair BC
5620H
LD (HL),B
Store the value held in Register B into the memory location pointed to by Register Pair HL
5621H
DEC HL
DECrement the value stored in Register Pair HL by 1
5622H
LD (HL),C
Store the value held in Register C into the memory location pointed to by Register Pair HL
5623H
JUMP to 5604H

5625H – Continue processing the FN Command; more string stuff – “DONRVL”

5625H
 ↳ “DONRVL”
PUSH DE
Preserve the text pointer to the stack because the routine at 562FH, which is a JUMP to 281AH, will POP the stack into Register Pair HL
5626H
PUSH AF
Save the function type to the stack to preseve it from the RST 20H instruction
5627H
RST 20H
GETYPE
Once again, we need to treat strings differently so we need to check the data type with a call to RST 20H.
NOTE: The RST 20H routine determines the type of the current value in ACCumulator and returns a combination of STATUS flags and unique numeric values in the A Register according to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • and Double Precision is NZ/NC/P/E and A is 5.
5628H
LD DE,40D3H
LD DE,DSCTMP

LD DE,DSCTMP
In preparation for the PUTTMP routine, DE needs to point to where to restore from. Set the “restore from” of 40D3H, which is the VARPTR storage area for string currently being created by BASIC. (first byte contains length, second and third bytes contain address of string).
NOTE: 40D3H is the storage location for the [TAKEN HACKER HANDBOOK] Contains length of current String
562BH
If the variable being created is a string, then the RST 20H call would have set the Z FLAG (Zero), so GOSUB to 2888H to restore the string
562EH
POP AF
Fetch the function back and flags back into Register Pair AF
562FH
JUMP to 281AH to convert the result of arithmetic routines to the proper destination type. At this jump point, whatever was at the stack is POPed into HL

5632H – Continue processing the FN Command; more string stuff – “STRREL”

Store the last temporary value into DSCTMP and check to see if the next available location in the string area is the same address as is stored in the ACCUMULATOR. If yes, JUMP to 5641H, otherwise 5603H
5632H
 ↳ “STRREL”
LD HL,(40B3H)
LD HL,(TEMPPT)
We aren’t sure where the runction result is so let’s first check TEMPPT. Fetch the value stored there into Register Pair HL
5635H
EX DE,HL
EXchange the value stored in Register Pair HL (i.e., the address of the next available location in the string area, now to be held in DE) with the value stored in Register Pair DE (which is irrelevant because HL will be overwritten in the next instruction)
5636H
LD HL,(4121H)
LD HL,(FACLO)
Fetch the value held in memory location 4121H (which is the LSB of the ACCumulator) and store it into Register Pair HL
5639H
RST 18H
COMPAR
Temporaries are below and variables are above, so running a COMPAR will help us determine where the result was actually kept. Use RST 18 to see if the variable address in HL (the ACCumulator) is the same as in DE (the next available location in String area), 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: CARRY SET=HL<DE; NO CARRY=HL>DE; NZ=Unequal; Z=Equal)
563AH
If DE and HL are the same, then the C FLAG (Carry) will have been set, so JUMP to 5641H to just copy the descriptor into DSCTEMP from the temporary variable and the free up the temporary variable
563CH
If we are here then we need to make a copy of the variable which holds the result so GOSUB to 2843H which is in the middle of the Model I ROM Routine for STR$(). On entry, HL should be pointing to the VARPTR of a string
563FH
At this point, the result is stored in DSCTMP. JUMP to 5603H to POP DE and AF, JUMP if Z or NC are set

5641H – Continue processing the FN Command; more string stuff – “STRRL2”

If the the next available location in the string area is the same address as the temporary variable we are using we wind up here
5641H
 ↳ “STRRL2”
POP DE
Restore the text pointer from the caller routine back into Register Pair DE
5642H
LD HL,40D3H
LD HL,DSCTMP
Set up HL to point to DSCTMP so we will ultimately store the result of the function there
5645H
PUSH HL
Save DSCTMP to the stack
5646H
 ↳ “POPSTR”
GOSUB to 29F5H free up the temporary string work area
5649H
LD A,(HL)
Fetch the length of the string location pointed to by HL
564AH
LD (40B3H),HL
LD (TEMPPT),HL
Update the pointer for the temporary
564DH
POP HL
Getch the place to restore the value to into Register Pair HL
564EH
LD (HL),A
Store the length of the string being created (held in Register A) into the memory location pointed to by Register Pair HL
564FH
INC HL
INCrement the value stored in Register Pair HL by 1
5650H
LD (HL),C
Store the LSB of the string being created (held in Register C) into the memory location pointed to by Register Pair HL
5651H
INC HL
INCrement the value stored in Register Pair HL by 1
5652H
LD (HL),B
Store the MSB of the string being created (held in Register B) into the memory location pointed to by Register Pair HL
5653H
JUMP to 5604H to restore more values

5655H – Process the DEF Command – “DEF”

5655H
 ↳ “DEF”
CP C1H
CP USRTK
Check to see if we are defining a call address of a USR() routine by comparing the value held in Register A against C1H (Token: USR). If Register A equals C1H, the Z FLAG is set
5657H
If the Z FLAG (Zero) has been set, then we have a DEF USR, so JUMP to 56ABH to set that call address
5659H
Get a pointer to the function name via a GOSUB to 5582H which will check for the FN and allocate some space. After execution, HL will point to the character following the variable name and the location of the variable will be returned in the DE register pair
565CH
GOSUB to 2828H to make sure we are not doing this from the COMMAND LINE, and, if so, throw an ILLEGAL DIRECT error
565FH
EX DE,HL
EXchange DE and HL so that DE holds the text pointer after the function name and HL will hold the porter to the place to store the value of the function variable
5660H
LD (HL),E
Now we are going to save the text pointer as that value! Store the LSB of the variables address (held in Register E) into the memory location pointed to by Register Pair HL
5661H
INC HL
INCrement the value stored in Register Pair HL by 1
5662H
LD (HL),D
Store the MSB of the variables address (held in Register D) into the memory location pointed to by Register Pair HL
5663H
EX DE,HL
Swap HL and DE back; HL hold the text pointer
5664H
LD A,(HL)
Fetch the next character on the program line and store it into Register A so that we can test to see if this has any arguments
5665H
CP 28H
CP “(“
Compare the value held in Register A against 28H (ASCII: (). If the next character is NOT a (, set the NZ Flag
5667H
If the NZ FLAG (Not Zero) has been set, then there are no aguments so skip over all that via a JUMP to 1F05H which is the Model I ROM Routine to scan a line
If we are here, then there are arguments to process.
566AH
RST 10H
GETCHR
Call the EXAMINE NEXT SYMBOL routine at RST 10H. RST 10H bumps HL by 1 and then looks for the first non-space, non-chr$(9), and non-chr$(10) character pointed to by HL. If that character is a number (0-9), the C FLAG is set; otherwise the NC FLAG is set. Z will be set if the character is a 0 or a :. RST 10H exits with HL still pointing to the character it checked, the character it checked in Register A, and BC and DE are unaffected
566BH
 ↳ “SCNLIS”
Get a pointer to a dummy variable (including creating one)
566EH
LD A,(HL)
Now we look for the terminator. Fetch the value held in the memory location pointed to by Register Pair HL and store it into Register A
566FH
CP 29H
CP “)”
Compare the value held in Register A against 29H (ASCII: )). If A is a ), the Z Flag will be set
5671H
If the Z FLAG (Zero) has been set, then we are done with processing the arguments, so JUMP to 1F05H to scan a line
5674H
RST 08H 2C
SYNCHK “,”
Since we have an argument, we must next make sure the next character is a , via a call to RST 08H, which is the COMPARE SYMBOL routine. That routine compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., 2CH which is a ,). If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the A Register and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase
5676H
Loop back to 566BH to keep checking for arguments and allocating RAM space for each one

5679H – Part of the USR(n) routine – “USROUT” and “USRFN”

JUMPed to routine to determine what (n) was in a USR(n) call, and fetch the appropriate jump points and address of the variable in RAM
5679H
 ↳ “USROUT”
POP AF
Clear off the RETurn address from the stack
567AH
 ↳ “USRFN”
GOSUB to 5699H to determine what the n is in a DEF USR n call, and set DE to the appropriate location in the USR jump table which is based at 5B77H
567DH
PUSH DE
Save the pointer location for the USR (n) (held in Register Pair DE) to the stack
567EH
Get the left parenthesis and the formula via GOSUB to 252CH which evaluates a nested expression at the location of the current BASIC program pointer in HL and then make sure a “)” follows (and if not, ERROR)
5681H
EX (SP),HL
Swap (SP) and HL so that HL now holds the index into the USR(n) table USRTAB and the text point is now saved to the stack
5682H
LD C,(HL)
Fetch the LSB of the dispatch address/jump point associated with the (n) provided in the DEF USR (n), and store it into Register C
5683H
INC HL
INCrement the value stored in Register Pair HL by 1
5684H
LD B,(HL)
Fetch the MSB of the dispatch address/jjump point associated with the (n) provided in the DEF USR (n), and store it into Register B
5685H
LD HL,26E7H
LD HL,POPHRT
Set POPHRT as the RETurn address
5688H
PUSH HL
Save the RETurn address to the stack
5689H
PUSH BC
Save the dispatch address/jump point associated with user routine (n) to the stack
568AH
LD A,(40AFH)
LD A,(VALTYP)

LD A,(VALTYP)
Fetch variable type of the argument into Register A. It will contain a 2 for integer, 3 for string, 4 for single-precision, and 8 for double precision
568DH
PUSH AF
Save the VALTYP to the stack
568EH
CP 03H
Test to see if the VALTYPE is a string. If it is, the Z FLAG will be set
5690H
If the variable type flat is a STRING, GOSUB to 29DAH to free it up
5693H
POP AF
Restore the VALTYP from the stack into Register A
5694H
EX DE,HL
EXchange DE and HL to move the possible description pointer (string address) into Register Pair DE. It doesn’t really matter what happens to HL
5695H
LD HL,4121H
LD HL,FACLO
Put the pointer to the ACCumulator into HL
5698H
RET
RETurn to the caller

5699H – SUBROUTINE of the DEF USR routine – “SCNUSR”

– This subroutine will determine what n is in a DEF USR n call, and set DE to the appropriate location in the USR jump table which is based at 5B77H
5699H
 ↳ “SCNUSR”
RST 10H
GETCHR
Call the EXAMINE NEXT SYMBOL routine at RST 10H. RST 10H bumps HL by 1 and then looks for the first non-space, non-chr$(9), and non-chr$(10) character pointed to by HL. If that character is a number (0-9), the C FLAG is set; otherwise the NC FLAG is set. Z will be set if the character is a 0 or a :. RST 10H exits with HL still pointing to the character it checked, the character it checked in Register A, and BC and DE are unaffected
569AH
LD BC,0000H
Since BC will be an accumulator, we need to zero it out, so set Register Pair BC to 0000H
569DH
If the next symbol is NOT a number then the NC FLAG (No Carry) will have been set, so we are going to assume this is a DEF USR 0, and JUMP to 56A4H
569FH
SUB 30H
If we are here, then it was a number (so we have a DEF USR n), so SUBtract the value 30H from Register A to convert an ASCII number ‘0’-‘9’ to its decimal equivalent (i.e., 6 in ASCII is 36H in Hex; so 36H-30H = 6)
56A1H
RLA
Since this is an offset, and the table is two bytes each, we need to multiply that number by 2
56A2H
LD C,A
Copy the offset (i.e., the doubled DEF USR n number) held in Register A into Register C
56A3H
RST 10H
GETCHR
Call the EXAMINE NEXT SYMBOL routine at RST 10H. RST 10H bumps HL by 1 and then looks for the first non-space, non-chr$(9), and non-chr$(10) character pointed to by HL. If that character is a number (0-9), the C FLAG is set; otherwise the NC FLAG is set. Z will be set if the character is a 0 or a :. RST 10H exits with HL still pointing to the character it checked, the character it checked in Register A, and BC and DE are unaffected
56A4H
 ↳ “NOARGU”
EX DE,HL
We need to save the text pointer held in HL somewhere, and an EX DE,HL is quickest, so EXchange the value stored in Register Pair HL with the value stored in Register Pair DE
56A5H
LD HL,5B77H
LD HL,USRTAB
Let Register Pair HL equal 5B77H, which is the base of the USR jump point table
56A8H
ADD HL,BC
LET Register Pair HL = Register Pair HL + Register BC, so now HL will point to the appropriate location in the USR jump point table for the DEF USR n we got
56A9H
EX DE,HL
Swap HL and DE, so now DE points to the appropriate location in the USR jump point table, and HL holds the text pointer
56AAH
RET
RETurn to the caller

56ABH – Process a DEF USR – “DEFUSR”

56ABH
 ↳ “DEFUSR”
GOSUB to 5699H to scann the user name and set DE to point to the applicable DEF USR n jump vector
56AEH
PUSH DE
Save the pointer in the USRTAB table applicable to this number
56AFH
RST 08H D5
SYNCHK “=”
An “=” is required after a “DEFUSR(x)” so call RST 08H with a parameter of the token = to compare the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., the token for =). 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
56B1H
At this point, we have a “DEF USR(n)=”. Next GOSUB to 2B02H to get the address
56B4H
EX (SP),HL
EXchange (SP) and HL so that the address is in HL and the text pointer is in the stack
56B5H
LD (HL),E
Now we want to save the USR call address. Store the LSB of the USR jump point table for the n given (held in Register E) into the memory location pointed to by Register Pair HL
56B6H
INC HL
INCrement the value stored in Register Pair HL by 1
56B7H
LD (HL),D
Store the MSB of the USR jump point table for the n given (held in Register D) into the memory location pointed to by Register Pair HL
56B8H
POP HL
Restore the text pointer (i.e., the pointer current character to examine on the BASIC line), which was swapped into the top of stack, back into HL
56B9H
RET
RETurn to the caller

56BAH – Process an “UNDEFINED FUNCTION” error – “UFERR”

56BAH
 ↳ “UFERR”
LD E,2EH
LD E,ERRUF
Let Register E equal 2EH, which is the error code an “UNDEFINED FUNCTION” error
56BCH
JUMP to 19A2H.
NOTE: 19A2H is the Model I ROM Routine to display the error message applicable to the error code held in Register E

56BFH – Check to see if the command was CASSETTE I/O or DISK I/O – “FILGTO”

56BFH
 ↳ “FILGTO”
PUSH HL
Save text pointer to the stack. This is in case the command was referring to cassette I/O instead of disk I/O (i.e., PRINT#-1 instead of PRINT #1)
56C0H
RST 10H
GETCHR
Call the EXAMINE NEXT SYMBOL routine at RST 10H. RST 10H bumps HL by 1 and then looks for the first non-space, non-chr$(9), and non-chr$(10) character pointed to by HL. If that character is a number (0-9), the C FLAG is set; otherwise the NC FLAG is set. Z will be set if the character is a 0 or a :. RST 10H exits with HL still pointing to the character it checked, the character it checked in Register A, and BC and DE are unaffected
56C1H
CP CEH
CP MINUTK
Compare the value held in Register A against CEH (i.e., a “-” token) and set the Z FLAG if that is a match
56C3H
POP HL
Restore the contents of Register Pair HL
56C4H
LD A,(HL)
Fetch the next character from the program line and store it into Register A
56C5H
RET Z
If we had found the “-“, then we are dealing with cassette instead of disk (i.e., PRINT#-1 instead of PRINT #1), so RETurn with HL just where we left it
56C6H
LD C,02H
LD C,MDSQO
Otherwise, we are dealing with sequential DISK I/O, so set Register C to 02H to flag SEQUENTIAL DISK OUTPUT
56C8H
JUMP to 5EC5H

56CBH – Process the CMD Command – “CMD”

56CBH
 ↳ “CMD”
We need to see what type of “CMD” we are dealing with so GOSUB to 2337H which will evaluate the BASIC expression pointed to by HL and return with the result in ACCumulator. Evaluate BASIC string expression (may include constants, BASIC variables, BASIC functions, operators, etc.) and place result in ACCumulator. On entry, HL must point to first character of the string to be evaluated. On exit, HL will point to the string delimiter, which must be an acceptable BASIC expression terminator (such as a zero byte, a colon, a right parenthesis, etc.)
56CEH
PUSH HL
Save the text pointer to the stack
56CFH
GOSUB to 29D7H to release the space and check to see if there is enough memory for the string. (HL) will be the length of the string, (HL+1) will be the LSB of the location of the string, and (HL+2) will be the MSB
56D2H
LD A,(HL)
Fetch the length of the string (held in the memory location pointed to by Register Pair HL) and store it into Register A
56D3H
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
56D4H
If the Z FLAG (Zero) has been set, then the string is length of 0, so JUMP to 1E4AH to display a ?FC ERROR
56D7H
INC HL
INCrement the value stored in Register Pair HL by 1, so it now points to the LSB of the string data
56D8H
LD E,(HL)
Fetch the LSB of the string (held in the memory location pointed to by Register Pair HL) and store it into Register E
56D9H
INC HL
INCrement the value stored in Register Pair HL by 1, so it now points to the MSB of the string
56DAH
LD D,(HL)
Fetch the MSB of the string (held in the memory location pointed to by Register Pair HL) and store it into Register D
56DBH
LD A,(DE)
Fetch the first character of the string (pointed to by Register Pair DE) and store it into Register A
56DCH
CP 44H
CP “D”
Compare the value held in Register A against 44H (ASCII: D). If Register A equals D, the Z FLAG is set
56DEH
If the Z FLAG (Zero) has been set, JUMP to 5740H to process a CMD”D” and display a directory.
56E1H
CP 45H
CP “E”
Compare the value held in Register A against 45H (ASCII: E). If Register A equals E, the Z FLAG is set
56E3H
If the Z FLAG (Zero) has been set, JUMP to 5736H to process a CMD”E”
56E6H
CP 54H
CP “T”
Compare the value held in Register A against 54H (ASCII: T). If Register A equals T, the Z FLAG is set
56E8H
If the Z FLAG (Zero) has been set, JUMP to 5709H to process a CMD”T” and turn the INTERRUPTS to OFF
56EAH
CP 52H
CP “R”
Compare the value held in Register A against 52H (ASCII: R). If Register A equals R, the Z FLAG is set
56ECH
If the Z FLAG (Zero) has been set, JUMP to 5706H to process a CMD”R” and turn the INTERRUPTS to ON
56EEH
CP 53H
CP “S”
Compare the value held in Register A against 53H (ASCII: S). If Register A equals S, the Z FLAG is set
56F0H
If the Z FLAG (Zero) has been set, JUMP to 5BB4H to process a CMD”S” with the CARRY FLAG off
56F3H
CP 41H
CP “A”
Compare the value held in Register A against 41H (ASCII: A). If Register A equals A, the Z FLAG is set
56F5H
SCF
To ease testing whether 5BB4H was entered into via a “S” or an “A”, the CARRY FLAG is set to indicate “A”
56F6H
If the Z FLAG (Zero) has been set, JUMP to 5BB4H to process a CMD”A” with the CARRY FLAG off
56F9H
CP 23H
CP “#”
Compare the value held in Register A against 23H (ASCII: #). If Register A equals #, the Z FLAG is set
56FBH
If the Z FLAG (Zero) has been set, JUMP to 5818H to process a CMD”#”
56FEH
CP 49H
CP “I”
Compare the value held in Register A against 49H (ASCII: I). If Register A equals I, the Z FLAG is set
5700H
If the Z FLAG (Zero) has been set, JUMP to 5711H to process a CMD”I”
5703H
If we’re here then we ran out of valid CMD”x” command, so JUMP to 1E4AH to display a ?FC ERROR

5706H – Process a CMD”R” and CMD”T” command – “NTSETT”

CMD”R” enters at 5706H, CMD”T” at 5709H. CMD”R” enables interrupts (start real-time clock)
5706H
 ↳ “NTSETT”
LD A,C3H
Let Register A equal C3H, which is the JP Opcode
5708H
LD BC,C93EH
This is a space saving trick. If the JUMP was to 5706H then A=C3 and this will set BC to C93EH which is not relevant. If the Jump was to 5709H, then the command is actually LD A,C9H
5709H
 ↳ “OFTIM”
LD A,C9H
Let Register Pair C9H, which is the RET Opcode
570BH
LD (4012H),A
LD (INTERP),A
Store the value held in Register A into memory location 4012H to either have a JUMP (195) or a RET (201) at the interrupt location
570EH
 ↳ “COMMON”
POP HL
Restore the text pointer back into Register Pair HL
570FH
EI
Enable Interrupts
5710H
RET
RETurn to the caller

5711H – Process a CMD”I” command. Return a command to TRSDOS – “CMDUUO”

5711H
 ↳ “CMDUUO”
POP HL
Restore the text pointer back into Register Pair HL
5712H
RST 08H 2C
SYNCHK “,”
Since a CMD”I” command requires a parameter, we need to make sure the next character is a , via a call to RST 08H, which is the COMPARE SYMBOL routine. That routine compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., 2CH which is a ,). If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the A Register and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase
5717H
PUSH HL
Save the contents of Register Pair HL (i.e., the next character to process) to the stack
571BH
LD A,(HL)
Fetch the length of the string pointed to by Register Pair HL
571CH
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
571DH
If the Z FLAG (Zero) has been set, meaning that the string was of 0 length, JUMP to 1E4AH to display a ?FC ERROR
5720H
INC HL
INCrement the value stored in Register Pair HL by 1, to now point to the LSB of the RAM address of the string
5721H
LD E,(HL)
Fetch the LSB of the RAM location of the string (held in the memory location pointed to by Register Pair HL) and store it into Register E
5722H
INC HL
INCrement the value stored in Register Pair HL by 1, to now point to the MSB of the RAM address of the string
5723H
LD D,(HL)
Fetch the MSB of the RAM location of the string (held in the memory location pointed to by Register Pair HL) and store it into Register D
5724H
LD L,A
Copy the contents of Register A (i.e., the length of the string pointed to be DE) into Register L
5725H
LD H,00H
Let Register H equal 00H, so that Register L is now usable for 16 byte commands
5727H
ADD HL,DE
LET Register Pair HL = Register Pair HL + Register DE, so now Register Pair HL will point to the end of the string
5728H
LD A,(HL)
Fetch the value held in the memory location pointed to by Register Pair HL (the end of the string to be passed) and store it into Register A
5729H
PUSH AF
Save the contents of Register Pair AF to the stack, since we are about to overwrite it with a CARRIAGE RETURN
572AH
LD (HL),0DH
Store the value 0DH (ASCII: “CARRIAGE RETURN”) into the memory location pointed to by Register Pair HL so that the string now ends in a CARRIAGE RETURN
572CH
PUSH HL
Save the RAM location of the end of the string to pass (held in Register Pair HL) to the stack
572DH
EX DE,HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair DE, that DE now holds the END OF THE STRING and HL holds the BEGINNING OF THE STRING
572EH
GOSUB to 4405H to call SYS1/SYS Request Code 3, which will process the command line buffer
5731H
POP HL
Put the value held at the STACK (i.e., RAM location of the end of the string to pass) into Register Pair HL
5732H
POP AF
Put the value held at the STACK (i.e., the original character at the end of the string to pass) into Register Pair AF
5733H
LD (HL),A
Replace the CARRIAGE RETURN at the end of the string to pass with the character which used to be the last character in the string
5734H
POP HL
Put the value held at the STACK (i.e., the next character to process) into Register Pair HL
5735H
RET
RETurn to the caller

5736H – Process a CMD”E” Command – “DERGO”

Get an error message from DOS
5736H
 ↳ “DERGO”
LD A,(5B8CH)
LD A,(DSKERR)
Fetch the value held in memory location 5B8CH and store it into Register A
5739H
OR C0H
OR Register A against C0H (Binary: 1100 0000). This has the effect of turning on bits 6 and 7 which, as explained in the next instruction, turns on the “** ERRCOD = XX” as part of an error message and flags whether to RETURN TO THE CALLER instead of RETURN TO DOS
573BH
GOSUB to 4409H which is the overlay call vector for SYS4/SYS, which handles ERRORS. On entry into SYS4, Register A’s bits 0-5 contain the error number, bit 6 flags whether or not to display “** ERRCOD = XX” as part of the message (1=display), and bit 7 flags whether to return to the caller (1=return to caller) or to return to DOS
573EH
POP HL
Put the RAM location of the next character to process (held at the STACK) into Register Pair HL
573FH
RET
RETurn to the caller

5740H – Process a CMD”D” Command – Enable and load the real-time debugging program – “DEBGO”

5740H
 ↳ “DEBGO”
GOSUB to 440DH which is the overlay call vector for SYS5/SYS, which handles DEBUG
5743H
POP HL
Put the value held at the STACK into Register Pair HL
5744H
RET
RETurn to the caller

5745H – Process the TIME$ Command – “TIME”

5745H
 ↳ “TIME”
RST 10H
GETCHR
Call the EXAMINE NEXT SYMBOL routine at RST 10H. RST 10H bumps HL by 1 and then looks for the first non-space, non-chr$(9), and non-chr$(10) character pointed to by HL. If that character is a number (0-9), the C FLAG is set; otherwise the NC FLAG is set. Z will be set if the character is a 0 or a :. RST 10H exits with HL still pointing to the character it checked, the character it checked in Register A, and BC and DE are unaffected
5746H
PUSH HL
Save the RAM location of the next character to process (held in Register Pair HL) to the stack
5747H
LD A,11H
Let Register A equal 11H (Decimal: 17), to allocate the 17 bytes of a TIME$ response
5749H
GOSUB to 2857H to allocate the number of bytes held in Register A of RAM in the temporary string work area
574CH
LD HL,(40D4H)
LD HL,(DSCTMP+1)
Fetch the value held in memory location 40D4H and store it into Register Pair HL.
NOTE: 40D4H is the storage location for the current string, and this is where the TIME$ will be built
574FH
LD DE,4046H
LD DE,XTIME+5
Let Register Pair DE equal 4046H (Decimal: 16454) which is the storage location for the current month
5752H
GOSUB to 5776H to process the number held at (DE) (i.e., the 2 digit MONTH) into ASCII numbers to be put into HL and HL+1
5755H
LD (HL),2FH
LD (HL),”/”
Store the value 2FH (ASCII: /) into the memory location pointed to by Register Pair HL
5757H
INC HL
INCrement the value stored in Register Pair HL by 1 to now point to where the DAY goes
5758H
GOSUB to 5776H to process the number held at (DE) (i.e., the 2 digit DAY) into ASCII numbers to be put into HL and HL+1
575BH
LD (HL),2FH
LD (HL),”/”
Store the value 2FH (ASCII: /) into the memory location pointed to by Register Pair HL
575DH
INC HL
INCrement the value stored in Register Pair HL by 1 to now point to where the YEAR goes
575EH
GOSUB to 5776H to process the number held at (DE) (i.e., the 2 digit YEAR) into ASCII numbers to be put into HL and HL+1
5761H
LD (HL),20H
LD (HL),” “
Store the value 20H (ASCII: “SPACE”) into the memory location pointed to by Register Pair HL
5763H
INC HL
INCrement the value stored in Register Pair HL by 1 to now point to where the HOUR goes
5764H
GOSUB to 5776H to process the number held at (DE) (i.e., the 2 digit HOUR) into ASCII numbers to be put into HL and HL+1
5767H
LD (HL),3AH
LD (HL),”:”
Store the value 3AH (ASCII: :) into the memory location pointed to by Register Pair HL
5769H
INC HL
INCrement the value stored in Register Pair HL by 1 to now point to where the MINUTES go
576AH
GOSUB to 5776H to process the number held at (DE) (i.e., the 2 digit MINUTE) into ASCII numbers to be put into HL and HL+1
576DH
LD (HL),3AH
LD (HL),”:”
Store the value 3AH (ASCII: :) into the memory location pointed to by Register Pair HL
576FH
INC HL
INCrement the value stored in Register Pair HL by 1 to now point to where the SECONDS go
5770H
GOSUB to 5776H to process the number held at (DE) (i.e., the 2 digit SECONDS) into ASCII numbers to be put into HL and HL+1
5773H
JUMP to 2884H.
NOTE: 2884H is the Model I ROM Routine to process strings

5776H – SUBROUTINE in the TIME$ Command Processor – “TWODIG”

Processes the number held at (DE) into ASCII numbers at HL and HL+1, and DECrement DE by 1
5776H
 ↳ “TWODIG”
LD A,(DE)
Fetch the value held in the memory location pointed to by Register Pair DE and store it into Register A
5777H
DEC DE
DECrement the value stored in Register Pair DE by 1 to point to the next entry in the series MONTH, DAY, YEAR
5778H
LD B,2FH
LD B,”/”
Let Register B equal 2FH / (ASCII: /)
577AH
 ↳ “LOPTND”
SUB 0AH
Top of a very small loop. SUBtract the value 0AH (Decimal: 10) from Register A
577CH
INC B
INCrement the value stored in Register B by 1
577DH
If the NC FLAG (No Carry) has been set, JUMP to 577AH
577FH
ADD 3AH
LD B,”:”
LET Register A = Register A + 3AH
5781H
LD (HL),B
Store the value held in Register B into the memory location pointed to by Register Pair HL
5782H
INC HL
INCrement the value stored in Register Pair HL by 1
5783H
LD (HL),A
Store the value held in Register A into the memory location pointed to by Register Pair HL
5784H
INC HL
INCrement the value stored in Register Pair HL by 1
5785H
RET
RETurn to the caller

5786H – Process the LINE (i.e., LINE INPUT) Command – “LINE”

5786H
 ↳ “LINE”
RST 08 89H
SYNCHK “INPUT”
Since the only valid use of LINE is “LINE INPUT”, Call RST 08H, which is the COMPARE SYMBOL routine which compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., 89H, which is the token for INPUT). 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
5788H
If we are here, then we have “LINE INPUT” and HL has been bumped by 1. GOSUB to 2828H.
NOTE: 2828H is the Model I ROM Routine to save a code string address
578BH
LD A,(HL)
Fetch the value held in the memory location pointed to by Register Pair HL and store it into Register A
578CH
CP 23H<
CP “#”
Compare the value held in Register A against 23H (ASCII: #). If Register A equals #, the Z FLAG is set
578EH
If we have a LINE INPUT #, then the the Z FLAG (Zero) will have been set, so JUMP to 5F4CH which is part of the LINE INPUT routine which will read code for item fetching from sequential input files
5791H
Deal with a quoted string (if any) via a GOSUB to 21CDH which is in the middle of the Model I ROM Routine for INPUT. It looks for a quote and a semi-colon and then displays the prompt
5794H
Read a string to store results into via a GOSUB to 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)
5797H
Make sure we have a string via a GOSUB to 0AF4H which will check a number via a RST 20H call. Returns if VALTYPE=3 (string) else if VALTYPE is not 3 then it generates a TM ERROR. BC, DE, and HL are saved
579AH
PUSH DE
Save the pointer to the variable to the stack
579BH
PUSH HL
Save the text pointer to the stack
579CH
Read a line of INPUT via a GOSUB to 0361H which will input a string from the keyboard, up to a maximum of 240 characters (F0H), and echo them to the screen. It puts this data into a buffer located at the address pointed to by the buffer pointer at 40A7H. (e.g. If 40A7H contains 5000H the data will be stored from 5000H onwards). The string is terminated with a zero byte. On return HL contains the start address of the input string and B contains the length of the string.
579FH
POP DE
Put the text pointer into Register Pair DE
57A0H
POP BC
Put the pointer to the variable Register Pair BC
57A1H
If the C FLAG (Carry) has been set then we had a BREAK so stop via a JUMP to 1DBEH.
NOTE: 1DBEH is in the END routine in the Model I ROM and is commonly jumped to if a command was from the command prompt instead of in a program
57A4H
PUSH BC
Save the pointer to the variable to the stack
57A5H
PUSH DE
Save the text pointer to the stack
57A6H
LD B,00H
Let Register B equal 00H
57A8H
Literalize the input via a GOSUB to 2868H which is the Model I ROM Routine to handle quoted strings
57ABH
POP HL
Restore the text pointer into Register Pair HL
57ACH
XOR A
Set Register A to ZERO to signify a string for the next JUMP
57ADH
Do the variable assignment via a JUMP to 1F32H which is in the middle of the Model I ROM Routine for the LET command; putting a number into a variable

57B0H – Vector from 552FH – “FINDRT”

This routines zeroes out PTRFIL and restores HL from the STACK. No registers or flags are affected. On entry A = 0
57B0H
 ↳ “FINDRT”
PUSH HL
Temporarily save HL to the stack so we can use it. Restored at the end of the routine
57B1H
LD L,A
Zero out HL, first copy the 00H from Register A into Register L
57B2H
LD H,A
Next copy the 00H from Register A into Register H
57B3H
LD (5B8DH),HL
LD (PTRFIL),HL

LD (PTRFIL),HL
Store the 00H into PTRFIL
57B6H
POP HL
Restore HL from the stack
57B7H
RET
RETurn to the caller

57B8H – Vector from 5547H for an INPUT command – “FILSTI”

This routine tries to trap an INPUT#n command, but not a INPUT#-n command. On entry HL is pointing to the current letter of the command line being interpreted, which letter is in Register A.
57B8H
 ↳ “FILSTI”
PUSH HL
Save the text pointer (held in Register Pair HL) to the stack. This would be the characer after the INPUT token
57B9H
CP 23H
Compare the value held in Register A against 23H (ASCII: #). If Register A does NOT equal 23H/#, the NZ FLAG is set
57BBH
If Register A does NOT equal # then there’s nothing for this routine to do, as its just a regular INPUT statement, so exit via a JUMP to 26E7H which just POPs HL (which was PUSHed at the beginning of this routine) and RETurns
If we are here, then we have a INPUT#. We next test to see if this is an INPUT#n or an INPUT#-n command.
57BEH
RST 10H
GETCHR
Call the EXAMINE NEXT SYMBOL routine at RST 10H. RST 10H bumps HL by 1 and then looks for the first non-space, non-chr$(9), and non-chr$(10) character pointed to by HL. If that character is a number (0-9), the C FLAG is set; otherwise the NC FLAG is set. Z will be set if the character is a 0 or a :. RST 10H exits with HL still pointing to the character it checked, the character it checked in Register A, and BC and DE are unaffected
57BFH
CP CEH
CP MINUTK
Compare the value held in Register A against CEH, which is a token for . If they match, the Z flag will be set
If we are here, are are re-setting HL and A to where they were when we entered this routine. HL will be POPped from the stack and will point to the character on the instruction line being interpreted right after the INPUT token, and Register A will hold that character.
57C1H
POP HL
Fetch the text pointer back into Register Pair HL
57C2H
LD A,(HL)
Fetch the character on the command line being interpreted into Register A
57C3H
RET Z
If it turns out we have a INPUT#-n command, the Z FLAG will have been set, and this routine is no longer needed as it is a cassette matter, so RETurn to the caller with HL and A as they were before we checked
If we are here, we have an INPUT#n command!
57C4H
POP BC
Clear the RETURN address from the stack
57C5H
GOSUB to 5EC3H to process and validate the n, set up the file buffers, make sure that we then get a comma after the n, and store a modified BC into 5ED5H
57C8H
PUSH HL
Save the contents of Register Pair HL to the stack
57C9H
LD HL,(40A7H)
LD HL,(BUFPNT)
Fetch the value held in memory location 40A7H and store it into Register Pair HL.
NOTE: 40A7H is the storage location for the Input Buffer Pointer
57CCH
DEC HL
DECrement the value stored in Register Pair HL by 1
57CDH
JUMP to 21EBH.
NOTE: 21EBH is the middle of the Model I ROM Routine for INPUT. It puts a COMMA into (HL) and then looks for a variable storage space in RAM

57D0H – Part of the LIST command – “EXCHDS”

We need to check to see if we are dealing with a disk file or not
57D0H
 ↳ “EXCHDS”
PUSH HL
Temporarily save Register Pair HL to the stack so it can be used in the next instruction
57D1H
LD HL,(5B8DH)
LD HL,(PTRFIL)
See if we have a live PTRFIL, by first fetching the value held in memory location 5B8DH and store it into Register Pair HL
57D4H
57D4H
LD A,H
OR L
Test (5B8DH) for ZERO. Since the Z-80 cannot test Register Pair HL against zero, the common trick is to set Register A to equal to Register H, and then OR A against Register L. Only if both Register H and Register L were zero can the Z FLAG be set
57D6H
POP HL
Restore Register Pair HL from the stack
57D7H
RET Z
If the Z FLAG (Zero) has been set, then there is no file to deal with, so we don’t need to be here anymore. RETurn to the caller
If we are here, then we are dealing with a disk file, so we need to actually start processing that. First we need to see which routine called this one.
57D8H
EX (SP),HL
EXchange the value stored in Register Pair HL with the value that was formerly at the stack. HL will now hold the return address, which we will be testing to see who called this routine.
57D9H
PUSH DE
Temporarily save Register Pair DE to the stack so it can be used in the RST 18H instruction which follows
57DAH
LD DE,2B2EH
LD DE,LIST
Let Register Pair DE equal 2B2EH which is the location in ROM for the LIST command
57DDH
RST 18H
COMPAR
Test to see if whoever called this routine called BEFORE the LIST routines or AFTER the LIST routines. To do this, we compare DE and HL via a call to RST 18. 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: CARRY SET=HL<DE; NO CARRY=HL>DE; NZ=Unequal; Z=Equal)
57DEH
POP DE
Restore Register Pair DE from the stack
57DFH
POP HL
Restore Register Pair HL from the stack (which was HL since the EX (SP), HL put HL there!)
57E0H
If the calling routine (in HL) > the location in ROM for the LIST command (in DE) then the NC FLAG will have been set by the RST 18H call, so JUMP to 2B4AH.
NOTE: 2B4AH is the middle of the Model I ROM Routine for LIST, to list a specific line pointed to by HL
57E3H
If HL<=DE, JUMP to 2282H.
NOTE: 2282H is the Model I ROM Routine. It will POP HL, turn off the cassette recorder, and return to the BASIC interpreter

57E6H – Process BASIC Error Messages – “EXDSKR”

57E6H
 ↳ “EXDSKR”
POP HL
Fetch the RAM location of the next character to process from the stanck into Register Pair HL
57E7H
LD HL,5203H
LD HL,ERRTAB
Let Register Pair HL equal 5203H, which is the disk basic error messages in this program
57EAH
LD A,E
Copy the error code offset (contained in Register E) into Register A for testing
57EBH
CP 8BH
Compare the value held in Register A against 8BH. If Register A >= 8BH the NO CARRY FLAG will be set
57EDH
If Register A >= 8BH then the NC FLAG (No Carry) will have been set, and JUMP to 57F7H
57EFH
CP 63H
Compare the value held in Register A against 63H. If Register A >= 63H the NO CARRY FLAG will be set
57F1H
If Register A >= 63H then the NC FLAG (No Carry) will have been set, and JUMP to 57F9H
57F3H
CP 2FH
Compare the value held in Register A against 2FH. If Register A < 2FH, the CARRY FLAG will be set
57F5H
If Register A <= 2FH then the C FLAG (Carry) will have been set, and JUMP to 57FBH
If we are here, then the error code was between 30H and 62H.
57F7H
 ↳ “UPERR”
LD A,5AH
Let Register A equal 5AH (Decimal: 90)
57F9H
 ↳ “NTDER2”
SUB 34H
SUBtract the value 34H (Decimal: 52) from Register A
In BASIC, error codes are really “error / 2 + 1”. So that’s what we are about to do!
57FBH
 ↳ “NTDERR”
RRCA
Rotate the bits in A right (i.e., higher bit moves lower), with Bit 0 being copied to both the CARRY FLAG and Bit 7. This is the same as dividing Register A by 2
57FCH
INC A
INCrement the value stored in Register A by 1
57FDH
LD E,A
Copy the error code into Register E
57FEH
 ↳ “LEPSKP”
Top of loop that counts down E and increases HL. 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
5801H
DEC E
DECrement the value stored in Register E by 1
5802H
INC HL
INCrement the error message table pointer (stored in Register Pair HL) by 1
5803H
If the NZ FLAG (Not Zero) has been set, LOOP BACK to 57FEH
5805H
GOSUB to 28A7H.
NOTE: 28A7H is the Model I ROM Routine to display a message pointed to by Register Pair HL
5808H
LD HL,(40A2H)
LD HL,(?????)
Fetch the value held in memory location 40A2H and store it into Register Pair HL.
NOTE: 40A2H is the storage location for the Current Line Number in a BASIC Program in 2 Bytes (LSB/MSB) or FFFFH if in direct mode
580BH
LD DE,FFFEH
Let Register Pair DE equal FFFEH
580EH
RST 18H
COMPAR
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: CARRY SET=HL<DE; NO CARRY=HL>DE; NZ=Unequal; Z=Equal)
580FH
If the Z FLAG (Zero) has been set, JUMP to 5C06H which is the startup for BASIC/CMD
5812H
GOSUB to 64F2H to either RETurn or CLEAR MEMORY if the error is such that protection must clear RAM
5815H
JUMP to 1A11H.
NOTE: 1A11H is in the middle of the Model I ROM Routine to handle the Level II BASIC command mode. It determines if we are in a program or command mode, sets to Video Display, turns off the tape recorder, and returns to BASIC or displays a ?SN ERROR

5818H – Process a CMD”#”# Command – This will display a copyright message – “MICPRT”

5818H
 ↳ “MICPRT”
POP HL
Fetch the RAM location of the next character to process from the stanck into Register Pair HL
5819H
LD A,(HL)
Fetch the next character to process (held in the memory location pointed to by Register Pair HL) and store it into Register A
581AH
CP 23H
CP “#”
Compare the value held in Register A against 23H (ASCII: #). If Register A does NOT equal #, the NZ FLAG is set
581CH
If Register A does NOT equal #, resulting in the NZ FLAG (Not Zero) being set, JUMP to 1E4AH, to display a ?FC ERROR
581FH
RST 10H
GETCHR
Call the EXAMINE NEXT SYMBOL routine at RST 10H. RST 10H bumps HL by 1 and then looks for the first non-space, non-chr$(9), and non-chr$(10) character pointed to by HL. If that character is a number (0-9), the C FLAG is set; otherwise the NC FLAG is set. Z will be set if the character is a 0 or a :. RST 10H exits with HL still pointing to the character it checked, the character it checked in Register A, and BC and DE are unaffected
5820H
If the NZ FLAG (Not Zero) has been set, meaning we have something other than CMD”#”# or CMD”#”#:, JUMP to 1E4AH, to display a ?FC ERROR
5823H
PUSH HL
Save the contents of Register Pair HL (i.e., the RAM location of the next character to process) to the stack since we are about to use HL
5824H
LD HL,582CH
LD HL,?????
Let Register Pair HL equal 582CH to point to the message “THIS BASIC WAS AUTHORED AND IS COPYRIGHTED BY MICROSOFT,1978.”
5827H
GOSUB to 28A7H, which is the Model I ROM Routine to display a message pointed to by Register Pair HL
582AH
POP HL
Put the RAM location of the next character to process (held at the STACK) into Register Pair HL
582BH
RET
RETurn to the caller

582CH – Message Storage Location – “MESMIC”

582CH
 ↳ “MESMIC”
DEFM ‘THIS BASIC WAS AUTHORED AND IS COPYRIGHTED BY MICROSOFT,1978.’ + 00H
586BH-588AH
 ↳ “PROTMS”
DEFM 0DH + ‘PROTECTION HAS CLEARED MEMORY’ + 0DH + 00H

588BH – Process the INSTR Command – “INSTR”

According to original source,this is the INSTR function, which takes one of two forms: instr(x% , Y$, Z$) or instr(Y$,Z$). In the first form the string Y$ is searched for the character Z$ starting at character position x%. The second form is identical, except that the search starts at position 1 . INSTR turns the character position of the first occurance of Z$ in Y$. if Y$ is null, 0 is returned, if Z$ is null, thaen x% is returned , unless x% .gt. len(Y$) in which case 0 is returned.
588BH
 ↳ “INSTR”
RST 10H
GETCHR
Call the EXAMINE NEXT SYMBOL routine at RST 10H. RST 10H bumps HL by 1 and then looks for the first non-space, non-chr$(9), and non-chr$(10) character pointed to by HL. If that character is a number (0-9), the C FLAG is set; otherwise the NC FLAG is set. Z will be set if the character is a 0 or a :. RST 10H exits with HL still pointing to the character it checked, the character it checked in Register A, and BC and DE are unaffected
588CH
GOSUB to 2335H.
NOTE: 2335H is the Model I ROM Routine to evaluate the evaluate a BASIC string expression (may include constants, BASIC variables, BASIC functions, operators, etc.) and place result in ACCumulator. At THIS entry point, the HL register pair MUST point to a left parenthesis (which precedes the expression to be evaluated) or a BASIC syntax error will result. On exit, HL will point to the string delimiter, which must be an acceptable BASIC expression terminator (such as a zero byte, a colon, a right parenthesis, etc.)
588FH
RST 20H
GETYPE
Check the data type with a call to RST 20H.
NOTE: The RST 20H routine determines the type of the current value in ACCumulator and returns a combination of STATUS flags and unique numeric values in the A Register according to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • and Double Precision is NZ/NC/P/E and A is 5.
5890H
LD A,01H
Reset A away from the RST 20H result to equal 01H so as to assume that the serarch start will be at the first character
5892H
PUSH AF
Save the offset in case there is a string (which includes the FLAGs which were set by the RST 20H) to the stack
5893H
If the first parameter was a STRING, then RST 20H weould have set the Z FLAG, so JUMP to 58A6H
5895H
POP AF
If we are here, then it wasn’t a string, so we don’t need to save a default offset anymore and actually need to process it as an offset (i.e., INSTR(x,….))!
5896H
Force the first argument in the INSTR to be an integer via a GOSUB to 2B1FH, which will put that number into Register Pair DE.
NOTE: 2B1FH is the Model I ROM Routine to evaluate the expression at the location of the current BASIC program pointer in HL and return with the integer result in DE
5899H
OR A
Since we can’t allow for a 0 offset, set the flags
589AH
If the number was ZERO (i.e., INSTR(0,xxxx)), which is an illegal command, then the Z FLAG (Zero) wil have been set, JUMP to 1E4AH.
NOTE: 1E4AH is the Model I ROM Routine to display a ?FC ERROR
589DH
PUSH AF
The offset is good, so save it to the stack
589EH
RST 08H 2C
SYNCHK “,”
We now have the starting number parameter set, and the next character must be a ,, so we test for that via a call to RST 08H, which is the COMPARE SYMBOL routine. That routine compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., 2CH which is a ,). If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the A Register and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase
58A0H
Get the first string argument via a GOSUB to 2337H, which is the Model I ROM Routine to evaluate the BASIC expression pointed to by HL and return with the result in ACCumulator. Evaluate BASIC string expression (may include constants, BASIC variables, BASIC functions, operators, etc.) and place result in ACCumulator. On entry, HL must point to first character of the string to be evaluated. On exit, HL will point to the string delimiter, which must be an acceptable BASIC expression terminator (such as a zero byte, a colon, a right parenthesis, etc.)
58A3H
Ensure the next parameter is a string via a GOSUB to 0AF4H.
NOTE: 0AF4H is the Model I ROM Routine to check the NUMBER TYPE FLAG via a RST 20H call. Returns if VALTYPE=3 (string) else if VALTYPE is not 3 then it generates a TM ERROR. BC, DE, and HL are saved
58A6H
 ↳ “WIZSTR”
RST 08H 2C
SYNCHK “,”
At this point we have a string parameter, and the next character MUST be a a , so call to RST 08H, which is the COMPARE SYMBOL routine. That routine compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., 2CH which is a ,). If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the A Register and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase
58A8H
PUSH HL
Save the current location in the INSTR() command being parsed (pointed to by Register Pair HL) to the stack
58A9H
LD HL,(4121H)
LD HL,(FACLO)
Get the descriptor pointer from the value held in memory location 4121H (which would be every number except a double-precision number) and store it into Register Pair HL
58ACH
EX (SP),HL
EXchange the descriptor pointer (stored in Register Pair HL) with the current location in the ISTR() command being processed (stored at the stack), so that HL once again points to the current character in the INSTR() command being parsed and the stack holds the number
58ADH
Fetch the next argument in the INSTR(x,y,z) string, which needs to be a string via a GOSUB to 2337H.
NOTE: 2337H is the Model I ROM Routine to evaluate the BASIC expression pointed to by HL and return with the result in ACCumulator. Evaluate BASIC string expression (may include constants, BASIC variables, BASIC functions, operators, etc.) and place result in ACCumulator. On entry, HL must point to first character of the string to be evaluated. On exit, HL will point to the string delimiter, which must be an acceptable BASIC expression terminator (such as a zero byte, a colon, a right parenthesis, etc.)
58B0H
RST 08H 29
SYNCHK “)”
Verify the next character is a “)”. To test for that we call RST 08H, which is the COMPARE SYMBOL routine which compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., 29H). 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
58B2H
PUSH HL
Save the position of the INSTR(x,y$,z$) command being processed (held in Register Pair HL) to the stack
58B3H
Free the temporary string area and see if there is enough memory for the string via a GOSUB to 29D7H. The HL Register Pair will point to the data in ACCumulator
58B6H
EX DE,HL
EXchange the pointer to the INSTR() command being evalulated (originally held in HL) and the Z$ descriptor (originally held in DE)
58B7H
POP BC
Put the position of the INSTR(x,y$,z$) command being processed (value held at the STACK) into Register Pair BC
58B8H
POP HL
Put the Y$ descriptor into Register Pair HL
58B9H
POP AF
Put the x value into Register Pair AF and then remove the entry from the stack
58BAH
PUSH BC
Save the the position of the INSTR(x,y$,z$) command being processed (held in Register Pair BC) to the stack
58BBH
LD BC,26E7H
LD BC,POPHRT
Let Register Pair BC equal 26E7H, which is the address of a POP HL, RET command set
58BEH
PUSH BC
Save POP HL, RET address to the stack
58BFH
LD BC,27F8H
LD BC,SNGFLT
Let Register Pair BC equal 27F8H, which is a ROM routine
58C2H
PUSH BC
Save the ROM routine address to the stack
58C3H
PUSH AF
Save the X (offset) to the stack
58C4H
PUSH DE
Save the Z$ descriptor to the stack
58C5H
Free the Y$ descriptor via a GOSUB to 29DDH
58C8H
POP DE
Restore the Z$ descriptor into Register Pair DE
58C9H
POP AF
Restore the X (offet) into Register Pair AF
58CAH
LD B,A
Copy the unmodified offset into Register B
58CBH
DEC A
Make sure we have a valid offset by DECrementing the value stored in Register A by 1
58CCH
LD C,A
Copy the modified offset into Register C
58CDH
CP (HL)
See if the modified offset is longer than the length of Y$ by comparing the value held in Register A (the modified offset) against the value held in the memory location pointed to by the value held in Register Pair HL. Results:
  • If Register A equals the value held in Register HL, the Z FLAG is set.
  • If A < HL/10232/, the CARRY FLAG will be set.
  • if A >= HL/10232/, the NO CARRY FLAG will be set.
58CEH
LD A,00H
Prepare to return an error condition by setting Register A equal 00H
58D0H
RET NC
If the NC FLAG (No Carry) has been set, then the offset is longer than Y$ so RETurn to the caller with Register A holding a 00H
58D1H
LD A,(HL)
Next we need to make sure Y$ isn’t null. First, fetch the Y$ string length (held in the memory location pointed to by Register Pair HL) and store it into Register A
58D2H
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
58D3H
RET Z
If the Z FLAG (Zero) has been set, then the length of Y$ was zero, so RETurn to the caller with a 0 stored in Register A to denote an error
58D4H
LD A,(DE)
Fetch the length of Z$ (held in the memory location pointed to by Register Pair DE)s and store it into Register A
58D5H
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
58D6H
LD A,B
Put the offset back into Register A
58D7H
RET Z
If the length of Z$ was zero, the Z FLAG (Zero) has been set, RETurn to the caller with a 0 in Register A, denoting an error
58D8H
LD A,(HL)
Fetch the length of Y$ (held in the memory location pointed to by Register Pair HL) and store it into Register A
58D9H
INC HL
INCrement the value stored in Register Pair HL by 1
58DAH
LD B,(HL)
Fetch the LSB of the pointer to Y$ (held in the memory location pointed to by Register Pair HL) and store it into Register B
58DBH
INC HL
INCrement the value stored in Register Pair HL by 1
58DCH
LD H,(HL)
Fetch the MSB of the pointer to Y$ (held in the memory location pointed to by Register Pair HL) and store it into Register H
58DDH
LD L,B
Copy the contents of Register B into Register L, so now HL has the pointer to Y$
58DEH
LD B,00H
Let Register B equal 00H so that it can be used for addition
58E0H
ADD HL,BC
Prepare to index the string. First set Register Pair HL = Register Pair HL + Register BC
58E1H
SUB C
LET Register A = Register A – Register C to adjust the length of Y$
58E2H
LD B,A
Copy the length of Y$ into Register B
58E3H
PUSH BC
Save the counter and the offset (held in Register Pair BC) to the stack
58E4H
PUSH DE
Save descriptor of Z$ (held in Register Pair DE) to the stack
58E5H
EX (SP),HL
Put the descriptor of Z$ in HL and the pointer for Y$ into the stack
58E6H
LD C,(HL)
Fetch the length of Z$ (held in the memory location pointed to by Register Pair HL) and store it into Register C
58E7H
INC HL
INCrement the value stored in Register Pair HL by 1
58E8H
LD E,(HL)
Fetch the LSB of Z$ (held in the memory location pointed to by Register Pair HL) and store it into Register E
58E9H
INC HL
INCrement the value stored in Register Pair HL by 1
58EAH
LD D,(HL)
Fetch the MSB of Z$ (held in the memory location pointed to by Register Pair HL) and store it into Register D
58EBH
POP HL
Restore the pointer to Y$ from the STACK into Register Pair HL
58ECH
 ↳ “CHK1”
PUSH HL
Save the position in the search string (held in Register Pair HL) to the stack
58EDH
PUSH DE
Save the start of the substring (held in Register Pair D)E to the stack
58EEH
PUSH BC
Save the location where we started this search (held in Register Pair BC) to the stack
58EFH
 ↳ “CHK”
LD A,(DE)
Fetch the character from the substring (held in the memory location pointed to by Register Pair DE) and store it into Register A
58F0H
CP (HL)
Compare that character against the character held in (HL). If Register A does NOT MATCH the value held in Register (HL), the NZ FLAG will be set
58F1H
If the NZ FLAG (Not Zero) has been set, then we didn’t have a match, so JUMP to 590AH
58F3H
INC DE
INCrement the compare pointer (stored in Register Pair DE) by 1
58F4H
DEC C
DECrement length of the search string (stored in Register C) by 1
58F5H
If C hits 0, then we have found all characters and the Z FLAG (Zero) will have been set, so JUMP to 5901H as we have finished successfully
58F7H
INC HL
INCrement the value stored in Register Pair HL by 1 to the next character
58F8H
DEC B
DECrement the number of characters left in the source string to compare (held in Register B) by 1
58F9H
If the NZ FLAG (Not Zero) has been set, then we hit the end of the string without a match, so JUMP to 58EFH
58FBH
 ↳ “RETZER”
POP DE
Clear the excess stack entries
58FCH
POP DE
Clear the excess stack entries
58FDH
POP BC
Clear the excess stack entries
58FEH
 ↳ “RETZR1”
POP DE
Clear the excess stack entries
58FFH
XOR A
Set Register A to ZERO and clear all Flags in preparation for a RET to SNGLFLT
5900H
RET
RETurn to the caller

5901H – Part of the INSTR(x,Y$,Z$) routine – Jumped if we did get a matc – “GOTSTR”

5901H
 ↳ “GOTSTR”
POP HL
Clear the excess stack entries
5902H
POP DE
Clear the excess stack entries
5903H
POP DE
Fetch the counter from the STACK into Register Pair DE
5904H
POP BC
Put the value held at the STACK into Register Pair BC
5905H
LD A,B
Get the original source counter (stored in Register B) into Register A
5906H
SUB H
Subtract the final counter via a Register A = Register A – Register H
5907H
ADD A,C
Add the original offset via a Register A = Register A + Register C
5908H
INC A
INCrement the value stored in Register A by 1 so that an offset of 0 will be position 1, etc
5909H
RET
RETurn to the caller

590AH – Part of the INSTR(x,Y$,Z$) routine – Jumped if we did NOT get a match – “HOWEKK”

590AH
 ↳ “OHWELL”
POP BC
Clear the excess stack entries
590BH
POP DE
Put the value where we started to compare (held at the STACK) into Register Pair DE
590CH
POP HL
Put the next character to compare (held at the STACK) into Register Pair HL
590DH
INC HL
INCrement the value stored in Register Pair HL by 1
590EH
DEC B
DECrement the number of characters left in the source string to compare (held in Register B) by 1
590FH
If the Z FLAG (Zero) has been set, then we are at the end of the source string with nothing else to check, so JUMP to 58FEH to POP DE, XOR A, and RETurn with a 00H in Register A
5911H
… otherwise JUMP to 58ECH to search for more

5913H – Process the & Command – “OCTCNS”

5913H
 ↳ “OCTCNS”
LD DE,0000H
LD DE,$CODE
Let Register Pair DE equal 0000H to initialize to zero and ignore any overflows
5916H
RST 10H
GETCHR
Get the first character via a call the EXAMINE NEXT SYMBOL routine at RST 10H. RST 10H bumps HL by 1 and then looks for the first non-space, non-chr$(9), and non-chr$(10) character pointed to by HL. If that character is a number (0-9), the C FLAG is set; otherwise the NC FLAG is set. Z will be set if the character is a 0 or a :. RST 10H exits with HL still pointing to the character it checked, the character it checked in Register A, and BC and DE are unaffected
5917H
CP 4FH
CP “O”
Compare the value held in Register A against 4FH (ASCII: O). If Register A equals O, the Z FLAG is set
5919H
If we have a “O”, then the Z FLAG (Zero) will have been set, so JUMP to 5947H
591BH
CP 48H
CP “H”
Compare the value held in Register A against 48H (ASCII: H). If Register A equals H, the Z FLAG is set
591DH
If we don’t have a “H”, then the NZ FLAG (Not Zero) will have been set, JUMP to 5946H
591FH
LD B,05H
If we’re here then process a “H”. First, set Register B to 05H to initialize a counter
5921H
“LOPHEX”
INC HL
Top of a loop. INCrement HL by 1 to point to the next character on the line being evaluated
5922H
LD A,(HL)
Fetch the next character being evaluated (pointed to by Register Pair HL) and store it into Register A
5923H
See if the character is alphanumeric via a GOSUB to 1E3EH, which is the Model I ROM Routine to examine a variable. At this jump location then routine tests the value A register and sets the C flag if it is an ASCII letter value. Otherwise it resets the C flag
5926H
EX DE,HL
Save the position on the command line being examined into Register Pair DE via an EXchange the value stored in Register Pair HL with the value stored in Register Pair DE. DE will now hold the next character to be evaluated and HL will hold the accumulator
5927H
If the character was not a ASCII letter value, the NC FLAG (No Carry) will have been set, JUMP to 5933H, which will look for a A-F value
5929H
CP 3AH
CP “9” + 1
If we are here, then we found a letter, so next see if it is bigger than the next largest digit by comparing that letter against 3AH (ASCII: :). Results:
  • If Register A equals :, the Z FLAG is set.
  • If A < :, the CARRY FLAG will be set.
  • if A >= :, the NO CARRY FLAG will be set.
592BH
If the character >= :, then the NC will have been set, so JUMP to 5964H to copy HL to the Accumulator, set the number type to INTEGER, swap DE and HL, and RETurn from this routine
592DH
SUB 30H
If we are here, then it is a number. SUBtract the value 30H from Register A to convert an ASCII number ‘0’-‘9’ to its decimal equivalent (i.e., 6 in ASCII is 36H in Hex; so 36H-30H = 6)
592FH
If the C FLAG (Carry) has been set then we have character less than a number (hopefully a “.”), so JUMP to 5964H to copy HL to the Accumulator, set the number type to INTEGER, swap DE and HL, and RETurn from this routine
5931H
JUMP to 5939H to add in the offset

5933H – Continuation of the & Command. Jumped here to check for A-F – “ALPTST”

5933H
 ↳ “ALPTST”
CP 47H
CP “F”+1
Compare the value held in Register A against 47H (ASCII: G). If Register A >= G, the NO CARRY FLAG will be set
5935H
If the character was not A-F, the NC FLAG (No Carry) will have been set, so JUMP to 5964H to copy HL to the Accumulator, set the number type to INTEGER, swap DE and HL, and RETurn from this routine
5937H
SUB 37H
SUB “A”-10
If we are here, then we had a A-F, so we subtract 37H from it to convert it to 10-15 decimal
This is a jump point if Register A is 0-9, or a pass through if Register A is 10-15.
5939H
 ↳ “NXTHEX”

593AH
593BH
593CH
ADD HL,HL
ADD HL,HL
ADD HL,HL
ADD HL,HL
LET Register Pair HL = Register Pair HL * 16
593DH
OR L
OR Register L against Register A to add on the new digit. The results are stored in Register A
593EH
LD L,A
Save the result back to Register L
593FH
DEC B
DECrement the value stored in Register B by 1 to see if we have too many digits
5940H
If we had too many digits then the Z FLAG (Zero) will have been set, JUMP to 07B2H.
NOTE: 07B2H is the Model I ROM Routine to output an OV ERROR message
5943H
EX DE,HL
Restore the pointer to the command line being examined back into Register Pair HL
5944H
LOOP BACK to 5921H to keep processing

5946H – Continuation of the & command – “LOPOC2”

Jumped to 5946H if there was a & but not a &H or &O. Jump to 5946H if there was a &O.
5946H
 ↳ “LOPOC2”
DEC HL
DECrement the pointer in the command line being examined by 1, so that the next instruction will put it into Register A and test if it is numeric
5947H
 ↳ “LOPOCT”
RST 10H
GETCHR
Top of a perpetual loop at the end of this routine. Read a digit via a call the EXAMINE NEXT SYMBOL routine at RST 10H. RST 10H bumps HL by 1 and then looks for the first non-space, non-chr$(9), and non-chr$(10) character pointed to by HL. If that character is a number (0-9), the C FLAG is set; otherwise the NC FLAG is set. Z will be set if the character is a 0 or a :. RST 10H exits with HL still pointing to the character it checked, the character it checked in Register A, and BC and DE are unaffected
5948H
EX DE,HL
Put the result of the RST 10H into (HL)
5949H
If t5he NC flag is set, then we have run out of digits to process and are done so JUMP to 5964H to copy HL to the Accumulator, set the number type to INTEGER, swap DE and HL, and RETurn from this routine
594BH
CP 38H
Compare the value held in Register A against 38H (ASCII: 8) to make sure it is an octal digit. If Register A >= “8“, the NO CARRY FLAG will be set.
594DH
If the NC FLAG (No Carry) has been set, JUMP to 1997H to display a SYNTAX ERROR error message
5950H
LD BC,07B2H
LD BC,OVERR
Let Register Pair BC equal 07B2H to as to point to the ?OV ERROR routine
5953H
PUSH BC
Save that address to the stack
5954H
ADD HL,HL
LET Register Pair HL = Register Pair HL + Register HL (so HL is now HL * 2)
5955H
RET C
If HL*2 causes an overflow, the C FLAG (Carry) will have been set, so RETurn (which will be a JUMP to the ?OV ERROR routine)
5956H
ADD HL,HL
LET Register Pair HL = Register Pair HL + Register HL (so HL is now HL * 4)
5957H
RET C
If HL*2 causes an overflow, the C FLAG (Carry) will have been set, so RETurn (which will be a JUMP to the ?OV ERROR routine)
5958H
ADD HL,HL
LET Register Pair HL = Register Pair HL + Register HL (so HL is now HL * 8)
5959H
RET C
If HL*2 causes an overflow, the C FLAG (Carry) will have been set, so RETurn (which will be a JUMP to the ?OV ERROR routine)
595AH
POP BC
Clear the ?OV ERROR address from the stack, as we don’t need to jump there anymore
595BH
LD B,00H
Let Register B equal 00H so that Register C can have 16 bit math applied to it
595DH
SUB 30H
SUBtract the value 30H / (Binary:0011 0000) / (Decimal: 48) / (ASCII: 0) from Register A. Note: Subtracting 30H from from Register A will convert an ASCII number ‘0’-‘9’ to its decimal equivalent (i.e., 6 in ASCII is 36H in Hex; so 36H-30H = 6)
595FH
LD C,A
Copy the contents of Register A into Register C
5960H
ADD HL,BC
Add in the digit via Register Pair HL = Register Pair HL + Register BC
5961H
EX DE,HL
Put the pointer to the BASIC command line being examined back into Register Pair HL
5962H
LOOP BACK to 5947H at the top of this routine

5964H – JUMPed to routine to copy HL to the Accumulator, set the number type to INTEGER, swap DE and HL, and RETurn to the caller of the original routine – “OCTFIN”

5964H
 ↳ “OCTFIN”
Load the value of Register Pair HL into the Accumulator (4121H) and set the variable type to INTEGER. Ohterwise known as the ISTOR routine
5967H
EX DE,HL
Put the pointer to the BASIC command line being examined back into Register Pair HL
5968H
RET
RETurn to the caller

5969H – Process the MID$() command – “DLHSMD”

5969H
 ↳ “DLHSMD”
INC HL
INCrement the pointer to the BASIC command line being examined by 1
596AH
RST 08H 28H
SYNCHK “(“
Since we MUST have a “(” first, call RST 08H, which is the COMPARE SYMBOL routine which compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., 28H). 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
596CH
CALL 260DH
CALL PTRGET
GOSUB to 260DH to for variable location and creation logic
596FH
CALL CHKSTR
Make sure the variable is a string
5972H
PUSH HL
Save the pointer to the BASIC command line being examined to the stack
5973H
PUSH DE
Save the string variable description pointer (held in Register Pair DE) to the stack
5974H
EX DE,HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair DE
5975H
INC HL
INCrement the value stored in Register Pair HL by 1 to now point to the LSB of the string variable
5976H
LD E,(HL)
Fetch the LSB of the variable and store it into Register E
5977H
INC HL
INCrement the value stored in Register Pair HL by 1 to now point to the MSB of the string variable
5978H
LD D,(HL)
Fetch the MSB of the variable and store it into Register D
5979H
LD HL,(40A0H)
LD HL,(STKTOP)
Prepare to see if the string is within the string space by fetching the value held in memory location 40A0H and store it into Register Pair HL.
NOTE: 40A0H is the storage location for the [TAKEN FROM PAGE] String Storage Area: 2 Bytes point to the lowest address available for string storage. This is ALSO the top of free memory. Start of string storage area, set to 50 less than top of memory pointer (at 40BlH) at power-up to provide 50 bytes of string storage area. Changed by use of CLEAR n command (with argument)
597CH
RST 18H
COMPAR
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: CARRY SET=HL<DE; NO CARRY=HL>DE; NZ=Unequal; Z=Equal)
597DH
If the C FLAG (Carry) has been set then the variable is already in the string space, so JUMP to 5989H
597FH
POP HL
Restore the variable description pointer into Register Pair HL from the stack
5980H
PUSH HL
Save the variable description pointer (held in Register Pair HL) to the stack
5981H
GOSUB to 2843H to copy the string literal into the string space.
NOTE: 2843H is the middle of the Model I ROM Routine for STR$(). On entry, HL should be pointing to the VARPTR of a string
5984H
POP HL
Restore the variable description pointer into Register Pair HL from the stack
5985H
PUSH HL
Save the variable description pointer (held in Register Pair HL) to the stack
5986H
Move the new description into the old slot via a GOSUB to 09D3H.
NOTE: 09D3H is the Model I ROM Routine to move the number of bytes specified in the type flag (40AFH) from the address in DE to the address in HL. Uses A, DE and HL
5989H
NCPMID
POP HL
Restore the variable description pointer into Register Pair HL from the stack
598AH
EX (SP),HL
EXchange the variable description pointer and the the pointer to the BASIC command line being examined
598BH
RST 08H 2C
SYNCHK “,”
Make sure the next character is a , via a call to RST 08H, which is the COMPARE SYMBOL routine. That routine compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., 2CH which is a ,). If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the A Register and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase
598DH
Get the next MID$ argument via a GOSUB to 2B1CH.
NOTE: 2B1CH is the Model I ROM Routine to evaluate the n portion of the STRING$ function
5990H
OR A
Set FLAGS based on the contents of Register A to prepare to make sure it isn’t zero
5991H
If the Z FLAG (Zero) has been set, JUMP to 1E4AH to display a ?FC ERROR
5994H
PUSH AF
Save the second argument in the MID$ function (held in Register Pair AF) to the stack
5995H
LD A,(HL)
Fetch the current character from the BASIC command line being examined (pointed to by Register Pair HL) and store it into Register A
5996H
Check for a possible third argument in the MID$() call via a GOSUB to 59DCH
5999H
PUSH DE
Save the third argument (held in Register Pair DE) to the stack
599AH
RST 08H D5
SYNCHK “=”
Call RST 08H, which is the COMPARE SYMBOL routine which compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., a token for =). 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
599CH
If we are here, then we got an “=” so now we need to evaluate the right hand side of a MID$(x,y,z)=???? command.NOTE: 2337H is the Model I ROM Routine to evaluate the BASIC expression pointed to by HL and return with the result in ACCumulator. Evaluate BASIC string expression (may include constants, BASIC variables, BASIC functions, operators, etc.) and place result in ACCumulator. On entry, HL must point to first character of the string to be evaluated. On exit, HL will point to the string delimiter, which must be an acceptable BASIC expression terminator (such as a zero byte, a colon, a right parenthesis, etc.)
599FH
PUSH HL
Save the pointer to the BASIC command line being examined to the stack
59A0H
Make sure we have room to store the string after the “=” via a GOSUB to 29D7H.
NOTE: 29D7H is the Model I ROM Routine to check to see if there is enough memory for the string
59A3H
EX DE,HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair DE, so now DE will hold the pointer to the right hand side of the function
59A4H
POP HL
Restore the pointer to the BASIC command line being examined from the stack into HL
59A5H
POP BC
Restore Argument 3 of the MID$(x,y,z) command into Register C
59A6H
POP AF
Restore Argument 2 of the MID$(x,y,z) command into Register A
59A7H
LD B,A
Copy Argument 2 of the MID$(x,y,z) command into Register B
59A8H
EX (SP),HL
EXchange the value stored in Register Pair HL with the value stored at the stack, so the left hand side description pointer goes to HL and the pointer to the BASIC command line being examined going to the stack
59A9H
PUSH HL
Save the the pointer to the BASIC command line being examined to the stack
59AAH
LD HL,26E7H
LD HL,POPHRT
Let Register Pair HL equal 26E7H as the address to RETurn to
59ADH
EX (SP),HL
Put the address to RETurn to at the stack and restore the pointer to the BASIC command line being examined to HL
59AEH
LD A,C
Copy Argument 3 to Register A
59AFH
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
59B0H
RET Z
If the Z FLAG (Zero) has been set, RETurn to the caller because we have nothing to do
59B1H
LD A,(HL)
Fetch the length of the left hand side argument and store it into Register A
59B2H
SUB B
Calculate how many character in the remainder of the string there are via a Register A = Register A – Register B
59B3H
If the C FLAG (Carry) has been set, then the user was trying to assign a string past the length of the string, so JUMP to 1E4AH to display a ?FC ERROR
59B6H
INC A
INCrement the value stored in Register A by 1 to be a proper count
59B7H
CP C
Compare the number of characters (held in Register A) against Argument 3 (held in Register C). If A < Argument 3, the CARRY FLAG will be set
59B8H
If the C FLAG (Carry) has been set, JUMP to 59BBH to avoid truncating
59BAH
LD A,C
OTHERWISE, truncate the string by using Argument 3
59BBH
“BIGLEN”
LD C,B
Get the offset of the string into Register C
59BCH
DEC C
DECrement the value stored in Register C by 1 to be a proper offset
59BDH
LD B,00H
Let Register B equal 00H as it will be used for addition
59BFH
PUSH DE
Save the contents of Register Pair DE to the stack
59C0H
INC HL
INCrement the pointer to the address field (stored in Register Pair HL) by 1
59C1H
LD E,(HL)
Fetch the LSB of the address field and store it into Register E
59C2H
INC HL
INCrement the value stored in Register Pair HL by 1
59C3H
LD H,(HL)
Fetch the LSB of the address field and store it into Register H
59C4H
LD L,E
Copy the contents of Register E into Register L so that HL now points to the address field
59C5H
ADD HL,BC
Calculate an offset by Register Pair HL = Register Pair HL + Register BC
59C6H
LD B,A
Copy the count of the left hand side into Register B
59C7H
POP DE
Put the value held at the STACK into Register Pair DE
59C8H
EX DE,HL
Move the right hand side description pointer into Register Pair HL
59C9H
LD C,(HL)
Fetch the length of the right hand side and store it into Register C
59CAH
INC HL
INCrement the value stored in Register Pair HL by 1
59CBH
LD A,(HL)
Fetch the LSB of the address to the right hand side and store it into Register A
59CCH
INC HL
INCrement the value stored in Register Pair HL by 1
59CDH
LD H,(HL)
Fetch the MSB of the address to the right hand side and store it into Register A
59CEH
LD L,A
Copy the contents of Register A into Register L so that Register Pair HL now points to the address of the right hand side
59CFH
EX DE,HL
Put the address of the right hand side into Register Pair DE
59D0H
LD A,C
Copy the contents of Register C into Register A so as to test to see if the right hand side is null
59D1H
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
59D2H
RET Z
If the Z FLAG (Zero) has been set then we are all done, so RETurn to the caller
If we are here we now have to set up for an assignment. (HL) points to the left hand side, (DE) points to the right hand side, C is the length of the right hand side, and B is the length of the left hand side.
59D3H
“MIDLP”
LD A,(DE)
Top of a DJNZ Loop. Fetch a byte from the right hand side into Register A
59D4H
LD (HL),A
… and put that byte into the left hand side
59D5H
INC DE
INCrement the right hand side pointer by 1
59D6H
INC HL
INCrement the left hand side pointer by 1
59D7H
DEC C
DECrement the counter of the bytes in the right hand side (stored in Register C) by 1
59D8H
RET Z
If the Z FLAG (Zero) has been set then we are done, so RETurn to the caller
59D9H
LOOP back to 59D3H to keep copying, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction
59DBH
RET
RETurn to the caller

59DCH – Part of the MID$(x,y,z)=”???????” routine – “MIDRST”

59DCH
 ↳ MIDRST”
LD E,FFH
Let Register E equal FFH to enable us to truncate if there are only 2 arguments so that E will hold an indication to use ALL characters
59DEH
CP 29H
CP “)”
Compare the value held in Register A against )). If Register A equals ), the Z FLAG is set
59E0H
If the Z FLAG (Zero) has been set, JUMP to 59E7H
59E2H
RST 08H 2C
SYNCHK “,”
Make sure the next character is a , via a call to RST 08H, which is the COMPARE SYMBOL routine. That routine compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., 2CH which is a ,). If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the A Register and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase
59E4H
If there was a “,” then there MUST be a third argument, so GOSUB to 2B1CH to evaluate the n portion of the STRING$ function
59E7H
“MID2”
RST 08H 29
SYNCHK “)”
Call RST 08H, which is the COMPARE SYMBOL routine which compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., “)”). 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
59E9H
RET
RETurn to the caller

59EAH – Routine to determine if the input is from a disk file – “INLINE”

59EAH
“INLINE”
PUSH HL
Save the buffer pointer (Register Pair HL) to the stack
59EBH
LD HL,(5B8DH)
LD HL,(PTRFIL)
Fetch the value held in memory location 5B8DH and store it into Register Pair HL so as to see if this is disk related
59EEH
59EEH
LD A,H
OR L
Since the Z-80 cannot test Register Pair HL against zero, the common trick is to set Register A to equal to Register H, and then OR A against Register L. Only if both Register H and Register L were zero can the Z FLAG be set
59F0H
POP HL
Restore the buffer pointer from the STACK into Register Pair HL
59F1H
RET Z
If the Z FLAG (Zero) has been set, then this is not from disk so, RETurn to the caller

59F2H – Vectors out from ROM Handling Disk I/O – “ISFILE”

This routine is entered when calling the keyboard LINE INPUT routine but the input is from a disk file and not the keyboard.
59F2H
 ↳ “ISFILE”
POP AF
Discard any return address from the stack
59F3H
PUSH BC
Save the contents of Register Pair BC to the stack
59F4H
PUSH DE
Save the contents of Register Pair DE to the stack
59F5H
LD B,F0H
Let Register B equal F0H (Decimal: 240) to set up a maximum character count
59F7H
LD D,7FH
Let Register D equal 7FH (Binary:0111 1111) to turn off any high bit
59F9H
LD HL,(40A7H)
LD HL,(BUFPNT)
Point HL to the buffer where we are going to store the line
59FCH
 ↳ “LOPBUF”
Get a character from the disk file via a GOSUB to 0384H, which is the Model I ROM Routine to wait for a keypress, with the key stored in Register A
59FFH
LD E,A
Copy the character into Register E
5A00H
SUB 80H
SUBtract the value 80H (Binary:1000 0000) from Register A
5A02H
SBC A,A
Subtracts the value stored in Register Pair A and the carry flag from the value stored in Register Pair A. If the character had a high bit, this will be 255
5A03H
OR D
OR Register D against Register A so that it will either be 127 or 255
5A04H
LD D,A
Save the masked character into Register D
5A05H
LD A,E
Restore the original character retrieved from the disk file back into Register A
5A06H
AND D
MASK the value of Register A against the value held in Register D
5A07H
LD (HL),A
Store the masked character (held in Register A) into the buffer (pointed to by Register Pair HL)
5A08H
CP 0DH
Compare the value held in Register A against 0DH (ASCII: “CARRIAGE RETURN”). If it is, the Z FLAG will be set
5A0AH
If the Z FLAG (Zero) has been set, then the line is done, so JUMP out of this loop to 5A18H
5A0CH
CP 0AH
Compare the value held in Register A against 0AH (ASCII: “LINE FEED”). If it isn’t, the NZ FLAG will be set
5A0EH
If the NZ FLAG (Not Zero) has been set, JUMP to 5A15H
If we are here, then we need to deal with a “LINE FEED”, which is to be ignored.
5A10H
LD A,B
Begin a test to see if this is at the start of the input by copying the contents of Register B into Register A
5A11H
CP F0H
Compare the value held in Register A against F0H, and if it is, set the Z FLAG
5A13H
If the Z FLAG (Zero) has been set, then we are at the start of a line, so JUMP BACK to 59FCH to just get another character
5A15H
“INOTLF”
INC HL
Since it isn’t a character we are ignoring or exiting based on, INCrement the buffer pointer (stored in Register Pair HL) by 1
5A16H
LOOP back to 59FCH, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction
5A18H
“FINLIN”
XOR A
If we are here, then we finished the read. First, set Register A to a terminator (i.e., ZERO)
5A19H
LD (HL),A
Store the terminator into the buffer (pointed to by Register Pair HL)
5A1AH
POP DE
Put the value held at the STACK into Register Pair DE
5A1BH
POP BC
Put the value held at the STACK into Register Pair BC
5A1CH
LD HL,(40A7H)
LD HL,(BUFPNT)
Fetch the value held in memory location 40A7H and store it into Register Pair HL so that HL will point to the buffer
5A1FH
DEC HL
DECrement the value stored in Register Pair HL by 1
5A20H
RET
RETurn to the caller

5A21H – Output a character to a disk file – “EXOUTC”

5A21H
 ↳ “EXOUTC”
PUSH HL
Save the contents of Register Pair HL to the stack
5A22H
LD HL,(5B8DH)
LD HL,(PTRFIL)
Fetch the value held in memory location 5B8DH and store it into Register Pair HL
5A25H
5A25H
LD A,H
OR L
Since the Z-80 cannot test Register Pair HL against zero, the common trick is to set Register A to equal to Register H, and then OR A against Register L. Only if both Register H and Register L were zero can the Z FLAG be set
5A27H
POP HL
Put the value held at the STACK into Register Pair HL
5A28H
LD A,C
Restore the character (saved in Register C) into Register A
5A29H
RET Z
If the Z FLAG (Zero) has been set, then we are NOT looking for Disk Output, so exit via a RETurn to the caller
5A2AH
POP AF
Clear the return address from the stack
5A2BH
LD A,C
Copy the character to send (held in Register C) into Register A
5A2CH
POP BC
Put the value held at the STACK into Register Pair BC
5A2DH
JUMP to 631CH

5A30H – Part of the LINE INPUT from Disk Routine – “EXINC”

5A30H
 ↳ “EXINC”
INC SP
INCrement the value stored in Register Pair SP by 1, since we know who called this routine
5A31H
INC SP
INCrement the value stored in Register Pair SP by 1, to position is to see who called the routine that called this routine, as it might be CHAR or INCHAR
5A32H
EX (SP),HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair SP
5A33H
PUSH DE
Save the contents of Register Pair DE to the stack
5A34H
LD DE,0387H
LD DE,INCHR+3
Let Register Pair DE equal 0387H
5A37H
RST 18H
COMPAR
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: CARRY SET=HL<DE; NO CARRY=HL>DE; NZ=Unequal; Z=Equal)
5A38H
POP DE
Put the value held at the STACK into Register Pair DE
5A39H
EX (SP),HL
Restore HL and put the RETURN ADDRESS back on stack
5A3AH
If the NZ FLAG (Not Zero) has been set, then this was a poll call, so JUMP to 5A71H
5A3DH
PUSH HL
Save the contents of Register Pair HL to the stack
5A3EH
LD HL,(5B8DH)
LD HL,(PTRFIL)
Fetch the value held in memory location 5B8DH and store it into Register Pair HL
5A41H
5A41H
LD A,H
OR L
Since the Z-80 cannot test Register Pair HL against zero, the common trick is to set Register A to equal to Register H, and then OR A against Register L. Only if both Register H and Register L were zero can the Z FLAG be set
5A43H
POP HL
Put the value held at the STACK into Register Pair HL
5A44H
If the Z FLAG (Zero) has been set, then this was not for disk I/O, so JUMP to 035BH.
NOTE: 035BH is the Model I ROM Routine to simulate the INKEY$ function without losing the contents of Register Pair DE
5A47H
PUSH HL
Save the contents of Register Pair HL to the stack
5A48H
Read a character from the disk via a GOSUB to INDSKC
5A4BH
If the NC FLAG (No Carry) has been set, then we have no EOF, so JUMP to 26E7H.
NOTE: 26E7H is the Model I ROM. It just POPs HL and RETurns
5A4EH
PUSH BC
In preparation for the CALL 60EFH, we need to save all the register pairs. Save the contents of Register Pair BC to the stack
5A4FH
PUSH DE
Save the contents of Register Pair DE to the stack
5A50H
PUSH HL
Save the contents of Register Pair HL to the stack
5A51H
GOSUB to 60EFH to zero PTRFIL and close the open disk file
5A54H
POP HL
And now we need to put all the registers back! Put the value held at the STACK into Register Pair HL
5A55H
POP DE
Put the value held at the STACK into Register Pair DE
5A56H
POP BC
Put the value held at the STACK into Register Pair BC
5A57H
LD A,(5BB1H)
LD A,(LSTFRE)
Fetch the value held in memory location 5BB1H to see if we need to RUN now. That is stored in “LSTFRE”
5A5AH
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG). If we need to run, this will NOT be zero
5A5BH
LD HL,1D1EH
LD HL,NEWSTT
Let Register Pair HL equal 1D1EH as the jump point to start the RUN
5A5EH
EX (SP),HL
Put the NEWSTT jump point into the stack so a RETurn goes there
5A5FH
If the NZ FLAG (Not Zero) has been set, then we need to run, so JUMP to 1B5DH.
NOTE: 1B5DH is the Model I ROM Routine to execute a RUN command
5A62H
EX (SP),HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair SP
5A63H
PUSH BC
Save the contents of Register Pair BC to the stack
5A64H
PUSH DE
Save the contents of Register Pair DE to the stack
5A65H
LD HL,1929H
LD HL,REDDY
Let Register Pair HL equal 1929H to prepare to display “READY”
5A68H
GOSUB to 28A7H.
NOTE: 28A7H is the Model I ROM Routine to display a message pointed to by Register Pair HL
5A6BH
POP DE
Put the value held at the STACK into Register Pair DE
5A6CH
POP BC
Put the value held at the STACK into Register Pair BC
5A6DH
LD A,0DH
Let Register A equal 0DH so as to force an exit from the disk LINE INPUT loop
5A6FH
POP HL
Put the value held at the STACK into Register Pair HL
5A70H
RET
RETurn to the caller

5A71H – This fixes a bug in the Cassette routines – “FIXCAS”

5A71H
 ↳ “FIXCAS”
LD (40A9H),A
LD (CASFLG),A
Store the value held in Register A into memory location 40A9H.
NOTE: 40A9H is the storage location for the [TAKEN FROM PAGE] Used by INPUT command routine, contains zero byte if (and only if) input is from cassette. A bug in the first release of the Model I Level II BASIC ROM required that this location be POKEd with a non-zero value prior to reading program DATA statements. This bug was corrected soon after Level II BASIC was released, so that this POKE is required only for older TRS-80 Model I machines.
NOTE: 40A9H is the storage location for the [TAKEN HACKER HANDBOOK] Input flag – 0 = Cassette , else non-zero
5A74H
JUMP to 035BH.
NOTE: 035BH is the Model I ROM Routine to simulate the INKEY$ function without losing the contents of Register Pair DE

5A77H – Variable Storage Area – “USRTAB”

5A77H
 ↳ “DIRTMP”
00H
5A78H
 ↳ “USRTAB”
DEFS 255
5B77H
4A 1E
DEF USR 0 2-byte Jump Vector
5B79H
4A 1E
DEF USR 1 2-byte Jump Vector
5B7BH
4A 1E
DEF USR 2 2-byte Jump Vector
5B7DH
4A 1E
DEF USR 3 2-byte Jump Vector
5B7FH
4A 1E
DEF USR 4 2-byte Jump Vector
5B81H
4A 1E
DEF USR 5 2-byte Jump Vector
5B83H
4A 1E
DEF USR 6 2-byte Jump Vector
5B85H
4A 1E
DEF USR 7 2-byte Jump Vector
5B87H
4A 1E
DEF USR 8 2-byte Jump Vector
5B89H
4A 1E
DEF USR 9 2-byte Jump Vector
5B8BH
“MAXTRK”
00H
This byte is used to track if we are doing a GET or a PUT. 00H = Get, NZ = Put
5B8CH
“DSKERR”
00H
This byte is used to pass an error code
5B8DH-5B8EH
“PTRFIL”
00H
Used for a few purposes including pointing to a buffer or holding a byte which designates whether a command needs to do DISK I/O or keyboard I/O

5B8FH – File Pointer Table – “FILPTR”

5B8FH
-5B90H
 ↳ “FILPTR”
NOP NOP
Vector for file number 01
5B91H
-5B92H
NOP NOP
Vector for file number 02
5B93H
-5B94H
NOP NOP
Vector for file number 03
5B95H
-5B96H
NOP NOP
Vector for file number 04
5B97H
-5B98H
NOP NOP
Vector for file number 05
5B99H
-5B9AH
NOP NOP
Vector for file number 06
5B9BH
-5B9CH
NOP NOP
Vector for file number 07
5B9DH
-5B9EH
NOP NOP
Vector for file number 08
5B9FH
-5BA0H
NOP NOP
Vector for file number 09
5BA1H
-5BA2H
NOP NOP
Vector for file number 10
5BA3H
-5BA4H
NOP NOP
Vector for file number 11
5BA5H
-5BA6H
NOP NOP
Vector for file number 12
5BA7H
-5BA8H
NOP NOP
Vector for file number 13
5BA9H
-5BAAH
NOP NOP
Vector for file number 14
5BABH
-5BACH
NOP NOP
Vector for file number 15
5BADH
NOP
5BAEH
NOP
5BAFH
 ↳ “FILPT1”
NOP
This is a temporary storage location which is usually flipped to FILPTR
5BB0H
NOP
5BB1H
 ↳ “LSTFRE”
NOP
This will flag if we RUN after a LOAD or not
5BB2H
 ↳ “LSTFRE+1”
NOP

5BB3H – Normal System Code to Return – “SYSOUT”

5BB3H
 ↳ “SYSOUT”
RET
RETurn to the caller

5BB4H – Process CMD”S” and CMD”A” RETURN TO DOS commands – “SYSGO”

On entry, Register A will hold the “S” or the “A” parameter, and the CARRY FLAG will be set if it was an “A”. CMD”S” is the normal return to TRSDOS (jump to EXIT routine)
5BB4H
 ↳ “SYSGO”
PUSH AF
Save the contents of Register Pair AF (i.e., was this a S or an A) to the stack
5BB5H
LD HL,(5D51H)
LD HL,(NXTFCN+1)
Fetch the exit jump address (held in memory location 5D51H) and store it into Register Pair HL
5BB8H
LD (4313H),HL
LD (XFCN),HL
Use a normal chain for a trap
5BBBH
LD A,C3H
Restore the jump for foreground breaks by setting Register A equal to C3H, which is the JP opcode
5BBDH
LD (4315H),A
LD (XBREAK),A
Store the JP opcode (held in Register A) into memory location 4315H
5BC0H
POP AF
Put the value held at the STACK into Register Pair AF
5BC1H
If the C FLAG (Carry) has been set (meaning, we entered this routine with a CMD”A”), JUMP to 4030H, which will Load and Execute the SYS1/SYS overlay with a Request Code of 2
5BC4H
OTHERWISE, JUMP to 402DH which will JUMP to 4400H to make the overlay call to load SYS1/SYS with a Request Code of 1

5BC7H – Part of DISK I/O – “EXDPOS”

5BC7H
 ↳ “EXDPOS”
LD HL,(5B8DH)
LD HL,(PTRFIL)
Check to see if the operation was for disk I/O or not by fetching the value held in memory location 5B8DH and store it into Register Pair HL
5BCAH
5BCAH
LD A,H
OR L
Since the Z-80 cannot test Register Pair HL against zero, the common trick is to set Register A to equal to Register H, and then OR A against Register L. Only if both Register H and Register L were zero can the Z FLAG be set
5BCCH
RET Z
If the Z FLAG (Zero) has been set, then disk I/O was not requested, so RETurn to the caller
5BCDH
INC HL
INCrement the value stored in Register Pair HL by 1 to point to the terminal position
5BCEH
LD A,(HL)
Fetch the value held in the memory location pointed to by Register Pair HL and store it into Register A
5BCFH
POP HL
Clear the RETurn address from the stack
5BD0H
PUSH DE
We are going to need to use DE for a RST 18H, so save the contents of Register Pair DE to the stack
5BD1H
PUSH AF
Save the character position (held in Register Pair AF) to the stack
5BD2H
LD DE,2130H
LD DE,MORCOM
Let Register Pair DE equal 2130H to test to divide the label between two calls
5BD5H
RST 18H
COMPAR
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: CARRY SET=HL<DE; NO CARRY=HL>DE; NZ=Unequal; Z=Equal)
5BD6H
POP DE
Restore the character position into Register Pair DE
5BD7H
LD A,D
Copy the contents of Register D into Register A
5BD8H
POP DE
Restore the original DE
5BD9H
If the C FLAG (Carry) has been set, JUMP to 2130H.
NOTE: 2130H is the Model I ROM Routine to check to see if there are at least 16 spaces left on the display line and fill that with blanks
5BDCH
JUMP to 2156H.
NOTE: 2156H is the Model I ROM Routine for TAB. It sends a certain number of spaces to the display

5BDFH – Routine when about to insert a line – “EXFIND”

5BDFH
 ↳ “EXFIND”
LD HL,(5B8DH)
LD HL,(PTRFIL)
Preserve PTRFIL because we may be doing an ASCII LOAD and if RUNC gets executed, PTRFIL will get cleared.
5BE2H
LD (40F3H),HL
LD (TEMP2),HL
Save the active file pointer into TEMP2
5BE5H
LD HL,5A77H
LD HL,DIRTMP
Let Register Pair HL equal 5A77H so file 0 will look like it was closed via mode 0
5BE8H
LD (HL),00H
… to prevent the load frile from being closed
5BEAH
LD (5B8FH),HL
LD (FILPTR),HL
Store HL into FILPTR to point it at the dummy FCB.
NOTE: 5B8FH is the storage location for the vector associated with file I/O into file number 1 (i.e., GET 1,x)
5BEDH
RET
RETurn to the caller

5BEEH – Routine when about to insert a line but after RUNC has executed – “EXFIN2”

5BEEH
 ↳ “EXFIN2”
LD HL,(40F3H)
LD HL,(TEMP2)
Fetch where we saved (TEMP2) the active file pointer PTRFIL so as to keep it from being erased by RUNC
5BF1H
LD (5B8DH),HL
LD (PTRFIL),HL
and put it back into PTRFIL where it belongs
5BF4H
LD HL,(5BAFH)
LD HL,(FILPT1)
Similarly, grab the saved copy of FILPTR and store it into Register Pair HL
5BF7H
LD (5B8FH),HL
LD (FILPTR),HL
and put it back into FILPTR where it belongs.
NOTE: 5B8FH is the storage location for the vector associated with file I/O into file number 1 (i.e., GET 1,x)
5BFAH
“EXDSCR”
RET
RETurn to the caller

5BFBH – RET.

5BFBH
RET
RETurn to the caller

5BFCH – See if LINE POSITION is important or not – “EXDSKL”

5BFCH
 ↳ “EXDSKL”
LD HL,(5B8DH)
LD HL,(PTRFIL)
Prepare to see if line position is important
5BFFH
5BFFH
LD A,H
OR L
Since the Z-80 cannot test Register Pair HL against zero, the common trick is to set Register A to equal to Register H, and then OR A against Register L. Only if both Register H and Register L were zero can the Z FLAG be set
5C01H
RET Z
If the Z FLAG (Zero) has been set, then we are not doing disk I/O and, therefore, line position isn’t important as files have an infinite width, so RETurn to the caller
5C02H
POP HL
If we are doing disk I/O then get rid of the return address from the stack
5C03H
and then don’t do a CRLF check via a JUMP to 20E9H.
NOTE: 20E9H is the middle of the Model I ROM Routine for PRINT@. It sends a string to the output device, followed by a space, until it gets an end of statement code

5C06H – Start of the BASIC program (Jumped to at the ORG).

5C06H
LD A,(HL)
Fetch the value held in the memory location pointed to by Register Pair HL and store it into Register A
5C07H
LD (5C98H),A
LD (5C98H),A
Store the value held in Register A into memory location 5C98H, which is a placeholder
5C0AH
LD HL,(40A4H)
LD HL,(40A4H)
Fetch the value held in memory location 40A4H and store it into Register Pair HL.
NOTE: 40A4H is the storage location for the BASIC Program Beginning Pointer in 2 bytes (LSB/MSB)
5C0DH
LD (5C99H),HL
LD (5C99H),HL
Store the value held in Register Pair HL (i.e., the BASIC Program Beginning Pointer) into memory location 5C99H
5C10H
LD HL,(408EH)
LD HL,(MAXFIL)
Fetch the value held in memory location 408EH and store it into Register Pair HL.
NOTE: 408EH is the storage location for the answer to the FILES? question asked at the entry of BASIC
5C13H
LD (5C9BH),HL
LD (5C9BH),HL
Store the value held in Register Pair HL (i.e., the answer to the FILES? question) into memory location 5C9BH
5C16H
LD HL,(40A0H)
LD HL,(40A0H)
Fetch the value held in memory location 40A0H and store it into Register Pair HL.
NOTE: 40A0H is the storage location for the string storage area: 2 Bytes point to the lowest address available for string storage. This is ALSO the top of free memory
5C19H
LD (5C9DH),HL
LD (5C9DH),HL
Store the value held in Register Pair HL (i.e., lowest address available for string storage a/k.a top of free memory) into memory location 5C9DH
5C1CH
LD HL,(4313H)
LD HL,(4313H)
Fetch the value held in memory location 4313H and store it into Register Pair HL. From what I can tell, this represents an exit jump ddress
5C1FH
LD (5D51H),HL
LD (5D51H),HL
Store the value held in Register Pair HL into memory location 5D51H which is the nnnn in a JP nnnn instruction
5C22H
LD HL,5D4DH
LD HL,5D4DH
Let Register Pair HL equal 5D4DH, which is a routine in this BASIC/CMD which tests Register A. If it is 01H then a RETurn is executed, otherwise the JP nnnn referred to above is executed
5C25H
LD (4313H),HL
LD (4313H),HL
Store the value held in Register Pair HL (i.e., the jump point of 5D4DH) into memory location 4313H
5C28H
XOR A
Set Register A to ZERO and clear all Flags
5C29H
LD (4315H),A
LD (4315H),A
Store the value held in Register A into memory location 4315H. I have no idea what 4315H is used for
The next 4 instructions handle the moving of the 39 byte single precision division routine from 18F7-191DH to 4080H-40A5H.
5C2CH
LD DE,4080H
LD DE,4080H
Let Register Pair DE equal 4080H
5C2FH
LD HL,18F7H
LD HL,18F7H
Let Register Pair HL equal 18F7H
5C32H
LD BC,0027H
Let Register Pair BC equal 0027H
5C35H
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing
5C37H
LD HL,(5C9BH)
Fetch the value held in memory location 5C9BH (i.e., the answer to the FILES? question) and store it into Register Pair HL
5C3AH
LD (408EH),HL
LD (MAXFIL),HL
Store the value held in Register Pair HL into memory location 408EH.
NOTE: 408EH is the storage location for the [TAKEN FROM PAGE] TRSDOS 2.3 stores the answer to the FILES? Question
NOTE: 408EH is the storage location for the [TAKEN HACKER HANDBOOK] (16526) Address of USR Routine
5C3DH
LD HL,(4049H)
LD HL,(MEMEND)
Fetch the value held in memory location 4049H and store it into Register Pair HL.
NOTE: 4049H is the storage location for the [TAKEN FROM FK DIS] Top of memory LSB.
NOTE: 4049H is the storage location for the [TAKEN FROM PAGE] DOS MEMORY SIZE. Highest available memory location (On a Model III it is stored at 4411H)
NOTE: 4049H is the storage location for the [TAKEN HACKER HANDBOOK] (16457) Contains Memory Size as shown in the HIMEM value
NOTE: 4049H is the storage location for the HIMEM value (2 bytes)
5C40H
LD (40A0H),HL
LD (40A0H),HL
Store the value held in Register Pair HL into memory location 40A0H.
NOTE: 40A0H is the storage location for the [TAKEN FROM PAGE] String Storage Area: 2 Bytes point to the lowest address available for string storage. This is ALSO the top of free memory. Start of string storage area, set to 50 less than top of memory pointer (at 40BlH) at power-up to provide 50 bytes of string storage area. Changed by use of CLEAR n command (with argument).
NOTE: 40A0H is the storage location for the [TAKEN HACKER HANDBOOK] Address of String area lower boundary
5C43H
LD SP,HL
Copy the contents of Register Pair HL into Register Pair SP
5C44H
LD HL,5D53H
LD HL,5D53H
Let Register Pair HL equal 5D53H / (Decimal: 23891)
5C47H
LD (HL),3AH
Store the value 3AH (ASCII: :) into the memory location pointed to by Register Pair HL
5C49H
INC HL
INCrement the value stored in Register Pair HL by 1
5C4AH
LD (HL),B
Store the value held in Register B into the memory location pointed to by Register Pair HL
5C4BH
INC HL
INCrement the value stored in Register Pair HL by 1
5C4CH
LD (HL),2CH
Store the value 2CH (ASCII: ,) into the memory location pointed to by Register Pair HL
5C4EH
INC HL
INCrement the value stored in Register Pair HL by 1
5C4FH
LD (40A7H),HL
LD (40A7H),HL
Store the value held in Register Pair HL into memory location 40A7H.
NOTE: 40A7H is the storage location for the [TAKEN FROM PAGE] Input Buffer Pointer (in BASIC). The address of the basic keyboard buffer.
Note: Also used by BASIC while encoding and decoding BASIC lines (as during LIST, etc.)
NOTE: 40A7H is the storage location for the [TAKEN HACKER HANDBOOK] Points to Address of Keyboard Buffer + 2
5C52H
LD DE,4152H
LD DE,4152H??????????
Let Register Pair DE equal 4152H
5C55H
LD HL,54C3H
LD HL,54C3H??????????????????
Let Register Pair HL equal 54C3H / (Decimal: 21699)
5C58H
LD BC,0093H
Let Register Pair BC equal 0093H (Decimal: 147)
5C5BH
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing
5C5DH
LD HL,5E56H
LD HL,5E56H??????????????????
Let Register Pair HL equal 5E56H / (Decimal: 24150)
5C60H
LD (HL),00H
Store the value 00H into the memory location pointed to by Register Pair HL
5C62H
GOSUB to 1B8FH.
NOTE: 1B8FH is the middle of the RUN command in the Model I ROM Routine
5C65H
GOSUB to 01C9H.
NOTE: 01C9H is the Model I ROM Routine to clear the screen, select 64 characters and home the cursor. All registers are used
5C68H
LD A,(403EH)
LD A,(CURDOS)
Fetch the value held in memory location 403EH and store it into Register A.
NOTE: 403EH is the storage location for the [TAKEN FROM PAGE] OSVER$: Holds the DOS Version Number. Stored in DCB format. Note on a M3 this is stored in 441FH and on the M4 in 0085H
NOTE: 403EH is the storage location for the [TAKEN FROM PAGE] Unused in non-Disk systems. Real time clock storage locations are kept here. For the Model III this would be 4216H-421CH
5C6BH
CP 22H
CP “"
Compare the value held in Register A against 22H / (Binary:0010 0010) / (Decimal: 34) / (ASCII: ). Results:
  • If Register A equals 22H/34/, the Z FLAG is set.
  • If A < 22H/34/, the CARRY FLAG will be set.
  • if A >= 22H/34/, the NO CARRY FLAG will be set.
5C6DH
If the NC FLAG (No Carry) has been set, JUMP to 5C78H
5C6FH
LD HL,5E57H
LD HL,5E57H??????????????????
Let Register Pair HL equal 5E57H / (Decimal: 24151)
5C72H
GOSUB to 28A7H.
NOTE: 28A7H is the Model I ROM Routine to display a message pointed to by Register Pair HL
5C75H
JUMP to 5C6FH

5C78H – XXXXXXXXXXXXXXXXXXX – “??????”

5C78H
 ↳ “????????”
LD A,(5C98H)
Fetch the value held in memory location 5C98H and store it into Register A
5C7BH
CP 2AH
Compare the value held in Register A against 2AH / (Binary:0010 1010) / (Decimal: 42) / (ASCII: *). Results:
  • If Register A equals 2AH/42/*, the Z FLAG is set.
  • If A < 2AH/42/*, the CARRY FLAG will be set.
  • if A >= 2AH/42/*, the NO CARRY FLAG will be set.
5C7DH
If the NZ FLAG (Not Zero) has been set, JUMP to 5C9FH
5C80H
LD A,(408EH)
LD A,(MAXFIL)
Fetch the value held in memory location 408EH and store it into Register A.
NOTE: 408EH is the storage location for the [TAKEN FROM PAGE] TRSDOS 2.3 stores the answer to the FILES? Question
NOTE: 408EH is the storage location for the [TAKEN HACKER HANDBOOK] (16526) Address of USR Routine
5C83H
GOSUB to 5CD0H
5C86H
LD BC,1A18H
LD BC,1A18H
Let Register Pair BC equal 1A18H / (Decimal: 6680)
5C89H
LD HL,(5C9DH)
LD HL,(5C9DH)
Fetch the value held in memory location 5C9DH (i.e., lowest address available for string storage a/k.a top of free memory) and store it into Register Pair HL
5C8CH
LD (40A0H),HL
LD (40A0H),HL
Store the value held in Register Pair HL into memory location 40A0H.
NOTE: 40A0H is the storage location for the [TAKEN FROM PAGE] String Storage Area: 2 Bytes point to the lowest address available for string storage. This is ALSO the top of free memory. Start of string storage area, set to 50 less than top of memory pointer (at 40BlH) at power-up to provide 50 bytes of string storage area. Changed by use of CLEAR n command (with argument).
NOTE: 40A0H is the storage location for the [TAKEN HACKER HANDBOOK] Address of String area lower boundary
5C8FH
LD HL,(5C99H)
LD HL,(5C99H)
Fetch the value held in memory location 5C99H and store it into Register Pair HL
5C92H
LD (40A4H),HL
LD (40A4H),HL
Store the value held in Register Pair HL into memory location 40A4H.
NOTE: 40A4H is the storage location for the [TAKEN FROM PAGE] BASIC Program Beginning Pointer in 2 bytes (LSB/MSB).
NOTE: 40A4H is the storage location for the [TAKEN HACKER HANDBOOK] Address of start of Basic Program
5C95H
JUMP to 19AEH.
NOTE: 19AEH is in the middle of the Model I ROM Routine to handle the Level II BASIC command mode. It is where an error has occurred and it needs to deal with it

5C98H – RAM Storage Locations – “??????”

5C98H
 ↳ “????????”
DEFB 00H
This is a storage location, initially loaded on start of BASIC (at 5C07H) to contain the value held in the RAM location pointed to by Register Pair HL
5C99H-5C9AH
DEFB 00H 00H
This is a 2-byte storage location, initially loaded on start of BASIC (at 5C0DH) to contain the LSB/MSB of the RAM address of start of a Basic Program
5C9BH-5C9CH
DEFB 00H 00H
This is a 2-byte storage location, initially loaded on start of BASIC (at 5C13H) to contain the answer to the FILES? question which is answered on entry into DOS BASIC
5C9DH-5C9EH
DEFB 00H 00H
This is a 2-byte storage location, initially loaded on start of BASIC (at 5C19H) to contain the lowest address available for string storage a/k/a top of free memory

5C9FH – XXXXXXXXXXXXXXXXXXX – “??????”

5C9FH
 ↳ “????????”
LD HL,5E70H
Let Register Pair HL equal 5E70H / (Decimal: 24176)
5CA2H
GOSUB to 28A7H.
NOTE: 28A7H is the Model I ROM Routine to display a message pointed to by Register Pair HL
5CA5H
GOSUB to 1BB3H.
NOTE: 1BB3H is the Model I ROM Routine to process an INPUT command, complete with the ? prompt
5CA8H
If the C FLAG (Carry) has been set, JUMP to 5C9FH
5CAAH
XOR A
Set Register A to ZERO and clear all Flags
5CABH
LD (408FH),A
Store the value held in Register A into memory location 408FH
5CAEH
RST 10H
GETCHR
Call the EXAMINE NEXT SYMBOL routine at RST 10H. RST 10H bumps HL by 1 and then looks for the first non-space, non-chr$(9), and non-chr$(10) character pointed to by HL. If that character is a number (0-9), the C FLAG is set; otherwise the NC FLAG is set. Z will be set if the character is a 0 or a :. RST 10H exits with HL still pointing to the character it checked, the character it checked in Register A, and BC and DE are unaffected
5CAFH
OR A
Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
5CB0H
LD A,03H
Let Register A equal 03H
5CB2H
If the Z FLAG (Zero) has been set, JUMP to 5CCDH
5CB4H
LD A,(HL)
Fetch the value held in the memory location pointed to by Register Pair HL and store it into Register A
5CB5H
GOSUB to 1E5AH.
NOTE: 1E5AH is the Model I ‘DECBIN’ ROM Routine which converts a 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
5CB8H
CP 56H
CP 56H??????????
Compare the value held in Register A against 56H / (Binary:0101 0110) / (Decimal: 86) / (ASCII: V). Results:
  • If Register A equals 56H/86/V, the Z FLAG is set.
  • If A < 56H/86/V, the CARRY FLAG will be set.
  • if A >= 56H/86/V, the NO CARRY FLAG will be set.
5CBAH
If the NZ FLAG (Not Zero) has been set, JUMP to 5CC0H
5CBCH
LD (408FH),A
LD (408FH),A??????????
Store the value held in Register A into memory location 408FH
5CBFH
RST 10H
GETCHR
Call the EXAMINE NEXT SYMBOL routine at RST 10H. RST 10H bumps HL by 1 and then looks for the first non-space, non-chr$(9), and non-chr$(10) character pointed to by HL. If that character is a number (0-9), the C FLAG is set; otherwise the NC FLAG is set. Z will be set if the character is a 0 or a :. RST 10H exits with HL still pointing to the character it checked, the character it checked in Register A, and BC and DE are unaffected
5CC0H
OR A
Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
5CC1H
If the NZ FLAG (Not Zero) has been set, JUMP to 1997H.
NOTE: 1997H is the Model I ROM Routine to display a SYNTAX ERROR error message
5CC4H
LD A,D
Copy the contents of Register D into Register A
5CC5H
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
5CC6H
If the NZ FLAG (Not Zero) has been set, JUMP to 5C9FH
5CC8H
LD A,E
Copy the contents of Register E into Register A
5CC9H
CP 10H
Compare the value held in Register A against 10H / (Binary:0001 0000) / (Decimal: 16). Results:
  • If Register A equals 10H/16, the Z FLAG is set.
  • If A < 10H/16/, the CARRY FLAG will be set.
  • if A >= 10H/16/, the NO CARRY FLAG will be set.
5CCBH
If the NC FLAG (No Carry) has been set, JUMP to 5C9FH
5CCDH
LD (408EH),A
LD (MAXFIL),A
LD (408EH),A
LD (MAXFIL),A??????????
Store the value held in Register A into memory location 408EH.
NOTE: 408EH is the storage location for the [TAKEN FROM PAGE] TRSDOS 2.3 stores the answer to the FILES? Question
NOTE: 408EH is the storage location for the [TAKEN HACKER HANDBOOK] (16526) Address of USR Routine
5CD0H
INC A
INCrement the value stored in Register A by 1
5CD1H
LD HL,659BH
LD HL,659BH??????????
Let Register Pair HL equal 659BH / (Decimal: 26011)
5CD4H
LD DE,5B8FH
LD DE,5B8FH??????????
Let Register Pair DE equal 5B8FH.
NOTE: 5B8FH is the storage location for the vector associated with file I/O into file number 1 (i.e., GET 1,x)
5CD7H
LD (5BAFH),HL
LD (5BAFH),HL??????????
Store the value held in Register Pair HL into memory location 5BAFH
5CDAH
LD (HL),00H
Store the value 00H into the memory location pointed to by Register Pair HL
5CDCH
EX DE,HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair DE
5CDDH
LD (HL),E
Store the value held in Register E into the memory location pointed to by Register Pair HL
5CDEH
INC HL
INCrement the value stored in Register Pair HL by 1
5CDFH
LD (HL),D
Store the value held in Register D into the memory location pointed to by Register Pair HL
5CE0H
INC HL
INCrement the value stored in Register Pair HL by 1
5CE1H
EX DE,HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair DE
5CE2H
LD BC,0122H
LD BC,0122H??????????
Let Register Pair BC equal 0122H / (Decimal: 290)
5CE5H
ADD HL,BC
LET Register Pair HL = Register Pair HL + Register BC
5CE6H
LD B,A
Copy the contents of Register A into Register B
5CE7H
LD A,(408FH)
LD A,(408FH)??????????
Fetch the value held in memory location 408FH and store it into Register A
5CEAH
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
5CEBH
If the Z FLAG (Zero) has been set, JUMP to 5CEEH
5CEDH
INC H
INCrement the value stored in Register H by 1
5CEEH
LD A,B
Copy the contents of Register B into Register A
5CEFH
DEC A
DECrement the value stored in Register A by 1
5CF0H
If the NZ FLAG (Not Zero) has been set, JUMP to 5CDAH
5CF3H
LD A,(5C98H)
Fetch the value held in memory location 5C98H and store it into Register A
5CF6H
CP 2AH
CP “*”
Compare the value held in Register A against 2AH / (Binary:0010 1010) / (Decimal: 42) / (ASCII: *). Results:
  • If Register A equals 2AH/42/*, the Z FLAG is set.
  • If A < 2AH/42/*, the CARRY FLAG will be set.
  • if A >= 2AH/42/*, the NO CARRY FLAG will be set.
5CF8H
RET Z
If the Z FLAG (Zero) has been set, RETurn to the caller

5CF9H – XXXXXXXXXXXXXXXXXXX – “??????”

5CF9H
 ↳ “????????”
LD (HL),00H
Store the value 00H into the memory location pointed to by Register Pair HL
5CFBH
INC HL
INCrement the value stored in Register Pair HL by 1
5CFCH
LD (40A4H),HL
LD (40A4H),HL??????????
Store the value held in Register Pair HL into memory location 40A4H.
NOTE: 40A4H is the storage location for the [TAKEN FROM PAGE] BASIC Program Beginning Pointer in 2 bytes (LSB/MSB).
NOTE: 40A4H is the storage location for the [TAKEN HACKER HANDBOOK] Address of start of Basic Program
5CFFH
LD HL,0105H
LD HL,0105H??????????
Let Register Pair HL equal 0105H / (Decimal: 261)
5D02H
GOSUB to 28A7H.
NOTE: 28A7H is the Model I ROM Routine to display a message pointed to by Register Pair HL
5D05H
GOSUB to 1BB3H.
NOTE: 1BB3H is the Model I ROM Routine to process an INPUT command, complete with the ? prompt
5D08H
If the C FLAG (Carry) has been set, JUMP to 5CFFH
5D0AH
RST 10H
GETCHR
Call the EXAMINE NEXT SYMBOL routine at RST 10H. RST 10H bumps HL by 1 and then looks for the first non-space, non-chr$(9), and non-chr$(10) character pointed to by HL. If that character is a number (0-9), the C FLAG is set; otherwise the NC FLAG is set. Z will be set if the character is a 0 or a :. RST 10H exits with HL still pointing to the character it checked, the character it checked in Register A, and BC and DE are unaffected
5D0BH
OR A
Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
5D0CH
If the NZ FLAG (Not Zero) has been set, JUMP to 5D1AH
5D0EH
LD HL,(4049H)
LD HL,(MEMEND)
Fetch the value held in memory location 4049H and store it into Register Pair HL.
NOTE: 4049H is the storage location for the [TAKEN FROM FK DIS] Top of memory LSB.
NOTE: 4049H is the storage location for the [TAKEN FROM PAGE] DOS MEMORY SIZE. Highest available memory location (On a Model III it is stored at 4411H)
NOTE: 4049H is the storage location for the [TAKEN HACKER HANDBOOK] (16457) Contains Memory Size as shown in the HIMEM value
NOTE: 4049H is the storage location for the HIMEM value (2 bytes)
5D11H
LD DE,FFF9H
Let Register Pair DE equal FFF9H
5D14H
RST 18H
COMPAR
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: CARRY SET=HL<DE; NO CARRY=HL>DE; NZ=Unequal; Z=Equal)
5D15H
If the C FLAG (Carry) has been set, JUMP to 5D29H
5D17H
EX DE,HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair DE
5D18H
JUMP to 5D29H

5D1AH – XXXXXXXXXXXXXXXXXXX – “??????”

5D1AH
 ↳ “????????”
GOSUB to 1E5AH.
NOTE: 1E5AH is the Model I ‘DECBIN’ ROM Routine which converts a 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
5D1DH
OR A
Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
5D1EH
If the NZ FLAG (Not Zero) has been set, JUMP to 1997H.
NOTE: 1997H is the Model I ROM Routine to display a SYNTAX ERROR error message
5D21H
DEC DE
DECrement the value stored in Register Pair DE by 1
5D22H
LD HL,(4049H)
LD HL,(MEMEND)
Fetch the value held in memory location 4049H and store it into Register Pair HL.
NOTE: 4049H is the storage location for the [TAKEN FROM FK DIS] Top of memory LSB.
NOTE: 4049H is the storage location for the [TAKEN FROM PAGE] DOS MEMORY SIZE. Highest available memory location (On a Model III it is stored at 4411H)
NOTE: 4049H is the storage location for the [TAKEN HACKER HANDBOOK] (16457) Contains Memory Size as shown in the HIMEM value
NOTE: 4049H is the storage location for the HIMEM value (2 bytes)
5D25H
RST 18H
COMPAR
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: CARRY SET=HL<DE; NO CARRY=HL>DE; NZ=Unequal; Z=Equal)
5D26H
EX DE,HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair DE
5D27H
If the C FLAG (Carry) has been set, JUMP to 5CFFH
5D29H
DEC HL
DECrement the value stored in Register Pair HL by 1
5D2AH
EX DE,HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair DE
5D2BH
LD HL,(40A4H)
LD HL,(40A4H)??????????
Fetch the value held in memory location 40A4H and store it into Register Pair HL.
NOTE: 40A4H is the storage location for the [TAKEN FROM PAGE] BASIC Program Beginning Pointer in 2 bytes (LSB/MSB).
NOTE: 40A4H is the storage location for the [TAKEN HACKER HANDBOOK] Address of start of Basic Program
5D2EH
LD BC,012CH
Let Register Pair BC equal 012CH / (Decimal: 300)
5D31H
ADD HL,BC
LET Register Pair HL = Register Pair HL + Register BC
5D32H
EX DE,HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair DE
5D33H
RST 18H
COMPAR
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: CARRY SET=HL<DE; NO CARRY=HL>DE; NZ=Unequal; Z=Equal)
5D34H
If the C FLAG (Carry) has been set, JUMP to 197AH.
NOTE: 197AH is the Model I ROM Routine to display an OUT OF MEMORY error message
5D37H
LD DE,FFCEH
Let Register Pair DE equal FFCEH
5D3AH
LD (40B1H),HL
LD (40B1H),HL??????????
Store the value held in Register Pair HL into memory location 40B1H.
NOTE: 40B1H is the storage location for the [TAKEN FROM PAGE] $MEMTOP. Top of memory pointer. Last usable location for BASIC.
NOTE: 40B1H is the storage location for the [TAKEN HACKER HANDBOOK] Top of Memory Pointer
5D3DH
ADD HL,DE
LET Register Pair HL = Register Pair HL + Register DE
5D3EH
LD (40A0H),HL
LD (40A0H),HL??????????
Store the value held in Register Pair HL into memory location 40A0H.
NOTE: 40A0H is the storage location for the [TAKEN FROM PAGE] String Storage Area: 2 Bytes point to the lowest address available for string storage. This is ALSO the top of free memory. Start of string storage area, set to 50 less than top of memory pointer (at 40BlH) at power-up to provide 50 bytes of string storage area. Changed by use of CLEAR n command (with argument).
NOTE: 40A0H is the storage location for the [TAKEN HACKER HANDBOOK] Address of String area lower boundary
5D41H
GOSUB to 1B4DH.
NOTE: 1B4DH is the Model I ROM Routine to execute a NEW command, but without clearing the screen
5D44H
LD HL,5E7FH
LD HL,5E7FH??????????
Let Register Pair HL equal 5E7FH / (Decimal: 24191)
5D47H
GOSUB to 28A7H.
NOTE: 28A7H is the Model I ROM Routine to display a message pointed to by Register Pair HL
5D4AH
JUMP to 1A19H.
NOTE: 1A19H is the Model I ROM Routine to return to the READY prompt

5D4DH – XXXXXXXXXXXXXXXXXXX – “??????”

5D4DH
 ↳ “????????”
CP 01H
CP 01H??????????
Compare the value held in Register A against 01H / (Binary:0000 0001) / (Decimal: 1). Results:
  • If Register A equals 01H/1, the Z FLAG is set.
  • If A < 01H/1/, the CARRY FLAG will be set.
  • if A >= 01H/1/, the NO CARRY FLAG will be set.
5D4FH
RET Z
If the Z FLAG (Zero) has been set, RETurn to the caller
5D50H
JUMP to nnnnn.
NOTE: nnnn is set at 5C1FH with the value which was stored in 4313H on entry into DISK BASIC

5D53H – STORAGE LOCATIONS – “??????”

5D53H
 ↳ “????????”
DEFS 260
5E57H
DEFM ‘USE TRSDOS 2.2 OR LATER’
5E6EH
DEFB 0DH
5E6FH
NOP
No Operation (Do Nothing)
5E70H
DEFM ‘HOW MANY FILES’
5E7EH
NOP
No Operation (Do Nothing)
5E7FH
DEFM ‘RADIO SHACK DISK BASIC VERSION 2.2’ + 0DH + 00H
5E3A3H
 ↳ “FILNAM”
DEFS 32
Filename gets stored here

5EC3H – Called from 57C5H once we know we have a INPUT#n command to process to validate the n, set up the file buffers, make sure that we then get a comma after the n, and store a modified BC into 5ED5H. On entry HL should point to the character on the instruction line being interpreted right after the INPUT token, Register A will hold that character, and BC will point to the ROM location in the middle of the INPUT routine – “??????”

5EC3H
 ↳ “FILINP”
LD C,01H
LD C,MDSQI
Let Register C equal 01H to force SEQUENTIAL INPUT as the file mode
5EC5H
 ↳ “FILGET”
CP 23H
CP “#”
Check to see if there is a “#” symbol next, so compare the value held in Register A against #. If Register A does NOT equal #, the NZ FLAG is set
5EC7H
RET NZ
If the character following the INPUT token is NOT a #, then we are not doing Disk I/O so RETurn
If we are here, then we have a INPUT# so far.
5EC8H
PUSH BC
Save the revised contents of Register Pair BC (where B remains, but C is now 01H), which is the file mode, to the stack
5EC9H
GOSUB to the next routine at 5EDBH to process the #n part of a GET#n, PUT#n, FIELD#n, INPUT#n, etc. to get the appropriate pointer
5ECCH
POP DE
Put the value held at the STACK into Register Pair DE, where E will be the file mode
5ECDH
CP E
Compare the expected file mode with the actual file mode
5ECEH
If the file modes do not match, then JUMP to 6547H to process a “BAD FILE MODE” error
5ED1H
 ↳ “GDFILM”
RST 08H 2C
SYNCHK “,”
Make sure the next character is a , via a call to RST 08H, which is the COMPARE SYMBOL routine. That routine compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., 2CH which is a ,). If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the A Register and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase
5ED3H
EX DE,HL
Let Register Pair DE = Register Pair HL. Whatever was in DE is not relevant as it will be lost in the next statement
5ED4H
5ED5H
LD H,B
LD L,C
Let Register Pair HL = Register Pair BC
5ED6H
LD (5B8DH),HL
LD (PTRFIL),HL
Store the value held in Register Pair HL (which was the modified BC) into memory location 5ED5H
5ED9H
EX DE,HL
Restore HL back from DE
5EDAH
RET
RETurn to the caller

5EDBH – This is a common subroutine used to process the #n part of a GET#n, PUT#n, FIELD#n, INPUT#n, etc. It will validate the n, and load/set the file vectors – “??????”

5EDBH
 ↳ “FILSCN”
DEC HL
DECrement the value stored in Register Pair HL by 1 to point to the token on the instruction line being interpreted, in preparation for checking the character after the token. So this would be the GET, INPUT, PUT, FIELD, etc. of a GET#, INPUT#, PUT#, FIELD#, test
5EDCH
RST 10H
GETCHR
Call the EXAMINE NEXT SYMBOL routine at RST 10H. RST 10H bumps HL by 1 and then looks for the first non-space, non-chr$(9), and non-chr$(10) character pointed to by HL. If that character is a number (0-9), the C FLAG is set; otherwise the NC FLAG is set. Z will be set if the character is a 0 or a :. RST 10H exits with HL still pointing to the character it checked, the character it checked in Register A, and BC and DE are unaffected
5EDDH
CP 23H
Compare the value held in Register A against 23H (ASCII: #). If the next character (after the token) is a #, the Z FLAG is set
5EDFH
Skip the # — if the next character (after the token) is a #, GOSUB to 1D78H to execute the RST 10H (EXAMINE NEXT SYMBOL) code
5EE2H
Read the file number into the ACCumulator. NOTE: 2337H is the Model I ROM Routine to evaluate the BASIC expression pointed to by HL and return with the result in ACCumulator. Evaluate BASIC string expression (may include constants, BASIC variables, BASIC functions, operators, etc.) and place result in ACCumulator. On entry, HL must point to first character of the string to be evaluated. On exit, HL will point to the string delimiter, which must be an acceptable BASIC expression terminator (such as a zero byte, a colon, a right parenthesis, etc
At this entry point, the ACCumulator has the file number already stored in it.
5EE5H
 ↳ “FILFRM”
Put the file number into the ACCumulator via a GOSUB to 2B1FH which will convert the current result in ACCumulator to an integer and return with the 8-bit result in register A
At this point it is assumed the file number is in A, the file number is returned is in E, D is set to 0, HL is saved, BC is set to point at the file data block for file E, A has the mode of the file and Z FLAG is set if the file is mode 0 (which is NOT OPEN)

At this point we have a token#n and n is in the A Register. Next we need to make sure that whatever that n is, it is less than the number of FILES reserved on entry into BASIC.
5EE8H
 ↳ “FILIDX”
LD E,A
Copy the file number (held in Register A) into Register E
5EE9H
 ↳ “FILID2”
LD A,(408EH)
LD A,(MAXFIL)
Fetch the value the answer to the FILES? question, to permit us to test to see if the file number requested is equal to or less than the number of files reserved on the entry into BASIC
5EECH
CP E
Compare the value held in Register A (the highest allocated number of files that can be open) against the value held in Register E (the value given with regard to the command line being parsed). If the highest allocated number of files that can be open < the value given with regard to the command line being parsed, the CARRY FLAG will be set
5EEDH
If the C FLAG (Carry) has been set, then the file number being requested is bigger than the highest permissible file number, so JUMP to 654AH to throw a “BAD FILE NUMBER” error
5EF0H
LD D,00H
If we are here, then the file number requested on the BASIC command line is permissible. We need to set up a double-byte (16 bit) offset to get the pointer to the file data block, so Let Register D equal 00H
5EF2H
PUSH HL
Save the contents of Register Pair HL to the stack
5EF3H
LD HL,5B8FH
LD HL,FILPTR
Set Register Pair HL to the base of the storage table for 15 2 byte vectors based on the file number being used
5EF6H,5EF7H
ADD HL,DE
ADD HL,DE
Add the table offset twice because each entry is two bytes
5EF8H
LD C,(HL)
The next 3 instructions put the applicable pointer into Register Pair BC. First, fetch the LSB of the file number vector held in in the memory location pointed to by Register Pair HL and store it into Register C
5EF9H
INC HL
INCrement the value stored in Register Pair HL by 1
5EFAH
LD B,(HL)
Fetch the MSB of the file number vector held in in the memory location pointed to by Register Pair HL and store it into Register B
5EFBH
LD A,(BC)
Fetch the file mode (the value held in the memory location pointed to by Register Pair BC) and store it into Register A
5EFCH
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG). This will set the Z FLAG if the file mode isn’t open (i.e., is 0)
5EFDH
POP HL
Restore HL from the stack
5EFEH
RET
RETurn to the caller

5EFFH – Process the MKI$, MKS$ and MKD$ Commands, based on the entry location – “??????”

5EFFH
 ↳ “MKI”
LD A,02H
Let Register A equal 02H, which is the ROM variable type code for integer
5F01H
LD BC,043EH
Z-80 Trick. This will change BC but leave A alone if passed through
5F02H
 ↳ “MKS”
LD A,04H
Entry point for MKS$ routine (which restores a single-precision number to numeric form fter GETting from disk). Let Register A equal 04H, which is the ROM variable type code for single-precision
5F04H
LD BC,083EH
Z-80 Trick. This will change BC but leave A alone if passed through
5F1EH
 ↳ “MKD”
LD A,08H
Entry point for MKD$ routine (which restores a double-precision number to numeric form fter GETting from disk). Let Register A equal 08H, which is the ROM variable type code for double-precision
5F07H
PUSH AF
Save the number of bytes needed to the stack
5F08H
GOSUB to 2819H.
NOTE: 2819H is the Model I ROM Routine to convert the result of arithmetic routines to the proper destination type. At this jump point, HL is preserved
5F0BH
POP AF
Restore the number of bytes needed back into Register A
5F0CH
GOSUB to 2857H.
NOTE: 2857H is the Model I ROM Routine for making room for a new string variable
5F0FH
LD HL,(40D4H)
LD HL,(DSCTMP+1)
Fetch the value held in memory location 40D4H and store it into Register Pair HL.
NOTE: 40D4H is the storage location for the address of the current String
5F12H
GOSUB to 09FFH.
NOTE: 09FFH is the Model I ROM Routine to move a number of bytes (the number depending on the value stored in the VALTYPE) from the ACC into the ARG. ((ARG)=(ACCumulator))
5F15H
JUMP to 2A2BH.
NOTE: 2A2BH is the Model I ROM Routine to cleans the stack and then jumps to 2884H in the string routine

5F18H – Process the CVI, CVS, and CVD commands, based on the entry location – “??????”

5F18H
 ↳ “CVI”
LD A,01H
Entry point for CVI routine (which restores an integer to numeric form fter GETting from disk). Let Register A equal 01H
5F1AH
LD BC,033EH
Z-80 Trick. This will change BC but leave A alone if passed through
5F1BH
 ↳ “CVS”
LD A,03H
Entry point for CVS routine (which restores a single-precision number to numeric form fter GETting from disk). Let Register A equal 03H
5F1DH
LD BC,073EH
Z-80 Trick. This will change BC but leave A alone if passed through
5F1EH
 ↳ “CVD”
LD A,07H
Entry point for CVD routine (which restores a double-precision number to numeric form fter GETting from disk). Let Register A equal 03H
At this point A will be 01H if the CVI function was called, 03H if the CVS function was called, and 07H if the CVD function was called. These are one less than the ROM code for the associated variable type (i.e., 2 = Integer, 4 = Single, etc)
5F20H
PUSH AF
Save the VALTYP (from A) so it doesn’t get destroyed in the next CALL
5F21H
GOSUB to 29D7H.
NOTE: 29D7H is the Model I ROM Routine to check to see if there is enough memory for a string
5F24H
POP AF
Restore the number of characters – 1 back into Register A
5F25H
CP (HL)
Compare the amount of space we allocated for the string (held in (HL)) against the number of characters we need (held in Register A). If A >= (HL) the NO CARRY FLAG will be set
5F26H
If the NC FLAG (No Carry) has been set, JUMP to 1E4AH.
NOTE: 1E4AH is the Model I ROM Routine to display a ?FC ERROR
5F29H
INC A
INCrement the value stored in Register A by 1; so NOW it matches the ROM’s expectations of the what the code is for Integer, Single, and Double
5F2AH
INC HL
INCrement the value stored in Register Pair HL by 1
5F2BH
LD C,(HL)
Fetch the LSB of the variable (held in the memory location pointed to by Register Pair HL) and store it into Register C
5F2CH
INC HL
INCrement the value stored in Register Pair HL by 1
5F2DH
LD H,(HL)
Fetch the MSB of the variable (held in the memory location pointed to by Register Pair HL) and store it into Register H
5F2EH
LD L,C
Copy the LSB of the variable (held in Register C) into Register L, so now Register Pair HL points to the variable
5F2FH
LD (40AFH),A
LD (VALTYP),A
Before we can go to VMOVFM, the VALTYP must be properly set, so set it to a 2 for integer, 3 for string, 4 for single-precision, and 8 for double precision
5F32H
JUMP to 09F7H to move a number of bytes (the number depending on the value stored in the VALTYPE) from the ARG into the ACC. ((ACCumulator)=(ARG))

5F35H – Set up to read a sequential item – “FILIND”

5F35H
 ↳ “FILIND”
EX DE,HL
Swap DE and HL so that the contents of HL are saved
5F36H
LD HL,(5B8DH)
LD HL,(PTRFIL)
We need to see if this is a disk file or not. Fetch the value held in memory location 5B8DH and store it into Register Pair HL
5F39H
5F39H
LD A,H
OR L
Since the Z-80 cannot test Register Pair HL against zero, the common trick is to set Register A to equal to Register H, and then OR A against Register L. Only if both Register H and Register L were zero can the Z FLAG be set
5F3BH
EX DE,HL
Restore the prior contents of HL back into HL
5F3CH
RET Z
If HL=0, then this is NOT a disk file, so RETurn to the caller
5F3DH
POP AF
Clear the return address off of the stack
5F3EH
RST 20H
GETYPE
Check to see if the input is a STRING or a NUMBER by calling RST 20H.
NOTE: The RST 20H routine determines the type of the current value in ACCumulator and returns a combination of STATUS flags and unique numeric values in the A Register according to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • and Double Precision is NZ/NC/P/E and A is 5.
5F3FH
LD BC,2243H
LD BC,DOASIG
Let Register Pair BC equal the address of the DOASIG routine in ROM which will set up the ACCumulator
5F42H
LD DE,2C20H
LD DE,CON1
Let Register D equal a “,” and let Register E equal a “SPACE”
5F45H
If the NZ FLAG (Not Zero) has been set, then it was numeric, so JUMP to INPDOR to read the file
5F48H
LD E,D
Make BOTH terminator values a “,”
5F49H
JUMP to INPDOR to read the file

5F4CH – LINE INPUT Routine to READ CODE FOR ITEM FETCHING FROM SEQUENTIAL INPUT FILES – “DLINE”

5F4CH
 ↳ “DLINE”
Get the file number set up via a GOSUB to FILINP
5F4FH
Read the string to store into via a GOSUB to 260DH.
NOTE: 260DH is the Model I ROM Routine to searche 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)
5F52H
Make sure its a string via a GOSUB to 0AF4H.
NOTE: 0AF4H is the Model I ROM Routine to check a number via a RST 20H call. Returns if VALTYPE=3 (string) else if VALTYPE is not 3 then it generates a TM ERROR. BC, DE, and HL are saved
5F55H
LD BC,2169H
LD BC,FINPRT
Let Register Pair BC equal the FINPRT routine as the RETurn address. That routine resets the device type flag at 409CH to zero (output to video display), also turns off cassette drive if necessary. Routine will call FINDTR before RETurning
5F58H
PUSH BC
Save the contents of Register Pair BC to the stack to act as a return address
5F59H
PUSH DE
Save the pointer to the variable (held in Register Pair DE) to the stack
5F5AH
LD BC,1F31H
LD BC,LETCON
Let Register Pair BC equal the LETCON routine as the RETurn address. Since that routine is part of the LET variable assignment routine it is a great place to exit to when we need to assign
5F5DH
XOR A
Set Register A to ZERO to indicate a string value
5F5EH
LD D,A
Clear the TERMINATOR held in Register D
5F5FH
LD E,A
Clear the TERMINATOR held in Register E
5F60H
 ↳ “INPDOR”
PUSH AF
Save the Value Type (held in Register A) to the stack
5F61H
PUSH BC
Save the return address (held in Register Pair BC) to the stack
5F62H
PUSH HL
Save the pointer to the data coming in (held in Register Pair HL) to the stack
5F63H
 ↳ “NOTNWT”
Top of a loop. Read a character from the disk via a GOSUB to INDSKC
5F66H
If the C FLAG (Carry) has been set, then we have tried to read past the EOF, so JUMP to 6550H to throw that error
5F69H
CP 20H
CP “SPACE”
We want to skip over leading spaces so compare the value held in Register A against (ASCII: “SPACE”). If it is not a “SPACE” the NZ FLAG will be set
5F6BH
If the NZ FLAG (Not Zero) has been set, JUMP to NOTSPC to then skip over numbers
5F6EH
INC D
INCrement the value stored in Register D by 1
5F6FH
DEC D
DECrement the value stored in Register D by 1
5F70H
LOOP back to NOTNWT until D=0 (and the Z FLAG is set)
5F73H
 ↳ “NOTSPC”
CP 22H
CP “””
We need to see if a quoted string is coming in, so compare the value held in Register A against “””. If the character is not a “”” then the NZ FLAG will be set
5F75H
If the character is not a “””, JUMP to NOTQTE
5F78H
LD B,A
If we are here, then we have a quoted string coming in. First, preserve the “”” (from Register A) into Register B
5F79H
LD A,E
If we have that quote then this needs to be a string input so set up to test Register E by copying the contents of Register E into Register A
5F7AH
CP 2CH
CP “,”
Check to see if Register E held a “,”. If it didn’t, the NZ FLAG will be set
5F7CH
LD A,B
Copy the quote back into Register A
5F7DH
If Register E did not hold a “,”, JUMP to NOTQTE
5F80H
LD D,B
Set up the terminators. If we are here, then they both need to be “””, so copy that into Register D …
5F81H
LD E,B
… and into Register E
5F82H
Move past the “”” and read a character from the disk via a GOSUB to INDSKC
5F85H
If the C FLAG (Carry) has been set then we have hit the EOF and are done, so JUMP to QUITSI
5F88H
 ↳ “NOTQTE”
LD HL,(40A7H)
LD HL,(BUFPNT)
Fetch the value held in memory location 40A7H and store it into Register Pair HL.
NOTE: 40A7H is the storage location for the [TAKEN FROM PAGE] Input Buffer Pointer (in BASIC). The address of the basic keyboard buffer.
Note: Also used by BASIC while encoding and decoding BASIC lines (as during LIST, etc.)
NOTE: 40A7H is the storage location for the [TAKEN HACKER HANDBOOK] Points to Address of Keyboard Buffer + 2
5F8BH
LD B,FFH
Let Register B equal FFH, which is the maximum number of characters
5F8DH
 ↳ “LOPCRS”
LD C,A
Top of a loop. Copy the character from Register A into Register C
5F8EH
LD A,D
Prepare to check for a quoted string by copying the terminator held in Register D into Register A
5F8FH
CP 22H
CP “"
Compare the value held in Register A against . If they match, the Z FLAG will get set
5F91H
LD A,C
Restore the character being held in C back into Register A
5F92H
If the Z FLAG (Zero) has been set, then we have a quoted character, meaning that we will not ignore CARRIAGE RETURNS or stop on LINE FEEDS. Bypass that code via a JUMP to 5FC1H
5F95H
CP 0DH
CP “CARRIAGE RETURN”
Compare the character held in Register A against a “CARRIAGE RETURN”. If they are the same, the Z FLAG will get set
5F97H
PUSH HL
Save the destination pointer to the stack
5F98H
If the Z FLAG (Zero) has been set, JUMP to 5FF6H to eat the line feed
5F9BH
POP HL
Restore the destination pointer from the stack
5F9CH
CP 0AH
CP “LINE FEED”
Compare the character held in Register A against a “LINE FEED”. If they do not match, the NZ FLAG will be set
5F9EH
If the character is NOT a “LINE FEED”, then we will test for other terminators via a JUMP to 5FC1H
5FA1H
LD C,A
Copy the current character from Register A into Register C
5FA2H
LD A,E
Copy the OTHER terminator from Register E into Register A
5FA3H
CP 2CH
CP “,
Compare the value held in Register A against , to see if we have a comma in an unquoted string. If we do NOT have a comma, the NZ FLAG will be set
5FA5H
LD A,C
Put the character back into Register A
5FA6H
If we do not have a comma, then GOSUB to 6056H to store the line feed. That routine This routine will set the FLAGS, store a non-Zero character into the buffer at (HL) bumping HL after and DECrementing Register B, RETurning if B isn’t ZERO and POPping BC if it is, before JUMPING to 603DH
5FA9H
Read a character from the disk via a GOSUB to INDSKC
5FACH
If the C FLAG (Carry) has been set then we have hit the EOF and are done, so JUMP to QUITSI
5FAFH
CP 0DH
CP “CARRIAGE RETURN”
Compare the value held in Register A against “CARRIAGE RETURN”. If they DO NOT match, the NZ FLAG will be set
5FB1H
If the NZ FLAG (Not Zero) has been set, JUMP to 5FC1H to see if we can just store the character normally
5FB4H
LD A,E
Copy the TERMINATOR # 2 from Register E into Register A
5FB5H
CP 20H
CP “SPACE”
Compare the value held in Register A against “SPACE”. If Terminator # 2 was reset to be a “SPACE”, the Z FLAG will be set
5FB7H
If Terminator # 2 was reset to be a “SPACE”, JUMP to LPCRGT to ignore the CARRIAGE RETURN
5FBAH
CP 2CH
CP “,”
Compare the value held in Register A against “,”. If the character in Register A is a “,” then the Z FLAG will be set
5FBCH
LD A,0DH
Let Register A equal “CARRIAGE RETURN”
5FBEH
If the Z FLAG (Zero) has been set, then this is a non-quoted string, so JUMP to LPCRGT to ignore the character
5FC1H
 ↳ “NOTQTL”
OR A
Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
5FC2H
If the character is a 00H then we will always ignore it, as it is natural terminator, so so JUMP to LPCRGT to ignore the character
5FC5H
CP D
Compare the value held in Register A against TERMINATOR #1. If they match, the Z FLAG will be set
5FC6H
If they match, then we have hit a terminator, so stop all this via a JUMP to QUITSI
5FC9H
CP E
Compare the value held in Register A against TERMINATOR #2. If they match, the Z FLAG will be set
5FCAH
If they match, then we have hit a terminator, so stop all this via a JUMP to QUITSI
5FCDH
If we are here then we are going to save the character so do that via a GOSUB to STRCHR. That routine sets the FLAGS, stores a non-Zero character into the buffer at (HL) bumping HL after and DECrementing Register B, RETurning if B isn’t ZERO and POPping BC if it is, before JUMPING to 603DH
5FD0H
 ↳ “LPCRGT”
Read a character from the disk via a GOSUB to INDSKC
5FD3H
If the NC FLAG (No Carry) has been set, JUMP to LOPCRS to check to see if we have a terminator
5FD6H
 ↳ “QUITSI”
PUSH HL
Save the pointer held in Register Pair HL to stack
5FD7H
CP 22H
CP “””
Compare the value held in Register A and set the Z FLAG if they match
5FD9H
If the character we stopped at is a “””, then we stopped on a quote then JUMP to 5FE1H to keep all spaces but skip a “,” or “CARRIAGE RETURN”
5FDCH
CP 20H
CP “SPACE”
Compare the value held in Register A SPACE and set the NZ FLAG if they dont match
5FDEH
If the character we stopped at is NOT a “SPACE”, then JUMP to NOSKCR and do not skip spaces
5FE1H
 ↳ “MORSPC”
Top of a loop. Read a character from the disk via a GOSUB to INDSKC
5FE4H
If the C FLAG (Carry) has been set then we are at EOF, so JUMP to NOSKCR
5FE7H
CP 20H
CP “SPACE”
Compare the character held in Register and a “SPACE” and set the Z FLAG if they match
5FE9H
If the character held in Register A is a “SPACE”, JUMP to MORSPC
5FECH
CP 2CH
CP “,”
Compare the value held in Register A against , and set the Z FLAG if they match
5FEEH
If the character is a “,” then JUMP to NOSKCR to skip it
5FF1H
CP 0DH
CP “CARRIAGE RETURN”
Compare the value held in Register A against a “CARRIAGE RETURN” and set the NZ FLAG if they are not the same
5FF3H
If the character is NOT a “CARRIAGE RETURN” then JUMP to BAKUPT to back up past this character
5FF6H
 ↳ “ICASLF”
Read a character from the disk via a GOSUB to INDSKC
5FF9H
If the C FLAG (Carry) has been set then we are at EOF, so JUMP to NOSKCR
5FFCH
CP 0AH
Compare the character held in Register A against a “LINE FEED” and set the N FLAG if they are the same
5FFEH
If character held in Register A is a “LINE FEED”, JUMP to NOSKCR

6001H – LINE INPUT Routine to Move Forward a Certain Number of Characters – “BAKUPT”

6001H
 ↳ “BAKUPT”
LD HL,(5B8DH)
LD HL,(PTRFIL)
Fetch the value held in memory location 5B8DH and store it into Register Pair HL
6004H
LD BC,0007H
LD BC,NMLOFS
Let Register Pair BC equal 0007H / (Binary:0000 0000 0000 0111) / (Decimal: 7)
6007H
ADD HL,BC
Set HL to 7 bytes after PTRFIL
6008H
GOSUB to 600EH
600BH
JUMP to NOSKCR to continue

600EH – LINE INPUT Routine to Back up a Character – “BAKCHR”

600EH
 ↳ “BAKCHR”
DEC (HL)
Back up one character by DECrementing (HL)
600FH
LD A,(HL)
Fetch the character pointed to by HL
6010H
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
6011H
So long as the character is not a 00H, JUMP to 6027H. That will also RETurn
6013H
LD BC,FFFCH
If we are here, then we have gone past the boundary, so set BC to point backwards
6016H
ADD HL,BC
Back up HL
Next, turn on bit 5 of the prior character and write it back out.
6017H
LD A,(HL)
Fetch the character pointed to by Register Pair HL and store it into Register A
6018H
OR 20H
OR Register A against 20H (0010 0000). This has the effect of turning on bit 5
601AH
LD (HL),A
Store the value held in Register A into the memory location pointed to by Register Pair HL
Next, move 9 bytes forward, get the vector into BC, reduce the vector by 1, and write it back out.
601BH
LD BC,0009H
Let Register Pair BC equal 0009H (Decimal: 9)
601EH
ADD HL,BC
LET Register Pair HL = Register Pair HL + Register BC
601FH
LD C,(HL)
Fetch the LSB of the value held in (HL) it into Register C
6020H
INC HL
INCrement the value stored in Register Pair HL by 1
6021H
LD B,(HL)
Fetch the MSB of the value held in (HL) it into Register C
6022H
DEC BC
DECrement the MSB/LSB by 1
6023H
LD (HL),B
Store the updated MSB
6024H
DEC HL
DECrement the value stored in Register Pair HL by 1
6025H
LD (HL),C
Store the updated LSB
6026H
RET
RETurn to the caller

6027H – LINE INPUT Routine. Jumped here if we back up one character and it isn’t a 00H – “??????”

6027H
CP FFH
Compare the value held in Register A against FFH and if they are different set the NZ FLAG
6029H
RET NZ
If the NZ Flag is set then we RETURN to see if we can wrap back
602AH
PUSH HL
Otherwise, we may have to back up since the buffer is only 256 characters. Generically save HL for POPPing just before we RETurn
602BH
PUSH DE
Generically save DE for POPPing just before we RETurn
602CH
LD BC,FFFBH
Let Register Pair BC equal FFFBH to point to the OS DCB
602FH
ADD HL,BC
Offset Register Pair HL by BC
6030H
EX DE,HL
Swap DE and HL, so that the HL pointer is preserved in DE
6031H
GOSUB to XBKSP to back up one record
6034H
If that CALL returns a NZ FLAG, then we have a problem! JUMP to 6561H to process the error based on Register A on entry via a lookup table at 6575H, and then exits with a ROM call to process an error. Routine also loads the value in the selected table entry into 5B8CH
6037H
POP DE
Restore DE from the stack
6038H
POP HL
Restore HL from the stack
6039H
LD (HL),FFH
Store a FFH into the location pointed to by HL to indicate that only character is active
603BH
RET
RETurn to the caller

603CH – LINE INPUT Routine Subroutine. – “NOSKCR”

603CH
 ↳ “NOSKCR”
POP HL
Restore the current position into HL. This is where we are going to store the terminator
603DH
 ↳ “QUIT2B”
LD (HL),00H
Store the terminator (i.e., 00H) into the memory location pointed to by Register Pair HL
603FH
LD HL,(40A7H)
LD HL,(BUFPNT)
Fetch the value held in memory location 40A7H and store it into Register Pair HL.
NOTE: 40A7H is the storage location for an Input Buffer Pointer
6042H
DEC HL
DECrement the value stored in Register Pair HL by 1 because NUMIMK is going to BUMP it first
6043H
LD A,E
Copy the contents of Register E into Register A
6044H
SUB 20H
SUBtract the value 20H from Register A
6046H
If Register E was a “SPACE” then JUMP to NUMIMK read the next character, convert it to binary, POP HL and RETurn
6049H
LD B,00H
If we didn’t jump away, then we need to scan a string literal. Let Register B equal 00H
604BH
GOSUB to 2868H to handle quoted strings
604EH
POP HL
Get back the actual pointer from the stack into Register Pair HL
604FH
RET
RETurn to the caller

6050H – LINE INPUT Routine Subroutine. – “NUMIMK”

6050H
 ↳ “NUMIMK”
RST 10H
GETCHR
We know we have a number. Read the first character via a Call the EXAMINE NEXT SYMBOL routine at RST 10H. RST 10H bumps HL by 1 and then looks for the first non-space, non-chr$(9), and non-chr$(10) character pointed to by HL. If that character is a number (0-9), the C FLAG is set; otherwise the NC FLAG is set. Z will be set if the character is a 0 or a :. RST 10H exits with HL still pointing to the character it checked, the character it checked in Register A, and BC and DE are unaffected
6051H
GOSUB to 0E6CH to convert the ASCII string pointed to by HL to binary. The binary value will be left in ACCumulator and the mode flag will be to the proper value
6054H
POP HL
Restore the Pointer to HL from the STACK
6055H
RET
RETurn to the caller

6056H – This routine will store a character into (HL) – – “STRCHR”.

This routine will set the FLAGS, store a non-Zero character into the buffer at (HL) bumping HL after and DECrementing Register B, RETurning if B isn’t ZERO and POPping BC if it is, before JUMPING to 603DH.
6056H
OR A
Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
6057H
RET Z
If we are dealing with an 00H then don’t store it … RETurn to the caller
6058H
LD (HL),A
Store the character held in Register A into the memory location pointed to by Register Pair HL
6059H
INC HL
INCrement the value stored in Register Pair HL by 1
605AH
DEC B
DECrement the counter stored in Register B by 1
605BH
RET NZ
If the NZ FLAG (Not Zero) has been set, then we have not processed 128 and still have more room in the buffer, so RETurn to the caller
605CH
POP BC
We are out of room, so clear the RETurn that we no longer need from the stack
605DH
JUMP to 603DH to process a special exit

6060H – Prepare for Sequential Input by finding a file and setting up for the INDSKC Routine – “PRGFLI”

6060H
 ↳ “PRGFLI”
LD D,01H
Let Register D equal 01H to signal that we are doing SEQUENTIAL INPUT
6062H
 ↳ “PRGFLI2”
XOR A
Set Register A be the internal file number (which would always be ZERO)
6063H
JUMP to 6474H to scan the file name and disk number

6066H – XXXXXXXXXXXXXXXXXXX – “LRUN”

6066H
 ↳ “LRUN”
RET C
If we have a line number, then the C FLAG (Carry) will have been set, so RETurn to the address in the stack for returning to
6067H
POP AF
Otherwise, get rid of the return address that we no longer need
6068H
LD A,FFH
Let Register A equal FFH for the next instruction
606AH
LD (651FH),A
LD (DOPROT),A
Store the FF into (DOPROT) to permit the running of a protected file
606DH
 ↳ “LRUN2”
OR AFH
OR Register A against AFH to ensure that we have a non-zero to flag a “RUN” command
606FH
PUSH AF
Save RUN/LOAD Flag to the stack
6070H
Finding the file and set up for the INDSKC Routine via a GOSUB to 6060H
6073H
LD A,(408EH)
LD A,(MAXFIL)
Fetch the number of files into Register A
NOTE: 408EH is the storage location for the TRSDOS 2.3 stores the answer to the FILES? Question
6076H
LD (5BB2H),A
LD (LSTFRE+1),A
Store the number of files into LSTFRE+1
6079H
DEC HL
DECrement the value stored in Register Pair HL by 1 so we can check the next character
607AH
RST 10H
GETCHR
Call the EXAMINE NEXT SYMBOL routine at RST 10H. RST 10H bumps HL by 1 and then looks for the first non-space, non-chr$(9), and non-chr$(10) character pointed to by HL. If that character is a number (0-9), the C FLAG is set; otherwise the NC FLAG is set. Z will be set if the character is a 0 or a :. RST 10H exits with HL still pointing to the character it checked, the character it checked in Register A, and BC and DE are unaffected
607BH
If the Z FLAG (Zero) has been set, then the “RUN” option was not selected, so JUMP to 608BH to just LOAD the file
607EH
RST 08H 2C
SYNCHK “,”
If we’re here, then we need to see if we have the RUN option, and, for this, need to make sure the next character is a , via a call to RST 08H, which is the COMPARE SYMBOL routine. That routine compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., 2CH which is a ,). If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the A Register and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase
6080H
RST 08H 52
SYNCHK “R”
If we have the “,” then we also need to make sure we have a “R” after that, so call RST 08H, which is the COMPARE SYMBOL routine which compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., 52H). 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
6082H
If the NZ FLAG (Not Zero) has been set, JUMP to 1997H.
NOTE: 1997H is the Model I ROM Routine to display a SYNTAX ERROR error message
6085H
POP AF
Clear the RUN/LOAD Flag from the stack
6086H
 ↳ “CHNENT”
XOR A
We need to make sure the file isn’t closed, so we will set Register A to ZERO
6087H
LD (408EH),A
LD (MAXFIL),A
Store the 0 into (MAXFIL) to pretend that there aren’t any files.
NOTE: 408EH is the storage location where TRSDOS 2.3 stores the answer to the FILES? Question
608AH
OR F1H
OR Register A against F1H to set the flag to “DO NOT RUN AFTER LOAD”
We need to process a straight LOAD, without any RUN.
608CH
 ↳ “NOTRNL”
LD (5BB1H),A
LD (LSTFRE),A
Store the value held in Register A into memory location 5BB1H, which stores whether we RUN after a LOAD
608FH
LD HL,5A77H
LD HL,DIRTMP
Let Register Pair HL equal the DIRTMP storage location
6092H
LD (HL),00H
Store a value 00H into (DIRTMP)
6094H
LD (5B8FH),HL
LD (FILPTR),HL
Store the DIRTMP storage location to (FILPTR) to mess up the pointer to file 0
6097H
GOSUB to 1B4DH to execute a NEW command, but without clearing the screen
609AH
LD A,(5BB2H)
LD A,(LSTFRE+1)
Fetch the value held in LSTFRE+1 (which should be the saved MAXFIL) and store it into Register A
609DH
LD (408EH),A
LD (MAXFIL),A
Restore MAXFIL from the byte preserved in LSTFRE+1 back in 6076H
60A0H
LD HL,(5BAFH)
LD HL,(FILPT1)
Fetch the value held in memory location FILPT1
60A3H
LD (5B8FH),HL
LD (FILPTR),HL
Store the HL into FILPTR (the vector for the storage for FILE 1)
60A6H
LD (5B8DH),HL
LD (PTRFIL),HL
Store the HL into PTRFIL which also was corrupted, so now we repair it
60A9H
 ↳ “NOTINI”
Read the first character from the disk via a GOSUB to INDSKC
60ACH
If the C FLAG (Carry) has been set, then we have hit the EOF without havign read any characters, so JUMP to the start the Level II BASIC interpreter
60AFH
 ↳ “NTPROL”
INC A
We need to see if the character we just read is a binary character so first INCrement the value stored in Register A by 1
60B0H
If character was not FFH, then this is NOT a binary file so JUMP to 6126H with PTRFIL being non-zero (which will cause INCHR to use INDSKC)
At this point we need to do a binary load. After the load, the file is linged toegther. LSTFRE is used as a flag as to whether to run or not once completed.
60B3H
 ↳ “BINLOD”
LD HL,(40A4H)
LD HL,(TXTTAB)
First, set HL to where we will load the file, which is stored in memory location 40A4H (the storage location for the BASIC Program Beginning Pointer in 2 bytes (LSB/MSB))
60B6H
 ↳ “LPBLDR”
EX DE,HL
Next we need to make sure there is room, so save HL into DE
60B7H
LD HL,(40A0H)
LD HL,(STKTOP)
Fetch the start of the string space (held in memory location 40A0H) and store it into Register Pair HL
60BAH
LD BC,FFAAH
LD BC,-86
Subtract 86 bytes from BC (which will give 86 extra bytes in the next addition)
60BDH
ADD HL,BC
Calculate how much room is available for a program by adding the start (HL) to the length (BC) + 86
60BEH
RST 18H
COMPAR
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: CARRY SET=HL<DE; NO CARRY=HL>DE; NZ=Unequal; Z=Equal)
60BFH
EX DE,HL
Restore the starting address to load BASIC program into back into Register Pair HL
60C0H
If the C FLAG (Carry) has been set then there is not enough room, so we need to clear the garbage and error with an OUT OF MEMORY error via a JUMP to 6103H
60C3H
Read a character from the disk via a GOSUB to INDSKC
60C6H
LD (HL),A
Store the value held in Register A into the memory location pointed to by Register Pair HL
60C7H
INC HL
INCrement the value stored in Register Pair HL by 1
60C8H
If the NC FLAG (No Carry) has been set, JUMP to 60B6H to keep reading in bytes
60CBH
If the NC FLAG wasn’t set, we need to clean things up so GOSUB to 1AF8H to fix the links.
NOTE: 1AF8H is the Model I ROM Routine to fix the line pointers in a BASIC program, most commonly used in renumbering. Registers A, HL and DE are used
60CEH
INC HL
When LINKER exits, it points to 2 00H’s so we need to advance past them. INCrement the value stored in Register Pair HL by 1
60CFH
INC HL
INCrement the value stored in Register Pair HL by 1
60D0H
LD (40F9H),HL
LD (VARTAB),HL
Set the end of program location in RAM by storing HL into 40F9H.
NOTE: 40F9H is the storage location for the simple variables & End Basic Program
60D3H
LD HL,408EH
LD HL,(MAXFIL)
Prepare to close file # 0 by setting Register Pair HL equal 408EH (which is where TRSDOS 2.3 stores the answer to the FILES? Question)
60D6H
LD A,(HL)
Fetch the value held in the memory location pointed to by Register Pair HL and store it into Register A
60D7H
LD (5BB2H),ALD (LSTFRE+1),A
Store the value held in Register A into memory location 5BB2H
60DAH
LD (HL),00H
Store the value 00H into the memory location pointed to by Register Pair HL
60DCH
GOSUB to 1B5DH to set up ARYTAB and STREND and execute a RUN command
60DFH
LD A,(5BB2H)
Restore the number of files. First, fetch the value held in memory location 5BB2H and store it into Register A
60E2H
LD (408EH),A
LD (MAXFIL),A
Store the value held in Register A into memory location 408EH (the storage location where TRSDOS 2.3 stores the answer to the FILES? Question)
60E5H
LD A,(5BB1H)
LD A,(LSTFRE)
Fetch the value held in memory location 5BB1H and store it into Register A
60E8H
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
60E9H
If the Z FLAG (Zero) has been set, JUMP to 1A19H to return to the READY prompt
60ECH
Otherwise JUMP to 1D1EH (Level II BASIC Interpreter routine in the Model I ROM)

60EFH – Zero PTRFIL and close the open disk file – “PRGFIN”

60EFH
 ↳ “PRGFIN”
GOSUB to 2169H to reset PTRFIL, reset the device type flag at 409CH to zero (output to video display), turn off cassette drive if necessary, and then CALLs Disk BASIC link at 41BEH prior to return
60F2H
GOSUB to 62DDH to close File # 0
60F5H
POP HL
Get the RETurn address off of the stack so that we can test to see who called this routine
60F6H
PUSH DE
Temporarily preserve DE because DE is needed for the COMPAR routine
60F7H
LD DE,1A1FH
LD DE,READY+6
Set DE to see if we were called from the READY routine at 1A1FH
60FAH
RST 18H
COMPAR
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: CARRY SET=HL<DE; NO CARRY=HL>DE; NZ=Unequal; Z=Equal)
60FBH
POP DE
Restore DE from the stack
60FCH
PUSH HL
Restore the CALLing address to the stack
60FDH
If the Z FLAG (Zero) has been set, then we were called from the READY routine, so GOSUB to 64F2H (part of the OPEN statement and all directory handling) to test to see what the protection may be
6100H
Re-fetch the text pointer via a JUMP to 1BAFH, which is the Model I ROM Routine to load register pair HL with the current value of the BASIC program pointer and RETurn

6103H – Routine to clear any program in RAM and error out with an OUT OF MEMORY error – “OUTLOD”

6103H
 ↳ “OUTLOD”
GOSUB to 1B4DH to execute a NEW command, but without clearing the screen
6106H
JUMP to 197AH.
NOTE: 197AH is the Model I ROM Routine to display an OUT OF MEMORY error message

6109H – Process the MERGE Command – “MERGE”

6109H
 ↳ “MERGE”
POP BC
Clear off the NEWSTT RETurn address from the stack
610AH
Parse the filename and disk from the MERGE command via a GOSUB to 6060H
610DH
DEC HL
DECrement the value stored in Register Pair HL by 1 in preparation for the RST 10H which starts off with an INC HL
610EH
RST 10H
GETCHR
Call the EXAMINE NEXT SYMBOL routine at RST 10H. RST 10H bumps HL by 1 and then looks for the first non-space, non-chr$(9), and non-chr$(10) character pointed to by HL. If that character is a number (0-9), the C FLAG is set; otherwise the NC FLAG is set. Z will be set if the character is a 0 or a :. RST 10H exits with HL still pointing to the character it checked, the character it checked in Register A, and BC and DE are unaffected
610FH
If the Z FLAG (Zero) has been set, read the file via a JUMP to 6118H
6112H
Otherwise we have a problem, so first GOSUB to 60EFH to close out everything and then …
6115H
… JUMP to 1997H to display a SYNTAX ERROR error message

6118H – Part of the MERGE Command – Jumped Here After SYNTAX Check – “OKGETM”

6118H
 ↳ “OKGETM”
XOR A
Since you cannot automatically RUN after a merge, prepare to set the system for that. First, set Register A to ZERO and clear all Flags
6119H
LD (5BB1H),A
LD (LSTFRE),A
Store the 0 into LSTFRE to signify “no auto-run”
611CH
Read a character from the file/disk established by PTRFIL via a GOSUB to INDSKC
611FH
If the C FLAG (Carry) has been set then we have hit EOF, so JUMP to the Level II BASIC interpreter
6122H
INC A
Test to see if this is a binary file (i.e., the first byte is FFH) by INCrementing the value stored in Register A by 1
6123H
If the Z FLAG (Zero) has been set, then this was a BINARY file, then JUMP to 6547H to process a “BAD FILE MODE” error
6126H
 ↳ “MAINGO”
LD HL,(5B8DH)
LD HL,(PTRFIL)
Fetch the file pointer from 5B8DH into HL
6129H
LD BC,0007H
LD BC,NMLOFC
Let Register Pair BC equal 0007H to act as an offset to the next record number
612CH
ADD HL,BC
Set Register Pair HL to point to the next record number (i.e., PTRFIL + 7)
612DH
Back up one character via a GOSUB to 600EH
6130H
JUMP to the start of the Level II BASIC interpreter

6133H – This is the dispatch for a direct statement
– “DIRDO”

6133H
 ↳ “DIRDO”
RET C
If the C FLAG (Carry) has been set, then we are in the middle of a LINE INPUT, so RETurn to the caller
6134H
POP AF
Clear the RETurn address from the stack
6135H
PUSH HL
Generally save the pointer in HL (will be POPped after the next few instructions)
6136H
LD HL,(5B8DH)
LD HL,(PTRFIL)
Fetch the file pointer into HL
6139H
6139H
LD A,H
OR L
Since the Z-80 cannot test Register Pair HL against zero, the common trick is to set Register A to equal to Register H, and then OR A against Register L. Only if both Register H and Register L were zero can the Z FLAG be set
613BH
LD DE,0084H
LD DE,ERRFDR
Let Register Pair DE equal 0084H for a DIRECT STATEMENT IN FILE error
613EH
If PTRFIL was ZERO it means we were not reading a file, so we would throw this error only if we were reading a file. SO .. only if NZ is set do we JUMP to 19A2H to display the error message applicable to the error code held in Register E
6141H
POP HL
If we are here, then the statement at issue was entered instead of being read from a file. Restore the pointer back to HL
6142H
Check the FILE PROTECTION byte via a GOSUB to 64F2H (which handles the OPEN statement and all directory handling)
6145H
JUMP to 1D5AH to handle a directly entered command

6148H – Process the SAVE Command – ASCII or Binary – “SAVE”

6148H
 ↳ “SAVE”
LD D,02H
LD D,MDSQO
Let Register D equal 02H to clear whatever was in D
614AH
GOSUB to 6062H to read the file name and the disk number and look it up. This entry starts with a XOR A to clear all flags and Register A
614DH
DEC HL
Back up HL by 1 character since the GETCHR routine INCrements HL as its first step
614EH
RST 10H
GETCHR
Call the EXAMINE NEXT SYMBOL routine at RST 10H. RST 10H bumps HL by 1 and then looks for the first non-space, non-chr$(9), and non-chr$(10) character pointed to by HL. If that character is a number (0-9), the C FLAG is set; otherwise the NC FLAG is set. Z will be set if the character is a 0 or a :. RST 10H exits with HL still pointing to the character it checked, the character it checked in Register A, and BC and DE are unaffected
614FH
If the Z FLAG (Zero) has been set, then there are no more characters, so we default to a BINARY save, so JUMP to 6159H
6152H
RST 08H 2C
SYNCHK “,”
If we are here then there were more characters to read, which could only possibly be “,A” to be valid. So first, make sure the next character is a , via a call to RST 08H, which is the COMPARE SYMBOL routine. That routine compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., 2CH which is a ,). If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the A Register and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase
6154H
RST 08H 41
SYNCHK “A”
Call RST 08H, which is the COMPARE SYMBOL routine which compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., 41H). 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
6156H
If we are here then we got a “,A” at the end, so we JUMP to 2B2EH to let the LIST command handle this output

6159H – SAVE Command Routine – Handle a BINARY (i.e., not ASCII) Save – “BINSAV”

6159H
 ↳ “BINSAV”
LD A,FFH
A binary save will always start with a FFH
615BH
 ↳ “BINPSV”
Send to a file via a GOSUB to 631CH
615EH
LD HL,(40F9H)
LD HL,(VARTAB)
Fetch the STOP POINT from VARTAB into Register Pair HL.
NOTE: 40F9H is the storage location for the address of simple variables & End Basic Program
6161H
EX DE,HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair DE
6162H
LD HL,(40A4H)
LD HL,(TXTTAB)
Fetch the START POINT from TXTTAB and store it into Register Pair HL.
NOTE: 40A4H is the storage location for the BASIC Program Beginning Pointer in 2 bytes (LSB/MSB)
6165H
 ↳ “BSAVLP”
RST 18H
COMPAR
loop. First, make sure we still have characters to process via a call to 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: CARRY SET=HL<DE; NO CARRY=HL>DE; NZ=Unequal; Z=Equal)
6166H
If the Z FLAG (Zero) has been set then we have reached the end of the program, so JUMP to 60EFH to re-get the TEXTR pointer and close file # 0
6169H
LD A,(HL)
If we are here, then there are still bytes to be read (i.e., we haven’t hit the end pointed to by DE). Fetch the data (held in the memory location pointed to by Register Pair HL) and store it into Register A
616AH
INC HL
INCrement the value stored in Register Pair HL by 1 to point to the next byte
616BH
PUSH DE
Save the STOP POINT IN RAM (held in Register Pair DE) to the stack
616CH
GOSUB to 631CH to send the character to the file
616FH
POP DE
Restore the STOP POINT IN RAM back into Register Pair DE
6170H
JUMP to 6165H

6173H – Process the CLOSE Command – “CLOSE”

6173H
 ↳ “CLOSE”
LD BC,62DDH
LD BC,CLSFIL
Let Register Pair BC with a return address of CLSFIL
6176H
LD A,(408EH)
LD A,(MAXFIL)
Fetch the highest number of files reserved from MAXFIL, which is the storage location for the TRSDOS 2.3 FILES? Question
6179H
 ↳ “PTALLR”
If we entered this routine with the NZ FLAG set, then we are not yet at the end of a statement and need to scan arguments, so JUMP to RTLOOP
617CH
PUSH HL
if we entered this routine with the Z FLAG, then continue. Save the text pointer (held in Register Pair HL) to the stack
617DH
 ↳ “MRALL”
PUSH BC
Save the service routine’s address (held in Register Pair BC) to the stack
617EH
PUSH AF
Save the file number (held in Register Pair AF) to the stack
617FH
LD DE,6185H
LD DE,RETALL
Put a return address of RETALL into the stack
6182H
PUSH DE
Save the return address to the stack
6183H
PUSH BC
Save the service routine’s address (held in Register Pair BC) to the stack
6184H
RET
RETurn to the caller

6185H – XXXXXXXXXXXXXXXXXXX – “RETALL”

6185H
 ↳ “RETALL”
POP AF
Restore the file number to close from the stack into Register A
6186H
POP BC
Restore the service routine’s address (held in Register Pair BC) from the stack
6187H
DEC A
DECrement the file number (stored in Register) A by 1
6188H
If the P FLAG is set, loop back to MRALL for more arguments
618BH
POP HL
Restore the text pointer from the stack into Register Pair HL
618CH
RET
RETurn to the caller

618DH – XXXXXXXXXXXXXXXXXXX – “RETRTS”

618DH
 ↳ “RETRTS”
POP BC
Reestore the service routine’s address into Register Pair BC
618EH
POP HL
Restore the text pointer from the stack into Register Pair HL
618FH
LD A,(HL)
Fetch the next character to see if there are any more arguments
6190H
CP 2CH
CP “,”
If there are more arguments, they need to be separated by a “,” so compare the value held in Register A against a , and set the Z FLAG if they match, and the NZ FLAG if they don’t
6192H
RET NZ
If the NZ FLAG (Not Zero) has been set, then we didn’t get a “,” when we expected one, so RETurn to the caller
6193H
RST 10H
GETCHR
If we are still here, then we got a comma, which means that there are more arguments. Call the EXAMINE NEXT SYMBOL routine at RST 10H. RST 10H bumps HL by 1 and then looks for the first non-space, non-chr$(9), and non-chr$(10) character pointed to by HL. If that character is a number (0-9), the C FLAG is set; otherwise the NC FLAG is set. Z will be set if the character is a 0 or a :. RST 10H exits with HL still pointing to the character it checked, the character it checked in Register A, and BC and DE are unaffected
6194H
 ↳ “RTLOOP”
PUSH BC
Save the service routine’s address (held in Register Pair BC) to the stack
6195H
LD A,(HL)
Fetch the value held in the memory location pointed to by Register Pair HL and store it into Register A
6196H
CP 23H
The CLOSE command can have an option “#”, so let’s see if we got that. Compare the value held in Register A against #). If they match, set the Z FLAG otherwise set the NZ FLAG
6198H
If we got a “#” then skip over it via a GOSUB to 1D78H to do another RST 10H (EXAMINE NEXT SYMBOL) code
619BH
Get the next character via a GOSUB to 2B1CH
619EH
EX (SP),HL
EXchange (SP) and HL, so that HL now holds the service address and the text pointer is at the stack
619FH
PUSH HL
Save the service routine’s address (held in Register Pair HL) to the stack
61A3H
PUSH DE
Save the contents of Register Pair DE (which will act as the RETurn address) to the stack
61A4H
JP (HL)
JUMP to HL (which, in the case of a CLOSE instruction is CLSFIL) to actually do the function

61A5H – Close ALL Files – “CLSALL”

61A5H
 ↳ “CLSALL”
PUSH DE
Save the contents of Register Pair DE to the stack
61A6H
PUSH BC
Save the contents of Register Pair BC to the stack, as STKINI will need it and “CLOSE” overwrites it with CLSFIL
61A7H
XOR A
Set Register A to ZERO so that ALL files will be closed
61A8H
GOSUB to 6173H to process a CLOSE command
61ABH
POP BC
Put the value held at the STACK into Register Pair BC
61ACH
POP DE
Put the value held at the STACK into Register Pair DE
61ADH
XOR A
Prepare the return values of A=0 and Z FLAG
61AEH
RET
RETurn to the caller

61AFH – Process the FIELD Command – “FIELD”

61AFH
 ↳ “FIELD”
GOSUB to 5EDBH to process the #n part of a GET#n, PUT#n, FIELD#n, INPUT#n, etc. This will be the “data block pointer”
61B2H
If the Z FLAG (Zero) has been set from that CALL, then the file was not open, so JUMP to 654AH to throw a “BAD FILE NUMBER” error
61B5H
SUB 03H
SUB MDRND
We know the file is open, so now we need to make sure that the file is a RANDOM FILE. To do this we need to test Register A to see if it is 3. To do THAT, first SUBtract the value 03H from Register A
61B7H
If the NZ FLAG (Not Zero) has been set then Register A wasn’t 3 to begin with, meaning it was not a RANDOM file, so JUMP to 6547H to process a “BAD FILE MODE” error
61BAH
EX DE,HL
EXchange DE and HL so that the text pointer is preserved in Register Pair DE
61BBH
LD HL,000BH
LD HL,NMLOFC+4
Let Register Pair HL equal 000BH (Decimal: 11)
61BEH
ADD HL,BC
Let Register Pair HL point to 11 bytes after the DATA BLOCK pointer
61BFH
LD A,(HL)
Fetch the record size (held at the DATA BLOCK POINTER + 11 bytes)
61C0H
LD (651EH),A
LD (FLRL),A
Store the record size into FLRL (tracking the logical record size)
61C3H
XOR A
Set Register A to ZERO and clear all Flags. Register B, which will be a byte counter, will be reset to 0 because of this
61C4H
EX DE,HL
EXchange DE and HL so that DE now holds the DATA BLOCK POINTER + 11 and HL holds the text pointer
61C5H
LD DE,0022H
LD DE,DATOFS
Let Register Pair DE equal 0022H (Decimal: 34), so that it will be an offset to point to the data
61C8H
 ↳ “LOPFLD”
EX DE,HL
EXchange DE and HL so that the text pointer is preserved into Register Pair DE
61C9H
ADD HL,BC
LET Register Pair HL = the DATA BLOCK POINTER + 11 + 34, so that it points to the data in the data block
61CAH
LD B,A
Set up a counter to count the bytes processed in the data area
61CBH
EX DE,HL
EXchange DE and HL so that HL now holds the text pointer, and DE holds the pointer into the DATA area
61CCH
LD A,(HL)
Fetch the next character on the line being interpreted
61CDH
CP 2CH
CP “,”
Compare the value held in Register A against a ,. They match, set the Z FLAG, otherwise set the NZ FLAG
61CFH
RET NZ
If the NZ FLAG (Not Zero) has been set, then there was no comma, so we are done processing FIELD entries and so we RETurn to the caller
61D0H
PUSH DE
If we are here, then we have more field entries to process. First, save the pointer into the data back (held in Register Pair DE) to the stack
61D1H
PUSH BC
Save Register B (whcih is tracking the number of characters allocated) to the stack
61D2H
Read a number into Register (A) via a GOSUB to GTBYTC which the Model I ROM Routine to evaluate a number at the location of the current BASIC program pointer in HL and return with the result in register A
61D5H
PUSH AF
Save the newly fetched number (held in Register A) to the stack
61D6H
RST 08H 41
SYNCHK “A”
So far we have a FIELD, a file number, and a number of bytes. Next we need the word “AS”, so we have to check for those 2 letters. Call RST 08H, which is the COMPARE SYMBOL routine which compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., 41H). 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
61D8H
RST 08H 53
SYNCHK “S”
Call RST 08H, which is the COMPARE SYMBOL routine which compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., 53H). 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
61DAH
Now we have “Field x, nnn AS”, so we need the pointer to the chosen variable name next. Process that by first doing a GOSUB to 260DH to search 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)
61DDH
After thatn we GOSUB to 0AF4H to check a number via a RST 20H call. Returns if VALTYPE=3 (string) else if VALTYPE is not 3 then it generates a TM ERROR. BC, DE, and HL are saved
61E0H
POP AF
Restore the number of characters being assigned in this part of the FIELD statement from the STACK into Register Pair AF
61E1H
POP BC
Restore the counter of the number of characters already committed from the STACK into Register Pair BC
61E2H
EX (SP),HL
EXchange (SP) and HL so that HL will now be the pointer into the DATA BLOCK and the text pointer will be at the stack
61E3H
LD C,A
Preserve the number of characters being assigned in this part of the FIELD statement into Register C
61E4H
ADD A,B
Augment the cumulative number of characters (tracked in B) by the number being current assigned (held in A); result in A
61E5H
If there was no overflow (i.e., the NC FLAG has been set), then we are all good, so JUMP to 61EBH
61E8H
If the NZ FLAG (Not Zero) has been set, then JUMP to 655CH to throw an error
61EBH
 ↳ “FEVSOK”
LD B,A
Put the field position into Register B
61ECH
LD A,(651EH)
LD A,(FLRL)
Fetch logical record length from FLRL and store it into Register A
61EFH
CP B
Compare the filed position (in Register B) against the applicable logical record length (in Register A). If A < B, the CARRY FLAG will be set
61F0H
If the NC FLAG is set, then the field position is less than the logocal record length and we are OK so JUMP to GOODFL
61F2H
OR A
There’s another way we can be good as well, if the record size is zero, so set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
61F3H
If the NZ FLAG (Not Zero) has been set, then JUMP to 655CH to throw an error
61F6H
 ↳ “GOODFL”
LD A,B
Copy the field position from Register B into Register A
61F7H
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
61F8H
EX DE,HL
EXchange DE and HL so that HL now points to the string descriptor and DE points to the data block
61F9H
LD (HL),C
Store length (held in Register C) into the string descriptor pointed to by Register Pair HL
61FAH
INC HL
INCrement the value stored in Register Pair HL by 1 (to now point to the LSB of the string variable)
61FBH
LD (HL),E
Store the LSB of the pointer to the data block as the LSB of the applicable string variable
61FCH
INC HL
INCrement the value stored in Register Pair HL by 1 (to now point to the MSB of the string variable)
61FDH
LD (HL),D
Store the MSB of the pointer to the data block as the MSB of the applicable string variable
61FEH
LD B,00H
Let Register B equal 00H so that C can be used for 16 bit arithmetic as it wil be the double byte offset to the data pointeer
6200H
POP HL
Restore the text pointer from the STACK into Register Pair HL
6201H
If HL didn’t hit 256 yet, go back for more via a JUMP to 61C8H
6204H
LD A,C
We next need to test to see how much we added, so we copy the contents of Register C into Register A
6205H
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
6206H
RET NZ
If we did not add 256 then pass through. If we hit 256, and the NZ FLAG (Not Zero) has been set, RETurn to the caller
6207H
LOOP back to see if there are more “AS” clauses via a LOOP BACK to LOPFLD

620AH – Process the LSET and RSET Commands – “LSET” and “RSET”

The format of the LSET and RST command is LSET STRINGVARiable = STRINGEXPression.

If STRINGVAR points to an I/O buffer, use the string size to justify the string. If, instead, STRINGVAR is a literal, we will need to make a new variable with the length that matches the literal. If, instead, STRINGVAR points to string space, use it.

If the length of the variable is zero, return the null string

If a copy must be created, and STRINGEXP is a temporary string storage location, then use this space over unless length STRINGVAR greater than STRINGEXP.
620AH
 ↳ “RSET”
OR 37H
F6H 37H
Z-80 Trick. If jumped here, then the [1] OR will occur, which, among other things, resets the CARRY FLAG and [2] the next instruction will be invisible
620BH
 ↳ “LSET”
SCF
37H
This only gets processed if jumped to. Set the LSET flag by setting the CARRY flag
620CH
PUSH AF
Preserve the RSET/LSET flag (carry bit)
620DH
We need to get the pointer to the STRINGVAR so we GOSUB to 260DH to search 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)
6210H
And, as usual, once we run a PTRGET we need to verify that it is, in fact, a string variable so we GOSUB to 0AF4H to check a number via a RST 20H call. Returns if VALTYPE=3 (string) else if VALTYPE is not 3 then it generates a TM ERROR. BC, DE, and HL are saved
6213H
PUSH DE
Save the pointer to the string’s descriptor to the stack
6214H
RST 08H D5
SYNCHK “=”
So far we have either LSET or RSET and a valid string variable. The next character MUST be an “=” so we Call RST 08H, which is the COMPARE SYMBOL routine which compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., D5H). 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
6216H
Now we have “LSET/REST valid-string-variable =”, so we need to process the STRINGEXPression. To do that we GOSUB to FRMEVL to evaluate the BASIC expression pointed to by HL and return with the result in ACCumulator. Evaluate BASIC string expression (may include constants, BASIC variables, BASIC functions, operators, etc.) and place result in ACCumulator. On entry, HL must point to first character of the string to be evaluated. On exit, HL will point to the string delimiter, which must be an acceptable BASIC expression terminator (such as a zero byte, a colon, a right parenthesis, etc.)
6219H
POP BC
Restore the pointer to the string’s descriptor from the stack into DE
621AH
EX (SP),HL
EXchange (SP) and HL so that the text pointer will move to the STACK and the RSET/LSET flag will move to HL
621BH
PUSH HL
Save the RSET/LSET flag (held in Register Pair HL) to the stack
621CH
PUSH BC
Save the pointer to the string’s descriptor to the stack
621DH
GOSUB to 29D7H to check to see if there is enough memory for the string; it not it will error out
6220H
LD B,(HL)
FRESTR messes with the stack so now HL will point to the string descriptor of STRINGVAR. Fetch the length of STRINGVAR into Register B
6221H
EX (SP),HL
EXchange (SP) and HL so that HL now points to the descriptor of the STRINGEXPressiona nd the (SP) has the descriptor of the STRINGVariable. Note: I am making a guess as to the order here
6222H
LD A,(HL)
Fetch the length of STRINGEXP into Register A
6223H
LD C,A
Copy the length of STRINGEXP into Register C, so now Register Pair BC has both lengths
6224H
PUSH BC
Save the combination both string lengths to the stack
6225H
PUSH HL
Save the pointer to the string descriptor (no clue which one) to the stack
6226H
PUSH AF
Save the contents of Register Pair AF, which should hold whether or not the string pointer was to the temporary string storage location or not, to the stack
6227H
INC HL
INCrement the value stored in Register Pair HL (i.e. the pointer to the STRINGExpression descriptor) by 1
We are not going to need to see if STRINGExpression is a variable or a literal.
6228H
LD E,(HL)
Fetch the LSB of the STRINGExpression and store it into Register E
6229H
INC HL
INCrement the value stored in Register Pair HL by 1
622AH
LD D,(HL)
Fetch the MSB of the and store it into Register D
622BH
OR A
Check Register A (which should hold the length of STRINGVAR)
622CH
If the Z FLAG (Zero) has been set, meaning STRINGVAR is null, then don’t change it and just JUMP to RETCUR
622FH
LD HL,(40A4H)
LD HL,(TXTTAB)
Fetch the BASIC Program Beginning Pointer in 2 bytes (LSB/MSB), held in memory location 40A4H and store it into Register Pair HL
6232H
RST 18H
COMPAR
Next we want to see if the string variable is in the disk buffer so 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: CARRY SET=HL<DE; NO CARRY=HL>DE; NZ=Unequal; Z=Equal)
6233H
If HL>DE then the NC FLAG (No Carry) will have been set, then the string variable is in the disk buffer, so we can use it. JUMP to OLDSTR
6236H
LD HL,(40F9H)
LD HL,(VARTAB)
OK, we know that the variable is not in the disk buffer, so next let’s check it against the pointer to the end of a BASIC program ram. If its within this, then it is a literal string and not a simple variable
6239H
RST 18H
COMPAR
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: CARRY SET=HL<DE; NO CARRY=HL>DE; NZ=Unequal; Z=Equal)
623AH
If HL (the end of the BASIC program) < DE (the pointer to STRINGEXPression), then the C FLAG (Carry) will have been set, and the variable is in string space, so we can use it. JUMP to 6265H
If we are here, then we are dealing with a literal string being put into the STRINGVariable, so we need to make new string. If STRINGEXP was a temporary, it has been freed. If the length of STRINGEXP is greater than or equal to the length if STRINGVAR, then GETSPA can be called and no garbage collection can occur so TEMP can be reused. If STRINGVAR is greater, must get a TEMP to point to STRINGEXP. If it was a TEMP, then call GETSPA which in this case can garbage collect.
623DH
LD E,C
Put the number of bytes to allocate into Register E
623EH
LD D,00H
Let Register D equal 00H, so now Register Pair DE = the number of bytes to allocate
6240H
LD HL,(40A0H)
LD HL,(STKTOP)
Fetch the String Storage Area (held in memory location 40A0H) and store it into Register Pair HL
6243H
ADD HL,DE
LET Register Pair HL = the string storage area (HL) plus the length of the string we need to allocate (Register DE)
6244H
EX DE,HL
EXchange DE and HL so that DE now holds the location of the string storage area if we included this new variable and HL will be the length of the variable we need to create
6245H
LD HL,(40D6H)
LD HL,(FRETOP)
Fetch the next free byte in string storage area (held in memory location 40D6H) and store it into Register Pair HL
6248H
GOSUB to 1C90H to do a RST 18H (COMPARE DE:HL)
624BH
If CARRY SET=HL<DE then the C FLAG (Carry) will have been set, then the string pointer was actually to the temporary string space, so we need to JUMP to 62A0H
624EH
 ↳ “MADESC”
POP AF
Put the value held at the STACK into Register Pair AF
624FH
LD A,C
Put the length of STRINGVAR into Register A
6250H
GOSUB to 28BFH to see if there is enough string space for the new string. This will also garbage collect. On Exit, DE points to the string; and if there wasn’t room, an ?OS ERROR will get thrown
6253H
POP HL
Put the the pointer to the string descriptor of STRINGVAR (that’s a guess) into Register Pair HL
6254H
POP BC
Put the both lengths value held at the STACK into Register Pair BC
6255H
EX (SP),HL
EXchange (SP) and HL so that HL now holds the string descriptor for STRINGEXP, and the pointer to STRINGVAR is now at the stack
6256H
PUSH DE
Save the pointer to the new string we made via GETSPA to the stack
6257H
PUSH BC
Save both lengths value to the stack
6258H
GOSUB to 29D7H to see if there is enough memory for the string
625BH
POP BC
FRESTR does a POP and maybe its subroutines to more stack stuff, so at this point I have no idea really what’s where. The next 5 instructions are to put the stack back to where it was before
625CH
POP DE
Put the value held at the STACK into Register Pair DE
625DH
EX (SP),HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair SP
625EH
PUSH BC
Save the contents of Register Pair BC to the stack
625FH
PUSH HL
Save the contents of Register Pair HL to the stack
6260H
INC HL
INCrement the value stored in Register Pair HL by 1. HL should be pointing to the 2nd byte of STRINGVAR
6261H
LD (HL),E
Fetch the LSB of STRINGVAR into Register E
6262H
INC HL
INCrement the value stored in Register Pair HL by 1
6263H
LD (HL),D
Fetch the LSB of STRINGVAR into Register D
6264H
PUSH AF
Save the contents of Register Pair AF to the stack
6265H
 ↳ “OLDSTR”
POP AF
Put the value held at the STACK into Register Pair AF
6266H
POP HL
Put the string descritor for STRINGVAR into Register Pair HL
6267H
INC HL
INCrement the value stored in Register Pair HL by 1 to now point to the LSB of STRINGVAR
6268H
LD E,(HL)
Fetch the LSB of STRINGVAR into Register E
6269H
INC HL
INCrement the value stored in Register Pair HL by 1 to now point to the MSB of STRINGVAR
626AH
LD D,(HL)
Fetch the MSB of STRINGVAR into Register D
626BH
POP BC
Fetch the string lengths from the stack into Register Pair BC
626CH
POP HL
Fetch the string descriptor pointer to STRINGEXP into Register Pair HL
626DH
PUSH DE
Save pointer to STRINGVAR to the stack
626EH
INC HL
INCrement the value stored in Register Pair HL by 1 to now point to the LSB of STRINGEXP
626FH
LD E,(HL)
Fetch the LSB of STRINGEXP into Register E
6270H
INC HL
INCrement the value stored in Register Pair HL by 1 to now point to the MSB of STRINGEXP
6271H
LD D,(HL)
Fetch the MSB of STRINGEXP into Register D
6272H
EX DE,HL
EXchange DE and HL, so that HL now holds the address of the contents of STRINGEXP and DE now holds the address of the contents of STRINGVAL
6273H
POP DE
Restore the pointer to STRINGVAR from the stack into Register Pair DE
6274H
LD A,C
Put the length of STRINGVAR into Register A
6275H
CP B
Compare the the length of STRINGVAR against the length of STRINGEXP. if the length of STRINGVAR >= the length of STRINGEXP, the NO CARRY FLAG will be set
6276H
If the NC FLAG (No Carry) has been set, then amount allocated to STRINGVAR is more than the length of STRINGEXP, so we can hold it just fine — JUMP to 627AH
6279H
LD B,A
Copy the number of bytes to copy into Register B
627AH
 ↳ “FILDOK”
SUB B
LET Register A = Register A – Register B
627BH
LD C,A
Put the number of blanks we need to fill in for the LSET/RSET into Register C
627CH
POP AF
Fetch the LSET or RSET flag from the stack into Register F
627DH
If the NC FLAG (No Carry) has been set then we have a “RSET” to process, so GOSUB to 6296H to fill the LEADING characters
6280H
INC B
If we are here, then we are processing a “LSET”. Prepare for the next loop, which starts by DEC B, by INC B, so that if B was 0 we can test for it
6281H
 ↳ “COPLOP”
DEC B
DECrement the number of bytes to copy (tracked in Register B) by 1
6282H
If the Z FLAG (Zero) has been set, then we are all done filling, so JUMP to 6291H
6285H
LD A,(HL)
Fetch the a byte from STRINGEXP (pointed to by HL) into Register A
6286H
LD (DE),A
Put that byte from STRINGEXP into the STRINGVAR
6287H
INC HL
INCrement the value stored in Register Pair HL by 1
6288H
INC DE
INCrement the value stored in Register Pair DE by 1
6289H
LOOP BACK to COPLOP until all the bytes have been copied from STRINGEXP into STRINGVAR

628CH – Part of the LSET/RSET Routine – This is when we are done with everything except LSET – “RETCUR”

628CH
 ↳ “RETCUR”
POP BC
Clear the stack from all the variables put into it
628DH
POP BC
Clear the stack from all the variables put into it
628EH
POP BC
Clear the stack from all the variables put into it
628FH
POP BC
Clear the stack from all the variables put into it
6290H
POP BC
Clear the stack from all the variables put into it
6291H
 ↳ “LRSTDN”
If the C FLAG (Carry) has been set, then we were processing a “LSET” and need to fill in the trailing characters, so GOSUB to 6296H
6294H
POP HL
Restore the pointer to the BASIC line being processed back into Register Pair HL
6295H
RET
RETurn to the caller

6296H – Part of the LSET/RSET Routine – This routine will fill in the leading or trailing characters, as needed – “BLKFIL”

6296H
 ↳ “BLKFIL”
LD A,20H
LD A,”SPACE”
Let Register A equal to “SPACE”
6298H
INC C
Since the next loop starts with a DEC C, and we need to preserve a ZERO if we have it now, INCrement the value stored in Register C by 1
6299H
 ↳ “BLKFL1”
DEC C
DECrement the number of characters to fill (stored in Register C) by 1
629AH
RET Z
If the Z FLAG (Zero) has been set, then we are done, so RETurn to the caller
629BH
LD (DE),A
Fill the destination space of STRINGVAR with a “SPACE”
629CH
INC DE
INCrement STRINGVAR to the next character
629DH
LOOP BACK to 6299H until all characters required by Register C have been filled in

62A0H – – Part of the LSET/RSET Routine – “MAKDSC”

If STRINGEXP was a temporary, create a new temporary to point to STRINGEXP since old one was freed. This must be done since GETSPA will be called and garbage collection might occur. If STRINGEXP is not a temporary, return.
62A0H
 ↳ “MAKDSC”
POP AF
Fetch the flag which indicates whether or not the string pointer was to the temporary string storage location or not into Register Pair AF
62A1H
POP HL
Put the pointer to the string descriptor for STRINGVAR into Register Pair HL
62A2H
POP BC
Put the combination both string lengths into Register Pair BC
62A3H
EX (SP),HL
EXchange (SP) and HL so that HL now holds string descriptor for STRINGEXP
62A4H
EX DE,HL
Put the string descriptor for STRINGEXP into Register Pair DE because MAKDS1 needs it there
62A5H
If the NZ FLAG (Not Zero) has been set, then the variable is NOT stored in the temporary string space, and so we do not need to reallocate that space. JUMP to 62B1H
62A8H
PUSH BC
Otherwise, we need to reallocate that space. First, save the combination both string lengths to the stack
62A9H
LD A,B
Fetch the length into Register A
62AAH
GOSUB to 2857H to initialize the temporary string point
62ADH
GOSUB to 2884H to make the temporary string point to STRINGEXP
62B0H
POP BC
Restore the save the combination both string lengths from the stack
62B1H
 ↳ “MAKDS1”
EX (SP),HL
The next 4 instructions restore the STACK to where it was
62B2H
PUSH BC
Save the contents of Register Pair BC to the stack
62B3H
PUSH HL
Save the contents of Register Pair HL to the stack
62B4H
PUSH AF
Save the contents of Register Pair AF to the stack
62B5H
Exit via a JUMP to 624EH

62B8H – Process the EOF Command – “EOF”

62B8H
 ↳ “EOF”
Convert the argument to a file number via a GOSUB to 5EE5H, which is a SUBROUTINE which will convert ACCumulator into a number and check to see if that number is within the number of files reserved when TRSDOS received the answer to FILES? on entry to BASIC. If valid, BC will point to the vector for that file number (i.e., that files’ data block) and Register A will hold the first byte at that vector with flags set based on Register A. HL is preserved
62BBH
CP 02H
CP MDSQO
We need to see if this is a saequential output file, so we need to check the first byte at that vector (put into Register A by the CALL to FILFRM) against 02H and set the Z FLAG if they match.
62BDH
If we have a sequential output file, then EOF is not proper! JUMP to 6547H to process a “BAD FILE MODE” error
62C0H
LD HL,000FH
LD HL,RECEOF+1
If we are here, then we are good to go and need to start by comparing record numbers. First, set Register Pair HL equal 000FH (Decimal: 15)
62C3H
ADD HL,BC
LET Register Pair HL = 0FH (stored in HL) + the vector for that file number (stored in BC)
62C4H
LD A,(HL)
Fetch the MSB of the vector for that file number into Register A
62C5H
DEC HL
DECrement the value stored in Register Pair HL by 1
62C6H
LD E,(HL)
Fetch the LSB of the vector for that file number into Register A
62C7H
DEC HL
DECrement the value stored in Register Pair HL by 1
62C8H
CP (HL)
Compare the MSB of the vector against the value held in the memory location pointed to by the value held in Register Pair HL to see if the MSB’s match
62C9H
If they don’t match, bail out to NOEOF
62CBH
DEC HL
Next let’s check the LSB’s. DECrement the value stored in Register Pair HL by 1
62CCH
LD A,E
Copy the contents of Register E into Register A
62CDH
CP (HL)
Compare the LSB of the vector against the value held in the memory location pointed to by the value held in Register Pair HL to see if the MSB’s match
62CEH
If they don’t match, bail out to NOEOF
62D0H
DEC HL
DECrement the value stored in Register Pair HL by 1
62D1H
DEC HL
DECrement the value stored in Register Pair HL by 1; now HL will point to the EOF BYTE
62D2H
LD A,(HL)
Fetch the EOF BYTE into Register A
62D3H
DEC HL
Next we need to back up 3 bytes so that HL points to the current byte location
62D4H
DEC HL
DECrement the value stored in Register Pair HL by 1
62D5H
DEC HL
DECrement the value stored in Register Pair HL by 1
62D6H
SUB (HL)
LET Register A = the EOF BYTE – the current byte location
62D7H
SUB 01H
Two step process to convert 0 to -1 and everything else to 0. First subtract 1
62D9H
SBC A,A
Subtract the value stored in Register Pair A and the carry flag from the value stored in Register Pair A
62DAH
To finish up we need to convert that to an integer and RETURN via a JUMP to 098DH which will process a SGN function. To use, put the value of X is in 4121H-4122H (integer), in 4121H-4124H (single precision), or in, s-4124H (double precision) and then store the variable type (2, 4, or 8, respectively) in 40AFH. The result (in integer format) is in 4121H-4122H and in the HL register pair

62DDH – Close a file – “CLSFIL”

This routine is called by PRGFIN and as the EXIT VECTOR in CLOSE

The file number must be in Register A. If the file “sequential output” then the final sector of data will also be sent.
62DDH
 ↳ “CLSFIL”
Get the pointer to the data via a GOSUB to 5EE8H, which is a SUBROUTINE which will check to see if that number in Register A is within the number of files reserved when TRSDOS received the answer to FILES? on entry to BASIC. If valid, BC will point to the vector for that file number and Register A will hold the first byte at that vector with flags set based on Register A. HL is preserved
62E0H
RET Z
If the Z FLAG (Zero) has been set, RETurn to the caller
62E1H
CP 01H
CP MDSQI
Since we don’t need to close INPUT, check it against 01H and set the Z FLAG if A=01H
62E3H
If Register A = 01H then JUMP to 62F4H
62E6H
PUSH BC
Save the the vector for the provided file number (held in Register Pair BC after the CALL to 5338H) to the stack
62E7H
XOR A
Set Register A to ZERO and clear all Flags. This will make sure we don’t close again if this fails
62E8H
LD (BC),A
Store a ZERO into the first RAM location of the vector for the provided file number (pointed to by Register Pair BC) to indicate that the file is not open
62E9H
INC BC
The next few instructions point DE and BC to the OS DCB
62EAH
INC BC
INCrement the value stored in Register Pair BC by 1
62EBH
62ECH
LD D,B
LD D,B
Let DE = BC
62EDH
GOSUB to 4428H which is the vector for the CLOSE command
62F0H
If the NZ FLAG (Not Zero) has been set, JUMP to 6561H to process the error based on Register A on entry via a lookup table at 6575H, and then exit with a ROM call to process an error. Routine also loads the value in the selected table entry into 5B8CH
62F3H
POP BC
Restore the vector for the provided file number back into Register Pair BC
62F4H
 ↳ “NTOPNC”
LD D,22H
LD D,DATOFS
Let Register D equal 22H (Decimal: 34), as the number of bytes to ZERO out
62F6H
XOR A
Set Register A to ZERO and clear all Flags
62F7H
 ↳ “MORCZR”
LD (BC),A
Top of a Loop to put in those zeroes. Store the value held in Register A into the memory location pointed to by Register Pair BC
62F8H
INC BC
INCrement the value stored in Register Pair BC by 1
62F9H
DEC D
DECrement the value stored in Register D by 1
62FAH
If the NZ FLAG (Not Zero) has been set, then there are still more bytes to ZERO OUT so LOOP BACK to 62F7H
62FDH
RET
RETurn to the caller

62FEH – Process the LOC Command and LOF Command – “LOC”

62FEH
 ↳ “LOC”
This makes no sense to me. 6547H is an error for BAD FILE MODE, but that’s what the disassembly shows. The actual source code says that this ia a CALL to FILFRM so let’s make believe that’s what the disassembly says too! GOSUB to FILFRM to convert the provided argument and point at the applicable data block
6301H
If the Z FLAG (Zero) has been set, then JUMP to 654AH to process a “BAD FILE NUMBER” error
6304H
LD HL,000CH
LD HL,LOCOFS
Let Register Pair HL equal 000CH (Decimal: 12) which is the CURLOC High Byte
6307H
 ↳ “LOFEND”
ADD HL,BC
LET Register Pair HL = Register Pair HL + Register BC, so now HL points to the ERN (a 2 byte value in LSB/MSB order)
6308H
LD E,(HL)
Fetch the LSB of the ERN from (HL) into Register E
6309H
INC HL
INCrement the value stored in Register Pair HL by 1 to now point to the MSB of the ERN
630AH
LD D,(HL)
Fetch the MSB of the ERN from (HL) into Register E
630BH
EX DE,HL
EXchange DE and HL so that HL will contain the 2-byte address of the ERN and DE will hold the pointer to the MSB of the ERN
630CH
JUMP to 0A9AH to convert a value to integer and store it in ACCumulator (4121H) and set the variable to INTEGER. Ohterwise known as the ISTOR routine

630FH – Process the LOF Command – “LOF”

630FH
 ↳ “LOF”
Convert the argument provided as n of LOF(n) and index it via a GOSUB to 5EE5H, which is a SUBROUTINE which will convert ACCumulator into a number and check to see if that number is within the number of files reserved when TRSDOS received the answer to FILES? on entry to BASIC. If valid, BC will point to the vector for that file number and Register A will hold the first byte at that vector with flags set based on Register A. HL is preserved
6312H
If the Z FLAG (Zero) has been set, JUMP to 654AH to throw a “BAD FILE NUMBER” error
6315H
LD HL,000EH
Let Register Pair HL equal 000EH (Decimal: 14) for an offset to the EOF Record Number
6318H
JUMP to LOFEND above to do the offset and fetch the appropriate addresses into HL and E

631BH – Put a Character into the OUTPUT BUFFER and Output (if needed) – “FILOUT”

Call at FILOUT with (HL) to be saved on the stack and the character in the high order byte below the (HL) on the stack.

The current data is output if there are DATPSC chars stuffed into the data area.

FILOUT is normally called from OUTDO (OUTCHR)
631BH
 ↳ “FILOUT”
POP HL
If this is the entry point, then HL is on the stack and we need to restore it into HL
631CH
 ↳ “FILOU3”
PUSH HL
Save the contents of Register Pair HL to the stack
631DH
PUSH AF
Save the character to be output (held in Register Pair AF) to the stack
631EH
LD HL,(5B8DH)
LD HL,(PTRFIL)
Fetch the pointer to the file and put it in Register Pair HL
6321H
LD A,(HL)
Check the first byte of the file pointer so that we can test the file mode
6322H
CP 01H
CP MDSQI
Compare the value held in Register A against 01H to see if SEQUENTIAL INPUT is the file mode, in which case the Z FLAG will be set
6324H
If we have SEQUENTIAL INPUT as the current file mode, then the Z FLAG (Zero) has been set, JUMP to 1DFDH to ignore this character by just POPping AF, then POPping HL, and then RETurns
6327H
POP AF
Restore the character from the stack
6328H
PUSH DE
Save the contents of Register Pair DE to the stack
6329H
PUSH BC
Generally preserve BC to the stack, to be restored just before exiting
632AH
INC HL
INCrement HL to point to the terminal position
632BH
LD B,00H
Let Register B equal 00H
632DH
PUSH AF
Save the character to the stack
632EH
LD D,(HL)
Fetch the position (held in memory location pointed to by Register Pair HL) and store it into Register D
632FH
CP 0DH
Compare the value held in Register A against 0DH (Decimal: 13) and, if they match, set the Z FLAG
6331H
LD (HL),B
Store a 00H into (HL)
6332H
If the Z FLAG (Zero) has been set, JUMP to the next routine at 6339H
6334H
ADD E0H
IF the terminal position wasn’t a 0DH then continue here. LET Register A = Register A + E0H which will then force the CARRY FLAG for space saving codes and higher
6336H
LD A,D
Copy the position into Register A
6337H
ADC A,B
LET Register A = Register A + Register B to make sure to add in the carry
6338H
LD (HL),A
Store the modified character into the memory location pointed to by Register Pair HL
6339H
 ↳ “ISCRDS”
INC HL
INCrement the value stored in Register Pair HL by 1 to now point to the OS DCB
633AH
EX DE,HL
EXchange DE and HL so that the pointer to the starting address of the device is now stored in DE (as is required by a CALL to PUT)
633BH
POP AF
Restore the character from the STACK into Register A (as is required by a CALL to PUT)
633CH
PUSH AF
Save the character to the STACK
633DH
PUSH DE
Save the pointer to the address of the DCB of the device to the stack
633EH
GOSUB to 001BH to output a byte to a device. When calling, A = output byte, DE = starting address of DCB of device. On exit, Z set if device ready. Uses AF
6341H
POP DE
Restore the pointer to the address of the DCB of device to the stack
6342H
If the NZ FLAG (Not Zero) has been set by PUT then we need to GOSUB to ERRCHK to see if we had an error or not
6345H
 ↳ “NOERRP”
POP AF
All the rest of this is just to restore all the register from where they were before the routine. Put the value held at the STACK into Register Pair AF
6346H
POP BC
Put the value held at the STACK into Register Pair BC
6347H
POP DE
Put the value held at the STACK into Register Pair DE
6348H
POP HL
Put the value held at the STACK into Register Pair HL
6349H
RET
RETurn to the caller

634AH – Part of the OUTPUT A CHARACTER ROUTINE; check the result of the PUT routine to see if an error was returned – “ERRCHK”

634AH
 ↳ “ERRCHK”
LD C,A
Preserve (A) into C
634BH
LD A,(DE)
Fetch the byte at DCB+0 to check for an error
634CH
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
634DH
LD A,C
Restore the original Register A contents into Register A
634EH
If the S FLAG has been SET, then we have an error, and Register A is holding it so JUMP to 6561H to process the error based on Register A on entry via a lookup table at 6575H, and then exit with a ROM call to process an error. Routine also loads the value in the selected table entry into 5B8CH
6351H
Otherwise, we had no error, so JUMP to 6345H

6354H – Process the PUT and GET Command – “GET” and “PUT”

6354H
 ↳ “PUT”
OR AFH
Part of a Z-80 Trick. OR Register A against AFH so that NZ FLAG is set, to indicate a PUT and the bypass the next opcode which was just part of this opcode
6355H
 ↳ “GET”
XOR A
Set the ZERO FLAG to inidicate this is a GET
6356H
LD (5B8BH),A
LD (MAXTRK),A
Save the flag into (MAXTRK)
6359H
GOSUB to 5EDBH to process the #n part of a GET#n, PUT#n, FIELD#n, INPUT#n, etc
635CH
CP 03H
CP MDRND
Compare the value held in Register A against 03H to make sure we are in RANDOM file mode, and set the Z FLAG if they match and the NZ flag otherwise
635EH
If the NZ FLAG (Not Zero) has been set, then we are NOT in RANDOM file mode, so JUMP to 6547H to process a “BAD FILE MODE” error
6361H
PUSH BC
Save the pointer at the file data block to the stack
6362H
PUSH HL
Save the text pointer to the stack
6363H
LD HL,000CH
LD HL,LOCOFS
Let Register Pair HL equal 000CH as an offset to CURLOC
6366H
ADD HL,BC
LET Register Pair HL = file data block + 0CH to point to CURLOC
6367H
LD E,(HL)
Fetch the LSB of CURLOC into Register E
6368H
INC HL
INCrement the value stored in Register Pair HL by 1 to point to the MSB of CURLOC
6369H
LD D,(HL)
Fetch the MSB of CURLOC into Register E
636AH
INC DE
INCrement CURLOC by 1 to compensate
636BH
POP HL
Restore the text pointer back into Register Pair HL
636CH
LD A,(HL)
Fetch the character from the text pointer into Register A
636DH
CP 2CH
Compare the value held in Register A against 2CH (ASCII: ,) and if it is a “,” then set the Z FLAG

 ↳ “GET1”
636FH
We have a COMMA which means we now need to get the RECORD NUMBER, so GOSUB to 1E45H to evaluate a subscript for a variable reference

 ↳ “GET2”
6372H
DEC HL
That needs to be the end of the statement, so, in preparation for a RST 10 (which first bumps HL) we need to DECrement HL
6373H
RST 10H
GETCHR
Call the EXAMINE NEXT SYMBOL routine at RST 10H. RST 10H bumps HL by 1 and then looks for the first non-space, non-chr$(9), and non-chr$(10) character pointed to by HL. If that character is a number (0-9), the C FLAG is set; otherwise the NC FLAG is set. Z will be set if the character is a 0 or a :. RST 10H exits with HL still pointing to the character it checked, the character it checked in Register A, and BC and DE are unaffected
6374H
If there was ANY other character, then we have a bad command, so JUMP to 1997H to display a SYNTAX ERROR error message
If we are here, then we have now gotten a GET #n,y or PUT #n,y command.
6377H
EX (SP),HL
EXchange (SP) and HL so that the text pointer is now saved to the stack and HL now holds the DCB pointer
6378H
PUSH HL
Save the DCB pointer (held in Register Pair HL) to the stack
6379H
LD A,E
Next we need to test DE to make sure its not 0. First, copy the contents of Register E into Register A
637AH
OR D
OR Register D against Register A. The results are stored in Register A
637BH
If the Z FLAG (Zero) has been set then DE was 0, so JUMP to 6559H to error out with a “BAD RECORD NUMBER”
637EH
DEC DE
DECrement the value stored in Register Pair DE by 1 so that the record count (which is what it is tracking) it is in the range of 0-n
637FH
6380H
LD B,D
LD C,E
Let BC = the record count
6381H
EX DE,HL
EXchange DE and HL so that DE now points to the DCB and HL now points to the record count
6382H
6383H
INC DE
INC DE
INCrement the value stored in Register Pair DE by 2, so that DE is now DCB + 02H
6384H
LD HL,0020H
LD HL,DATOFC-2
Let Register Pair HL equal 0020H, which is the blocking buffer
6387H
ADD HL,DE
LET Register Pair HL = Register Pair HL + Register DE so that HL is now equal to the variable length
6388H
PUSH HL
Save the contents of Register Pair HL to the stack
6389H
GOSUB to 4442H to execute the DOS vector for the reoutine to position a file to a specified record number. Routine exits Z FLAG = no error, NZ = Error
638CH
POP HL
Restore the pointer to the blocking buffer into Register Pair HL
638DH
If the Z FLAG (Zero) has been set, then POSN had no error, so JUMP to 63A7H to continue
638FH
CP 1CH
Compare the value held in Register A against 1CH (Decimal: 28), which is the EOF. If they match, the Z FLAG will be set
6391H
If we hit the EOF byte, JUMP to 6398H
6393H
CP 1DH
Compare the value held in Register A against 1DH (Decimal: 29), which is a position past the end. If they do not match, the NZ FLAG will be set
6395H
If we didn’t go past the end, then just JUMP to 6561H to process the error based on Register A on entry via a lookup table at 6575H, and then exits with a ROM call to process an error. Routine also loads the value in the selected table entry into 5B8CH
6398H
 ↳ “ENDRND”
LD A,(5B8BH)
LD A,(MAXTRK)
Fetch the flag as to whether this was a GET or a PUT
639BH
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
639CH
If the Z FLAG (Zero) has been set, then this was a GET, so just ZERO the buffer via a JUMP to 63B6H
639EH
 ↳ “PUTDO”
GOSUB to 4439H to write the sector into the DESTINATION file pointed to by DE. Returns with Z FLAG if there were no errors, or NZ FLAG if there were errors
63A1H
If the NZ FLAG (Not Zero) has been set, JUMP to 6561H to process the error based on Register A on entry via a lookup table at 6575H, and then exits with a ROM call to process an error. Routine also loads the value in the selected table entry into 5B8CH
63A4H
POP AF
Clear the DCB pointer from the stack
63A5H
POP HL
Restore the pointer to the text back into Register Pair HL
63A6H
RET
RETurn to the caller

63A7H – Part of the GET/PUT routine – Jumped here when we have POSITIONED to the desired record – “SEEKOK”

63A7H
 ↳ “SEEKOK”
LD A,(5B8BH)
LD A,(MAXTRK)
Fetch the flag as to whether this was a GET or a PUT
63AAH
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
63ABH
If the NZ FLAG (Not Zero) has been set then this is a PUT command so JUMP to 639EH
63ADH
If we are here, then we are processing a GET, so GOSUB to 4436H to read. Will return Z FLAG if no errors, and NZ FLAG if there were errors
63B0H
If the NZ FLAG (Not Zero) has been set, then the READ routine had errors, so JUMP to 6561H to process the error based on Register A on entry via a lookup table at 6575H, and then exits with a ROM call to process an error. Routine also loads the value in the selected table entry into 5B8CH
63B3H
 ↳ “SEEK04”
POP BC
If we are heree, then the READ routine was successfully run, so clear the DCB pointer from the stack
63B4H
POP HL
Restore the text pointer to Register Pair HL
63B5H
RET
RETurn to the caller

63B6H – Part of the GET/PUT routine – Jumped here for a GET if we positioned correctly but there’s nothing there – “ZERBUF”

63B6H
 ↳ “ZERBUF”
POP HL
Put the DCB into Register Pair HL
63B7H
LD DE,0022H
LD DE,DATOFS
Let Register Pair DE equal 0022H to act as an offset
63BAH
ADD HL,DE
LET Register Pair HL = Register Pair HL + Register DE so that HL now points to the DATA BUFFER
63BBH
LD B,00H
Let Register B equal 00H
63BDH
XOR A
Set Register A to ZERO and clear all Flags
63BEH
 ↳ “LOPZRB”
LD (HL),A
Top of a loop. Store a 00H into the memory location pointed to by Register Pair HL
63BFH
INC HL
INCrement the value stored in Register Pair HL by 1
63C0H
LOOP back to 63BEH, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction
63C2H
POP HL
Restore the text pointer to Register Pair HL
63C3H
RET
RETurn to the caller

63C4H – Read a Character from Disk – “INDSKC”

This routine will get a character from the SEQUENTIAL FILE pointed to by PTRFIL. Only DE is unchanged.
63C4H
 ↳ “INDSKC”
PUSH BC
Save the character counter to the the stack
63C5H
PUSH HL
Save the contents of Register Pair HL to the stack
63C6H
 ↳ “INDSK3”
LD HL,(5B8DH)
LD HL,(PTRFIL)
Fetch data block pointer from (PTRFIL) into Register Pair HL
63C9H
PUSH DE
Save the contents of Register Pair DE to the stack
63CAH
EX DE,HL
EXchange DE and HL so that DE now points to the file data block and HL now points to the OS DCB
63CBH
63CCH
INC DE
INC DE
INCrement the value stored in Register Pair DE by 2
63CDH
 ↳ “GETAGN”
PUSH DE
Save the pointer to the file data block + 2 to the stack
63CEH
GOSUB to 0013H to input a byte from an input device. When calling, DE = starting address of DCB of device. On exit, A = byte received from device, Z set if device ready. Uses AF
63D1H
POP DE
Restore the pointer to the file data block + 2 to DE
63D2H
PUSH AF
Save the byte just read (held in Register A) to the stack
63D3H
LD A,(DE)
Fetch the byte at file data block + 2 into Register A
63D4H
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
63D5H
If the S FLAG has been RESET, JUMP to 63E7H to toss the character and read another one
63D8H
POP AF
Restore the byte which just read from the STACK into Register A
63D9H
If the Z FLAG (Zero) has been set, JUMP to 63E2H to return with the byte
63DBH
 ↳ “REDERR”
CP 1CH
Compare the value held in Register A against 1CH (Decimal: 28), which is the EOF. If they match, the Z FLAG will be set
63DDH
If the ERROR was not 1CH, JUMP to 6561H to process the error based on Register A on entry via a lookup table at 6575H, and then exits with a ROM call to process an error. Routine also loads the value in the selected table entry into 5B8CH
63E0H
 ↳ “REDER1”
SCF
Set the CARRY FLAG to indicate that we have hit the EOF
63E1H
LD B,B7H
Z-80 Trick. If passing through this will just set Register B = B7H and the next OPCODE won’t even be seen
63E2H
 ↳ “OKGET”
OR A
B7
Clear the CARRY FLAG (to indicate that we have NOT hit the EOF)
63E3H
POP DE
We’re done, so just restore all the registers from the Stack. Put the value held at the STACK into Register Pair DE
63E4H
POP HL
Put the value held at the STACK into Register Pair HL
63E5H
POP BC
Put the value held at the STACK into Register Pair BC
63E6H
RET
RETurn to the caller

63E7H – Part of the Read a Character from Disk Routine; jumped to when we want to toss the character – “WC”

63E7H
 ↳ “WC”
POP AF
Restore the byte just read back into Register A, and restore the flags (which were set by the GET routine) as well. That routine would set Z FLAG if the device ready
63E8H
If the Z FLAG (Zero) has been set, JUMP to 63CDH to get another byte
63EAH
JUMP to 63E2H to exit out of the routine with the CARRY FLAG cleared

63EDH – Scan a Filename and NAME Command. Used by OPEN and KILL – “NAMFIL”

Fetch the filename of the file pointed to by BC into FILNAM and the disk number into LSTDSK
63EDH
 ↳ “NAMFIL”
PUSH BC
Save the pointer to the file information to the stack
63EEH
Parse the string formula via a CALL 2337H to evaluate the BASIC expression pointed to by HL and return with the result in ACCumulator. Evaluate BASIC string expression (may include constants, BASIC variables, BASIC functions, operators, etc.) and place result in ACCumulator. On entry, HL must point to first character of the string to be evaluated. On exit, HL will point to the string delimiter, which must be an acceptable BASIC expression terminator (such as a zero byte, a colon, a right parenthesis, etc.)
63F1H
PUSH HL
Save the text pointer (contents of Register Pair HL) to the stack
63F2H
Process what we hope is the FILENAME via a GOSUB to 29D7H to make sure the argument is a string and check to see if there is enough memory for the string; it not it will error out
63F5H
LD A,(HL)
Fetch the length of the string from (HL) and store it into Register A
63F6H
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
63F7H
If the Z FLAG (Zero) has been set, then the FILENAME’s length is zero, so JUMP to 6556H to error out with a BAD FILENAME error
63FAH
CP 17H
CP FILLEN
Compare the length of the filename against 23 characters.. If the length of the filename (held in A) >= 23 charaters, the NO CARRY FLAG will be set.
63FCH
If the NC FLAG has been set then we have too many characters in the FILENAME so JUMP to 6556H to error out with a BAD FILENAME error
63FFH
INC HL
INCrement the value stored in Register Pair HL by 1 to now point to the name data
6400H
LD C,(HL)
Fetch the LSB (held in the memory location pointed to by Register Pair HL) and store it into Register C
6401H
INC HL
INCrement the value stored in Register Pair HL by 1 to now point to the MSB
6402H
LD B,(HL)
Fetch the MSB (held in the memory location pointed to by Register Pair HL) and store it into Register B
6403H
LD HL,5EA3H
LD HL,FILNAM
Let Register Pair HL point to the FILNAM routine
6406H
LD E,A
Put the length of the filename into Register E
6407H
 ↳ “MVFLNM”
LD A,(BC)
Fetch a character from the filename and store it into Register A
6408H
CP 61H
CP “a”
Test for lowercase via a compare of the character from the filename against 61H (ASCII: a). If the character from the filename is < a, the CARRY FLAG will be set
640AH
If the character is < “a” then the C FLAG (Carry) will have been set, JUMP to 6414H
640DH
CP 7BH
CP “Z”+1
Compare of the character from the filename (ASCII: Z+01). So long as A >= Z+01, the NO CARRY FLAG will be set.
640FH
If the NC FLAG (No Carry) has been set, JUMP to 6414H
6412H
XOR 20H
eXclusive OR 20H to flop Register A to UPPER CASE
6414H
 ↳ “FILLCC”
LD (HL),A
Store the, now uppercase, character from the filename (held in Register A) into the memory location pointed to by Register Pair HL
6415H
INC HL
Move to the next character in the FILNAM buffer
6416H
INC BC
Move to the next character of the provided filename to test (tracked in Register Pair BC)
6417H
DEC E
DECrement the counter of the length of the filename left to process (stored in Register E) by 1
6418H
So long as we haven’t finished processing characters of the filename (tracked in E) LOOP back to 6407H
641BH
LD (HL),E
If we are here, then we finished processing and moving characters of the filename into the buffer at FILNAM and HL has been advanced by 1. Store the 00H held in Register E into the memory location pointed to by Register Pair HL to act as a terminator
641CH
POP HL
Restore the text pointer to Register Pair HL
641DH
POP DE
Restore the pointer to the file information to Register Pair DE
641EH
641FH
LD B,D
LD C,E
Let BC point to the file information
6420H
PUSH BC
Save the file information (held in Register Pair BC) to the stack
6421H
PUSH HL
Save the text pointer (held in Register Pair HL) to the stack
6422H
LD HL,5EA3H
LD HL,FILNAM
Let Register Pair HL equal 5EA3H, which is the storage location for the filename
6425H
6426H
INC DE
INC DE
INCrement the pointer to the file informatio (tracked in Register Pair DE) by 2
6427H
GOSUB to 441CH to copy/edit a filename into DCB (SYS1, Code 4). This validates the filename, puts it into 5551H+, and returns NZ if there are illegal characters
642AH
If the NZ FLAG has been set, then there were illegal characters in the filename, so JUMP to 6556H to error out with a BAD FILENAME error
642DH
OR A
Set FLAGS based on the contents of Register A
642EH
If the NZ FLAG has been set, JUMP to 6556H to error out with a BAD FILENAME error
6431H
POP HL
Restore the text pointer into Register Pair HL
6432H
POP BC
Restore the file information into Register Pair BC
6433H
RET
RETurn to the caller

6434H – Process the OPEN Command – “OPEN”

This routine will handle the OPEN statement as well as all directory handling.
6434H
 ↳ “OPEN”
LD BC,2169H
LD BC,FINPRT
Let Register Pair BC equal the address of the FINPRT routine, to be set as the RETurn address. That routine resets the device type flag at 409CH to zero (output to video display), also turns off cassette drive if necessary. Routine will call FINDTR and will zero PTRFIL before RETurning
6437H
PUSH BC
Save the contents of Register Pair BC to the stack
6438H
Read the file mode via a GOSUB to the Model I ROM Routine to evaluate the BASIC expression pointed to by HL and return with the result in ACCumulator. Evaluate BASIC string expression (may include constants, BASIC variables, BASIC functions, operators, etc.) and place result in ACCumulator. On entry, HL must point to first character of the string to be evaluated. On exit, HL will point to the string delimiter, which must be an acceptable BASIC expression terminator (such as a zero byte, a colon, a right parenthesis, etc.)
643BH
PUSH HL
Save the text pointer (held in Register Pair HL) to the stack
643CH
Next we need to free up the string and get the pointer to the descriptor into Register Pair HL. We do this via a GOSUB to 29D7H to check to see if there is enough memory for the string
643FH
LD A,(HL)
Fetch the character stored at (HL) into Register A
6440H
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
6441H
If we have an empty string then the the Z FLAG will have been set, so JUMP to 6547H to process a “BAD FILE MODE” error
Next we want to check the mode character. BC will point to it, A will fetch it, and then we will test for O, I, E, and R
6444H
INC HL
INCrement the string pointer (stored in Register Pair HL) by 1
6445H
LD C,(HL)
Fetch the LSB of the string’s location and store it into Register C
6446H
INC HL
INCrement the value stored in Register Pair HL by 1 to point to the MSB of the string
6447H
LD B,(HL)
Fetch the MSB of the string’s location and store it into Register C
6448H
LD A,(BC)
Fetch the character held in the string being examined and store it into Register A
6449H
AND DFH
MASK the value of Register A against DFH (1101 1111). This has the effect of turning off bit 5, to mask to upper case
644BH
LD D,02H
LD D,MDSQO
Let Register D equal 02H, which would be the mode for SEQUENTIAL OUTPUT
644DH
CP 4FH
CP “O”
Compare the value held in Register A against 4FH (ASCII: O) and set the Z FLAG if they match, and the NZ FLAG if they don’t
644FH
If the Z FLAG (Zero) has been set, JUMP to 6460H
6452H
LD D,01H
LD D,MDSQI
Let Register D equal 01H, which would be the mode for SEQUENTIAL INPUT
6454H
CP 49H
CP “I”
Compare the value held in Register A against 49H (ASCII: I) and set the Z FLAG if they match, and the NZ FLAG if they don’t
6456H
If the Z FLAG (Zero) has been set, JUMP to 6460H
6459H
LD D,03H
LD D,MDRND
Let Register D equal 03H, which would be the mode for RANDOM I/O
645BH
CP 52H
CP “R”
Compare the value held in Register A against 52H (ASCII: R) and set the Z FLAG if they match, and the NZ FLAG if they don’t
645DH
If the NZ FLAG (Not Zero) has been set, then we are out of valid choicese, so JUMP to 6547H to process a “BAD FILE MODE” error
If we are here, then we have a valid file mode and it is held in DE.
6460H
 ↳ “HAVMOD”
POP HL
Restore the text pointer into Register Pair HL
6461H
RST 08H 2C
SYNCHK “,”
Make sure the next character is a , via a call to RST 08H, which is the COMPARE SYMBOL routine. That routine compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., 2CH which is a ,). If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the A Register and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase
6463H
PUSH DE
Save the file mode (held in Register Pair DE) to the stack
6464H
CP 23H
There might be a “#”, but doesn’t have to be one. Since it’s optional, we can’t call RST 08H because that will error out if the desginated target isn’t found. Instead, we compare the value held in Register A against 23H(ASCII: #) and set the Z FLAG if they match, and the NZ FLAG if they don’t
6466H
If they match, then skip it by fetching another character. To do this, GOSUB to 1D78H which is the RST 10H (EXAMINE NEXT SYMBOL) code
6469H
GOSUB to 2B1CH to evaluate what we expect is the file number number (part of the STRING$ function) and put it into Register E
646CH
RST 08H 2C
SYNCHK “,”
Now that we have the file number, we MUST have a “,” so to make sure the next character is a , we call to RST 08H, which is the COMPARE SYMBOL routine. That routine compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., 2CH which is a ,). If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the A Register and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase
646EH
LD A,E
Copy the file number from Register E into Register A
646FH
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
6470H
If the file number was zero, then we have an illegal file number, so JUMP to 654AH to throw a “BAD FILE NUMBER” error
6473H
CP D5H
Z-80 Trick. If passing through, this will just mess with the flags, but will skip the next command. This command will compare the value held in Register A against D5H.
6474H
 ↳ “PRGFIL”
PUSH DE
D5H
This will be executed only if jumped to. Save the file mode (held in DE) to the stack.
6475H
Fetch the file data block pointer into BC via a GOSUB to 5EE8H, which is a SUBROUTINE which will check to see if that number in Register A is within the number of files reserved when TRSDOS received the answer to FILES? on entry to BASIC. If valid, BC will point to the vector for that file number and Register A will hold the first byte at that vector with flags set based on Register A. HL is preserved
6478H
If FILIDX exited with the NZ FLAG set, then we are in “file always open” mode, so JUMP to 6553H in that case
647BH
PUSH BC
Save the pointer to the file data block (held in Register Pair BC) to the stack
647CH
Fetch the filename of the file pointed to by BC into FILNAM and the disk number into LSTDSK via a GOSUB to 63EDH
647FH
LD B,00H
Set the default record size (tracked by Register B) to 00H
6481H
POP DE
Restore the pointer to the file data block (held in the stack) to Register Pair DE
6482H
POP AF
Restore the file mode (held in the stack) to Register A
6483H
PUSH AF
Save the file mode (held in Register Pair DE) to the stack
6484H
PUSH DE
Save the pointer to the file data block (held in Register Pair DE) to the stack
6485H
CP 03H
CPO MDRND
Compare the value held in Register A against 03H to make sure we are in RANDOM file mode, and set the Z FLAG if they match and the NZ flag otherwise
6487H
If the file mode does NOT indicate RANDOM, then JUMP to 6493H
6489H
DEC HL
DECrement the test pointer by 1 haracter
648AH
RST 10H
GETCHR
Call the EXAMINE NEXT SYMBOL routine at RST 10H. RST 10H bumps HL by 1 and then looks for the first non-space, non-chr$(9), and non-chr$(10) character pointed to by HL. If that character is a number (0-9), the C FLAG is set; otherwise the NC FLAG is set. Z will be set if the character is a 0 or a :. RST 10H exits with HL still pointing to the character it checked, the character it checked in Register A, and BC and DE are unaffected
648BH
If the Z FLAG (Zero) has been set, then there was no specification, so JUMP to 6493H
648DH
RST 08H 2C
SYNCHK “,”
Make sure the next character is a , via a call to RST 08H, which is the COMPARE SYMBOL routine. That routine compares the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call (i.e., 2CH which is a ,). If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the A Register and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase
648FH
GOSUB to 2B1CH to evaluate a number
6492H
LD B,E
Copy the contents of Register E into Register B

 ↳ “NORECL”
6493H
LD (40DFH),HL
LD (TEMP),HL
Store the text pointer into (TEMP)
6496H
POP HL
Restore the pointer to the file data block into Register Pair HL
6497H
LD A,(430FH)
LD A,(XMODE)
Set Register A so as to clear the prtected bit by first fetching the value from (XMODE) …
649AH
AND F9H
… and then MASKing the value of Register A against F9H (1111 1001)to turning off bits 2 and 1,
649CH
LD C,A
Copy the masked XMODE into Register C
649DH
LD A,(651FH)
LD A,(DOPROT)
Determine if we may open a protected file by fetching the status of the DOPROT flag
64A0H
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
64A1H
LD A,C
Now that the flags are set, put the masked XMODE back into Register A
64A2H
If the protection level held in DOPROT was 0, skip the next instruction and go to NOPRIV
64A4H
OR 04H
OR Register A against 04H to turn on privilege mode (only for OPEN/SEQEUNTIAL)

 ↳ “NOPRIV”
64A6H
LD (430FH),A
LD (XMODE),A
Store adjusted protection level back into XMODE
64A9H
POP AF
Restore the file mode (held in the stack) to Register A
64AAH
PUSH AF
Save the file mode (held in Register Pair DE) to the stack
64ABH
PUSH HL
Save the pointer to the file data block to the stack
64ACH
LD (5B8DH),HL
LD (PTRFIL),HL
Set up as the current file by putting t he pointer to the file data block into PTRFIL
64AFH
EX DE,HL
EXchange DE and HL so that DE now points to the file data block and HL now points to the OS DCB POINTER
The next bunch of instructions do an offset
64B0H
64B0H
INC DE
INC DE
INCrement the value stored in Register Pair DE by 2
64B2H
LD HL,0020H
LD HL,DATOFC-2
Let Register Pair HL equal 0020H (Decimal: 32)
64B5H
ADD HL,DE
LET Register Pair HL = Register Pair HL + Register DE
64B6H
LD C,A
Preserve the file mode into Register C
64B7H
LD A,B
Copy the record size (held in Register B) into Register A
64B8H
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
64B9H
If the record size was 00H, then it is not a variable file, and JUMP to 64C3H
64BBH
LD A,(0000H)
LD A,(VARREC)
If we are here, then the record size was variable, so first fetch the VARREC flag to see if variable sizes are permitted
64BEH
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
64BFH
If we are here, we know the record size is variable, and that the VARREC flag says we can’t have a variable record size, so JUMP to 6547H to process a “BAD FILE MODE” error
64C2H
INC H
INCrement the value stored in Register H by 1

 ↳ “NVARCH”
64C3H
LD A,C
Restore the file mode back into Register A
64C4H
CP 01H
CP MDSQI
Compare the file mode (held in Register A against 01H, which would be the mode for SEQUENTIAL INPUT and set the Z FLAG if they match
64C6H
 ↳ “NOTEOF”
If the Z FLAG has been set then weare in INPUT mode, so JUMP to 64CDH
64C8H
 ↳ “NOETO1”
Otherwise, we need to create the file so GOSUB to 4420H
64CBH
We are finished so JUMP to 64E5H to finish up

64CDH – OPEN a File for INPUT – “INOPN”

64CDH
 ↳ “INOPN”
GOSUB to 4424H to open the file. Note: When calling OPEN, Register B must be set to 0 to flag that physical I/O is needed for the source file, Register Pair DE must point to the local DCB area of the filename, and Register Pair HL must point to a buffer to use
64D0H
PUSH AF
Save any error flags which were returned from the CALL to OPEN
64D1H
LD A,(651FH)
LD A,(DOPROT)
Fetch the protection flag
64D4H
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
64D5H
If the Z FLAG (Zero) has been set, then this file is NOT protected, so JUMP to 64E4H
64D7H
XOR A
If we are here, then we sought to open a protected file, first, set Register A to ZERO and clear all Flags
64D8H
LD (651FH),A
LD (DOPROT),A
Set a 00H into the DOPROT flag to indicate that we should not run a protected file
64DBH
LD A,(430FH)
LD A,(XMODE)
Fetch the value held in memory location 430FH and store it into Register A.
NOTE: 430FH is the storage location used by TRSDOS 2.3 to track certain system conditions.
  • If Bit 4 is set, then SYS6/SYS is loaded in RAM (and can be called by RST 28H).
  • If Bit 5 is set, then CHAINING is in effect.
  • If Bit 7 is set, then DEBUG was set to active.
The next instructions convert the XMODE flag into a PROTFL flag.
64DEH
RRA
Rotate the XMODE flag rotated right one bit position, with bit 0 moving to CARRY FLAG and CARRY FLAG moving to bit 7.
64DFH
RRA
Rotate the XMODE flag rotated right one more one bit position, with bit 0 moving to CARRY FLAG and CARRY FLAG moving to bit 7.
64E0H
SBC A,A
Subtracts the value stored in Register Pair A and the carry flag from the value stored in Register Pair A
64E1H
LD (6520H),A
LD (PROTFL),A
Store the internal protection flags into PROTFL
64E4H
 ↳ “NOPRTC”
POP AF
Restore the error flags which were returned from the CALL to OPEN
64E5H
 ↳ “OPNDON”
If the NZ FLAG has been set, then OPEN threw an error, so we must JUMP to 6561H to process the error based on Register A on entry via a lookup table at 6575H, and then exits with a ROM call to process an error. Routine also loads the value in the selected table entry into 5B8CH
64E8H
POP HL
Restore the pointer to the file data block back to HL
64E9H
POP AF
Restore the file mode back into Register A
64EAH
LD (HL),A
Now we need to set up the file mode. Store the value held in Register A into the memory location pointed to by Register Pair HL
64EBH
INC HL
INCrement the value stored in Register Pair HL (the pointer to the file data block) by 1
64ECH
LD (HL),00H
Store the value 00H into the memory location pointed to by Register Pair HL
64EEH
LD HL,(40DFH)
LD HL,(TEMP)
Restore the text pointer back into Register Pair HL
64F1H
RET
RETurn to the caller

64F2H – Part of the OPEN statement and ALL Directory handling. – “TSTPRT”

This routine will test and deal with protection.
64F2H
 ↳ “TSTPRT”
PUSH AF
Save the contents of Register Pair AF to the stack because are are about to use Register A
64F3H
XOR A
Set Register A to ZERO and clear all Flags
64F4H
LD (651FH),A
LD (DOPROT),A
Set a 00H into the DOPROT flag to indicate that we should not run a protected file
64F7H
LD A,(6520H)
LD A,(PROTFL)
Fetch the value held in memory location 6520H and store it into Register A
64FAH
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG)
64FBH
If the Z FLAG (Zero) has been set, JUMP to 651CH to POP AF and RETurn
If we are here, then we need to process “PROTECTION HAS CLEARED MEMORY”.
64FEH
LD HL,(40A4H)
LD HL,(TXTTAB)
Fetch the value held in memory location 40A4H and store it into Register Pair HL.
NOTE: 40A4H is the storage location for the BASIC Program Beginning Pointer in 2 bytes (LSB/MSB)
6501H
LD BC,044CH
Let Register Pair BC equal 044CH (Decimal: 1100), which will be a counter for the number of bytes to ZERO out, starting from the BASIC program
6504H
 ↳ “PLPZER”
LD (HL),00H
Top of a loop to erase BC bytes starting from HL. Store the value 00H into the memory location pointed to by Register Pair HL
6506H
INC HL
INCrement HL to point the next byte of the BASIC Program RAM Area
6507H
DEC BC
DECrement the byte counter (stored in Register Pair BC) by 1
6508H
6508H
LD A,B
OR C
Since the Z-80 cannot test Register Pair BC against zero, the common trick is to set Register A to equal to Register B, and then OR A against Register C. Only if both Register B and Register C were zero can the Z FLAG be set
650AH
If the BC counter has not yet hit ZERO, LOOP BACK to 6504H to keep wiping bytes
650DH
LD (6520H),A
LD (PROTFL),A
Store the value held in Register A (which is a ZERO at this point, or else we would have jumped away) into memory location 6520H
6510H
GOSUB to 1B4DH which is the routine to execute a NEW command, but without clearing the screen
6513H
LD HL,586BH
LD HL,PROTMS
Let Register Pair HL equal 586BH, which is the message 0DH + “PROTECTION HAS CLEARED MEMORY”
6516H
GOSUB to 28A7H.
NOTE: 28A7H is the Model I ROM Routine to display a message pointed to by Register Pair HL (i.e., 0DH + “PROTECTION HAS CLEARED MEMORY”)
6519H
JUMP to 1A19H to return to the READY prompt

651CH – Part of the TSTPRT protection routine; this is an exit – “POPSRT”

651CH
 ↳ “POPSRT”
POP AF
Put the value held at the STACK into Register Pair AF
651DH
RET
RETurn to the caller

651EH – Memory Storage Locations

651EH
 ↳ “FLRL”
00H
Storage for the logical record size
651FH
 ↳ “DOPROT”
00H
FLAG for whether we should run a protected file. FF = Permit the running of a protected file, 00H DO not run a protected file
6520H
 ↳ “PROTFL”
00H
Flag for PROTECTION HAS CLEARED MEMORY. If this byte is ZERO, no need to do so. Otherwise, 64FEH and on will clear the first 1100 bytes of Program RAM

6521H – Process the KILL command – “KILL”

Actually, this is the KILL, LOAD, and MERGE code
6521H
 ↳ “KILL”
XOR A
Set Register A to ZERO. Register A points to the file to use, so in this case, file 0
6522H
GOSUB to 5EE8H, which is a SUBROUTINE which will check to see if that number in Register A is within the number of files reserved when TRSDOS received the answer to FILES? on entry to BASIC. If valid, BC will point to the DCB vector for that file number and Register A will hold the first byte at that vector with flags set based on Register A. HL is preserved
6525H
Fetch the filename of the file pointed to by BC into FILNAM and the disk number into LSTDSK via a GOSUB to 63EDH
6528H
PUSH HL
Save the text pointer to the stack
We are going to call the OPEN routine which requires B, DE, and HL to be set, so let’s set them up.
6529H
LD HL,(5B8FH)
LD HL,(FILPTR)
The OPEN routine requires that Register Pair DE point to the local DCB area of the filename, so set HL to point to the DCB of FILE 0
652CH
EX DE,HL
EXchange DE and HL, so that DE will point to local DCB area of the filename and HL will point to the buffer to use.
652DH
INC DE
INCrement the value stored in Register Pair DE by 1
652EH
INC DE
INCrement the value stored in Register Pair DE by 1
652FH
LD B,00H
The OPEN routine requires that Register B be set to 0 to flag that physical I/O is needed for the source file
6531H
GOSUB to 4424H to open the file. Note: When calling OPEN, Register B must be set to 0 to flag that physical I/O is needed for the source file, Register Pair DE must point to the local DCB area of the filename, and Register Pair HL must point to a buffer to use
6534H
If the NZ FLAG (Not Zero) has been set by the OPEN routine, JUMP to 6561H to process the error based on Register A on entry via a lookup table at 6575H, and then exits with a ROM call to process an error. Routine also loads the value in the selected table entry into 5B8CH
6537H
GOSUB to 442CH to perform the actual deletion
653AH
If the NZ FLAG (Not Zero) has been set by the KILL routine, JUMP to 6561H to process the error based on Register A on entry via a lookup table at 6575H, and then exits with a ROM call to process an error. Routine also loads the value in the selected table entry into 5B8CH
653DH
LD HL,(5B8FH)
LD HL,(FILPTR)
Fetch the poiner to the kill file into Register Pair HL
6540H
LD (HL),00H
Store the value 00H into the memory location pointed to by Register Pair HL to show that the file is closed
6542H
POP HL
Restore the text pointer from the STACK into Register Pair HL
6543H
RET
RETurn to the caller

6544H – Process the NAME Command – “NAME”

6544H
 ↳ “NAME”
JUMP to 1E4AH which is the Model I ROM Routine to display a ?FC ERROR

6547H – This is subroutine sets error codes based on the JUMP point – “DERBFM”.

6547H
 ↳ “DERBFM”
LD E,6CH
LD E,ERRBFM
Let Register E equal 6CH to process a (ASCII: BAD FILE MODE error
6549H
LD BC,681EH
011E68
Z-80 Trick. If passing through, the next instruction won’t execute
654AH
 ↳ “DERBFN”
LD E,68H
LD E,ERRBFN
Let Register E equal 68H to process a (ASCII: BAD FILE NUMBER error
654CH
LD BC,661EH
Z-80 Trick. If passing through, the next instruction won’t execute
654DH
 ↳ “DERIER”
LD E,66H
LD E,ERRIER
Let Register E equal 66H to process a (ASCII: ILLEGAL LOGICAL FILE NUMBER error
654FH
LD BC,7C1EH
Z-80 Trick. If passing through, the next instruction won’t execute
6550
 ↳ “DERRPE”
LD E,7CH
LD E,ERRRPE
Let Register E equal 7CH to process a (ASCII: ???????????? error. we have read past the EOF
6552H
LD BC,6E1EH
Z-80 Trick. If passing through, the next instruction won’t execute
6553H
 ↳ “DERFAO”
LD E,6EH
LD E,ERRFAO
Let Register E equal 6EH to process a (ASCII: ???????????? error. we have read past the EOF
6555H
LD BC,801EH
Z-80 Trick. If passing through, the next instruction won’t execute
6556H
 ↳ “DERNMF”
LD E,80H
LD E,ERRNMF
Let Register E equal 80H to process a (ASCII: BAD FILE NAME error
6558H
LD BC,7E1EH
Z-80 Trick. If passing through, the next instruction won’t execute
6559H
 ↳ “DERBRN”
LD E,7EH
LD E,ERRBRN
Let Register E equal 7EH to process a (ASCII: ???????????? error. we have read past the EOF
655BH
LD BC,641EH
Z-80 Trick. If passing through, the next instruction won’t execute
655CH
 ↳ “DERFOV”
LD E,64H
LD E,ERRFOV
Let Register E equal 64H to process a (ASCII: ???????????? error. we have read past the EOF
655EH
JUMP to 19A2H.
NOTE: 19A2H is the Model I ROM Routine to display the error message applicable to the error code held in Register E

6561H – ERROR PROCESSING ROUTINE – “ERRTRP”

This routine will process an error held in Register A on entry, based on the lookup table at 6575H, and exits with a ROM call to process an error. Routine also loads the value in the selected table entry into 5B8CH.
6561H
 ↳ “ERRTRP”
LD B,00H
Let Register B equal 00H so that Register C can be applied to 16 bit math (and added to HL)
6563H
LD HL,6574H
LD A,DERTAB-1
Let Register Pair HL equal 6574H, which is 1 byte before the lookup able at 6574H
6566H
CP 27H
Compare the value held in Register A against 27H (Decimal: 39). If A < 27H, the CARRY FLAG will be set
6568H
If A < 27H, then skip the next instruction because we have a valid entry for a lookup in the table at 6575H (which is 38 bytes)
656AH
LD A,01H
… otherwise, we had an entry higher than the highest entry in the table, so set Register A to equal 01H which would be the first entry of the table at 6575H
656CH
 ↳ “KNWERR”
LD C,A
Copy the table offset (held in Register A) into Register C, so that BC can be used to calculate an offset from HL’s 6574H
656DH
ADD HL,BC
LET Register Pair HL = Register Pair HL + Register BC, so now HL points to an entry in the table at 6575H
656EH
LD E,(HL)
Fetch the byte from the table at 6574H which corresponds to the offset and store it into Register E
656FH
LD (5B8CH),A
LD (DSKERR),A
Store the value held in Register A into memory location 5B8CH. This byte will be fetched at 5736H which processes a CMD”E” Command.

6572H
 ↳ “BBB”
JUMP to 19A2H.
NOTE: 19A2H is the Model I ROM Routine to display the error message applicable to the error code held in Register E

6575H – Data Storage Table of 38 Bytes for the value to put into 5B8CH based on the error code offsetE – “DERTAB”

6575H
72H
ERRIOE
Pass code ERRIOE to 5B8CH to pass to SYS4/SYS to process “ERROR DURING HEADER READ”
6576H
72H
ERRIOE
Pass code ERRIOE to 5B8CH to pass to SYS4/SYS to process “SEEK ERROR DURING READ”
6577H
72H
ERRIOE
Pass code ERRIOE to 5B8CH to pass to SYS4/SYS to process “LOST DATA DURING READ”
6578H
72H
ERRIOE
Pass code ERRIOE to 5B8CH to pass to SYS4/SYS to process “PARITY ERROR DURING READ”
6579H
72H
ERRIOE
Pass code ERRIOE to 5B8CH to pass to SYS4/SYS to process “DATA RECORD NOT FOUND DURING READ”
657AH
72H
ERRIOE
Pass code ERRIOE to 5B8CH to pass to SYS4/SYS to process “READ FROM LOCKED/DELETED DATA RECORD”
657BH
72H
ERRIOE
Pass code ERRIOE to 5B8CH to pass to SYS4/SYS to process “ATTEMPT TO READ SYSTEM DATA RECORD”
657CH
80H
ERRNMF
Pass code ERRNMF to 5B8CH to pass to SYS4/SYS to process “DEVICE NOT AVAILABLE”
657DH
72H
ERRIOE
Pass code ERRIOE to 5B8CH to pass to SYS4/SYS to process “PARITY ERROR DURING HEADER WRITE”
657EH
72H
ERRIOE
Pass code ERRIOE to 5B8CH to pass to SYS4/SYS to process “SEEK ERROR DURING WRITE”
657FH
72H
ERRIOE
Pass code ERRIOE to 5B8CH to pass to SYS4/SYS to process “LOST DATA DURING WRITE”
6580H
72H
ERRIOE
Pass code ERRIOE to 5B8CH to pass to SYS4/SYS to process “PARITY ERROR DURING WRITE”
6581H
72H
ERRIOE
Pass code ERRIOE to 5B8CH to pass to SYS4/SYS to process “DATA RECORD NOT FOUND DURING WRITE”
6582H
72H
ERRIOE
Pass code ERRIOE to 5B8CH to pass to SYS4/SYS to process “WRITE FAULT ON DISK DRIVE”
6583H
88H
ERRDWP
Pass code ERRDWP to 5B8CH to pass to SYS4/SYS to process “WRITE PROTECTED DISKETTE”
6584H
66H
ERRIER
Pass code ERRIER to 5B8CH to pass to SYS4/SYS to process “ILLEGAL LOGICAL FILE NUMBER”
6585H
72H
ERRIOE
Pass code ERRIOE to 5B8CH to pass to SYS4/SYS to process “DIRECTORY READ ERROR”
6586H
72H
ERRIOE
Pass code ERRIOE to 5B8CH to pass to SYS4/SYS to process “DIRECTORY WRITE ERROR”
6587H
80H
ERRNMF
Pass code ERRNMF to 5B8CH to pass to SYS4/SYS to process “ILLEGAL FILE NAME”
6588H
72H
ERRIOE
Pass code ERRIOE to 5B8CH to pass to SYS4/SYS to process “GAT READ ERROR”
6589H
72H
ERRIOE
Pass code ERRIOE to 5B8CH to pass to SYS4/SYS to process “GAT WRITE ERROR”
658AH
72H
ERRIOE
Pass code ERRIOE to 5B8CH to pass to SYS4/SYS to process “HIT READ ERROR”
658BH
72H
ERRIOE
Pass code ERRIOE to 5B8CH to pass to SYS4/SYS to process “HIT WRITE”
658CH
6AH
ERRFNF
Pass code ERRFNF to 5B8CH to pass to SYS4/SYS to process “FILE NOT IN DIRECTORY”
658DH
8AH
ERRFAD
Pass code ERRFAD to 5B8CH to pass to SYS4/SYS to process “FILE ACCESS DENIED”
658EH
86H
ERRTMF
Pass code ERRTMF to 5B8CH to pass to SYS4/SYS to process “DIRECTORY SPACE FULL”
658FH
7AH
ERRDFL
Pass code ERRDFL to 5B8CH to pass to SYS4/SYS to process “DISK SPACE FULL”
6590H
66H
ERRIER
Pass code ERRIER to 5B8CH to pass to SYS4/SYS to process “READ PAST END”
6591H
66H
ERRIER
Pass code ERRIER to 5B8CH to pass to SYS4/SYS to process “RECORD NUMBER OUT OF RANGE”
6592H
7AH
ERRIER
Pass code ERRIER to 5B8CH to pass to SYS4/SYS to process “RECORD NUMBER OUT OF RANGE” and “DIRECTORY FULL CANT EXTEND FILE”
6593H
66H
ERRIER
Pass code ERRIER to 5B8CH to pass to SYS4/SYS to process “PROGRAM NOT FOUND”
6594H
80H
ERRNMF
Pass code ERRNMF to 5B8CH to pass to SYS4/SYS to process “ILLEGAL DRIVE NUMBER”
6595H
66H
ERRIER
Pass code ERRIER to 5B8CH to pass to SYS4/SYS to process “NO DEVICE SPACE AVAILABLE”
6596H
66H
ERRIER
Pass code ERRIER to 5B8CH to pass to SYS4/SYS to process “LOAD FILE FORMAT ERROR”
6597H
66H
ERRIER
Pass code ERRIER to 5B8CH to pass to SYS4/SYS to process “MEMORY FAULT”
6598H
66H
ERRIER
Pass code ERRIER to 5B8CH to pass to SYS4/SYS to process “ATTEMPTED TO LOAD READ ONLY MEMORY”
6599H
8AH
ERRFAD
Pass code ERRFAD to 5B8CH to pass to SYS4/SYS to process “ACCESS ATTEMPTED TO PROTECTED FILE”
659AH
66H
ERRIER
Pass code ERRIER to 5B8CH to pass to SYS4/SYS to process “FILE NOT OPEN”