TRS-80 DOS – TRSDOS v1.3 – SYS11/SYS Disassembled

General:

SYS11/SYS handles the TAPE, PURGE, and LIST library commands.


Disassembly:

 
ORG 5200H
“BEGIN”
5200
LD A,55H
Let Register A equal 55H to set the CLEAR RAM flag.
5202
LD (42B4H),A
Store the value held in Register A into memory location 42B4H.
NOTE: 42B4H is the storage location for the PROGRAM PROTECT/CLEAR RAM Flag.
5205
XOR A
Set Register A to ZERO and clear all Flags.
5206
LD (4414H),A
Clear the overlay in RAM flag by storing the value held in Register A into memory location 4414H.
NOTE: 4414H is the storage location for the NUMBER OF THE OVERLAY CURRENTLY IN MEMORY.
5209
LD (42FFH),A
Clear the protection override switch by storing the value held in Register A into memory location 42FFH.
NOTE: 42FFH is the storage location for whether a password check is skipped or undertaken in an OPEN command. If Bit 0 is set, the check is skipped.
520C
DEC A
Set Register A to -1 by DECrementing the value stored in Register A by 1.
520D
LD (427AH),A
Clear the BASIC IN RAM Flag by storing the value held in Register A into memory location 427AH.
NOTE: 427AH is the storage location for the EXECUTE FILE FLAG/BASIC IN RAM Flag.
5210
PUSH HL
Save the COMMAND LINE (pointed to by Register Pair HL) to the top of the stack.
5211
CALL GETTAB
     [5226H]
Identify the executor which called the Overlay via a GOSUB to 5226H.
5214
JR C,NOCMD
     [5218H]
If the C FLAG (Carry) has been set then that routine wound up with an error, so exit via a JUMP to 5218H.
5216
EX (SP),HL
Put the COMMAND LINE POINTER (held in Register Pair HL) at the top of the stack and the COMMAND ADDRESS (held at the top of the stack) into Register Pair HL.
5217
RET
RETurn to the the executor address.

5218H – Exit with a ILLEGAL PARAMETER error.

“NOCMD”
5218
POP HL
Clear the stack.
“ERR2”
5219
LD A,0BH
Let Register A equal 0BH to point to an ILLEGAL PARAMETER error.
521B
JR ERRX
   [5223H]
Display the ILLEGAL PARAMETER error and exit via a JUMP to 5223H.

521DH – Exit with a PARAMETER NOT FOUND error.

“ERR3”
521D
LD A,0AH
Let Register A equal 0AH to point to a PARAMETER NOT FOUND error.
521F
JR ERRX
   [5223H]
Display the PARAMETER NOT FOUND error and exit via a JUMP to 5223H.

5221H – Exit with an error of DISK DRIVE NOT ON.

“ERR9”
5221
LD A,02H
Let Register A equal 02H to point to a DISK DRIVE NOT ON error.
“ERRX”
5223
JP 4409H
   [4409H]
JUMP to 4409H.
NOTE: 4409H is the SYS00/SYS routine to process DOS errors.

5226H – Decode the COMMAND LINE.

“GETTAB”
5226
LD HL,TABLE
Let Register Pair HL equal 523EH, which is the top of the COMMAND TABLE.
“GETTA1”
5229
LD A,(HL)
Fetch the first byte on the current row of the COMMAND TABLE and store it into Register A.
522A
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).
522B
JR NZ,GETTA2
      [522FH]
If the NZ FLAG (Not Zero) has been set, then we have not run out of table entries, so look up the command by JUMPing to 522FH.
522D
SCF
We ran out of table entries without a match, so we turn the CARRY FLAG on to indicate an error.
522E
RET
RETurn to the caller.

522FH – Scan the COMMAND TABLE for a match.

“GETTA2”
522F
CP C
Check to see if the command given matches the command table entry by comparing the value held in Register A against the value held in Register C. Results: If they match, the Z FLAG is set …
5230
JR Z,GETTA3
     [5237H]
… so JUMP to 5237H to get the address and continue.
5232
5233
5234
INC HL
INC HL
INC HL
INCrement the value stored in Register Pair HL by 3 (i.e., LSB of non-matching command, MSB of non-matching command, next command to test) to move to the next line of the COMMAND TABLE.
5235
JR GETTA1
   [5229H]
Loop back to 5229H to keep checking the command table.

5237H – Determine the JUMP POINT from a MATCHING ENTRY of the COMMAND TABLE.

“GETTA3”
5237
INC HL
INCrement the value stored in Register Pair HL by 1 to point to the LSB byte of the address of the command.
5238
LD E,(HL)
Fetch the LSB byte of the address of the command (held in the memory location pointed to by Register Pair HL) and store it into Register E.
5239
INC HL
INCrement the value stored in Register Pair HL by 1 to point to the MSB byte of the address of the command.
523A
LD D,(HL)
Fetch the MSB byte of the address of the command (held in the memory location pointed to by Register Pair HL) and store it into Register D.
523B
EX DE,HL
EXchange the value stored in Register Pair HL (the pointer to the COMMAND TABLE) with the value stored in Register Pair DE (the jump address for the matched command).
523C
OR A
Make sure the CARRY FLAG is off.
523D
RET
RETurn to the caller.

523EH – COMMAND TABLE.

“TABLE”
523E
DEFB 23H
Code for the TAPE command
523F
DEFB A9H 52H
Jump location of 52A9H
5241
DEFB 1EH
Code for the PURGE command
5242
DEFB 0DH 56H
Jump location of 560DH
5244
DEFB 18H
Code for the LIST command
5245
DEFB CCH 58H
Jump location of 58CCH
5247
DEFB 00H
End of Table Delimeter.

5246H – Compare the first “BC” number of bytes of the string at (DE) againg the String at (HL).

“COMPAR”
5248
PUSH BC
Save the contents of Register Pair BC to the top of the stack.
5249
PUSH DE
Save the contents of Register Pair DE to the top of the stack.
524A
PUSH HL
Save the contents of Register Pair HL to the top of the stack.
“COMPA1”
524B
LD A,(DE)
Fetch a character from the memory location pointed to by Register Pair DE and store it into Register A.
524C
CP (HL)
Compare the fetched character against the character from the memory location pointed to by Register Pair HL.
524D
JR NZ,COMPA2
      [5254H]
If they don’t match then the NZ FLAG (Not Zero) will have been set and we are done, so JUMP to 5254H to restore the registers from the stack with NZ set.
524F
LDI
Move to the 2nd character of both HL and DE via LDI command; which copies BC number of characters from (HL) to (DE), dropping BC each time. When BC hits 0, the PE flag is reset.
5251
JP PE,COMPA1
      [524BH]
If the PARITY/OVERFLOW FLAG has been SET then we have not reached the end of the string, so loop back to 524BH.
“COMPA2”
5254
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
5255
POP DE
Put the value held at the top of the STACK into Register Pair DE, and then remove the entry from the stack.
5256
POP BC
Put the value held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
5257
RET
RETurn to the caller.

5258H – Position HL to the next non-space character.

“SKIPSP”
5258
LD A,(HL)
Fetch the value held in the memory location pointed to by Register Pair HL and store it into Register A.
5259
CP 20H
Compare the value held in Register A against 20H (ASCII: SPACE) and set the NZ flag if it isn’t a SPACE.
525B
RET NZ
If it isn’t a SPACE then the the NZ FLAG (Not Zero) will have been set, RETurn to the caller.
“SKIPS1”
525C
INC HL
INCrement HL by 1 to point to the next character to check.
525D
JR SKIPSP
   [5258H]
JUMP to 5258H to check that character against a space.

525FH – Pause if “@” is Pressed.

“HLDPAT”
525F
CALL 002BH
     [002BH]
GOSUB to 002BH.
NOTE: 002BH is the Model III ROM Keyboard scanning routine; Register A exits with the ASCII value for the key that was pressed or ZERO if no key was pressed.
5262
OR A
Set FLAGS based on the contents of Register A.
5263
RET Z
If no key was pressed then the Z FLAG (Zero) will have been set, RETurn to the caller.
5264
CP 40H
Compare the value held in Register A against 40H (ASCII: @).
5266
RET NZ
If the key pressed was anything other than a @, the NZ FLAG (Not Zero) will have been set, RETurn to the caller.

If we are here, then we got a @ so now we are going to sit and wait for an ENTER.

"HLDPA1"
5267
CALL 0049H
     [0049H]
GOSUB to 0049H which is the Model III ROM routine to scan the keyboard and wait until a key is pressed, and then return with the key pressed in Register A. BREAK returns 01H.
526A
CP 0DH
Compare the value held in Register A against 0DH (ASCII: CARRIAGE RETURN). Results: If Register A equals CARRIAGE RETURN, the Z FLAG is set; otherwise the NZ FLAG is set.
526C
JR NZ,HLDPA1
      [5267H]
If the key we received was not a ENTER then the NZ FLAG (Not Zero) will have been set, so loop back to 5267H.
526E
RET
If we're here, then an ENTER was received, so RETurn to the caller.

526FH - Output a Byte held in Register A to the Screen and, if 5277H is set to 0000H, to the Printer.

"PDATA"
526F
CP 09H
Compare the value held in Register A against 09H (ASCII: TAB). Results: If Register A equals TAB, the Z FLAG is set; otherwise the NZ FLAG is set.
5271
JP Z,SPACIT
     [5A91H]
If a TAB was found, the Z FLAG (Zero) will have been set, so JUMP to 5A91H to process a TAB.
5274
PUSH DE
Save the contents of Register Pair DE to the top of the stack.
5275
PUSH BC
Save the contents of Register Pair BC to the top of the stack.
5276
LD BC,(LPFLAG)
Let Register Pair BC equal the value placed into memory location 5277H elsewhere in this overlay. This will be the LINE PRINTER flag.
5279
527A
INC C
DEC C
We need to test BC against 0 and, for some reason, the authors decided to do this by INCrementing and then DECrementing the value stored in Register C by 1.
527B
PUSH AF
Save the character being processed (held in Register Pair AF) to the top of the stack.
527C
CALL NZ,003BH
        [003BH]
If the NZ FLAG (Not Zero) has been set, PRINT the character via a GOSUB to 003BH.
NOTE: 003BH is the Model III ROM routine to write the byte held in Register A to the printer, including waiting for the printer to be available OR getting a BREAK. Uses Register Pair DE.
527F
POP AF
Restore the character being processed (held at the top of the stack) into Register Pair AF.
5280
CALL 0033H
     [0033H]
Display the character via a GOSUB to 0033H.
NOTE: 0033H is the Model III ROM character print routine; displays the character held in Register A at the current cursor position.
5283
POP BC
Put the value held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
5284
POP DE
Put the value held at the top of the STACK into Register Pair DE, and then remove the entry from the stack.
5285
RET
RETurn to the caller.

5286H - Output a text string pointed to by Register Pair HL to the Screen and, if 5277H is set to 0000H, to the Printer as well.

"PRINTT"
5286
LD A,(HL)
Fetch a character from the memory location pointed to by Register Pair HL and store it into Register A.
5287
CP 03H
Check to see if the character is a terminator by comparing the value held in Register A against 03H. If the character is a terminator ...
5289
RET Z
... RETurn to the caller ...
528A
CALL PDATA
     [526FH]
... otherwise, output the character held in Register A to the screen and, if applicable, the printer, via a GOSUB to 526FH.
528D
CP 0DH
Check to see if we are at the end of the line by comparing the character held in Register A against 0DH (ASCII: CARRIAGE RETURN) and if so ...
528F
RET Z
... RETurn to the caller ...
5290
INC HL
Otherwise ... INCrement the pointer to the current character to deal with (held in Register Pair HL) by 1.
5291
JR PRINTT
   [5286H]
LOOP back to the top of this routine (i.e., 5286H).

5293H - Output the low nybble of Register A in Hexadecimal to the Screen and, if 5277H is set to 0000H, to the Printer.

The DAA opcode is fairly complicated and beyond this discussion. The next 5 instructions, however, are the standard routine to conver the lower 4 bits of Register A into the ASCII values of "0" ... "F".

"HEXC"
5293
AND 0FH
Turn off the high nybble by MASKing the value of Register A against 0FH (0000 1111), turning off bits 7, 6, 5, 4.
5295
ADD A,90H
LET Register A = Register A + 90H, so that 0-9=90H-99H and A-F=01H-05H.
5297
DAA
Adjust Register A for BCD addition and subtraction operations. DAA is way too complicated to go into here, but if the low 4 bits are greater than 9, the H FLAG is set and 06H is addded to Register A and if the high 4 bits are greater than 9, the C FLAG is set and 60H is added to Register A. The explanation for this is that there are 6 ASCII characters between 9 and A, so adding 6H (for the ones digit) or 60H (for the tens digit), changes A-F into 10-15 in decimal.
5298
ADC A,40H
Let Register A = Register A + 40H (plus carry), so that 0-9=30H-39H and A-F=40H-45H)
529A
DAA
Adjust Register A for BCD addition and subtraction operations. DAA is way too complicated to go into here, but if the low 4 bits are greater than 9, the H FLAG is set and 06H is addded to Register A and if the high 4 bits are greater than 9, the C FLAG is set and 60H is added to Register A. The explanation for this is that there are 6 ASCII characters between 9 and A, so adding 6H (for the ones digit) or 60H (for the tens digit), changes A-F into 10-15 in decimal.
529B
JR PDATA
   [526FH]
JUMP to 526FH to output the character held in Register A to the screen and, if applicable, the printer, via a GOSUB to 526FH.

529DH - Encode a Two Digit Decimal Number in Text at (HL).

"DECBIN"
529D
LD (HL),2FH
Initialize the routine by starting (HL), which is the first digit, at one character below "0".
"DECBI1"
529F
INC (HL)
Start of a loop. INCrement the first digit (stored in the memory location pointed to by Register Pair HL) by 1.
52A0
SUB 0AH
Let the first character (held in Register A) = that character - 10.
52A2
JR NC,DECBI1
      [529FH]
As long as that SUB didn't go below 0, the NC flag will be set. In that case, loop back to 529FH and increase the digit held in the memory location pointed to by Register Pair HL by 1 and subtract another 10 from Register A.
52A4
ADD A,3AH
Loop has ended. Correct Register A and then convert to ASCII by setting Register A = Register A + 3AH to convert the remainder (i.e., the 2nd digit) to ASCII.
52A6
INC HL
INCrement the value stored in Register Pair HL by 1 to point to the second digit.
52A7
LD (HL),A
Store the converted 2nd digit (held in Register A) into the memory location pointed to by Register Pair HL.
52A8
RET
RETurn to the caller.

52A9H - "TAPE" Routine.

"SYSTEN"
52A9
PUSH HL
Save the pointer to the COMMAND LINE (poinetd to by Register Pair HL) to the top of the stack.

The next 5 instructions are a standard way of clearing a memory region which will be used for DCB's. HL is the base, DE = HL + 1, BC = the bytes to move. Then (HL) is set to 00H, which means 00H is then successively copied from one location to the next location, BC number of times.

52AA
LD HL,SDCB1
Let Register Pair HL equal 5BA2H, which will be the base of a buffer 97 characters long to hold a file control block.
52AD
LD DE,SDCB1 + 1
Let Register Pair DE equal 5BA3H.
52B0
LD BC,0060H
Let Register Pair BC equal 0060H, which is the size of two DCB's.
52B3
LD (HL),00H
Store the value held in 00H into the memory location pointed to by Register Pair HL.
52B5
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.

Now 97 bytes of a buffer starting at 5BA2H has been zero'ed.

52B7
POP HL
Restore the pointer to the COMMAND LINE from the stack back into Register Pair HL.
52B8
CALL SKIPSP
     [5258H]
Position HL to the next non-space character on the COMMAND LINE via a GOSUB to 5258H.
52BB
CP 0DH
Compare the value held in Register A against 0DH (ASCII: CARRIAGE RETURN). Results: If Register A equals CARRIAGE RETURN, the Z FLAG is set; otherwise the NZ FLAG is set.
52BD
JP Z,ERR3
     [521DH]
We hit a CARRIAGE RETURN, which means we did not get parameters, the Z FLAG (Zero) will have been set and we JUMP to 521DH to exit with an error.
52C0
CP 28H
Compare the value held in Register A against 28H (ASCII: (). Results: If Register A equals (, the Z FLAG is set; otherwise the NZ FLAG is set.
52C2
JP NZ,ERR2
      [5219H]
If Register A does NOT equal ( then we have a bad COMMAND LINE and the NZ FLAG (Not Zero) will have been set, so JUMP to 5219H to display an ILLEGAL PARAMETER error and exit via a JUMP to 5223H.
52C5
CALL SKIPS1
     [525CH]
Fetch the next non-space character (pointed to by Register Pair HL) into Register A via a GOSUB to 525CH.
52C8
CP 29H
Compare the value held in Register A against 29H (ASCII: )). Results: If Register A equals ), the Z FLAG is set; otherwise the NZ FLAG is set.
52CA
JP Z,ERR3
     [521DH]
If we hit a ) which means we have a bad COMMAND LINE, the Z FLAG (Zero) will have been set and we JUMP to 521DH to exit with an error.
"SYSTE1"
52CD
CP 53H
Compare the value held in Register A against 53H (ASCII: S). Results: If Register A equals S, the Z FLAG is set; otherwise the NZ FLAG is set.
52CF
JR NZ,SYSTE2
      [52D9H]
If we didn't get a S (for SOURCE) then the NZ FLAG (Not Zero) will have been set, JUMP to 52D9H to look for the destination spec.
52D1
LD BC,SDCB1
If we're here then we are ready to process the SOURCE filename, so set Register Pair BC to the SOURCE DCB buffer at 5BA2H.
52D4
CALL SYSPAR
     [531FH]
GOSUB to 531FH to get the source device name.
52D7
JR SYSTE1
   [52CDH]
LOOP BACK 5 instructions to 52CDH to get the next spec.

52D9H - Continuation of "TAPE" Routine. Jumped here to process the command line looking for the Destination spec.

"SYSTE2"
52D9
CP 44H
Compare the value held in Register A against 44H (ASCII: D). Results: If Register A equals D, the Z FLAG is set; otherwise the NZ FLAG is set.
52DB
JR NZ,SYSTE3
      [52E5H]
If we didn't get a D (for DESTINATION) then the NZ FLAG (Not Zero) will have been set, JUMP to 52E5H.
52DD
LD BC,SDCB2
Let Register Pair BC equal 5BD2H to point to the DESTINATION DCB buffer.
52E0
CALL SYSPAR
     [531FH]
GOSUB to 531FH to get the destination device name.
52E3
JR SYSTE1
   [52CDH]
LOOP back to 52CDH to get the next spec.

52E5H - Continuation of "TAPE" Routine. Jumped here if we didn't get a destination spec.

"SYSTE3"
52E5
CP 20H
Compare the value held in Register A against 20H (ASCII: SPACE). Results:
  • If Register A equals SPACE, the Z FLAG is set.
  • If A < SPACE, the CARRY FLAG will be set.
  • if A >= SPACE, the NO CARRY FLAG will be set.
52E7
JR C,SYSTE4
     [52EEH]
If the character was so low in the ASCII range that the C FLAG (Carry) has been set, then we will assume we hit the end of the COMMAND LINE and JUMP to 52EEH.
52E9
CP 29H
Compare the value held in Register A against 29H (ASCII: )). Results: If Register A equals ), the Z FLAG is set; otherwise the NZ FLAG is set.
52EB
JP NZ,ERR2
      [5219H]
If Register A does NOT equal ) then we have a bad COMMAND LINE and the NZ FLAG (Not Zero) will have been set, so JUMP to 5219H to display an ILLEGAL PARAMETER error and exit via a JUMP to 5223H.
"SYSTE4"
52EE
LD A,(SDCB1)
Fetch the SOURCE OPERATOR (where the source file is coming from), which is first character in the SOURCE DCB Buffer (held in the buffer starting at 5BA2H), and store it into Register A.
52F1
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
52F2
JP Z,ERR3
     [521DH]
If there is no character then we have no idea where the source file is coming from and the Z FLAG (Zero) will have been set, so exit with an error via a JUMP to 521DH.
52F5
LD B,A
Copy the SOURCE FILE OPERATOR (held in Register A) into Register B.
52F6
LD A,(SDCB2)
Fetch the DESTINATION FILE OPERATOR (where the destination file is going) held in the buffer starting at 5BD2H and store it into Register A.
52F9
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).
52FA
JP Z,ERR3
     [521DH]
If there is no character then we have no idea where the source file is coming from and the Z FLAG (Zero) will have been set, so exit with an error via a JUMP to 521DH.
52FD
CP B
We now have a non-null SOURCE FILE OPERATOR and DESTINATION FILE OPERATOR. Next we need to check to make sure they aren't the same, so compare them. If they are the same then ...
52FE
JP Z,ERR2
     [5219H]
... JUMP to 5219H to display an ILLEGAL PARAMETER error and exit via a JUMP to 5223H.
5301
PUSH AF
Save the contents of Register Pair AF to the top of the stack.
5302
PUSH BC
Save the contents of Register Pair BC to the top of the stack.
5303
CALL 3042H
     [3042H]
GOSUB to 3042H, which is a routine in the Model III ROM to set the tape transfer speed.
5306
LD HL,TSRCT
Let Register Pair HL equal 53ADH, to point to the message "DEVICE = ".
5309
CALL 021BH
     [021BH]
GOSUB to 021BH, which is a routine in the Model III ROM to display the character at (HL) until a 03H is found.
530C
POP BC
Put the value held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
530D
POP AF
Put the value held at the top of the STACK into Register Pair AF, and then remove the entry from the stack.
530E
PUSH AF
Save the DESTINATION FILE OPERATOR (held in Register A) to the top of the stack.
530F
LD A,B
Copy the SOURCE FILE OPERATOR (held in Register B) into Register A.
5310
CP 44H
Check to see if the SOURCE file is on DISK by comparing the value held in Register A against 44H (ASCII: D).
5312
POP BC
Put the DESTINATION FILE OPERATOR (held at the top of the STACK) into Register Pair BC, and then remove the entry from the stack.
5313
JP Z,DSRC
     [53BCH]
If SOURCE FILE OPERATOR is set for DISK, the Z FLAG (Zero) will have been set, so JUMP to 53BCH.
5316
LD A,B
Copy the DESTINATION FILE OPERATOR (held in Register B) into Register A.
5317
CP 44H
Check to see if the DESTINATION file is on DISK by comparing the value held in Register A against 44H (ASCII: D).
5319
JP Z,TSRC
     [54D3H]
If the destination spec is "D"ISK then the Z FLAG (Zero) will have been set, so JUMP to 54D3H.
531C
JP TRAM
   [55ADH]
We know it's not tape or disk, so it must be RAM. Continue the routine via a JUMP to 55ADH.

531FH - Continuation of "TAPE" Routine. Evaluate the Parameter in a Given String.

"SYSPAR"
531F
CALL SKIPS1
     [525CH]
Fetch the next non-space character (pointed to by Register Pair HL) into Register A via a GOSUB to 525CH.
5322
CP 3DH
Compare the value held in Register A against 3DH (ASCII: =). Results: If Register A does NOT equal = the NZ FLAG is set ...
5324
JP NZ,ERR2
      [5219H]
... and we have a problem; so, so JUMP to 5219H to display an ILLEGAL PARAMETER error and exit via a JUMP to 5223H.
5327
CALL SKIPS1
     [525CH]
Fetch the next non-space character (pointed to by Register Pair HL) into Register A via a GOSUB to 525CH.
532A
LD (BC),A
Store the parameter character (held in Register A) into the DCB at the memory location pointed to by Register Pair BC.
532B
CP 54H
Compare the value held in Register A against 54H (ASCII: T) to see if TAPE was chosen; Z FLAG will be set it they match.
532D
JR Z,SYSPA0
     [5338H]
If the Z FLAG (Zero) has been set, skip the rest of the tests via a JUMP to 5338H.
532F
CP 44H
Compare the value held in Register A against 44H (ASCII: D) to see if DISK was chosen; Z FLAG will be set it they match.
5331
JR Z,SYSPA0
     [5338H]
If the Z FLAG (Zero) has been set, skip the rest of the tests via a JUMP to 5338H.
5333
CP 52H
Compare the value held in Register A against 52H (ASCII: R) to see if RAM was chosen; Z FLAG will be set it they match.
5335
JP NZ,ERR2
      [5219H]
If the NZ FLAG (Not Zero) has been set then it wasn't D, T, or R which is a problem; so JUMP to 5219H to display an ILLEGAL PARAMETER error and exit via a JUMP to 5223H.
"SYSPA0"
5338
CALL SKIPS1
     [525CH]
Fetch the next non-space character (pointed to by Register Pair HL) into Register A via a GOSUB to 525CH.
533B
CP 2CH
Compare the value held in Register A against 2CH (0010 1100) (ASCII: ,). If we got a comma ...
533D
JP Z,SKIPS1
     [525CH]
... JUMP to 525CH to fetch the next non-space character (pointed to by Register Pair HL) into Register A. Since this is a JP rather than a CALL, this will RETurn to the caller.
5340
CP 29H
Compare the value held in Register A against 29H (ASCII: )). If we did then we are at the end of the parameter and ...
5342
RET Z
... RETurn to the caller with the Z FLAG set.
5343
CP 20H
Compare the value held in Register A against 20H. If A < 20H, the CARRY FLAG will be set. This is to trap all the usable characters below 20H and we will assume it means we are at the end of line.
5345
RET C
If the C FLAG (Carry) has been set then we have a bad character, so RETurn to the caller with the C FLAG set.
5346
JR SYSPA0
   [5338H]
If we're here then we will loop back to 5338H and keep processing characters.

5348H - Continuation of "TAPE" Routine. Prompt the user to insert a cassette and wait for a key.

"RDYCAS"
5348
LD HL,5356H
Let Register Pair HL equal 5356H, to point to the message 'Press Any key when Cassette ready' + 0DH.
534B
CALL 021BH
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
534E
CALL 0049H
     [0049H]
Wait for a key press via a GOSUB to the MODEL III ROM Routine at 0049H which is is the Model III ROM routine to scan the keyboard and wait until a key is pressed, and then return with the key pressed in Register A. BREAK returns 01H.
5351
LD A,0DH
Display a CARRIAGE RETURN by setting Register A equal 0DH (ASCII: CARRIAGE RETURN).
5353
JP 0033H
   [0033H]
JUMP to 0033H.
NOTE: 0033H is the Model III ROM character print routine; displays the character held in Register A at the current cursor position. Since this was JUMPED to instead of CALLed, the RET at the end of this ROM routine will then RETurn to the caller of this subroutine instead of returning to this place.

5356H - "TAPE" Routine - Message and Byte Storage.

"RDYCMG"
5356
DEFM 'Press Any key when Cassette ready' + 0DH
"DISK"
5378
DEFM 'Disk to Tape - Filespec? ' + 03H
"TAPE"
5392
DEFM 'Tape to Disk' + 0DH
"RAM"
539F
DEFM 'Tape into Ram' + 0DH
"TSRCT"
53AD
DEFM 'Device = ' + 03H
"CMEXT"
53B7
DEFM '/CMD' + 03H

53CBH - Contination of "TAPE" Routine for SOURCE = DISK, DEST = TAPE.

"DSRC"
53BC
LD HL,DISK
Let Register Pair HL equal 5378H, to point to the message 'Disk to Tape - Filespec? ' + 03H.
53BF
CALL 021BH
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
53C2
LD HL,SDCB1
Let Register Pair HL equal 5BA2H which is the SOURCE DCB Buffer.
53C5
LD B,18H
Let Register B equal 18H for a LDIR MOVE of 24 characters, which is the maximum number of characters in a filespec.
53C7
CALL 0040H
     [0040H]
GOSUB to 0040H.
NOTE: 0040H is the Model III ROM routine to get a full line from the keyboard. In this routine, a line is terminated by a carriage return or BREAK, and characters typed are echoed to the display. On entry, B must be the maximum length of line to be accepted and (HL) must be the storage buffer which should be set to B+1. On Exit, CARRY will be set if the BREAK key was hit, Register B will contain the number of characters entered, and (HL) will contain the line from the keyboard followed by the terminating character. Register paid DE is altered in this routine.
53CA
RET C
If a BREAK was pressed the C FLAG (Carry) will have been set; RETurn to the caller.
53CB
LD A,B
Copy the number of the characters received (held in Register B) into Register A.
53CC
OR A
Test to see if anything was entered via an OR. If the Z FLAG is set, nothing was entered ...
53CD
RET Z
... and we will just RETurn to the caller.
53CE
53CF
LD C,B
LD B,00H
Copy the number of the characters received (held in Register B) into Register Pair BC.
53D1
LD DE,SDCB2
Let Register Pair DE equal 5BD2H to point to the DESTINATION DCB buffer.
53D4
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.
53D6
LD A,0DH
Let Register A equal 0DH so that a CARRIAGE RETURN terminator can be put at the end of the filename.
53D8
LD (DE),A
Store the CARRIAGE RETURN held in Register A at the end of the filename (i.e., the memory location pointed to by Register Pair DE).
53D9
LD HLBUFER1
Let Register Pair HL equal 5D00H for a FILE BUFFER.
53DC
LD DE,SDCB1
Let Register Pair DE equal 5BA2H which is the SOURCE DCB Buffer.
53DF
LD B,00H
Let Register B equal 00H so that the next routine will set for FULL SECTOR I/O.
53E1
CALL 4424H
     [4424H]
GOSUB to 4424H.
NOTE: 4424H is the SYS00/SYS routine to OPEN A DISK FILE for use. This RST 28H's with a value of 92H so as to call ROUTINE 2 in OVERLAY 3.
53E4
JP NZ,4409H
      [4409H]
If the NZ FLAG (Not Zero) has been set, JUMP to 4409H.
NOTE: 4409H is the SYS00/SYS routine to process DOS errors.
53E7
LD HLBUFER2
Let Register Pair HL equal 5E00H for a FILE BUFFER / DATA STORAGE BUFFER.
"DSRC1"
53EA
LD DE,SDCB1
Let Register Pair DE equal 5BA2H which is the SOURCE DCB Buffer.
53ED
CALL 0013H
     [0013H]
GOSUB to 0013H.
NOTE: 0013H is the Model III ROM routine to read a byte from an input device. Requires DE = starting address of DCB of device and on Exit Register A = byte received from device, Z set if device ready. Uses AF.
53F0
JP NZ,4409H
      [4409H]
If the NZ FLAG (Not Zero) has been set, JUMP to 4409H.
NOTE: 4409H is the SYS00/SYS routine to process DOS errors.
53F3
CP 01H
We need to analyze what kind of file block we are reading. First, compare the value held in Register A against 01H, which would be an executable file CODE BLOCK. If it is ...
53F5
JR Z,DSRC5
     [540FH]
... get the data by JUMPing to 540FH.
53F7
CP 02H
Compare the value held in Register A against 02H, which would be an executable file TRANSFER ADDRESS. If it is ...
53F9
JR Z,DSRC7
     [542CH]
... fet the transfer address by JUMPing to 542CH.
53FB
CP 06H
Compare the value held in Register A against 06H, which would be an executable file COMMENT BLOCK. If it is ...
53FD
JR C,DSRC3
     [5404H]
... we need to just stall via a JUMP to 5404H.

If we are here, then we didn't get a valid block indicator, so we will declare the file as bad.

"BADLFE"
53FF
LD A,22H
Let Register A equal 22H for a INVALID FILE FORMAT error..
5401
JP 4409H
   [4409H]
JUMP to 4409H.
NOTE: 4409H is the SYS00/SYS routine to process DOS errors.

5404H - Contination of "TAPE" Routine. Routine to handle a COMMENT BLOCK.

"DSRC3"
5404
CALL GETBYT
     [54B3H]
Fetch the COMMENT BLOCK size byte into Register A via a GOSUB to 54B3H, which reads a byte from diskettte.
5407
LD B,A
In preparation for a DJNZ loop, copy the COMMENT BLOCK size byte (held in Register A) into Register B.
"DSRC4"
5408
CALL GETBYT
     [54B3H]
Get the comment byte into Register A via a GOSUB to 54B3H, which reads a byte from diskettte.
540B
DJNZ DSRC4
     [5408H]
LOOP back to the prior instruction, 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.

540FH - Contination of "TAPE" Routine. Routine to handle a CODE BLOCK.

"DSRC5"
540F
LD (HL),A
Store BLOCK MARKER (currently held in Register A) into the FILE BUFFER / DATA STORAGE BUFFER location pointed to by Register Pair HL.
5410
INC HL
Move to the next space in the FILE BUFFER / DATA STORAGE BUFFER by INCrementing the value stored in Register Pair HL by 1.
5411
CALL GETBYT
     [54B3H]
Fetch the CODE BLOCK size byte into Register A via a GOSUB to 54B3H, which reads a byte from diskettte.
5414
LD B,A
In preparation for a DJNZ loop, copy the CODE BLOCK LENGTH byte (held in Register A) into Register B.
5415
LD (HL),A
Store the CODE BLOCK LENGTH (held in Register A) into the FILE BUFFER / DATA STORAGE BUFFER location pointed to by Register Pair HL.
5416
INC HL
Move to the next space in the FILE BUFFER / DATA STORAGE BUFFER by INCrementing the value stored in Register Pair HL by 1.
5417
CALL GETBYT
     [54B3H]
Fetch the LSB of the CODE BLOCK ADDRESS into Register A via a GOSUB to 54B3H, which reads a byte from diskettte.
541A
DEC B
DECrement the bytes-left-to-process counter stored in Register B by 1.
541B
LD (HL),A
Store the LSB of the CODE BLOCK ADDRESS (held in Register A) into the FILE BUFFER / DATA STORAGE BUFFER location pointed to by Register Pair HL.
541C
INC HL
Move to the next space in the FILE BUFFER / DATA STORAGE BUFFER by INCrementing the value stored in Register Pair HL by 1.
541D
CALL GETBYT
     [54B3H]
Fetch the MSB of the CODE BLOCK ADDRESS into Register A via a GOSUB to 54B3H, which reads a byte from diskettte.
5420
DEC B
DECrement the bytes-left-to-process counter stored in Register B by 1.
5421
LD (HL),A
Store the MSB of the CODE BLOCK ADDRESS (held in Register A) into the FILE BUFFER / DATA STORAGE BUFFER location pointed to by Register Pair HL.
5422
INC HL
Move to the next space in the FILE BUFFER / DATA STORAGE BUFFER by INCrementing the value stored in Register Pair HL by 1.
"DSRC6"
5423
CALL GETBYT
     [54B3H]
Top of a DJNZ loop. Fetch a CODE BYTE into Register A via a GOSUB to 54B3H, which reads a byte from diskettte.
5426
LD (HL),A
Store the CODE BYTE (held in Register A) into the FILE BUFFER / DATA STORAGE BUFFER location pointed to by Register Pair HL.
5427
INC HL
Move to the next space in the FILE BUFFER / DATA STORAGE BUFFER by INCrementing the value stored in Register Pair HL by 1.
5428
DJNZ DSRC6
     [5423H]
Keep processing the entire CODE BLOCK by LOOPing back to 5423H, 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.
542A
JR DSRC1
   [53EAH]
Get the file's next block by JUMPing back to to 53EAH.

542CH - Contination of "TAPE" Routine. Routine to handle a TRANSFER ADDRESS BLOCK.

"DSRC7"
542C
LD (HL),A
Store BLOCK MARKER (currently held in Register A) into the memory location pointed to by Register Pair HL.
542D
INC HL
Move to the next space in the FILE BUFFER / DATA STORAGE BUFFER by INCrementing the value stored in Register Pair HL by 1.
542E
CALL GETBYT
     [54B3H]
Fetch the LENGTH BYTE of the CODE BLOCK ADDRESS into Register A via a GOSUB to 54B3H. This is not going to get preserved.
5431
CALL GETBYT
     [54B3H]
Fetch the LSB of the TRANSFER ADDRESS into Register A via a GOSUB to 54B3H, which reads a byte from diskettte.
5434
LD (HL),A
Store the LSB of the TRANSFER ADDRESS (held in Register A) into the FILE BUFFER / DATA STORAGE BUFFER location pointed to by Register Pair HL.
5435
INC HL
Move to the next space in the FILE BUFFER / DATA STORAGE BUFFER by INCrementing the value stored in Register Pair HL by 1.
5436
CALL GETBYT
     [54B3H]
Fetch the MSB of the TRANSFER ADDRESS into Register A via a GOSUB to 54B3H, which reads a byte from diskettte.
5439
LD (HL),A
Store the MSB of the TRANSFER ADDRESS (held in Register A) into the FILE BUFFER / DATA STORAGE BUFFER location pointed to by Register Pair HL.

543AH - Contination of "TAPE" Routine. Passed through from the above routine, this code writes the file from RAM to TAPE.

543A
CALL RDYCAS
     [5348H]
Prompt the user to insert a cassette and wait for a key via a GOSUB to 5348H.
543D
CALL 0287H
     [0287H]
Write the TAPE LEADER via a GOSUB to 0287H.
5440
LD A,55H
Let Register A equal 55H to designate the file as a SYSTEM file.
5442
CALL 0264H
     [0264H]
GOSUB to 0264H which is the Model III ROM routine to output a byte held in Register A to cassette. This routine must be called often enough to keep up with the baud rate.
5445
LD HL,SDCB2
Let Register Pair HL equal 5BD2H to point to the DESTINATION DCB buffer.
5448
LD B,06H
Since SYSTEM file filenames are 6 characters, set Register B equal 06H.
"TDES"
544A
LD A,(HL)
Fetch a byte from the DESTINATION BUFFER (pointed to by Register Pair HL) and store it into Register A.
544B
CP 2FH
Test the character to see if we have hit the extension by comparing the value held in Register A against 2FH (ASCII: /). If yes ...
544D
JR Z,TDES1
     [545FH]
... stop reading characters and JUMP to 545FH.
544F
CP 3AH
Test the character to see if we have hit a drivespec by comparing the value held in Register A against 3AH (ASCII: :). If yes ...
5451
JR Z,TDES1
     [545FH]
... stop reading characters and JUMP to 545FH.
5453
CP 30H
Test the character to see it is below the lowest permitted character in a filespec (i.e., "0") by comparing the value held in Register A against 30H (ASCII: 0). Results:
  • If Register A equals 0, the Z FLAG is set.
  • If A < 30H 0, the CARRY FLAG will be set.
  • if A >= 30H 0, the NO CARRY FLAG will be set.
5455
JR C,TDES1
     [545FH]
If the CARRY FLAG has been set then we will skip writing the rest of the filename via a JUMP to 545FH.
5457
CALL 0264H
     [0264H]
GOSUB to 0264H which is the Model III ROM routine to output a byte held in Register A to cassette. This routine must be called often enough to keep up with the baud rate.
545A
INC HL
Move to the next space in the buffer by INCrementing the value stored in Register Pair HL by 1.
545B
DJNZ TDES
     [544AH]
Process up to 6 bytes for a filename by LOOPing back to 544AH, 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.
545D
JR TDES2
   [5466H]
If 6 characters found, continue by JUMPing to 5466H.

545FH - Contination of "TAPE" Routine. Jumped to when less than 6 characters of the filename has been written.

First we need to output the remaining characters in the filename as spaces. Register B holds the number of filename characters left to output.

"TDES2"
545F
LD A,20H
Let Register A equal 20H which is a SPACE character.
5461
CALL 0264H
     [0264H]
GOSUB to 0264H which is the Model III ROM routine to output a byte held in Register A to cassette. This routine must be called often enough to keep up with the baud rate.
5464
DJNZ TDES1
     [545FH]
LOOP back to 545FH, 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.
"TDES2"
5466
LD HLBUFER2
Let Register Pair HL equal 5E00H for a FILE BUFFER / DATA STORAGE BUFFER.
"TDES3"
5469
LD A,(HL)
Fetch a character from the FILE DATA BUFFER (held held in the memory location pointed to by Register Pair HL) and store it into Register A.
546A
CP 02H
Compare the value held in Register A against 02H, which would be an executable file TRANSFER ADDRESS (which is also the end of the file). If so ...
546C
JR Z,TDES6
     [54A1H]
... JUMP to 54A1H to write the TRANSFER ADDRESS block and exit.
546E
CP 01H
Compare the value held in Register A against 01H, which would be an executable file CODE BLOCK. If not, then something is wrong so ...
5470
JP NZ,BADLFE
      [53FFH]
.... JUMP BACK to 53FFH ... otherwise ...
5473
INC HL
... Point HL to the next byte in the FILE BUFFER / DATA STORAGE BUFFER by INCrementing the value stored in Register Pair HL by 1.
5474
LD A,(HL)
Fetch the block length, which should be the next character from the FILE BUFFER / DATA STORAGE BUFFER (held held in the memory location pointed to by Register Pair HL) and store it into Register A.
5475
SUB 02H
Adjust the block length down by 2 by SUBtracting the value 02H from Register A.
5477
LD B,A
Copy the adjusted block length (held in Register A) into Register B.
5478
INC HL
Point HL to the LSB of the address (which should be the next byte in the FILE BUFFER / DATA STORAGE BUFFER) by INCrementing the value stored in Register Pair HL by 1.
5479
CALL TDES4
     [547EH]
Write the entire block via a GOSUB to 547EH.
547C
JR TDES3
   [5469H]
LOOP BACK to 5469H to keep processing data blocks.

547EH - Subroutine in the "TAPE" Routine - Write an entire code block to tape, with checksum. Register B holds the data block length and Register C will calculate the checksum.

"TDES4"
547E
LD A,3CH
Prepare to write the DATA BLOCK IDENTIFIER by setting Register A to 3CH.
5480
CALL 0264H
     [0264H]
GOSUB to 0264H which is the Model III ROM routine to output a byte held in Register A to cassette. This routine must be called often enough to keep up with the baud rate.
5483
LD A,B
Copy the DATA BLOCK LENGTH from Register B into Register A.
5484
CALL 0264H
     [0264H]
GOSUB to 0264H which is the Model III ROM routine to output a byte held in Register A to cassette. This routine must be called often enough to keep up with the baud rate.
5487
LD A,(HL)
Fetch the LSB of the address, which should be the next character from the FILE BUFFER / DATA STORAGE BUFFER (held held in the memory location pointed to by Register Pair HL) and store it into Register A.
5488
LD C,A
Initialize a checksum counter in Register C by copying the LSB of the address (held in Register A) into Register C.
5489
CALL 0264H
     [0264H]
GOSUB to 0264H which is the Model III ROM routine to output a byte held in Register A to cassette. This routine must be called often enough to keep up with the baud rate.
548C
INC HL
Point HL to the MSB of the address, which should be the next byte in the data block, by INCrementing the value stored in Register Pair HL by 1.
548D
LD A,(HL)
Fetch the MSB of the address, which should be the next character from the FILE BUFFER / DATA STORAGE BUFFER (held held in the memory location pointed to by Register Pair HL) and store it into Register A.
548E
CALL 0264H
     [0264H]
GOSUB to 0264H which is the Model III ROM routine to output a byte held in Register A to cassette. This routine must be called often enough to keep up with the baud rate.
5491
ADD A,C
Update the checksum to now include the MSB by setting Register A = Register A + Register C.
5492
LD C,A
Copy the updated checksum (held in Register A) into Register C.
"TDES5"
5493
INC HL
Top of DJNZ loop. Point HL to the next byte in the FILE BUFFER / DATA STORAGE BUFFER by INCrementing the value stored in Register Pair HL by 1.
5494
LD A,(HL)
Fetch a data byte (held in the FILE BUFFER / DATA STORAGE BUFFER location pointed to by Register Pair HL) and store it into Register A.
5495
CALL 0264H
     [0264H]
GOSUB to 0264H which is the Model III ROM routine to output a byte held in Register A to cassette. This routine must be called often enough to keep up with the baud rate.
5498
ADD A,C
Update the checksum by setting Register A = Register A + Register C.
5499
LD C,A
Copy the updated checksum (held in Register A) into Register C.
549A
DJNZ TDES5
     [5493H]
LOOP back to 5493H for the entire data block length, 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.
549C
INC HL
Point HL to the next byte in the FILE BUFFER / DATA STORAGE BUFFER by INCrementing the value stored in Register Pair HL by 1.
549D
LD A,C
Copy the final checksum (held in Register C) into Register A.
549E
JP 0264H
   [0264H]
JUMP to 0264H which is the Model III ROM routine to output a byte held in Register A to cassette. This routine must be called often enough to keep up with the baud rate. Since this is a JUMP instead of a GOSUB, the RET inside that JUMP will return to the caller.

54A1H - Contination of "TAPE" Routine. Jumped to when we have an TRANSFER ADDRESS BLOCK. This routine will write the block and then exit the routine.

"TDES6"
54A1
INC HL
Point HL to the LSB of the TRANSFER ADDRESS, which should be the next byte in the data block, by INCrementing the value stored in Register Pair HL by 1.
54A2
LD A,78H
Prepare to write the TRANSFER ADDRESS IDENTIFIER by setting Register A to 78H.
54A4
CALL 0264H
     [0264H]
GOSUB to 0264H which is the Model III ROM routine to output a byte held in Register A to cassette. This routine must be called often enough to keep up with the baud rate.
54A7
LD A,(HL)
Fetch the LSB of the address, which should be the next character from the FILE BUFFER / DATA STORAGE BUFFER (held held in the memory location pointed to by Register Pair HL) and store it into Register A.
54A8
CALL 0264H
     [0264H]
GOSUB to 0264H which is the Model III ROM routine to output a byte held in Register A to cassette. This routine must be called often enough to keep up with the baud rate.
54AB
INC HL
Point HL to the MSB of the TRANSFER ADDRESS, which should be the next byte in the data block, by INCrementing the value stored in Register Pair HL by 1.
54AC
LD A,(HL)
Fetch the MSB of the address, which should be the next character from the FILE BUFFER / DATA STORAGE BUFFER (held held in the memory location pointed to by Register Pair HL) and store it into Register A.
54AD
CALL 0264H
     [0264H]
GOSUB to 0264H which is the Model III ROM routine to output a byte held in Register A to cassette. This routine must be called often enough to keep up with the baud rate.
54B0
JP 01F8H
   [01F8H]
JUMP to the Model III ROM Routine at 01F8H to turn off the cassette motor. Since this is a JUMP instead of a GOSUB, the RET inside that JUMP will return to the caller.

54B3H - Subroutine in the "TAPE" Routine. Read a Byte from the Disk File.

"GETBYT"
54B3
LD DE,SDCB1
Let Register Pair DE equal 5BA2H which is the SOURCE DCB Buffer.
54B6
CALL 0013H
     [0013H]
Get a byte from the disk via a GOSUB to 0013H.
NOTE: 0013H is the Model III ROM routine to read a byte from an input device. Requires DE = starting address of DCB of device and on Exit Register A = byte received from device, Z set if device ready. Uses AF.
54B9
JP NZ,4409H
      [4409H]
If the NZ FLAG (Not Zero) has been set, JUMP to 4409H.
NOTE: 4409H is the SYS00/SYS routine to process DOS errors.
54BC
RET
RETurn to the caller.

54BDH - Subroutine in the "TAPE" Routine. Write a Byte to the Disk File.

"WRIBYT"
54BD
PUSH AF
Save the contents of Register Pair AF to the top of the stack.
54BE
PUSH BC
Save the contents of Register Pair BC to the top of the stack.
54BF
PUSH DE
Save the contents of Register Pair DE to the top of the stack.
54C0
PUSH HL
Save the contents of Register Pair HL to the top of the stack.
54C1
PUSH IY
Save the contents of Special Index Register IY to the top of the stack.
54C3
LD DE,SDCB1
Let Register Pair DE equal 5BA2H which is the SOURCE DCB Buffer.
54C6
CALL 001BH
     [001BH]
Write the byte to diskette via a GOSUB to 001BH.
NOTE: 001BH is the Model III ROM routine to write a byte to an output device. Requires Register A to contain the byte to output and Register Pair DE to be the starting address of DCB of device. On exit, Z set if device ready. Uses AF.
54C9
JP NZ,4409H
      [4409H]
If the NZ FLAG (Not Zero) has been set, JUMP to 4409H.
NOTE: 4409H is the SYS00/SYS routine to process DOS errors.
54CC
POP IY
Put the value held at the top of the STACK into Special Index Register IY, and then remove the entry from the stack.
54CE
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
54CF
POP DE
Put the value held at the top of the STACK into Register Pair DE, and then remove the entry from the stack.
54D0
POP BC
Put the value held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
54D1
POP AF
Put the value held at the top of the STACK into Register Pair AF, and then remove the entry from the stack.
54D2
RET
RETurn to the caller.

54D3H - Part of "TAPE" Routine. Process SOURCE = TAPE, DEST = DISK.

"TSRC"
54D3
LD HL,TAPE
Let Register Pair HL equal 5392H, which points to the message "TAPE TO DISK".
54D6
CALL 021BH
     [021BH]
Display that message via a GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
54D9
CALL RDYCAS
     [5348H]
Prompt the user to insert a cassette and wait for a key via a GOSUB to 5348H.
54DC
CALL 0243H
     [0243H]
GOSUB to 0243H which is the Model III ROM Routine to start the tape and read the sync/header.
54DF
CALL 0235H
     [0235H]
GOSUB to 0235H which is the Model III ROM Routine to read one byte (the system byte here) from the cassette drive specified in register A, and returns the byte in register A.
54E2
CP 55H
Compare the byte which was just read from cassette (held in Register A) against 55H, which is the SYSTEM TAPE identifier. Results: If we didn't get the SYSTEM TAPE identifier ...
54E4
JP NZ,ERR2
      [5219H]
... then we have a problem; JUMP to 5219H to display an ILLEGAL PARAMETER error and exit via a JUMP to 5223H.
54E7
LD HL,(4020H)
Fetch the value held in memory location 4020H and store it into Register Pair HL.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
54EA
LD IY,SDCB1
Let Special Index Register IY equal 5BA2H which is the SOURCE DCB Buffer.
54EE
LD B,06H
Since a maching language file's filename is 6 characters, set Register B equal 06H.
"TSRC1"
54F0
GOSUB to 0235H which is the Model III ROM Routine to read one byte from the cassette drive specified in register A, and returns the byte in register A.
54F3
LD (HL),A
Store byte which was just read from cassette (held in Register A) into the screen location pointed to by Register Pair HL.
54F4
INC HL
INCrement the screen location (stored in Register Pair HL) by 1.
54F5
CP 21H
Compare the value held in Register A against 21H (ASCII: SPACE + 1). If Register A < SPACE + 1 we will want to skip that character so ...
54F7
JR C,54FEH
     [54FEH]
... skip the next 2 instructions via a JUMP to 54FEH ...
54F9
LD (IY+00H),A
... otherwise, store the byte read from tape (which is part of the filename) into the filename buffer pointed to by Special Index Register IY.
54FC
INC IY
INCrement Special Index Register IY by 1 to point to the next available spot in the filename buffer.
"TSRC11"
54FE
DJNZ TSRC1
     [54F0H]
LOOP back to 54F0H, 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.
5500
LD (4020H),HL
Store the value held in Register Pair HL into memory location 4020H.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
5503
5505
PUSH IY
POP DE
Let Register Pair DE = Special Register Index IY. At this point DE will the 1 byte beyond the filename.
5506
LD HL,CMEXT
Let Register Pair HL equal 53B7H to point to the message "/CMD + 03H".
5509
LD BC,0005H
There are 5 bytes in "/CMD + 03H" so so set Register Pair BC equal 0005H to prepare for a LDIR.
550C
LDIR
Add the "/CMD + 03H" to the end of the filename by 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.
550E
LD HLBUFER2
The filespec has now been completed, so reset the buffer by setting Register Pair HL equal 5E00H for a FILE BUFFER / DATA STORAGE BUFFER.

Top of a loop (ending at 5544H) to read the entire file from tape.

"TSRC2"
5511
CALL 0235H
     [0235H]
GOSUB to 0235H which is the Model III ROM Routine to read one byte from the cassette drive specified in register A, and returns the byte in register A.
5514
CP 78H
Check to see if the byte is an TRANSFER ADDRESS IDENTIFIER by comparing the value held in Register A against 78H. If it is ...
5516
JR Z,TSRC4
     [5546H]
... get the transfer address via a JUMP to 5546H.
5518
CP 3CH
Check to see if the byte is a CODE BLOCK IDENTIFIER by comparing the value held in Register A against 3CH. If it isn't ...
551A
JR NZ,TSRC2
      [5511H]
... we need to keep looking, so loop back to 5511H and keep reading.

If we are here, then the byte read from the cassette was a CODE BLOCK identifier.

551C
LD (HL),01H
Store a CODE BLOCK MARKER (01H) into the FILE BUFFER (pointed to by Register Pair HL).
551E
INC HL
INCrement the FILE BUFFER POINTER (stored in Register Pair HL) by 1.

Next, process the BLOCK LENGTH.

551F
CALL 0235H
     [0235H]
GOSUB to 0235H which is the Model III ROM Routine to read one byte from the cassette drive specified in register A, and returns the byte in register A.
5522
LD B,A
Register A should be holding the BLOCK LENGTH BYTE. Copy that into Register B.
5523
ADD A,02H
Adjust the BLOCK LENGTH by 2 to include the address (needed for a diskette file), by setting Register A = Register A + 02H.
5525
LD (HL),A
Store the adjusted BLOCK LENGTH into the FILE BUFFER (pointed to by Register Pair HL).
5526
INC HL
INCrement the FILE BUFFER POINTER (stored in Register Pair HL) by 1.

Next, process the LSB of the CODE ADDRESS.

5527
CALL 0235H
     [0235H]
GOSUB to 0235H which is the Model III ROM Routine to read one byte from the cassette drive specified in register A, and returns the byte in register A.
552A
LD C,A
Prepare to calculate the file's checksum by copying the contents of Register A (i.e., the LSB of the CODE ADDRESS) into Register C.
552B
LD (HL),A
Store the value held in Register A (which is the LSB of the CODE ADDRESS) into the memory location pointed to by Register Pair HL.
552C
INC HL
INCrement the FILE BUFFER POINTER (stored in Register Pair HL) by 1.

Next, process the MSB of the CODE ADDRESS.

552D
CALL 0235H
     [0235H]
GOSUB to 0235H which is the Model III ROM Routine to read one byte from the cassette drive specified in register A, and returns the byte in register A.
5530
LD (HL),A
Store the value held in Register A (which is the MSB of the CODE ADDRESS) into the memory location pointed to by Register Pair HL.
5531
INC HL
INCrement the FILE BUFFER POINTER (stored in Register Pair HL) by 1.
5532
ADD A,C
LET Register A = Register A + Register C.
5533
LD C,A
Copy the contents of Register A (i.e., the checksum which now includes the MSB of the CODE ADDRESS) into Register C.

Next, loop to read the block

"TSRC3"
5534
CALL 0235H
     [0235H]
GOSUB to 0235H which is the Model III ROM Routine to read one byte from the cassette drive specified in register A, and returns the byte in register A.
5537
LD (HL),A
Store the value held in Register A (i.e., a data byte) into the FILE BUFFER at the location pointed to by Register Pair HL.
5538
INC HL
INCrement the FILE BUFFER POINTER (stored in Register Pair HL) by 1.
5539
ADD A,C
LET Register A = Register A + Register C.
553A
LD C,A
Copy the contents of Register A (i.e., the checksum which now includes the most recently read data byte) into Register C.
553B
DJNZ TSRC3
     [5534H]
LOOP back 6 instructions to 5534H, 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.

The block is now read into the buffer at HL, and Register C now holds the checksum. So next, verify the checksum.

553D
CALL 0235H
     [0235H]
GOSUB to 0235H which is the Model III ROM Routine to read one byte from the cassette drive specified in register A, and returns the byte in register A.
5540
CP C
Compare the the checksum as read from the tape (held in Register A) against the checksum as just calculated (held in Register C). If the checksums DO NOT MATCH ...
5541
JP NZ,ERR2
      [5219H]
... JUMP to 5219H to display an ILLEGAL PARAMETER error and exit via a JUMP to 5223H ...
5544
JR TSRC2
   [5511H]
... otherwise, we are good, so get more data via a JUMP to 5511H.

5546H - Contination of "TAPE" Routine. Jumped to when we have an TRANSFER ADDRESS to write that block and finish.

"TSRC4"
5546
LD (HL),02H
Store an TRANSFER ADDRESS MARKER (02H) into the FILE BUFFER at the location pointed to by Register Pair HL.
5548
INC HL
INCrement the FILE BUFFER POINTER (stored in Register Pair HL) by 1.
5549
LD (HL),02H
Store the length of a TRANSFER ADDRESS, which is ALWAYS 2 bytes, into the FILE BUFFER at the location pointed to by Register Pair HL.
554B
INC HL
INCrement the FILE BUFFER POINTER (stored in Register Pair HL) by 1.
554C
PUSH HL
Save the current location in the FILE BUFFER (held in Register Pair HL) to the top of the stack.
554D
CALL 0314H
     [0314H]
Read the TRANSFER ADDRESS from the tape via a GOSUB to 0314H which reads 2 bytes from the cassette and puts them into HL and 40DFH and then turns off the cassette motor.
5550
POP DE
Restore the current location in the FILE BUFFER (held at the top of the stack) into Register Pair DE.
5551
EX DE,HL
EXchange the value stored in Register Pair HL (i.e., the TRANSFER ADDRESS from the CALL 0314H) with the value stored in Register Pair DE (i.e., the current location in the FILE BUFFER).
5552
5552
LD A,D
OR E
Since the Z-80 cannot test Register Pair DE against zero, the common trick is to set Register A to equal to Register D, and then OR A against Register E. Only if both Register D and Register E were zero can the Z FLAG be set.
5554
JR NZ,5559H
      [5559H]
If that OR showed that DE was NOT empty, then we have an TRANSFER ADDRESS then the NZ FLAG (Not Zero) will have been set, so skip the next instruction which (sets a default) and JUMP to 5559H.
5556
LD DE,402DH
Since DE was empty, set a default TRANSFER ADDRESS at 402DH, which is the address to transfer to DOS.
"YESADD"
5559
LD (HL),E
Store the LSB of the TRANSFER ADDRESS (held in Register E) into the memory location pointed to by Register Pair HL.
555A
INC HL
INCrement the FILE BUFFER POINTER (stored in Register Pair HL) by 1.
555B
LD (HL),D
Store the MSB of the TRANSFER ADDRESS (held in Register D) into the memory location pointed to by Register Pair HL.
555C
CALL 01F8H
     [01F8H]
Turn off the cassette player via a GOSUB to 01F8H.

555FH - Contination of "TAPE" Routine. Write a File from RAM to Diskette.

555F
LD HLBUFER1
Let Register Pair HL equal 5D00H for a FILE BUFFER.
5562
LD DE,SDCB1
Let Register Pair DE equal 5BA2H for a SOURCE DCB Buffer.
5565
LD B,00H
Let Register B equal 00H so that the next routine will set for FULL SECTOR I/O.
5567
CALL 4420H
     [4420H]
GOSUB to 4420H.
NOTE: 4420H is the SYS00/SYS routine to INITIALIZE A FILE (i.e., CREATE or OPEN). This RST 28H's with a value of A2H so as to call ROUTINE 2 in OVERLAY 2. Register HL needs to point to a RAM BUFFER for the DCB's.
556A
JP NZ,4409H
      [4409H]
If the NZ FLAG (Not Zero) has been set, JUMP to 4409H.
NOTE: 4409H is the SYS00/SYS routine to process DOS errors.
556D
LD HLBUFER2
Let Register Pair HL equal 5E00H for a FILE BUFFER / DATA STORAGE BUFFER.
"DDES"
5570
LD A,(HL)
Fetch a byte from the FILE BUFFER (the memory location pointed to by Register Pair HL) and store it into Register A.
5571
CP 02H
Compare the value held in Register A against 02H, which would be an executable file TRANSFER ADDRESS BLOCK indicator. Results: If Register A equals 02H the Z FLAG is set; otherwise the NZ FLAG is set.
5573
JR Z,DDES2
     [5599H]
If the Z FLAG (Zero) has been set, JUMP to 5599H to deal with an TRANSFER ADDRESS BLOCK.
5575
CP 01H
Compare the value held in Register A against 01H, which would be an executable file CODE BLOCK. Results: If Register A equals 01H the Z FLAG is set; otherwise the NZ FLAG is set.
5577
JP NZ,ERR2
      [5219H]
If the NZ FLAG (Not Zero) has been set, JUMP to 5219H to display an ILLEGAL PARAMETER error and exit via a JUMP to 5223H.
557A
CALL WRIBYT
     [54BDH]
Write the byte held in Register A to the disk file via a GOSUB to 54BDH.
557D
INC HL
INCrement the FILE BUFFER POINTER (stored in Register Pair HL) by 1.
557E
LD A,(HL)
Fetch the CODE BLOCK LENGTH (the next byte from the FILE BUFFER) and store it into Register A.
557F
LD B,A
Copy the contents of Register A into Register B, because B is the DJNZ LOOP counter.
5580
CALL WRIBYT
     [54BDH]
Write the CODE BLOCK LENGTH (i.e., the byte held in Register A) to the disk file via a GOSUB to 54BDH.
5583
INC HL
INCrement the FILE BUFFER POINTER (stored in Register Pair HL) by 1 to point to the LSB of the TRANSFER ADDRESS.
5584
LD A,(HL)
Fetch the the LSB of the TRANSFER ADDRESS (the next byte in the FILE BUFFER) and store it into Register A.
5585
CALL WRIBYT
     [54BDH]
Write the LSB of the TRANSFER ADDRESS (the byte held in Register A) to the disk file via a GOSUB to 54BDH.
5588
INC HL
INCrement the FILE BUFFER POINTER (stored in Register Pair HL) by 1 to point to the MSB of the TRANSFER ADDRESS.
5589
LD A,(HL)
Fetch the the MSB of the TRANSFER ADDRESS (the next byte in the FILE BUFFER) and store it into Register A.
558A
CALL WRIBYT
     [54BDH]
Write the MSB of the TRANSFER ADDRESS (the byte held in Register A) to the disk file via a GOSUB to 54BDH.
558D
558E
DEC B
DEC B
DECrement the BLOCK LENGTH (stored in Register B) by 2.
"DDES1"
558F
INC HL
INCrement the FILE BUFFER POINTER (stored in Register Pair HL) by 1.
5590
LD A,(HL)
Fetch a byte from the FILE BUFFER (the memory location pointed to by Register Pair HL) and store it into Register A.
5591
CALL WRIBYT
     [54BDH]
Write the byte held in Register A to the disk file via a GOSUB to 54BDH.
5594
DJNZ DDES1
     [558FH]
LOOP back to 558FH, 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.
5596
INC HL
INCrement the FILE BUFFER POINTER (stored in Register Pair HL) by 1.
5597
JR DDES
   [5570H]
Process the next block by JUMPing BACK to 5570H.

5599H - Contination of Write a File from RAM to Diskette portion of the "TAPE" Routine. Jumped here if an TRANSFER ADDRESS BLOCK was found.

"DDES2"
5599
CALL WRIBYT
     [54BDH]
Write the TRANSFER ADDRESS MARKER (which is 02H) held in Register A to the disk file via a GOSUB to 54BDH.
559C
CALL WRIBYT
     [54BDH]
Write the BLOCK LENGTH BYTE (which is always 02H) held in Register A to the disk file via a GOSUB to 54BDH.
559F
INC HL
INCrement the FILE BUFFER POINTER (stored in Register Pair HL) by 1 to point to the byte count. We don't care about this.
55A0
INC HL
INCrement the FILE BUFFER POINTER (stored in Register Pair HL) by 1.
55A1
LD A,(HL)
Fetch the LSB of the TRANSFER ADDRESS (held in the memory location pointed to by Register Pair HL) and store it into Register A.
55A2
CALL WRIBYT
     [54BDH]
Write the LSB of the TRANSFER ADDRESS held in Register A to the disk file via a GOSUB to 54BDH.
55A5
INC HL
INCrement the FILE BUFFER POINTER (stored in Register Pair HL) by 1.
55A6
LD A,(HL)
Fetch the MSB of the TRANSFER ADDRESS (held in the memory location pointed to by Register Pair HL) and store it into Register A.
55A7
CALL WRIBYT
     [54BDH]
Write the MSB of the TRANSFER ADDRESS held in Register A to the disk file via a GOSUB to 54BDH.
55AA
JP 4428H
   [4428H]
JUMP to 4428H.
NOTE: 4428H is the SYS00/SYS routine to CLOSE A DISK FILE. This RST 28H's with a value of 93H so as to call ROUTINE 1 in OVERLAY 3.

55ADH - Continuation of the "TAPE" Routine. SOURCE = Tape; DEST = RAM.

"TRAM"
55AD
LD HL,539FH
Let Register Pair HL equal 539FH, to point to the message "TAPE INTO RAM".
55B0
CALL 021BH
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
55B3
CALL 5348H
     [5348H]
Prompt the user to insert a cassette and wait for a key via a GOSUB to 5348H.
55B6
CALL 0243H
     [0243H]
Turn on the CASSETTE TAPE and READ THE FILE HEADER via a GOSUB to 0243H.
55B9
CALL 0235H
     [0235H]
GOSUB to 0235H which is the Model III ROM Routine to read one byte from the cassette drive specified in register A, and returns the byte in register A.
55BC
CP 55H
Compare the byte which was just read from cassette (held in Register A) against 55H, which is the SYSTEM TAPE identifier. Results: If Register A equals 55H, the Z FLAG is set; otherwise the NZ FLAG is set.
55BE
JP NZ,ERR2
      [5219H]
If the byte read was not a SYSTEM TAPE identifier, then we have a problem; JUMP to 5219H to display an ILLEGAL PARAMETER error and exit via a JUMP to 5223H.
55C1
LD HL,(4020H)
Fetch the value held in memory location 4020H and store it into Register Pair HL.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
55C4
LD B,06H
Since a maching language file's filename is 6 characters, set Register B equal 06H.
"TRAM1"
55C6H
CALL 0235H
     [0235H]
GOSUB to 0235H which is the Model III ROM Routine to read one byte from the cassette drive specified in register A, and returns the byte in register A.
55C9
LD (HL),A
Store byte which was just read from cassette (held in Register A) into the screen location pointed to by Register Pair HL.
55CA
INC HL
INCrement the FILE BUFFER POINTER (stored in Register Pair HL) by 1.
55CB
DJNZ TRAM1
     [55C6H]
LOOP back to 55C6H, 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.
"TRAM2"
55CD
CALL 0235H
     [0235H]
GOSUB to 0235H which is the Model III ROM Routine to read one byte from the cassette drive specified in register A, and returns the byte in register A. This will be a BLOCK MARKER.
55D0
CP 78H
Check to see if the BLOCK MARKER just read was an TRANSFER ADDRESS BLOCK by comparing the value held in Register A against 78H. Results: If Register A equals 78H, the Z FLAG is set; otherwise the NZ FLAG is set.
55D2
JR Z,TRAM5
     [5601H]
If the byte was an TRANSFER ADDRESS BLOCK then the Z FLAG (Zero) will have been set, JUMP to 5601H.
55D4
CP 3CH
>Check to see if the BLOCK MARKER just read was a CODE BLOCK by comparing the value held in Register A against 3CH. Results: If Register A equals 3CH, the Z FLAG is set; otherwise the NZ FLAG is set.
55D6
JR NZ,TRAM2
      [55CDH]
If the byte was NOT a CODE BLOCK then the NZ FLAG (Zero) will have been set; LOOP BACK to 55CDH to keep reading bytes.
55D8
CALL 0235H
     [0235H]
GOSUB to 0235H which is the Model III ROM Routine to read one byte from the cassette drive specified in register A, and returns the byte in register A. This should be the CODE BLOCK LENGTH BYTE.
55DB
LD B,A
Copy the CODE BLOCK LENGTH BYTE (held in Register A) into Register B.
55DC
CALL 0235H
     [0235H]
GOSUB to 0235H which is the Model III ROM Routine to read one byte from the cassette drive specified in register A, and returns the byte in register A. This should be the LSB of the CODE ADDRESS.
55DF
LD C,A
Copy the LSB of the CODE ADDRESS (held in Register A) into Register C.
55E0
LD L,A
Copy the LSB of the CODE ADDRESS (held in Register A) into Register L.
55E1
CALL 0235H
     [0235H]
GOSUB to 0235H which is the Model III ROM Routine to read one byte from the cassette drive specified in register A, and returns the byte in register A. This should be the MSB of the CODE ADDRESS.
55E4
LD H,A
Copy the MSB of the CODE ADDRESS (held in Register A) into Register H.
55E5
ADD A,C
LET Register A = the MSB of the CODE ADDRESS (held in Register A) + the LSB of the CODE ADDRESS (held in Register C).
55E6
LD C,A
Copy the results of that addition into Register C.
"TRAM3"
55E7
CALL 0235H
     [0235H]
GOSUB to 0235H which is the Model III ROM Routine to read one byte from the cassette drive specified in register A, and returns the byte in register A.
55EA
LD (HL),A
Store the byte just read from tape (held in Register A) into the FILE BUFFER location pointed to by Register Pair HL.
55EB
CP (HL)
Verify that the byte was properly written by comparing the value held in Register A against the value held in the memory location pointed to by the value held in Register Pair HL. Results: If they match, the Z FLAG is set; otherwise the NZ FLAG is set.
55EC
JR Z,TRAM4
     [55F3H]
If the write was verified successfully the Z FLAG (Zero) will have been set, JUMP to 55F3H.
55EE
LD A,23H
Let Register A equal 23H for a DOS ERROR of MEMORY FAULT.
55F0
JP 4409H
   [4409H]
JUMP to 4409H.
NOTE: 4409H is the SYS00/SYS routine to process DOS errors.

55F3H - Continuation of the SYSTEM Tape into RAM and RUN IT portion of the "TAPE" Routine. Jumped here if there was no memory fault.

"TRAM4"
55F3
ADD A,C
LET Register A = Register A + the checksum (held in Register C).
55F4
LD C,A
Copy the checksum (held in Register A) into Register C.
55F5
INC HL
INCrement the FILE BUFFER POINTER (stored in Register Pair HL) by 1.
55F6
DJNZ TRAM3
     [55E7H]
Process the entire code block (length of B) by LOOPing back to 55E7H, 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.
55F8
CALL 0235H
     [0235H]
GOSUB to 0235H which is the Model III ROM Routine to read one byte from the cassette drive specified in register A, and returns the byte in register A. This should be the CODE BLOCK's CHECKSUM
55FB
CP C
Compare the CODE BLOCK's CHECKSUM which was just calculated (held in Register C) against rhe CODE BLOCK's CHECKSUM read from cassette (held in Register A): If they match, the Z FLAG is set; otherwise the NZ FLAG is set.
55FC
JP NZ,ERR2
      [5219H]
If they don't match, then we had a bad read and the NZ FLAG (Not Zero) will have been set, JUMP to 5219H to display an ILLEGAL PARAMETER error and exit via a JUMP to 5223H.
55FF
JR TRAM2
   [55CDH]
If they did match, then LOOP BACK to 55CDH to read the next block.

5601H - Continuation of the SYSTEM Tape into RAM and RUN IT portion of the "TAPE" Routine. Jumped here if the we just got a TRANSFER ADDRESS BLOCK.

"TRAM5"
5601
CALL 0314H
     [0314H]
Read the TRANSFER ADDRESS via a GOSUB to the Model III ROM Routine at 0314H.
5604
PUSH HL
Save the TRANSFER ADDRESS (held in Register Pair HL from that CALL) to the top of the stack.
5605
CALL 01F8H
     [01F8H]
Turn off the cassette via a call to the MODEL III ROM Routine at 01F8H.
5608
POP HL
Restore the TRANSFER ADDRESS (held at the top of the stack) into Register Pair HL, and then remove the entry from the stack.
5609
5609
LD A,H
OR L
We want to see if HL is 0. However, 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.
560B
RET Z
If we didn't get an TRANSFER ADDRESS then the Z FLAG (Zero) will have been set, RETurn to the caller.
560C
JP (HL)
If we are here then we have an TRANSFER ADDRESS stored in Register Pair HL. So JUMP to it!.

560DH - "PURGE" Library Command.

"PURGE"
560D
CALL SKIPSP
     [5258H]
GOSUB to 5258H to position HL to the next non-space character on the COMMAND LINE.
5610
CP 0DH
Compare the value held in Register A against 0DH (ASCII: CARRIAGE RETURN). Results: If Register A equals CARRIAGE RETURN, the Z FLAG is set; otherwise the NZ FLAG is set.
5612
JR Z,PURGE2
     [5647H]
If all we got was a CARRIAGE RETURN, then we will assume that this is a request to delete user files from Drive 0; so JUMP to 5647H.
5614
CP 2AH
Compare the value held in Register A against 2AH (ASCII: *). Results: If Register A equals *, the Z FLAG is set; otherwise the NZ FLAG is set.
5616
JR NZ,CKCOLN
      [561DH]
If we didn't get a * (for DELETE DOS), JUMP to 561DH.

If we are here, then we got a * and need to delete DOS.

5618
LD (58C5H),A
Store a * unto the CP instruction at 58C5H.
561B
INC HL
BUMP the pointer to the COMMAND LINE by 1.
561C
LD A,(HL)
Fetch the next character on the COMMAND LINE from the memory location pointed to by Register Pair HL and store it into Register A.
"CKCOLN"
561D
CP 3AH
Compare the value held in Register A against 3AH (ASCII: :) to see if we were given a drivespec. Results: If Register A equals :, the Z FLAG is set; otherwise the NZ FLAG is set.
561F
JR NZ,PURGE1
      [563AH]
If we were not given a :, then skip the drivespec checking and JUMP to 563AH.

If we are here, then we got a : and need to check for a drive letter after the :

5621
INC HL
BUMP the pointer to the COMMAND LINE by 1.
5622
LD A,(HL)
Fetch the next character on the COMMAND LINE from the memory location pointed to by Register Pair HL and store it into Register A. A drive number is expected to be here.
5623
LD (58C7H),A
Store the drive spec held in Register A (which should be a drive number) into memory location 58C7H.
5626
SUB 30H
SUBtract the value 30H 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).
5628
JP C,ERR9
     [5221H]
If value on the command line was below "0" the C FLAG (Carry) will have been triggered; JUMP to 5221H.
562B
LD B,A
Copy the ASCII value of the drive number (held in Register A) into Register B.
562C
LD A,(4413H)
Fetch the value held in memory location 4413H and store it into Register A.
NOTE: 4413H is the storage location for the NUMBER OF DISK DRIVES in the system.
562F
CP B
Compare the NUMBER OF DISK DRIVES in the system (held in Register A) against the ASCII value of the user supplied drive number (held in Register B). If A < B then we have a BAD drive number, and the CARRY FLAG will be set.
5630
JP C,ERR9
     [5221H]
If the user supplied a bad drive number, JUMP to 5221H.
5633
LD A,B
Copy the ASCII value of the drive number (held in Register B) into Register A.
5634
LD (58C9H),A
Store the drive number (in ASCII) into memory location 58C9H.
5637
CALL SKIPS1
     [525CH]
Fetch the next non-space character (pointed to by Register Pair HL) into Register A via a GOSUB to 525CH.
"PURGE1"
563A
CP 28H
Compare the value held in Register A against 28H (ASCII: (). Results: If Register A equals (, the Z FLAG is set; otherwise the NZ FLAG is set.
563C
JR NZ,PURGE2
      [5647H]
If the next character on the command line was not "(" then we are going to assume that this is USER files only, so JUMP to 5647H.
563E
LD DE,PURSWT
Let Register Pair DE equal 58A6H to point to the PURGE command parameter table.
5641
CALL 4454H
     [4454H]
GOSUB to 4454H.
NOTE: 4454H is the DOS PARAMETER STRING PARSE routine. It decodes DOS LIBRARY parameters.
5644
JP NZ,ERR3
      [521DH]
If the CALL resulted in an error the NZ FLAG (Not Zero) will have been set, JUMP to 521DH.
"PURGE2"
5647
LD HL,MSPW
Let Register Pair HL equal 5866H to point to the message "MASTER PASSWORD?" .
564A
CALL 021BH
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
564D
LD HL,SDCB1
Let Register Pair HL equal 5BA2H which will be a buffer for the MASTER PASSWORD.
5650
LD B,08H
Since a password is 8 characters or less, set Register B equal 08H.
5652
CALL 0040H
     [0040H]
GOSUB to 0040H.
NOTE: 0040H is the Model III ROM routine to get a full line from the keyboard. In this routine, a line is terminated by a carriage return or BREAK, and characters typed are echoed to the display. On entry, B must be the maximum length of line to be accepted and (HL) must be the storage buffer which should be set to B+1. On Exit, CARRY will be set if the BREAK key was hit, Register B will contain the number of characters entered, and (HL) will contain the line from the keyboard followed by the terminating character. Register paid DE is altered in this routine.
5655
PUSH HL
Save the MASTER PASSWORD BUFFER ADDRESS (held in Register Pair HL) to the top of the stack.
5656
LD B,08H
Since a password is 8 characters or less, set Register B equal 08H.
"PURGE3"
5658
LD A,(HL)
We are in a loop here. Fetch a character from the MASTER PASSWORD BUFFER (i.e., held in the memory location pointed to by Register Pair HL) and store it into Register A.
5659
CP 20H
Compare the value held in Register A against 20H (ASCII: SPACE). Results:
  • If Register A equals SPACE, the Z FLAG is set.
  • If A < SPACE, the CARRY FLAG will be set.
  • if A >= SPACE, the NO CARRY FLAG will be set.
565B
JR C,PURGE4
     [5662H]
If the character from the MASTER PASSWORD BUFFER (held in Register A) < SPACE, we are at the end of the password and the C FLAG (Carry) will have been set; so JUMP to 5662H to stop processing characters.
565D
INC HL
BUMP HL by 1 to point to the next character in the MASTER PASSWORD BUFFER.
565E
DJNZ PURGE3
     [5658H]
LOOP back to 5658H, 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.
5660
JR PURGE5
   [5667H]
If we are here, then 8 characters were processed for the Master Password. Continue via a JUMP to 5667H.

5662H - Continuation of "PURGE". Jumped here if the MASTER PASSWORD provided by the user was less than 8 characters. Register B will hold the number of characters received and Register Pair HL will be pointing to the first non-valid character in the Master Password Buffer.

"PURGE4"
5662
LD (HL),20H
Overwrite whatever may be in the MASTER PASSWORD CHARACTER BUFFER at HL with a SPACE.
5664
INC HL
BUMP HL by 1 to point to the next character in the MASTER PASSWORD BUFFER.
5665
DJNZ PURGE4
     [5662H]
LOOP back to 5662H, 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.
"PURGE5"
5667
POP DE
Put the MASTER PASSWORD BUFFER ADDRESS (held at the top of the STACK into Register Pair DE), and then remove the entry from the stack.
5668
CALL TRAP
     [57A4H]
Encode the password pointed to by Register Pair DE into Register Pair HL via GOSUB to 57A4H.
566B
LD (PW),HL
Store hashed master password (held in Register Pair HL into) memory location 58CAH.
566E
LD A,(PDRV)
Fetch the drive number from memory location 58C9H and store it into Register A.
5671
LD C,A
Since SYS00/SYS Disk I/O calls usually require Register C to contain the drive number, copy the drive number (held in Register A) into Register C.
5672
CALL 4A93H
     [4A93H]
GOSUB to 4A93H.
NOTE: 4A93H is the SYS00/SYS routine to READ THE GAT sector into RAM (Buffer at 4D00H).
5675
JP NZ,4409H
      [4409H]
If that CALL resulted in an error the NZ FLAG (Not Zero) will have been set, JUMP to 4409H.
NOTE: 4409H is the SYS00/SYS routine to process DOS errors.
5678
CALL 4ABAH
     [4ABAH]
GOSUB to 4ABAH.
NOTE: 4ABAH is the SYS00/SYS routine to read the HIT sector into RAM.
567B
JP NZ,4409H
      [4409H]
If that CALL resulted in an error the NZ FLAG (Not Zero) will have been set, JUMP to 4409H.
NOTE: 4409H is the SYS00/SYS routine to process DOS errors.
567E
LD HL,BUFF1
Let Register Pair HL equal 4300H.
NOTE: 4300H is a memory buffer (referred to as Memory Buffer 1) where HIT TABLE was stored in RAM.
5681
LD DEBUFER1
Let Register Pair DE equal 5D00H, which will be a memory buffer for the HIT SAVE AREA.
5684
LD BC,0100H
Let Register Pair BC equal 0100H, which is a full disk sector of data.
5687
LDIR
Copy 256 bytes from 4300H to 5D00H via a LDIR which 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.
5689
LD HL,(4DCEH)
Fetch the actual hashed master password from the HIT (held in memory location 4DCEH) and store it into Register Pair HL.
568C
LD DE,(PW)
Fetch the user provided hashed master password (held in memory location 58CAH) and store it into Register Pair DE.
5690
OR A
Set FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG).
5691
SBC HL,DE
Compare the actual password (HL) with the user provided password (DE) by subtracting them.
5693
JR Z,PURG6
     [569AH]
If the two password match, the subtraction will be 0 and the Z FLAG (Zero) will have been set; JUMP to 569AH.
5695
LD A,19H
Let Register A equal 19H to set up for a FILE ACCESS DENIED error.
5697
JP 4409H
   [4409H]
JUMP to 4409H.
NOTE: 4409H is the SYS00/SYS routine to process DOS errors.

569AH - Continuation of "PURGE". Jumped here if the MASTER PASSWORD provided by the user was correct.

"PURG6"
569A
LD A,(58C5H)
Check to see if the user requested to delete all of DOS by fetching the value held in memory location 58C5H and store it into Register A.
569D
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).
569E
CALL NZ,PURSYS
        [57D4H]
If the NZ FLAG (Not Zero) has been set, then the user wants to delete DOS so GOSUB to 57D4H.
"PURGE6"
56A1
LD HL,BUFPNT
Let Register Pair HL equal a value placed here from other locations in this Overlay. The hope here is that HL points to the HASH TABLE ENTRY for the file to be deleted.
56A4
LD A,L
Isolate the position in the HIT into Register A by copying the contents of Register L into Register A.
56A5
CP 51H
Check to see if we are at the end of the HIT by comparing the value held in Register A against 51H. Results: If Register A equals 51H, the Z FLAG is set; otherwise the NZ FLAG is set.
56A7
JP Z,PUGEXT
     [5791H]
If Register A = 51H then we are past the end of the HIT and the Z FLAG (Zero) will have been set; JUMP to 5791H to finish.
56AA
LD A,(HL)
Fetch the HIT entry (held in the memory location pointed to by Register Pair HL) and store it into Register A.
56AB
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).
56AC
JR NZ,PURGE7
      [56B4H]
If the HIT entry is NOT ZERO, then there is a file there to be processed, so JUMP to 56B4H.
56AE
INC HL
Point to the next entry in the HIT TABLE by INCrementing the value stored in Register Pair HL by 1.
56AF
LD (BUFPNT),HL
Store the HIT TABLE pointer (which was just incremented) into the LD HL,nnnn instruction at 56A1 and then ...
56B2
JR PURGE6
   [56A1H]
... JUMP to 56A1H.

56B4H - Continuation of "PURGE". Jumped here if HL points to a HIT entry that needs to be deleted.

"PURGE7"
56B4
LD B,L
Copy the Logical File Number (held in Register L) into Register B.
56B5
LD A,(PDRV)
Fetch the drive number from memory location 58C9H and store it into Register A.
56B8
LD C,A
Since SYS00/SYS Disk I/O calls usually require Register C to contain the drive number, copy the drive number (held in Register A) into Register C.
56B9
CALL 4A67H
     [4A67H]
GOSUB to 4A67H.
NOTE: 4A67H is the SYS00/SYS routine to read the directory entry into RAM (Buffer at 4300H)
56BC
JP NZ,4409H
      [4409H]
If that CALL resulted in an error, the NZ FLAG (Not Zero) will have been set, JUMP to 4409H.
NOTE: 4409H is the SYS00/SYS routine to process DOS errors.
56BF
LD A,(HL)
Fetch the file attributes (held in the memory location pointed to by Register Pair HL) and store it into Register A.
56C0
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).
56C1
JR NZ,PURG07
      [56E3H]
If the NZ FLAG (Not Zero) has been set then the file is active, so skip the next routine and JUMP to 56E3H.

According to Frank Durda IV, the following code's purpose is to deal with the HIT saying a file exists, but the file doesn't. This reads in the HIT and clears out the offending byte.

56C3
PUSH BC
Save the contents of Register Pair BC to the top of the stack.
56C4
PUSH DE
Save the contents of Register Pair DE to the top of the stack.
56C5
PUSH HL
Save the contents of Register Pair HL to the top of the stack.
56C6
PUSH AF
Save the contents of Register Pair AF to the top of the stack.
56C7
PUSH BC
Save the LFN (held in Register Pair BC) to the top of the stack.
56C8
LD A,(PDRV)
Fetch the drive number from memory location 58C9H and store it into Register A.
56CB
LD C,A
Since SYS00/SYS Disk I/O calls usually require Register C to contain the drive number, copy the drive number (held in Register A) into Register C.
56CC
CALL 4ABAH
     [4ABAH]
GOSUB to 4ABAH.
NOTE: 4ABAH is the SYS00/SYS routine to read the HIT sector into RAM.
56CF
JP NZ,4409H
      [4409H]
If that CALL resulted in an error, the NZ FLAG (Not Zero) will have been set, JUMP to 4409H.
NOTE: 4409H is the SYS00/SYS routine to process DOS errors.
56D2
POP BC
Restore the Logical File Number held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
56D3
LD L,B
Set HL to point to the applicable file by copying the logical file number (held in Register B) into the LSB of the HIT pointer (i.e. Register L).
56D4
LD (HL),00H
Place a 00H into the HIT at the location of the logical file number being cleared.
56D6
CALL 4AC2H
     [4AC2H]
GOSUB to 4AC2H.
NOTE: 4AC2H is the SYS00/SYS routine to write the HIT sector from RAM to diskette.
56D9
JP NZ,4409H
      [4409H]
If that CALL resulted in an error, the NZ FLAG (Not Zero) will have been set, JUMP to 4409H.
NOTE: 4409H is the SYS00/SYS routine to process DOS errors.
56DC
POP AF
Put the value held at the top of the STACK into Register Pair AF, and then remove the entry from the stack.
56DD
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
56DE
POP DE
Put the value held at the top of the STACK into Register Pair DE, and then remove the entry from the stack.
56DF
POP BC
Put the value held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
56E0
JP NXTFIL
   [5750H]
Continue the routine via a JUMP to 5750H.

56E3H - Continuation of "PURGE". Jumped here if the file is active.

"PURG07"
56E3
LD A,(PALL)
Check to see if the user requested to purge ALL files by fetching the value held in memory location 58C3H and store it into Register A.
56E6
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).
56E7
JR NZ,GETFIL
      [5701H]
If the user requested to purge ALL files, then the NZ FLAG (Not Zero) will hav been set, JUMP to 5701H.
56E9
BIT 6,(HL)
Test for a system file by checking Bit Number 6 of Register HL. Z FLAG will be set if that bit is 0, and NZ FLAG will be set if that bit is 1.
56EB
JR Z,NOTSYS
     [56F6H]
If Bit 6 is 0, then this is not a SYSTEM file and the Z FLAG (Zero) will been set, so skip this file by JUMPing to 56F6H to continue checking the file.
56ED
LD A,(PSYS)
Check to see if the user requested to purge SYSTEM FILES by fetching the value held in memory location 58BFH and store it into Register A.
56F0
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).
56F1
JP Z,NXTFIL
     [5750H]
If the user did not request to purge system files the Z FLAG (Zero) will have been set, JUMP to 5750H.
56F4
JR GETFIL
   [5701H]
JUMP to 5701H to continue.

56F6H - Continuation of "PURGE".

"NOTSYS"
56F6
BIT 3,(HL)
Check to see if the selected file is invisible by testing Bit Number 3 of Register HL. Z FLAG will be set if that bit is 0, and NZ FLAG will be set if that bit is 1.
56F8
JR Z,GETFIL
     [5701H]
If the Z FLAG (Zero) has been set, then the file is not invisible, so JUMP to 5701H.
56FA
LD A,(PINV)
If we are here, the file is invisible, so check to see if the user requested to purge invisible files by fetching the value held in memory location 58C1H and store it into Register A.
56FD
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).
56FE
JP Z,NXTFIL
     [5750H]
If the user did not request to kill invisible files, then the Z FLAG (Zero) will have been set, JUMP to 5750H since we aren't going to kill the current (invisible) file.
"GETFIL"
5701
CALL COMPRS
     [575AH]
Get the filename to be killed from the directory entry via a GOSUB to 575AH.
"GETFI0"
5704
LD HL,SDCB1
Let Register Pair HL equal 5BA2H so as to point to the filename.
5707
CALL 021BH
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
570A
LD HL,QUERY
Let Register Pair HL equal 589AH so as to point to the message " (Y/N/Q) ? ".
570D
CALL 021BH
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
5710
LD HL,SDCB2
Let Register Pair HL equal 5BD2H to point to a buffer.
5713
LD B,03H
Fetch 3 characters from the keyboard by setting Register B equal 03H.
5715
CALL 0040H
     [0040H]
GOSUB to 0040H.
NOTE: 0040H is the Model III ROM routine to get a full line from the keyboard. In this routine, a line is terminated by a carriage return or BREAK, and characters typed are echoed to the display. On entry, B must be the maximum length of line to be accepted and (HL) must be the storage buffer which should be set to B+1. On Exit, CARRY will be set if the BREAK key was hit, Register B will contain the number of characters entered, and (HL) will contain the line from the keyboard followed by the terminating character. Register paid DE is altered in this routine.
5718
JP C,PUGEXT
     [5791H]
If the C FLAG (Carry) has been set then a BREAK was hit, JUMP to 5791H.
571B
LD A,(HL)
Fetch the response received from the user to the Y/N/Q question (held in the memory location pointed to by Register Pair HL) and store it into Register A.
571C
CP 51H
Compare the value held in Register A against 51H (ASCII: Q). Results: If Register A equals Q, the Z FLAG is set; otherwise the NZ FLAG is set.
571E
JP Z,PUGEXT
     [5791H]
If the user entered Q to quit, the Z FLAG (Zero) will have been set, JUMP to 5791H.
5721
CP 59H
Compare the value held in Register A against 59H (ASCII: Y). Results: If Register A equals Y, the Z FLAG is set; otherwise the NZ FLAG is set.
5723
JR Z,GETFI1
     [572BH]
If the user entered Y to kill that file, the Z FLAG (Zero) will have been set, JUMP to 572BH.
5725
CP 4EH
Compare the value held in Register A against 4EH (ASCII: N). Results: If Register A equals N, the Z FLAG is set; otherwise the NZ FLAG is set.
5727
JR NZ,GETFI0
      [5704H]
If the user did not enter a "N", then we have an unacceptable character as that was the only valid response left, so JUMP to 5704H.
5729
JR NXTFIL
   [5750H]
JUMP to 5750H to NOT delete the file and continue looping through the files.

572BH - Continuation of "PURGE". Jumped here if we found a file to delete, and the user confirmed to delete it.

"GETFI1"
572B
LD HL,BUFER2
Let Register Pair HL equal 5E00H for a FILE BUFFER / DATA STORAGE BUFFER.
572E
LD DE,SDCB1
Let Register Pair DE equal 5BA2H which is the File Control Block area in RAM.
5731
LD B,00H
Let Register B equal 00H so that the next routine will set for FULL SECTOR I/O.
5733
LD IYL,00FH
LD IYH,42H
Let Special Index Register IY = 4200H
5739
DEC (IY+00H)
Set the PROteCTION OVERRIDE FLAG by DECrementing the value stored in the memory location pointed to by Special Index Register IY by 1.
573C
CALL 4424H
     [4424H]
GOSUB to 4424H.
NOTE: 4424H is the SYS00/SYS routine to OPEN A DISK FILE for use. This RST 28H's with a value of 92H so as to call ROUTINE 2 in OVERLAY 3.
573F
JP NZ,4409H
      [4409H]
If the NZ FLAG (Not Zero) has been set, meaning that the prior CALL routine returned with an ERROR, then JUMP to 4409H.
NOTE: 4409H is the SYS00/SYS routine to process DOS errors.
"GETFI2"
5742
LD A,(5BA3H)
Fetch OPTIONS BYTE from the FILE CONTROL BLOCK (held in memory location 5BA3H) and store it into Register A.
5745
AND 0F8H
MASK the OPTIONS BYTE held in Register A against 0F8H (1111 1000). This has the effect of turning off bits 2, 1, 0, thus setting the file to UNLIMITED ACCESS.
5747
LD (5BA3H),A
Store the OPTIONS BYTE held in Register A back into the FILE CONTROL BLOCK (held in memory location 5BA3H).
574A
LD DE,SDCB1
Let Register Pair DE equal 5BA2H to point to the FILE CONTROL BLOCK.
574D
CALL 442CH
     [442CH]
GOSUB to 442CH.
NOTE: 442CH is the SYS00/SYS routine to KILL A DISK FILE. On Entry DE mus tpoint to th ememory location identifying if the file is open or not.
"NXTFIL"
5750
LD HL,(BUFPNT)
Fetch the HIT POINTER (held in memory location 56A2H) and store it into Register Pair HL.
5753
INC HL
INCrement the HIT POINTER to the next entry by BUMPING HL by 1.
5754
LD (BUFPNT),HL
Store HIT POINTER into memory location 56A2H.
5757
JP PURGE6
   [56A1H]
Loop to the next file by JUMPing to 56A1H.

575AH - SUBroutine in the "PURGE" command which will get the FILESPEC from a DIRECTORY ENTRY.

"COMPRS"
575A
PUSH HL
Save the directory entry pointer (held in Register Pair HL) to the top of the stack.
575B
LD DE,0005H
Since the filename of a file starts at the 5th byte of a directory entry, let Register Pair DE equal 0005H.
575E
ADD HL,DE
Advance the pointer to the applicable byte of the directory in RAM (pointed to by Register Pair HL) by 5.
575F
LD DE,SDCB1
Let Register Pair DE equal 5BA2H to point to the File Control Block.
5762
LD B,08H
Set up a loop of 8 characters by setting Register B equal to 08H.
"COMPR1"
5764
LD A,(HL)
Start of loop. Fetch a filename character from the directory entry (held in the memory location pointed to by Register Pair HL) and store it into Register A.
5765
CP 21H
Check to see if there is actually a usable character there by comparing the character we just fetched (held in Register A) against 21H (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.
5767
JR C,COMPR2
     [576EH]
If the filename byte in the directory entry is less than ! then we are apparently at the end of the filename and the C FLAG (Carry) will have been set, JUMP to 576EH.
5769
LD (DE),A
Store the filename character held in Register A into the file control block (the memory location pointed to by Register Pair DE).
576A
INC HL
INCrement the pointer in the directory entry (stored in Register Pair HL) by 1.
576B
INC DE
INCrement the pointer in the file control block entry (stored in Register Pair DE) by 1.
576C
DJNZ COMPR1
     [5764H]
Process up to 8 characters of the filespec by LOOPing back to 5764H, 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.
"COMPR2"
576E
POP HL
End of loop. Restore the directory entry pointer (held at the top of the stack) into Register Pair HL.
576F
LD BC,000DH
The filespec has been moved, time to process the extension. The extension is 13 bytes into a directory entry, so let Register Pair BC equal 000DH (Decimal: 13).
5772
ADD HL,BC
Advance the pointer to the applicable byte of the directory in RAM (pointed to by Register Pair HL) by 13 to point to the file's extension.
5773
LD A,(HL)
Fetch the first character of the file's extension (held in the memory location pointed to by Register Pair HL) and store it into Register A.
5774
CP 20H
Compare the value held in Register A against 20H (ASCII: SPACE). Results: If Register A equals SPACE, the Z FLAG is set; otherwise the NZ FLAG is set.
5776
JR Z,COMPR4
     [5788H]
If there is no extension because there was a SPACE as the first character and Z FLAG (Zero) has been set, JUMP to 5788H.
5778
LD A,2FH
If we are here then we know there is an extension, so add a slash into the file control block by setting Register A equal /.
577A
LD (DE),A
and then storing the / (held in Register A) into the file control block (the memory location pointed to by Register Pair DE).
577B
INC DE
Since we just put in another character into the File Control Block, we need to bump the File Control Block pointer (held in Register DE) by 1.
577C
LD B,03H
Since there are 3 characters max in a filename extension, set Register B equal 03H.
"COMPR3"
577E
LD A,(HL)
Start of a loop. Fetch a character from the filename's extension from the memory location pointed to by Register Pair HL and store it into Register A.
577F
CP 21H
Check to see if there is actually a usable character there by comparing the character we just fetched (held in Register A) against 21H (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.
5781
JR C,COMPR4
     [5788H]
If the filename's extension byte in the directory entry is less than ! then we are apparently at the end of the filename and the C FLAG (Carry) will have been set, JUMP to 5788H.
5783
LD (DE),A
We have a valid extension character in Register A so store it into the FCB at the memory location pointed to by Register Pair DE.
5784
INC HL
INCrement the pointer in the directory entry (stored in Register Pair HL) by 1.
5785
INC DE
INCrement the pointer in the file control block entry (stored in Register Pair DE) by 1.
5786
DJNZ COMPR3
     [577EH]
Process up to 3 characters of the extension by LOOPing back to 577EH, 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.
"COMPR4"
5788
LD HL,PUDRV
End of loop. Let Register Pair HL equal 58C6H to point to the drive number + terminator.
578B
LD BC,0003H
Since a drive number + terminator is 3 bytes, set Register Pair BC equal 0003H.
578E
LDIR
Copy the drive number + terminator from the directory entry into the file control block via LDIR which 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.
5790
RET
RETurn to the caller.

5791H - Continuation of the "PURGE" Routine - Finish the routine and request system disk if needed.

"PUGEXT"
5791
LD A,(58C5H)
Check to see if the DOS was deleted by fetching the value held in memory location 58C5H and store it into Register A.
5794
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).
5795
RET Z
If the Z FLAG (Zero) has been set then DOS was not deleted, so we are good to go. RETurn to the caller.
5796
LD A,(PDRV)
We now know that DOS was deleted, and need to get the drive number, so fetch the value held in memory location 58C9H and store it into Register A.
5799
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).
579A
RET NZ
If the drive we just modified wasn't :0 then we don't really care if DOS was deleted or not, so as long as it wasn't :0 RETurn to the caller.
579B
LD HL,SY4MSG
We now know that DOS was deleted and from Drive :0 and that we need to prompt for a DOS disk, so first set Register Pair HL equal 5885H to point to the message "INSERT A SYSTEM DISK.".
579E
CALL 021BH
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
57A1
JP 0049H
   [0049H]
Wait for a key press and then RETurn via JUMP to the Model III ROM routine at 0049H which is is the Model III ROM routine to scan the keyboard and wait until a key is pressed, and then return with the key pressed in Register A. BREAK returns 01H.

57A4H - Subroutine in the "PURGE" Routine - Encode the password stored in the memory location pointed to by Register Pair DE; results in Register Pair HL.

"TRAP"
57A4
LD HL,0FFFFH
LET Register Pair HL = 0FFFFH (Decimal: -1) as the default.
57A7
LD B,08H
LET Register B = 08H since a password is 8 characters.

The next few instructions skip to the end of the password (pointed to by Register Pair DE) by adding 7 to the LSB (i.e., Register E).

57A9
LD A,E
LET Register A = Register E.
57AA
ADD A,07H
ADD the value 07H to Register A (Results held in Register A).
57AC
LD E,A
LET Register E = Register A.
57AD
If the NC FLAG (No Carry) is set then we did not move to a new memory page (i.e., need to update D as well), so skip over the next instruction which increments D, and JUMP to 5113H.
57AF
INC D
Bump the value stored in Register D by 1.

At this point, Register Pair DE is now pointing to the END of the password.

"SETTD2"
57B9
LD A,(DE)
Fetch the value stored at memory location pointed to by Register Pair DE (i.e., 1 character of the 8 character password) and put it into Register A.
57B1
PUSH DE
Save Register DE (i.e., the location in the password string where Register A got the character from) to the top of the stack.
57B2
LD D,A
LET Register D = Register A (i.e., the password character pointed to by (DE)).
57B3
LD E,H
LET Register E = Register H (i.e., the MSB of the password).
57B4
LD A,L
LET Register A = Register L (i.e., the LSB of the password).
57B5
AND 07H
MASK the value of Register A against 07H (0000 0111). This has the effect of turning off bits 7, 6, 5, 4, 3, leaving only bits 2, 1, 0 active.
57B7
57B8
57B9
RRCA
RRCA
Move the bottom 3 bits (2, 1, and 0) to the top 3 bits (7, 6, and 5)
57BA
XOR L
eXclusive OR Register L against Register A to merge the masked Register A with the LSB. The results are stored in Register A.
57BB
LD L,A
LET Register L = Register A (i.e., the new LSB).
57BC
LD H,00H
LET Register H = 00H so that the MSB = 0.
57BE
SBC HL,DE
Let PASSWORD = PASSWORD - DE by subtracting the value stored in Register Pair DE and the carry flag from the value stored in Register Pair HL.
57C0
ADD HL,HL
Let PASSWORD = PASSWORD * 2 by adding the value held in Register Pair HL to Register Pair HL. The results are held in Register Pair HL.
57C1
ADD HL,HL
Let PASSWORD = PASSWORD * 4 by doing that again.
57C2
XOR H
eXclusive OR Register H (i.e., the new MSB) against Register A (i.e., the old LSB). The results are stored in Register A.
57C3
XOR D
eXclusive OR Register D (i.e., the character) against Register A (i.e., the old LSB / new MSB combination). The results are stored in Register A.
57C4
LD D,A
LET Register D = Register A (i.e., the mishmash we just did).
57C5
LD A,L
LET Register A = Register L (i.e., the new MSB).
57C6
ADD HL,HL
Let PASSWORD = PASSWORD * 2 by adding the value held in Register Pair HL to Register Pair HL. The results are held in Register Pair HL.
57C7
XOR H
eXclusive OR Register H (i.e., the NEWER MSB) against Register A (i.e., the prior new MSB). The results are stored in Register A.
57C8
XOR E
eXclusive OR Register E (i.e., the old MSB) against Register A. The results are stored in Register A.
57C9
LD E,A
LET Register E = Register A.
57CA
EX DE,HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair DE so that Register Pair HL now contains the newly encoded password.
57CB
POP DE
Restore Register Pair DE (i.e., the location in the pasword string for the character which was just processed) from the top of the STACK.
57CC
DEC DE
DECrement the value stored in Register Pair DE by 1 to point to the previous character in the password string.
57CD
LOOP back to 5113H until Register B is ZERO (i.e., all 8 characters of the password have been processed, in reverse).
57CE
57CF
LD A,H
OR L
The Z-80 does not have a way to check a register pair against 0 easily. So a common trick is to let Register A equal one part of the Register Pair and then to OR that against the other part of the Register Pair. Only if both parts of the register pair were 0 will A be 0.
57D1
RET NZ
If the NZ FLAG (Not Zero) is set, then Register Pair HL (i.e., the password) was not 0, so RETurn to the caller.
57D2
INC L
Bump the value stored in Register L by 1 so we don't have a password of 0.
57D3
RET
RETurn to the caller.

57D4H - Subroutine in the "PURGE" Routine - Delete all System Files.

"PURSYS"
57D4
LD HL,SYSMSG
Let Register Pair HL equal 5878H to point to the message "SYSTEM FILES".
57D7
CALL 021BH
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
57DA
LD HL,PUDRV
Let Register Pair HL equal 58C6H to point to the drivespec in ASCII.
57DD
CALL 021BH
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
57E0
LD HL,QUERY
Let Register Pair HL equal 589AH to point to the message " (Y/N/Q) ?".
57E3
CALL 021BH
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
57E6
LD HL,SDCB2
Let Register Pair HL equal 5BD2H to point to a buffer.
57E9
LD B,03H
Fetch 3 characters from the keyboard by setting Register B equal 03H.
57EB
CALL 0040H
     [0040H]
GOSUB to 0040H.
NOTE: 0040H is the Model III ROM routine to get a full line from the keyboard. In this routine, a line is terminated by a carriage return or BREAK, and characters typed are echoed to the display. On entry, B must be the maximum length of line to be accepted and (HL) must be the storage buffer which should be set to B+1. On Exit, CARRY will be set if the BREAK key was hit, Register B will contain the number of characters entered, and (HL) will contain the line from the keyboard followed by the terminating character. Register paid DE is altered in this routine.
57EE
LD A,(HL)
Fetch the response received from the user to the Y/N/Q question (held in the memory location pointed to by Register Pair HL) and store it into Register A.
57EF
CP 4EH
Compare the value held in Register A against 4EH (ASCII: N). Results: If Register A equals N, the Z FLAG is set; otherwise the NZ FLAG is set.
57F1
JR Z,CLRSTR
     [580AH]
If the user entered "N" then the Z FLAG (Zero) will have been set, JUMP to 580AH to skip this file.
57F3
CP 51H
Compare the value held in Register A against 51H (ASCII: Q). Results: If Register A equals Q, the Z FLAG is set; otherwise the NZ FLAG is set.
57F5
JR NZ,PURSY1
      [57FAH]
If the user did not enter a "Q" then skip the next few instructions (which return) and JUMP to 57FAH.
57F7
57F8
INC SP
INC SP
INCrement the value stored in Register Pair SP by 2 to affect the RETurn so that RET returns to DOS.
57F9
RET
RETurn to the caller.

57FAH - Continuation of the "PURGE" subroutine to Delete all System Files.

"PURSY1"
57FA
CP 59H
Compare the value held in Register A against 59H (ASCII: Y). Results: If Register A equals Y, the Z FLAG is set; otherwise the NZ FLAG is set.
57FC
JR NZ,PURSYS
      [57D4H]
If the user didn't enter a Y either, then we received no valid response to the Y/N/Q inquiry and the NZ FLAG (Not Zero) will have been set, JUMP back to 57D4H to display the Y/N/Q prompt again.
57FE
LD HL,43E0H
Let Register Pair HL equal 43E0H to point to the SYSTEM FILE DESCRIPTORS.
5801
LD E,(HL)
Fetch the first byte of the SYSTEM FILE DESCRIPTORS (held in the memory location pointed to by Register Pair HL) and store it into Register E.
5802
INC HL
Point HL to the next byte of the SYSTEM FILE DESCRIPTORS.
5803
LD D,(HL)
Fetch the second byte of the SYSTEM FILE DESCRIPTORS (held in the memory location pointed to by Register Pair HL) and store it into Register E.
5804
DEC HL
Point HL to the first byte of the SYSTEM FILE DESCRIPTORS.
5805
INC DE
INCrement the two-byte SYSTEM FILE DESCRIPTOR held in Register Pair DE by 1.
5806
5806
LD A,D
OR E
Since the Z-80 cannot test Register Pair DE against zero, the common trick is to set Register A to equal to Register D, and then OR A against Register E. Only if both Register D and Register E were zero can the Z FLAG be set.
5808
JR NZ,PRSYS0
      [580FH]
If descriptor was FF (exists) the NZ FLAG (Not Zero) will have been set, JUMP to 580FH to continue and delete the files.
"CLRSTR"
580A
XOR A
Set Register A to ZERO and clear all Flags.
580B
LD (58C5H),A
Store the a 00H into memory location 58C5H to clear the SYSTEM DELETE FLAG.
580E
RET
RETurn to the caller.

580FH - Continuation of the "PURGE" subroutine to Delete all System Files.

"PRSYS0"
580F
LD DE,43E1H
Let Register Pair DE equal 43E1H which is the pointer to the SYSTEM FILE DESCRIPTORs.
5812
LD BC,001FH
Let Register Pair BC equal 001FH to clear 31 sets of descriptors.
5815
LD (HL),0FFH
Store 0FFH's into the memory location pointed to by Register Pair HL.
5817
LDIR
Set all 31 descriptors to FFH via LDIR which 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.
5819
LD A,(PDRV)
Fetch the drive number (held in memory location 58C9H) and store it into Register A.
581C
LD C,A
Since SYS00/SYS Disk I/O calls usually require Register C to contain the drive number, copy the drive number (held in Register A) into Register C.
581D
CALL 4AC2H
     [4AC2H]
GOSUB to 4AC2H.
NOTE: 4AC2H is the SYS00/SYS routine to write the HIT sector from RAM to diskette.
5820
JP NZ,4409H
      [4409H]
If the NZ FLAG (Not Zero) has been set, meaning that the prior CALL routine returned with an ERROR, then 4409H.
NOTE: 4409H is the SYS00/SYS routine to process DOS errors.

We don't have an error, so next we need to clea out the SYSTEM ALLOCATION BYTES from the HIT.

5823
LD IX,BUFF2
Let Special Index Register Pair IX equal 4D00H.
NOTE: 4D00H is a memory buffer (referred to as Memory Buffer 2) where the GAT TABLE is stored in RAM.
5827
LD (IX+00H),01H
Free the entire track 0, except the BOOT sector, by storing a 00H into 1st byte of the GAT Table in RAM (pointed to by Special Index Register Pair IX+00H).
582B
LD (IX+01H),00H
Free the entire track 1 by storing a 00H into the 2nd byte of the GAT in RAM (pointed to by Special Index Register Pair IX+01H).
582F
LD A,(IX+02H)
To clear track 2 we need to do a little math because it isn't entirely a SYSTEM track. Fetch the value of the 3rd byte of the GAT in RAM (pointed to by Special Index Register Pair IX+02H).
5832
AND 0FCH
MASK the 3rd byte of the GAT against 0FCH (1111 1100). This has the effect of turning off bits 1, 0.
5834
LD (IX+02H),A
Free the system parts on track 2 by storing a the masked byte into the 3rd byte of the GAT in RAM (pointed to by Special Index Register Pair IX+02H).
5837
LD (IX+0FH),00H
Free the entire track 15 by storing a 00H into the 16th byte of the GAT in RAM (pointed to by Special Index Register Pair IX+0FH).
583B
LD (IX+10H),00H
Free the entire track 16 by storing a 00H into the 17th byte of the GAT in RAM (pointed to by Special Index Register Pair IX+10H).
583F
LD (IX+12H),00H
Free the entire track 18 by storing a 00H into the 19th byte of the GAT in RAM (pointed to by Special Index Register Pair IX+12H).
5843
LD (IX+13H),00H
Free the entire track 19 by storing a 00H into the 20th byte of the GAT in RAM (pointed to by Special Index Register Pair IX+13H).
5847
LD (IX+14H),00H
Free the entire track 20 by storing a 00H into the 21st byte of the GAT in RAM (pointed to by Special Index Register Pair IX+13H).
584B
LD A,(IX+15H)
To clear track 21 we need to do a little math because it isn't entirely a SYSTEM track. Fetch the value of the 22nd byte of the GAT in RAM (pointed to by Special Index Register Pair IX+15H).
584E
AND 0F0H
MASK the 22nd byte of the GAT against 0FCH (1111 1100). This has the effect of turning off bits 1, 0.
5850
LD (IX+15H),A
Free the system parts on track 21 by storing a the masked byte into the 22nd byte of the GAT in RAM (pointed to by Special Index Register Pair IX+15H).
5853
CALL 4A9BH
     [4A9BH]
GOSUB to 4A9BH.
NOTE: 4A9BH is the SYS00/SYS routine to to write the GAT sector from RAM to diskette.
5856
JP NZ,4409H
      [4409H]
If the NZ FLAG (Not Zero) has been set, meaning that the prior CALL routine returned with an ERROR, then JUMP to 4409H.
NOTE: 4409H is the SYS00/SYS routine to process DOS errors.

We now need to write out the DUMMY system (to display the need for a SYSTEM disk).

5859
LD DE,0002H
Let Register Pair DE equal 0002H (i.e., Track 00H in D, Sector 02H in E) since a call to 47F7H requires DE point to the TRACK and SECTOR to be written.
585C
LD HL,SYST
Let Register Pair HL equal 5F00H since a call to 47F7H requires HL point to a buffer. This is the dummy code to write to Track 0, Sector 2 when there is no DOS.
585F
CALL 45F7H
     [45F7H]
GOSUB to 45F7H which is the SYS00/SYS routine to WRITE A SECTOR TO DISK.
5862
JP NZ,4409H
      [4409H]
If the NZ FLAG (Not Zero) has been set, meaning that the prior CALL routine returned with an ERROR, then JUMP to 4409H.
NOTE: 4409H is the SYS00/SYS routine to process DOS errors.
5865
RET
RETurn to the caller.

5866H - "PURGE" Command Message and Byte Storage.

"MSPW"
5866
DEFM 'Master Password? ' + 03H
"SYSMSG"
5878
DEFM 'System Files' + 03H
"SY4MSG"
5885
DEFM 'Insert a SYSTEM disk' + 0DH
"QUERY"
589A
DEFM ' (Y/N/Q) ? ' + 03H

5866H - "PURGE" Command Parameter Table.

"PURSWT"
58A6
DEFM 'SYS '
58AC
DEFW BFH 58H
Pointer to the byte storage for SYS Option.
58AE
DEFM 'INV '
58B4
DEFW C1H 58H
Pointer to the byte storage for INV Option.
58B6
DEFM 'ALL '
58B4
DEFW C3H 58H
Pointer to the byte storage for ALL Option.
58BE
DEFB 00H
End of table delimeter

58BFH - "PURGE" Command Message and Byte Storage.

"PSYS"
58BF
DEFW 0000H
Flag for SYS Option
"PINV"
58C1
DEFW 0000H
Flag for INV Option
"PALL"
58C3
DEFW 0000H
Flag for ALL Option
"STAR"
58C5
DEFB 00H
Flag for DELETE ALL DOS SYSTEM Files
"PUDRV:"
58C6
DEFM ":N" + 0DH
"PDRV"
58C9
DEFB 00H
Drive Number for the PURGE Command
"PW"
58CA
DEFW 0000H
Hashed Master Password Supplied by the User

58CCH - "LIST" Command.

"LIST"
58CC
LD DE,SDCB1
Let Register Pair DE equal 5BA2H, which will be a buffer to hold a file control block.
58CF
CALL 441CH
     [441CH]
GOSUB to 441CH.
NOTE: 441CH is the SYS00/SYS routine to CHECK THE SYNTAX OF A FILESPEC before for use. This RST 28H's with a value of C1H so as to call ROUTINE 4 in OVERLAY 1.
58D2
JP NZ,ERR3
      [521DH]
If the NZ FLAG (Not Zero) has been set, meaning that the prior CALL routine returned with an ERROR, then JUMP to 521DH.
58D5
PUSH HL
Save the pointer to the current character of the COMMAND LINE (Register Pair HL) to the top of the stack.
58D6
LD HL,0000H
Let Register Pair HL equal 0000H to zero the current record number.
58D9
LD (RCNUM),HL
Store the 0000H (held in Register Pair HL) into memory location 5B04H to zer the current record number.
58DC
LD DE,SDCB1
Let Register Pair DE equal 5BA2H, which will be a buffer to hold a file control block.
58DF
LD HL,FILSAV
Let Register Pair HL equal 5B13H which will be a buffer to hold a filename.
58E2
LD B,19H
Prepare for a loop of 25 characters by setting Register B to 19H.
"LIST1"
58E4
LD A,(DE)
Top of a DJNZ loop. Fetch a character from the FCB (which will be the filename portion of the FCB) held in the memory location pointed to by Register Pair DE and store it into Register A.
58E5
CP 20H
Compare the value held in Register A against 20H (ASCII: SPACE). Results:
  • If Register A equals SPACE, the Z FLAG is set.
  • If A < SPACE, the CARRY FLAG will be set.
  • if A >= SPACE, the NO CARRY FLAG will be set.
58E7
JR C,LIST2
     [58EEH]
If the current character of the filename held in the FCB < SPACE then we have run out of valid characters to process and the C FLAG (Carry) will have been set, JUMP to 58EEH.
58E9
LD (HL),A
Store the validated character from the filename from the FCB (held in Register A) into the filename buffer (i.e., the memory location pointed to by Register Pair HL).
58EA
INC HL
INCrement the filename buffer pointer (stored in Register Pair HL) by 1.
58EB
INC DE
INCrement the pointer to the filename in the FCB (stored in Register Pair DE) by 1.
58EC
DJNZ LIST1
     [58E4H]
LOOP back to 58E4H, 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.

We are here either because of a pass through completion of 25 characters or because we hit a character which was not valid.

"LIST2"
58EE
LD (HL),09H
Store an ASCII TAB into the filename buffer pointed to by Register Pair HL.
58F0
INC HL
INCrement the filename buffer pointer (stored in Register Pair HL) by 1.
58F1
LD (HL),03H
Store an 03H terminator into the filename buffer pointed to by Register Pair HL.
58F3
POP HL
Save the pointer to the current character of the COMMAND LINE (held at the top of the stack) into Register Pair HL.
58F4
LD DE,SWTCH1
Let Register Pair DE equal 5B89H to point to the valid parameter table for LIST command parameters.
58F7
CALL 4454H
     [4454H]
GOSUB to 4454H.
NOTE: 4454H is the DOS PARAMETER STRING PARSE routine. It decodes DOS LIBRARY parameters.
58FA
JP NZ,ERR2
      [5219H]
If the NZ FLAG (Not Zero) has been set, meaning that the prior CALL routine returned with an ERROR, then JUMP to 5219H to display an ILLEGAL PARAMETER error and exit via a JUMP to 5223H.
58FD
LD DE,SDCB1
Let Register Pair DE equal 5BA2H, which will be a buffer to hold a file control block.
5900
LD HLBUFER1
Let Register Pair HL equal 5D00H for a FILE BUFFER.
5903
LD B,00H
Let Register B equal 00H so that the next routine will set for FULL SECTOR I/O.
5905
CALL 4424H
     [4424H]
GOSUB to 4424H.
NOTE: 4424H is the SYS00/SYS routine to OPEN A DISK FILE for use. This RST 28H's with a value of 92H so as to call ROUTINE 2 in OVERLAY 3.
5908
JP NZ,4409H
      [4409H]
If the NZ FLAG (Not Zero) has been set, meaning that the prior CALL routine returned with an ERROR, then JUMP to 4409H.
NOTE: 4409H is the SYS00/SYS routine to process DOS errors.
590B
LD A,(5BABH)
Fetch the LOGICAL RECORD LENGTH of the selected file (held in memory location 5BABH) and store it into Register A.
590E
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).
590F
JR NZ,LIST3
      [591EH]
If we were NOT set for FULL SECTOR I/O the the NZ FLAG (Not Zero) will have been set, skip the next few instrutions which prepare for a 256 byte LRL by JUMPing over them to 591EH.
5911
LD HL,5B42H
Let Register Pair HL equal 5B42H to point to the message "256".
5914
LD DE,5B32H
Let Register Pair DE equal 5B32H to point to the middle of the "LRL = nnn" message.
5917
LD BC,0003H
Let Register Pair BC equal 0003H to loop for the 3 characters of "256".
591A
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.
591C
JR LIST4
   [5938H]
JUMP to 5938H to continue.

591EH - Continuation "LIST" Command; jumped here if the LRL is not 256.

"LIST3"
591E
LD HL,LRLSAV
Let Register Pair DE equal 5B32H to point to the middle of the "LRL = nnn" message.
5921
CP 0C8H
Compare the value held in Register A against C8H (Decimal: 200). Results:
  • If Register A equals a LRL of 200, the Z FLAG is set.
  • If A < a LRL of 200, the CARRY FLAG will be set.
  • if A >= a LRL of 200, the NO CARRY FLAG will be set.
5923
JR C,LIST31
     [592CH]
If the LRL is less than 200, JUMP to 592CH.
5925
LD (HL),32H
Since the LRL is at least 200, fill the first slot of the "nnn" with a "2".
5927
INC HL
INCrement HL to point to the 2nd n character in the "LRL = nnn" message.
5928
SUB 0C8H
SUBtract 200 from Register A so that any additional routine processing the LRL is working with a number less than 200.
592A
JR LIST33
   [5935H]
JUMP to 5935H.

592CH - Continuation "LIST" Command; jumped here if the LRL is less than 200.

"LIST31"
592C
CP 64H
Compare the value held in Register A against 64H (Decimal: 100). Results:
  • If the LRL (held in Register A) equals 100, the Z FLAG is set.
  • If the LRL (held in Register A) < 100, the CARRY FLAG will be set.
  • if If the LRL (held in Register A) >= 100 the NO CARRY FLAG will be set.
592E
JR C,LIST33
     [5935H]
If the LRL is less than 100, JUMP to 5935H.
5930
LD (HL),31H
Since the LRL is at least 100, fill the first slot of the "nnn" with a "1".
5932
INC HL
INCrement HL to point to the 2nd n character in the "LRL = nnn" message.
5933
SUB 64H
SUBtract 100 from Register A so that any additional routine processing the LRL is working with a number less than 100.

5935H - Continuation "LIST" Command; jumped here if first digit of the LRL was "1" or "2".

"LIST33"
5935
CALL DECBIN
     [529DH]
Convert the remaining 2 digits of the LRL into ASCII via a GOSUB to 529DH.

5938H - Continuation "LIST" Command; jumped here to deal with the tens and ones position number of the LRL.

"LIST4"
5938
LD BC,(ASCFLG)
Fetch the value held in memory location 5B06H and 5B07H to see if the LIST command is to be output in ASCII and store it into Register Pair BC.
593C
593C
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.
593E
JR Z,LIST41
     [594BH]
If the Z FLAG (Zero) has been set, then we are not outputting in ASCII FORMAT, so JUMP to 594BH.
5940
LD HL,AMSG
Let Register Pair HL equal 5B89H, to point to the word "ASCII".
5943
LD DE,RECNUM
Let Register Pair DE equal 5B3CH, to point to the message "REC = 00000".
5946
LD BC,0005H
Since there are 5 0's to replace, set Register Pair BC equal 0005H.
5949
LDIR
Replace the "00000" with "ASCII" via a LDIR which 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.
"LIST41"
594B
CALL 01C9H
     [01C9H]
GOSUB to 01C9H.
NOTE: 01C9H is the Model III ROM routine to to CLEAR THE SCREEN and RETurn.
594E
CALL PRTHED
     [5AA5H]
Generate the LIST header via a GOSUB to 5AA5H.
5951
LD A,02H
We will want to protect the top 2 lines of the screen during the LIST so set Register A equal 02H.
5953
LD (4214H),A
Scroll protect the top 2 lines of the screen by storing a 2 (held in Register A) into memory location 4214H.
5956
LD BC,(ASCFLG)
Fetch the value held in memory location 5B06H and 5B07H to see if the LIST command is to be output in ASCII and store it into Register Pair BC.
595A
595A
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.
595C
JR Z,LREG
     [59B5H]
If the Z FLAG (Zero) has been set, then we are not outputting in ASCII FORMAT, so JUMP to 59B5H.

If we are here then we are outputting in ASCII Format.

595E
LD HL,CR2
Prepare the LIST to go to a new line by first setting Register Pair HL equal 5B49H to point to two CARRIAGE RETURN.
5961
CALL PRINTT
     [5286H]
Move to the new line via a GOSUB to 5286H which outputs a text string pointed to by Register Pair HL to the Screen and, if 5277H is set to 0000H, to the Printer as well.
"L6OP8"
5964
LD DE,SDCB1
Let Register Pair DE equal 5BA2H, which will be a buffer to hold a file control block.
5967
CALL 0013H
     [0013H]
GOSUB to 0013H.
NOTE: 0013H is the Model III ROM routine to read a byte from an input device. Requires DE = starting address of DCB of device and on Exit Register A = byte received from device, Z set if device ready. Uses AF.
596A
JP NZ,END1
      [5998H]
If the NZ FLAG (Not Zero) has been set, meaning that the prior CALL routine returned with an ERROR, then JUMP to 5998H.
596D
AND 7FH
Turn off the highest bit in Register A by MASKing the value of Register A against 7FH (0111 1111).
"L6OP8D"
596F
CP 09H
Compare the value held in Register A against 09H (ASCII: TAB). Results: If Register A equals TAB, the Z FLAG is set; otherwise the NZ FLAG is set.
5971
JR Z,L6OPC8
     [597FH]
If the character is a TAB then display it and skip to the next via a JUMP to 597FH.
5973
CP 20H
Compare the value held in Register A against 20H (ASCII: SPACE). Results:
  • If Register A equals SPACE, the Z FLAG is set.
  • If A < SPACE, the CARRY FLAG will be set.
  • if A >= SPACE, the NO CARRY FLAG will be set.
5975
JR NC,L6OPC8
      [597FH]
If A >= SPACE then display it and skip to the next via a JUMP to 597FH.
5977
CP 0DH
Compare the value held in Register A against 0DH (ASCII: CARRIAGE RETURN). Results: If Register A equals CARRIAGE RETURN, the Z FLAG is set; otherwise the NZ FLAG is set.
5979
JR Z,L6OPC8
     [597FH]
If the character is a CARRIAGE RETURN then display it and skip to the next via a JUMP to 597FH.
597B
CP 0AH
Compare the value held in Register A against 0AH (ASCII: LINE FEED). Results: If Register A equals LINE FEED, the Z FLAG is set; otherwise the NZ FLAG is set.
597D
JR NZ,L6OP8B
      [598FH]
If the character is a LINE FEED skip (and do not display it) via a JUMP to 598FH.
"L6OPC8"
597F
CALL PDATA
     [526FH]
Output the character held in Register A to the screen and, if applicable, the printer, via a GOSUB to 526FH.
5982
CP 0DH
Compare the value held in Register A against 0DH (ASCII: CARRIAGE RETURN). Results: If Register A equals CARRIAGE RETURN, the Z FLAG is set; otherwise the NZ FLAG is set.
5984
JR NZ,L6OP8B
      [598FH]
If the character is NOT a CARRIAGE RETURN then JUMP to 598FH.
5986
LD BC,(SLWFLG)
Fetch the value held in memory location 5B08H-5B09H (which indicate if a SLOW display was requested) and store it into Register Pair BC.
598A
598A
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.
598C
CALL NZ,0060H
        [0060H]
If 5B08H does not equal 0, meaning that the user requested a SLOW display, trigger a delay via a GOSUB to 0060H.
"L6OP8B"
598F
CALL 028DH
     [028DH]
GOSUB to 028DH.
NOTE: 028DH is the Model III ROM routine to CHECK FOR BREAK. On exit, the NZ FLAG will be set if BREAK was detected.
5992
RET NZ
If the BREAK was hit (and the NZ FLAG (Not Zero) has been set), RETurn to the caller.
5993
CALL HLDPAT
     [525FH]
Check for a shift-"@" PAUSE via a GOSUB to 525FH.
5996
JR L6OP8
   [5964H]
LOOP BACK to 5964H to process more data.

5998H - Continuation "LIST" Command; jumped here if we got an error retrieving the file from disk. Register A will contain the error code.

"END1"
5998
CP 1CH
Compare the value held in Register A against 1CH (END OF FILE ERROR). Results: If the error (held in Register A) equals 1CH (for END OF FILE ERROR), the Z FLAG is set; otherwise the NZ FLAG is set.
599A
JR Z,END2
     [59A3H]
If the Z FLAG (Zero) has been set, handle the ERROR CODE held in Register A via a JUMP to 59A3H.
599C
CP 1DH
Compare the value held in Register A against 1DH (END OF FILE ERROR). Results: If the error (held in Register A) equals 1DH (for RECORD OUT OF RANGE), the Z FLAG is set; otherwise the NZ FLAG is set.
599E
JR Z,END2
     [59A3H]
If the Z FLAG (Zero) has been set, handle the ERROR CODE held in Register A via a JUMP to 59A3H.
59A0
JP 4409H
   [4409H]
JUMP to 4409H.
NOTE: 4409H is the SYS00/SYS routine to process DOS errors.

59A3H - Continuation "LIST" Command; jumped here if the error we got error retrieving the file from disk was 1CH or 1DH.

"END2"
59A3
LD A,(4020H)
Fetch the value held in memory location 4020H and store it into Register A.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
59A6
AND 3FH
Isolate the column number of where the cursor is on screen by MASKing the value of Register A against 3FH (0011 1111), turning off bits 7 and 6.
59A8
JR Z,END3
     [59AFH]
If masked cursor position is at the left margin, the Z FLAG (Zero) will have been set, skip the next instructions which move to the left margin via a JUMP to 59AFH.
59AA
LD A,0DH
Let Register A equal 0DH (ASCII: CARRIAGE RETURN).
59AC
CALL PDATA
     [526FH]
Move to a new line by outputting the character held in Register A to the screen and, if applicable, the printer, via a GOSUB to 526FH.
"END3"
59AF
LD HL,EOFMSG
Let Register Pair HL equal 5B45H which points to the message "EOF".
59B2
JP PRINTT
   [5286H]
Display the "EOF" and exit via a JUMP to 5286H which outputs a text string pointed to by Register Pair HL to the Screen and, if 5277H is set to 0000H, to the Printer as well.

59B5H - Continuation "LIST" Command; jumped here if the file is to be listed in hex.

"LREG"
59B5
LD HL,DOTSTR
Let Register Pair HL equal 5B4BH to point to the message "1...5....10...15...20 ..."
59B8
CALL PRINTT
     [5286H]
Display that message via a GOSUB to 5286H which outputs a text string pointed to by Register Pair HL to the Screen and, if 5277H is set to 0000H, to the Printer as well.
59BB
LD A,0DH
Let Register A equal 0DH (ASCII: CARRIAGE RETURN).
59BD
CALL PDATA
     [526FH]
Move to a new line by outputting the character held in Register A to the screen and, if applicable, the printer, via a GOSUB to 526FH.
59C0
LD A,03H
We need to scroll protect three lines at the top of the screen so set Register A to equal 03H.
59C2
LD (4214H),A
Scroll protect the top 3 lines of the display by storing a 3 into memory location 4214H.
"LREG1"
59C5
LD DE,SDCB1
Let Register Pair DE equal 5BA2H, which will be a buffer to hold a file control block.
59C8
LD HLBUFER2
Let Register Pair HL equal 5E00H for a FILE BUFFER / DATA STORAGE BUFFER.
59CB
CALL 4436H
     [4436H]
GOSUB to 4436H.
NOTE: 4436H is the SYS00/SYS vector for 'READ', which reads the record that the disk drive is positioned over.
59CE
JR NZ,END1
      [5998H]
If the NZ FLAG (Not Zero) has been set, JUMP to 5998H.
59D0
CALL PRTHED
     [5AA5H]
Generate the LIST header via a GOSUB to 5AA5H.
59D3
LD HL,(RCNUM)
Fetch the record number (held in memory location 5B04H) and store it into Register Pair HL.
59D6
INC HL
INCrement the record number (stored in Register Pair HL) by 1.
59D7
LD (RCNUM),HL
Store the bumped record number (held in Register Pair HL) into memory location 5B04H.
59DA
LD A,(5BABH)
Fetch the LRL (held in memory location 5BABH) and store it into Register A.
59DD
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).
59DE
JR NZ,LREG3
      [59F0H]
If we are not looking at a FULL SECTOR I/O because the LRL was not 0, JUMP to 59F0H.
59E0
LD HLBUFER1
Let Register Pair HL equal 5D00H for a FILE BUFFER.
"LREG2"
59E3
LD B,3CH
Since a data line is 60 characters, set Register B to 3CH (Decimal: 60).
59E5
CALL DSPROW
     [5A18H]
Output Register B number of characters from the FILE BUFFER via a GOSUB to 5A18H.
59E8
JR Z,LREG1
     [59C5H]
If the Z FLAG (Zero) has been set the we need to move to a new disk sector, so JUMP to 59C5H.
59EA
LD DE,003CH
Let Register Pair DE equal 003CH for the next block of 60 characters.
59ED
ADD HL,DE
Position HL to the next 60 character block in the 5D00H file buffer.
59EE
JR LREG2
   [59E3H]
Loop back to 59E3H.

59F0H - Continuation "LIST" Command; jumped here if the file is to be listed in hex BUT we are not in FULL SECTOR I/O mode because the LRL was not 256. The way to handle is broken out into 2 pieces --- one if the LRL <= 60 and one if it is > 60.

"LREG3"
59F0
CP 3DH
Compare the value held in Register A against 3DH (Decimal: 61). If the LRL is >= 61 ...
59F2
JR NC,59FDH
      [59FDH]
... then we can fill one more line of screen data, so JUMP to 59FDH to handle it.
59F4
LD HLBUFER2
Let Register Pair HL equal 5E00H for a FILE BUFFER / DATA STORAGE BUFFER.
"LREG4"
59F7
LD B,A
Let Register B = the number of bytes left in the LRL (which we know is 60 or less).
59F8
CALL DSPROW
     [5A18H]
Output Register B number of characters via a GOSUB to 5A18H.
59FB
JR LREG1
   [59C5H]
Loop Back to 59C5H for the next record.

59FDH - Continuation "LIST" Command; jumped here if the file is to be listed in hex BUT we are not in FULL SECTOR I/O mode AND the LRL is at least 61 characters.

"LREG5"
59FD
LD HLBUFER2
Let Register Pair HL equal 5E00H for a FILE BUFFER / DATA STORAGE BUFFER.
"LREG6"
5A00
PUSH AF
Save the remaining byte count (held in Register A) to the top of the stack.
5A01
LD B,3CH
Let Register B equal 3CH (Decimal: 60).
5A03
CALL DSPROW
     [5A18H]
Output Register B number of characters via a GOSUB to 5A18H.
5A06
POP AF
Restore the remaining byte count from the top of the STACK back into Register Pair AF, and then remove the entry from the stack.
5A07
SUB 3CH
SUBtract 60 from the count.
5A09
JP C,LREG1
     [59C5H]
If the C FLAG (Carry) has been set, JUMP to 59C5H.
5A0C
PUSH AF
Save the remaining byte count (held in Register A) to the top of the stack.
5A0D
5A0F
5A10
LD A,3CH
ADD A,L
LD L,A
Let the location in the file buffer (held in HL) = HL + 60 bytes.
5A11
POP AF
Restore the remaining byte count from the top of the STACK back into Register Pair AF, and then remove the entry from the stack.
5A12
CP 3DH
Compare the remaining byte count (held in Register A) against 3DH (Decimal: 61). If the remaining byte count is < 61, ...
5A14
JR C,LREG4
     [59F7H]
... display the last buffer by JUMPing to 59F7H to deal with that.
5A16
JR LREG6
   [5A00H]
If there are at least 61 bytes, LOOP back to to 5A00H to keep processing bytes.

5A18H - Output Register B number of characters in ALPHA and HEX. On Entry: HL = the position in the FILE BUFFER to display, B = the number of characters to output

"DSPROW"
5A18
LD C,03H
We are going to need to make 3 passes so set Register C equal 03H.
"DSPRO1"
5A1A
PUSH BC
Save the number of characters per line to output (held in Register B) to the top of the stack.
5A1B
PUSH HL
Save the position in the FILE BUFFER to display (held in Register Pair HL) to the top of the stack.
5A1C
LD A,C
Copy the pass counter (held in Register C) into Register A.
5A1D
CP 03H
Check to see if this is the FIRST pass by compare the pass counter (held in Register A) against 03H. Results: If Register A equals 03H, the Z FLAG is set; otherwise the NZ FLAG is set.
5A1F
JR NZ,DSPRO3
      [5A36H]
If this is NOT the first pass, JUMP to 5A36H.
"DSPRO2"
5A21
LD A,(HL)
Top of a DJNZ loop. Fetch the character to output from (HL) into Register A.
5A22
CP 20H
Test if this is a control character by comparing it against 20H. If the character is < 20H, the CARRY FLAG will be set ...
5A24
JR C,DOT
     [5A2AH]
... and we will JUMP to 5A2AH to display a ".".
5A26
CP 7BH
Test if this is a regular character by comparing it against 7BH. If the character is < 7BH, the CARRY FLAG will be set ...
5A28
JR C,NODOT
     [5A2CH]
... and we will JUMP to 5A2AH to display the character held in Register A.
"DOT"
5A2A
LD A,2EH
Let Register A equal to a ..
"NODOT"
5A2C
CALL PDATA
     [526FH]
Outputting the character held in Register A to the screen and, if applicable, the printer, via a GOSUB to 526FH.
5A2F
INC L
Move to the next character by INCrementing the value stored in Register L by 1.
5A30
JR Z,DSPRO6
     [5A56H]
Did we move past the end of the buffer? If Register L hit 0 then we did, and so we must jump to 5A56H.
5A32
DJNZ DSPRO2
     [5A21H]
LOOP back to 5A21H for "B" characters, 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.
5A34
JR DSPRO6
   [5A56H]
Continue to the next pass by JUMPing to 5A56H.

5A36H - Output Register B number of characters in ALPHA and HEX; SECOND PASS.

"DSPRO3"
5A36
CP 02H
Check to see if this is the SECOND pass by compare the pass counter (held in Register A) against 02H. Results: If Register A equals 02H, the Z FLAG is set; otherwise the NZ FLAG is set.
5A38
JR NZ,DSPRO5
      [5A4DH]
If this is NOT the second pass, JUMP to PASS 1 at 5A4DH.
"DSPRO4"
5A3A
LD A,(HL)
Fetch the character to output from (HL) into Register A.
5A3B
5A3D
5A3F
5A41
SRL A
SRL A
SRL A
SRL A
Shift the LEFT NYBBLE (xxxx nnnn) to the RIGHT NYBBLE (0000 xxxx).
5A43
CALL HEXC
     [5293H]
Convert to ASCII and output Register A (which will be the prior LEFT NYBBLE) in HEX via a GOSUB to 5293H.
5A46
INC L
Move to the next character by INCrementing the value stored in Register L by 1.
5A47
JR Z,DSPRO6
     [5A56H]
Did we move past the end of the sector? If Register L hit 0 then we did, and so we must jump to 5A56H.
5A49
DJNZ DSPRO4
     [5A3AH]
LOOP back to 5A3AH for "B" characters, 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.
5A4B
JR DSPRO6
   [5A56H]
Continue the routine by JUMPing to 5A56H.

5A4DH - Output Register B number of characters in ALPHA and HEX; THIRD PASS.

"DSPRO5"
5A4D
LD A,(HL)
Top of a DJNZ loop. Fetch the character to output from (HL) into Register A.
5A4E
CALL HEXC
     [5293H]
Convert to ASCII and output Register A (which will be the prior LEFT NYBBLE) in HEX via a GOSUB to 5293H.
5A51
INC L
Move to the next character by INCrementing the value stored in Register L by 1.
5A52
JR Z,DSPRO6
     [5A56H]
Did we move past the end of the sector? If Register L hit 0 then we did, and so we must jump to 5A56H.
5A54
DJNZ DSPRO5
     [5A4DH]
LOOP back to 5A4DH for "B" characters, 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.

We have done the 3 passes - the letter, the left nybble, and the right nybble.

"DSPRO6"
5A56
LD A,0DH
Let Register A equal 0DH (ASCII: CARRIAGE RETURN).
5A58
CALL PDATA
     [526FH]
Output the character held in Register A to the screen and, if applicable, the printer, via a GOSUB to 526FH.
5A5B
POP DE
Put the BUFFER POINTER (held at the top of the STACK) into Register Pair DE, and then remove the entry from the stack.
5A5C
POP BC
Put the BYTE TO DISPLAY COUNT and PASS COUNTER (held at the top of the STACK) into Register Pair BC, and then remove the entry from the stack.
5A5D
DEC C
DECrement the pass counter (stored in Register C) by 1.
5A5E
JR Z,DSPRO7
     [5A63H]
If we have done all passes, JUMP to 5A63H.
5A60
EX DE,HL
Put the BUFFER POINTER to the DATA RECORD into Register Pair HL.
5A61
JR DSPRO1
   [5A1AH]
LOOP back to 5A1AH for another pass.

5A63H - Output Register B number of characters in ALPHA and HEX; after 3 passes.

"DSPRO7"
5A63
LD A,L
Copy the LSB of the BUFFER POINTER to the DATA RECORD (held in Register L) into Register A.
5A64
EX DE,HL
Reset the DATA RECORD address.
5A65
OR A
Determine if we are at the end of the sector by setting the FLAGS based on the contents of Register A (and, in all events, clear the CARRY FLAG).
"DSPRO9"
5A66
PUSH BC
Save the contents of Register Pair BC to the top of the stack.
5A67
PUSH DE
Save the contents of Register Pair DE to the top of the stack.
5A68
PUSH HL
Save the contents of Register Pair HL to the top of the stack.
5A69
PUSH AF
Save the contents of Register Pair AF to the top of the stack.
5A6A
LD B,3CH
We want to output 60 "-"'s so Let Register B equal 3CH (Decimal: 60).
"DSPROA"
5A6C
LD A,2DH
Top of a DJNZ loop. Let Register A equal 2DH (ASCII: -).
5A6E
PUSH BC
Save the dash counter (held in Register B) to the top of the stack.
5A6F
CALL PDATA
     [526FH]
Output the character held in Register A to the screen and, if applicable, the printer, via a GOSUB to 526FH.
5A72
POP BC
Put the dash counter (held at the top of the STACK) into Register Pair BC, and then remove the entry from the stack.
5A73
DJNZ DSPROA
     [5A6CH]
LOOP back to 5A6CH, 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.
5A75
LD A,0DH
Let Register A equal 0DH (ASCII: CARRIAGE RETURN).
5A77
CALL PDATA
     [526FH]
Output the character held in Register A to the screen and, if applicable, the printer, via a GOSUB to 526FH.
5A7A
LD BC,(SLWFLG)
Fetch the value held in memory location 5B08H-5B09H (which indicate if a SLOW display was requested) and store it into Register Pair BC.
5A7E
5A7E
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.
5A80
CALL NZ,0060H
        [0060H]
If 5B08H does not equal 0, meaning that the user requested a SLOW display, trigger a delay via a GOSUB to 0060H.
5A83
CALL HLDPAT
     [525FH]
Check for a shift-"@" PAUSE via a GOSUB to 525FH.
5A86
CALL 028DH
     [028DH]
GOSUB to 028DH.
NOTE: 028DH is the Model III ROM routine to CHECK FOR BREAK. On exit, the NZ FLAG will be set if BREAK was detected.
5A89
JP NZ,4030H
      [4030H]
If the BREAK was hit then the NZ FLAG (Not Zero) will have been set, JUMP to 4030H.
NOTE: 4030H is the OPERATION ABORTED routine. Routine runs, displays an error, and returns to the DOS PROMPT.
5A8C
POP AF
Put the value held at the top of the STACK into Register Pair AF, and then remove the entry from the stack.
5A8D
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
5A8E
POP DE
Put the value held at the top of the STACK into Register Pair DE, and then remove the entry from the stack.
5A8F
POP BC
Put the value held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
5A90
RET
RETurn to the caller.

5A91H - Part of the routine to output a Byte held in Register A to the Screen and, if 5277H is set to 0000H, to the Printer; JUMPED to if we have a TAB character.

"SPACIT"
5A91
LD A,(4020H)
Fetch the value held in memory location 4020H and store it into Register A.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.

The next 3 instructions are fancy math to take a screen position and determine how many spaces are needed to get to the next tab stop.

5A94
CPL
Reverse each bit in Register A (which is the same as NOT).
5A95
AND 07H
Cap Register A at a value of 8 by MASKing the value of Register A against 07H (0000 0111).
5A97
INC A
INCrement the value stored in Register A by 1 to make sure we don't have a 0.
5A98
PUSH BC
Save the contents of Register Pair BC to the top of the stack.
5A99
LD B,A
Set the tab counter by copying the contents of Register A into Register B.
"SPACI0"
5A9A
PUSH BC
Top of a DJNZ loop. Save the counter (held in Register Pair BC) to the top of the stack.
5A9B
LD A,20H
Let Register A equal 20H (ASCII: SPACE).
5A9D
CALL PDATA
     [526FH]
Output the character held in Register A to the screen and, if applicable, the printer, via a GOSUB to 526FH.
5AA0
POP BC
Restore the counter (held at the top of the STACK) into Register Pair BC, and then remove the entry from the stack.
5AA1
DJNZ SPACI0
     [5A9AH]
LOOP back to 5A9AH, 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.
5AA3
POP BC
Put the value held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
5AA4
RET
RETurn to the caller.

5AA5H - Generate the LIST header.

"PRTHED"
5AA5
PUSH BC
Save the contents of Register Pair BC to the top of the stack.
5AA6
PUSH DE
Save the contents of Register Pair DE to the top of the stack.
5AA7
PUSH HL
Save the contents of Register Pair HL to the top of the stack.
5AA8
LD HL,(4020H)
Fetch the value held in memory location 4020H and store it into Register Pair HL.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
5AAB
LD A,H
Copy the MSB of the cursor position (held in Register H) into Register A.
5AAC
CP 3CH
Check to see if the cursor is in the first quarter of the screen by comparing the value held in Register A against 3CH. NZ will be set if NOT ...
5AAE
JR NZ,PRTHE1
      [5AB9H]
... at which point we skip the next instructions and JUMP to 5AB9H.
5AB0
LD A,L
Copy the line number that the cursor is on (held in the LSB of the cursor position) into Register A.
5AB1
CP 30H
See if the cursor is after column 48 by comparing the value held in Register A against 30H (Decimal: 48). NC will be set if the column >= 48 ...
5AB3
JR NC,PRTHE1
      [5AB9H]
... and we will skip the next instructions and also JUMP to 5AB9H.
5AB5
LD DE,0040H
Set Register Pair DE to a full screen line by setting to 0040H (Decimal: 64).
5AB8
ADD HL,DE
Move the cursor one line down by adding a full screen line (held in DE) to the cursor position (held in HL).
"PRTHE1"
5AB9
PUSH HL
Save the new cursor position (held in Register Pair HL) to the top of the stack.
5ABA
LD HL,3C00H
Home the cursor by letting Register Pair HL equal 3C00H.
5ABD
LD (4020H),HL
Store the value held in Register Pair HL into memory location 4020H.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
5AC0
LD BC,(ASCFLG)
Fetch the value held in memory location 5B06H and 5B07H to see if the LIST command is to be output in ASCII and store it into Register Pair BC.
5AC3
5AC4
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.
5AC5
JR NZ,PRTH11
      [5AE1H]
If ASCII was requested, skip the display of the record number and JUMP to 5AE1H.
5AC7
LD HL,(RCNUM)
Fetch the record number (held in memory location 5B04H) and store it into Register Pair HL.
5ACA
INC HL
INCrement the value stored in Register Pair HL by 1 to correct for 1's offset.
5ACB
CALL 0A9AH
     [0A9AH]
GOSUB to 0A9AH.
NOTE: 0A9AH is the Model III ROM routine to STORE AN INTEGER. The value in HL is put into the single precision number storage area of 4121H and is flagged as an INTEGER.
5ACE
XOR A
Set Register A to ZERO and clear all Flags.
5ACF
CALL 1034H
     [1034H]
GOSUB to 1034H.
NOTE: 0A9AH is the Model III ROM routine to initializes the input buffer for an ASCII conversion.
5AD2
OR (HL)
Set the NZ Flag.
5AD3
CALL 0FD9H
     [0FD9H]
GOSUB to 0FD9H..
NOTE: 0A9AH is the Model III ROM routine to convert the integer value in REG 1 to an ASCII string. Return with register pair HL pointing to the result.
5AD6
LD HL,4131H
Let Register Pair HL equal 4131H which is where the ASCII converted text is stored.
5AD9
LD DE,RECNUM
Let Register Pair DE equal 5B3CH, to point to the message "REC = 00000".
5ADC
LD BC,0005H
Since there are 5 0's to replace, set Register Pair BC equal 0005H.
5ADF
LDIR
Replace the "00000" with the ASCII converted text via a LDIR which 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.
"PRTH11"
5AE1
LD HL,FILNAM
Let Register Pair HL equal 5B0CH to point to the filename and a TAB.
5AE4
CALL PRINTT
     [5286H]
GOSUB to 5286H which outputs a text string pointed to by Register Pair HL to the Screen and, if 5277H is set to 0000H, to the Printer as well.
5AE7
LD HL,3C20H
Position the cursor to position 32 (i.e., the middle of the screen) by setting Register Pair HL equal 3C20H.
5AEA
LD (4020H),HL
Store the value held in Register Pair HL into memory location 4020H.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
5AED
LD HL,FILLRL
Let Register Pair HL equal 5B2CH to point to "LRL = NNNN REC = NNNNN".
5AF0
CALL PRINTT
     [5286H]
GOSUB to 5286H which outputs a text string pointed to by Register Pair HL to the Screen and, if 5277H is set to 0000H, to the Printer as well.
5AF3
LD A,(LPFLAG)
Fetch the send-List-to-printer-too flag (held in memory location 5277H) and store it into Register A.
5AF6
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).
5AF7
LD A,0DH
Let Register A equal 0DH (ASCII: CARRIAGE RETURN).
5AF9
CALL NZ,003BH
        [003BH]
If the NZ FLAG (Not Zero) has been set, GOSUB to 003BH.
NOTE: 003BH is the Model III ROM routine to write the byte held in Register A to the printer, including waiting for the printer to be available OR getting a BREAK. Uses Register Pair DE.
5AFC
POP HL
Restore the cursor position (held at the top of the STACK) into Register Pair HL, and then remove the entry from the stack.
5AFD
LD (4020H),HL
Store the value held in Register Pair HL into memory location 4020H.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
5B00
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
5B01
POP DE
Put the value held at the top of the STACK into Register Pair DE, and then remove the entry from the stack.
5B02
POP BC
Put the value held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
5B03
RET
RETurn to the caller.

5B04H - "LIST" command MESSAGE and BYTE STORAGE.

"RCNUM"
5B04
DEFW 0000H
Record Number storage space during a HEX dump.
"ASCFLG"
5B06
DEFW 0000H
ASCII Format Flag
"SLWFLG"
5B08
DEFW 0000H
Slow List Flag
"DATA1"
5B0A
DEFW 0000H
NRN Storage Area.
"FILNAM"
5B0C
DEFM "FILE = "
"FILSAV"
5Bxx
DEFS 25
Enough bytes for a full filespec + 09H + 03H
"FILLRL"
5B2C
DEFM "LRL = "
"LRLSAV"
5B32
DEFM "00 " + 09H + "REC = "
"RECNUM"
5B2C
DEFM "00000" + 03H
"LRL256"
5B42
DEFM "256"
Full Sector LRL
"EOFMSG"
5B45
DEFM "EOF" + 0DH
End of Text File Message
"CR2"
5B49
DEFW 0AH 0DH
Line Feed / Carriage Return.
"DOTSTR"
5B4C
DEFM "1...5....10...15...20...25...30 ... 60" + 0DH

5B89H - "LIST" command PARAMETER TABLE.

"SWTCH1"
"AMSG"
5B89
DEFM "ASCII "
5B8F
DEFW ASCFLG
5B91
DEFM "SLOW "
5B97
DEFW SLWFLG
5B99
DEFM "PRT "
5B9F
DEFW LPFLAG
5BA1
DEFB 00H
End of Table

5BA2H - General BYTE STORAGE.

"SDCB1"
5BA2
DEFS 30H
48 byte storage location, used mostly for File Control Block storage.
"SDCB2"
5BD2
DEFS 30H
48 byte storage location, used mostly for File Control Block storage.
"BUFER1"
5D00
DEFS FFH
256 byte storage location, used mostly as a Disk I/O Buffer for SYSTEM Use.
"BUFER2"
5E00
DEFS FFH
256 byte storage location, used mostly as a Disk I/O Buffer for Program Use.

5F00H - Dummy image for a system if PURGE killed all the system files.

5F00
LD BC,0021H
Set up for a code block of 33 bytes
5F02
ORG 4D00H
Loading address will be 4D00H
5F04
(4D00H) LD A,17H
Prepare to LARGE CHARACTERS
5F06
(4D02H) CALL 0033H
Display the 17H held in Register A
5F09
(4D05H) LD HL,4D0DH
Point to "NOT A SYSTEM DISK" message
5F0C
(4D08H) CALL 021BH
Display "NOT A SYSTEM DISK" message
5F0F
(4D0BH) JR 4D0FH
Infinite Loop
5F11
(4D0DH) DEFM "NOT A SYSTEM DISK" + 0DH
5F23
02H 02H
TRANSFER ADDRESS of 2 BYTES follows
5F25
00 4DH
Execute at 4D00H