This is a disassembly of TRSDOS v2.3’s SYS6/SYS file. SYS6/SYS handles most library functions.


5200H – Entry into SYS6/SYS. Register A has the index of the library command passed to SYS6, so process

5200
LD A,C
When called, the command index has been passed in Register C. Copy that command index to Register A
5201
LD BC,402DH
Set the return address to 402DH
5204
PUSH BC
.. and save it to the Stack
5205
DEC A
For ease, the command will constantly be tested against 0, so this list is a DECrement of A, and then a JUMP if its ZERO. So … reduce A by 1
5206
If the passed command index was 1, then JUMP to 5700H for the APPEND command
5209
DEC A
Reduce A by 1 … again
520A
If the passed command index was 2, then JUMP to 5B00H for the ATTRIB command
520D
DEC A
Reduce A by 1 … again
521E
If the passed command index was 3, then JUMP to 5283H for the AUTO command
5211
DEC A
Reduce A by 1 … again
5212
If the passed command index was 4, then JUMP to 52C5H for the CLOCK command
5215
DEC A
Reduce A by 1 … again
5216
If the passed command index was 5, then JUMP to 574FH for the COPY command
5219
DEC A
Reduce A by 1 … again
521A
If the passed command index was 6, then JUMP to 529DH for the DATE command
521D
DEC A
Reduce A by 1 … again
522E
If the passed command index was 7, then JUMP to 531DH for the DEVICE command
5221
DEC A
Reduce A by 1 … again
5222
If the passed command index was 8, then JUMP to 5C6FH for the DIR command
5225
DEC A
Reduce A by 1 … again
5226
If the passed command index was 9, then JUMP to 57D7H for the DUMP command
5229
DEC A
Reduce A by 1 … again
522A
If the passed command index was 10, then JUMP to 5EE0H for the FREE command
522D
DEC A
Reduce A by 1 … again
523E
If the passed command index was 11, then JUMP to 5914H for the KILL command
5231
DEC A
Reduce A by 1 … again
5232
If the passed command index was 12, then JUMP to 533AH for the LIB command
5235
DEC A
Reduce A by 1 … again
5236
If the passed command index was 13, then JUMP to 592CH for the LIST command
5239
DEC A
Reduce A by 1 … again
523A
If the passed command index was 14, then JUMP to 5994H for the LOAD command
523D
DEC A
Reduce A by 1 … again
524E
If the passed command index was 15, then JUMP to 59ACH for the PRINT command
5241
DEC A
Reduce A by 1 … again
5242
If the passed command index was 16, then JUMP to 536AH for the PROT command
5245
DEC A
Reduce A by 1 … again
5246
If the passed command index was 17, then JUMP to 5F9CH for the RENAME command
5249
DEC A
Reduce A by 1 … again
524A
If the passed command index was 18, then JUMP to 52B1H for the TIME command
524D
DEC A
Reduce A by 1 … again
524E
If the passed command index was 19, then JUMP to 60CDH for the VERIFY command
5251
LD HL,525AH
If we are here, then we have an index which isn’t valid, so first load HL with the “RESERVED COMMAND” error message
5254
GOSUB to 4467H to display the message pointed to by HL
5257
JUMP to 4030H to go back to SYS1/SYS with an OPTION 2 set
525A
DEFM ‘RESERVED COMMAND’
‘RESERVED COMMAND’ message
526A
DEFB 0DH
Carriage Return/Message Terminator

526BH – Process a NOTHING DONE error and RETURN to DOS

526B
LD HL,5274H
load HL with the “NOTHING DONE” error message
526E
GOSUB to 4467H to display the message pointed to by HL
5271
JUMP to 4030H to go back to SYS1/SYS with an OPTION 2 set
5274
DEFM ‘NOTHING DONE’
‘NOTHING DONE’ message
5281
DEFB 2DH
‘-‘ message
5282
DEFB 0DH
Carriage Return/Message Terminator

5283H – AUTO Command.

5283
LD C,00H
Put the drive number into Register C
5285
GOSUB to 4AF0H to get the GAT table (Track 11, Sector 0) into a memory buffer at 4D00H
5288
If NZ is set, then there was an error reading the GAT, so JUMP to the general purpose Disk I/O error routine at 554CH
528B
528D
LD D,4DH
LD E,0E0H
Set up for a LDIR. The AUTO procedure is stored in the GAT memory buffer at 4DE0H, so put 4DE0H into Register Pair DE
528F
LD BC,0020H
The AUTO command has 32 characters available, so put 32 into Register Pair BC
5292
LDIR
Move 32 characters following the AUTO command from the keyboard line into the DCB buffer for the AUTO command
5294
LD C,00H
Put the drive number into Register C
5296
GOSUB to 4B03H to write the GAT table (Track 11, Sector 0) from a memory buffer at 4D00H
5299
If NZ is set, then there was an error writing the GAT, so JUMP to the general purpose Disk I/O error routine at 554CH
529C
RET
RETURN

529DH – DATE Command.

529D
LD C,’/’
Since a / is the only valid delimiter, put that into Register C
529F
GOSUB to 52EAH to process the DATE. Results are stored in 52DC-52DE
529A
If that returns a NZ, then the character provided was neither a number nor a “/”, so JUMP out to 52D3H
52A5
LD HL,52DCH
Setting up for a LDIR. If we are here, then we had a valid character (0,1,2,3,4,5,6,7,8,9,/) so set Register Pair HL to point to the address of the 3 byte date buffer (i.e. 52DCH)
52A8
LD DE,4044H
Set Register Pair DE to point to the address of the date in the system area (i.e. 4044H)
52AB
LD BC,0003H
Set Register Pair BC to 3, to move 3 bytes
52AE
LDIR
Move the first 3 bytes of the contents of 52DCH (the buffer area) to 4044H (the “date” system area)
52B0
RET
RETURN

52B1H – TIME Command.

52B1
LD C,’:’
Since a : is the only valid delimiter, put that into Register C
52B3
GOSUB to 52EAH to process the TIME. Results are stored in 52DC-52DE
52B6
If that returns a NZ, then the character provided was neither a number nor a “:”, so JUMP out to 52D3H
52B9
LD HL,52DCH
Setting up for a LDIR. If we are here, then we had a valid character (0,1,2,3,4,5,6,7,8,9,:) so set Register Pair HL to point to the address of the 3 byte time buffer (i.e. 52DCH)
52BC
LD DE,4041H
Set Register Pair DE to point to the address of the time in the system area (i.e. 4041H)
52BF
LD BC,0003H
Set Register Pair BC to 3, to move 3 bytes
52C2
LDIR
Move the first 3 bytes of the contents of 52DCH (the buffer area) to 4041H (the “time” system area)
52C4
RET
RETURN

52C5H – CLOCK Command.

52C5
GOSUB to CALL which processes ON/OFF parameters in SYS1/SYS
52C8
LD DE,4CA9H
Put the clock maintenance routine address of 4CA9H into Register Pair DE
52CB
LD A,06H
Set the index for the clock routine in the interrupt service list
52CD
If Z is set, JUMP to 4413H to remove the address from the interrupt service list (i.e., turn OFF the clock)
52D0
Otherwise, add the address to the interrupt service list (i.e., turn ON the clock)

Subroutine inside DATE and TIME Routines: Little routine which is called from DATE or TIME when a bad character was provided

52D3
LD HL,52DFH
Point Register Pair HL to the ‘BAD FORMAT’ message (stored at 52DFH)
52D6
GOSUB to 4467H to display the message pointed to by HL
52D9
JUMP back to SYS1/SYS to get the next command

Subroutine inside DATE and TIME Routines: Date Time Storage Area

52DC
52DD
52DE
DEFB 0
DEFB 0
DEFB 0
Set up a 3 byte storage area (used for TIME and DATE functions)

Subroutine inside DATE and TIME Routines: Location of the “BAD FORMAT” error mesage

52DF
DEFM ‘BAD FORMAT’
“BAD FORMAT” error mesage
52E9
DEFB 0DH
Carriage Return/Message Terminator

Subroutine inside DATE and TIME Routines: Process the DATE/TIME

52EA
LD DE,52DEH
Put the end of the 3 byte storage area (i.e., 52DEH) nto Register Pair DE
52ED
LD B,03H
Set Register B to the number of fields (i.e., 3) to process
52EF
PUSH DE
Save the storage area address held in Register Pair DE to the stack
52F0
GOSUB to 52FFH to process the next field, which must be 2 digits
52F3
POP DE
Restore the storage area address to Register Pair DE from the stack
52F4
RET NZ
If there was an error in the field (i.e., a non-numeric answer or a non-approved delimeter), then exit
52F5
LD (DE),A
If we are here, then we have a valid character, so load it into the memory buffer pointed to by DE
52F6
DEC DE
Decrement DE by to the prior byte in the buffer
52F7
DEC B
Decrement the counter of the number of fields to process
52F8
RET Z
If Z is set then the number of fields to process (held in Register B) is zero, so RETURN
52F9
LD A,(HL)
If we are here, then we have more fields to process, so put the separator into Register A
52FA
INC HL
Bump Register Pair HL to point to the next character
52FB
CP C
Compare the separator found with the valid separator (either “:” or “/” depending on which routine called this routine)
52FC
If it is a legitimate separator, then LOOP back to 52EFH to keep processing
52FE
RET
If we are here, then we had an illegitimate separator, so RETURN to caller

Subroutine inside DATE and TIME Routines: This routine was called from the prior routine to parse 2 characters

52FF
GOSUB to 5316H to get the next character from the command string
5302
If the NC flag is set, then we have an alpha character, which is bad, so JUMP to 5314H
5304
LD E,A
If we are here, then we have a valid character, so put it into Register E for safe keeping
5305
5306
5307
5308
RLCA
RLCA
ADD A,E
RLCA
Multiply A by 10 so that it can be added to the next digit (i.e., a “2” and then a “3” would be need to be “20” + “3”, so convert the 2 to 20)
5309
LD E,A
Put the digit * 10 into Register E
530A
GOSUB to 5316H to get the next character from the command string
530D
If the NC flag is set, then we have an alpha character, which is bad, so JUMP to 5314H
530F
ADD A,E
Combine the new digit with the old digit
5310
LD E,A
Put the combined decimal digit into Register E
5311
XOR A
Clear all the flags to indicate no error
5312
LD A,E
Put the combined decimal digit into Register A
5313
RET
RETURN to caller

Subroutine inside DATE and TIME Routines: If we are here, then there was an alphabetic character when taking in the DATE and TIME

5314
OR A
Set the NZ flag
5315
RET
RETURN

Subroutine inside DATE and TIME Routines: This routine gets the next character from the command string

5316
LD A,(HL)
Fetch the character pointed to by HL into Register A
5317
INC HL
Bump HL to point to the next character
5318
SUB ‘0’
Convert the ASCII digit to binary
531A
CP 0AH
Test to that converted character against 0AH, and set flags accordingly
531C
RET
RETURN

531DH – DEVICE Command.

531D
LD HL,43C0H
Set Register Pair HL to point to the device table, held at 43C0H
5320
LD A,(HL)
Get the first ASCII character of the device type from the table pointed to by HL
5321
INC L
Bump Register L to point to the second ASCII character in the device type
5322
OR A
Check to see if we have reached the end of the list
5323
If we have reached the end of the list, JUMP to 5337H
5325
If we are here, then we have not reached the end of the list, so GOSUB to 0033H in the ROM to display the first ASCII character of the device type
5328
LD A,(HL)
Get the second ASCII character of the device type from the table pointed to by HL
5329
GOSUB to 0033H in the ROM to display the second ASCII character of the device type
532C
LD A,0DH
Put a carriage return into Register A for displaying
532E
GOSUB to 0033H in the ROM to display the carriage return
5331
LD A,L
Put the LSB of the device table into Register A
5332
ADD A,03H
Bump Register A by 3 to skip over the driver address and move to the next entry
5334
LD L,A
Put that next entry into Register L
5335
If NC is set then we have reached the end of the list, (i.e., 43CFH) to JUMP to 5320H
5337
If we are here, then we are not at the end of the list, so JUMP to SYS1/SYS

533AH – LIB Command.

533A
LD HL,4EBDH
Set Register Pair HL to point to the address of the second command list in SYS1/SYS
533D
LD C,04H
Set Register C to 4 to represent how many commands will be displayed per line
533F
LD A,0C2H
Set Register A to the compression code for ” “
5341
GOSUB to 0033H in the ROM to display the ” “
5344
LD B,06H
Set Register B to the maximum number of characters for each LIBrary command (i.e., 6)
5346
LD A,(HL)
Get a character from the command list (pointed to by HL) and put it into Register A for processing
5347
INC HL
BUMP HL to point to the next character in the command list
5348
GOSUB to 0033H in the ROM to display the character from the command list
534B
LOOP back to 5346H until all characters have been displayed
534D
LD A,0C8H
Set Register A to the compression code for 8 spaces
534F
GOSUB to 0033H in the ROM to display the 8 spaces
5352
5353
INC HL
INC HL
BUMP HL to skip over the associated address for the routine
5354
LD A,(HL)
Put the first character of the next command into Register A
5355
OR A
Set the status for end of list
5356
If we are at the end of the list then JUMP down to 5362H to put up a carriage return and then exit
5358
DEC C
DECremenet C by 1 for each command line already displayed
5359
If C is NOT ZERO, then we haven’t filled the line yet, so JUMP back to 5344H to keep going
535B
LD A,0DH
If we are here, then we need to move to a new line, so Load Register A with a carriage return
535D
GOSUB to 0033H in the ROM to display the carriage return
5360
LOOP back to 533DH to reset the number of commands per line to 4 and process the next commands
5362
LD A,0DH
Load Register A with a carriage return
5364
GOSUB to 0033H in the ROM to display the carriage return
5368
JUMP back to SYS1/SYS for the next command

536AH – PROT Command.

536A
LD A,(430FH)
Put the system condition/permission flag (held at 430FH) into Register A for processing
536D
BIT 5,A
Test bit 5 of the system condition/permission flag to see if the PROT command is allowed
536F
If NZ is set, then the PROT command is not allowed, so JUMP to 546EH to display the INVALID COMMAND DURING PROGRAM CHAINING message
5372
LD BC,0000H
If we are here, then it is allowed, so set BC to 00 so we can set all the associated flags to 00
5375
LD (53D9H),BC
Set the PASSWORD flag to 00
5379
LD (53F9H),BC
Set the LOCK flag to 00
537D
LD (5403H),BC
Set the UNLOCK flag to 00
5381
LD C,00H
Put the default drive number (i.e., “0”) into Register C
5383
LD A,(HL)
Get the first character following the PROT command, pointed to by HL
5384
CP ‘:’
Check that character to see if it is a “:”. If there is one, then we will need to fetch a drive spec. If not, we already have Register C set to 0 as the default
5386
If there is no “:” then there is no drive spec to be read, so skip over the drive spec read code
5388
INC HL
Bump HL to point to the character after the “:” on the command line
5389
LD A,(HL)
Put that character into Register A
538A
SUB ‘0’
Subtract from “0” to convert to binary
538C
LD C,A
Put the binary value of the drive number into Register C
538D
INC HL
BUMP HL to point to the next character on the line
538E
LD A,C
Put the drive number from Register C into Register A for processing
538F
LD (53BCH),A
Put the drive number into 53BCH
5392
LD DE,54EBH
Set Register Pair DE to 54EBH, which is the address of the PASSWORD/LOCK/UNLOCK options
5395
GOSUB to 4476H in SYS1 to compare the rest of the command line to the option list pointed to by DE
5398
LD A,(53D9H)
Put the PASSWORD Flag (stored in 53D9H) into Register A
539B
LD HL,53F9H
Set HL to point to the LOCK flag
539E
OR (HL)
Combine the Password and Lock test results
539F
LD HL,5403H
Set HL to point to the UNLOCK flag
53A2
OR (HL)
Combine the Password/LOCK/UNLOCK test results
53A3
If the Z flag is set from that prior OR, then there was no PASSWORD/LOCK/UNLOCK specified, so JUMP to 536BH
53A6
LD A,03H
If we are here, then we have an illegal character, so set Register A to an illegal character code of 03H
53A8
LD DE,5551H
Put the local DCB address (i.e., 5551H) into Register DE
53AB
LD (DE),A
Put the illegal character into the DCB so that OPEN will return immediately
53AC
GOSUB to 4424H to open the dummy file, which will load SYS2/SYS into 4E00H
53AF
LD HL,54A0H
Point HL to the MASTER PASSWORD? message
53B2
GOSUB to 4467H to display the message pointed to by HL
53B5
GOSUB to 5454H to read the password from the keyboard
53B8
LD (5168H),HL
Save the encoded version of the password (held in HL following that call) into 5168H
53BB
LD C,00H
Set the default drive number to read into Register C (i.e. 0)
53BD
GOSUB to 4AF0H to get the GAT table (Track 11, Sector 0) into a memory buffer at 4D00H
53C0
If NZ is set, there was an error reading the GAT table from Disk into Memory so JUMP to the general purpose Disk I/O error routine at 554CH
53C3
LD HL,(4DCEH)
If we are here, the GAT table was successfully read into 4D00H so put the address of the password from the buffer into Register Pair HL
53C6
LD DE,(5168H)
Put the new password (held in the SYS2 storage area) into Register Pair DE
53CA
XOR A
Clear the carry flag
53CB
SBC HL,DE
Subtract with carry the encoded password from disk and the new encoded password
53CD
If the Z flag is set, they are the same, so JUMP to 53D8H
53CF
LD HL,54D2H
If we are here, then they are not the same, so we need to report an error. Set HL to point to the “INVALID MASTER PASSWORD” error at 54D2H
53D2
GOSUB to 4467H to display the message pointed to by HL
53D5
JUMP back to SYS1/SYS to get the next command

Subroutine inside PROT Routine: This is the jump point if the master passwords matched

53D8
LD DE,0000H
Get the SYS1 flag for a PASSWORD option. Yes, the command is just a LD DE with zero, but later routines save data to 53D9-53DA which are the 2 bytes filled by 0000. It will ultimately be FFFFH if PASSWORD was specified
53DB
53DC
LD A,D
OR E
Check DE against 0
53DD
If DE is zero, then the PASSWORD option was not selected, so JUMP to 53F5H
53DF
LD HL,54B9H
IF we are here, then the PASSWORD option was selected, so point HL to the address of the “NEW MASTER PASSWORD?” message
53E2
GOSUB to 4467H to display the message pointed to by HL
53E5
GOSUB to 5454H to put the reply (the new password) into the buffer at 5600H
53E8
LD (4DCEH),HL
Put the new password hash into the GAT sector buffer
53EB
LD A,(53BCH)
Put the drive number into Register A
53EE
LD C,A
… and then Register C
53EF
GOSUB to 4B03H to write the GAT sector buffer to diskette
53F2
If NZ is set, then there was an error writing the GAT sector to diskette so JUMP to the general purpose Disk I/O error routine at 554CH
53F5
LD HL,(4DCEH)
If we are here, then the GAT sector with the new password was successfully written to disk, so next we put the hash of the password into HL
53F8
LD DE,0000H
Get the SYS1 flag for a LOCK option. Yes, the command is just a LD DE with zero, but later routines save data to 53F9-53FA which are the 2 bytes filled by 0000. It will ultimately be FFFFH if LOCK was specified
53FB
53FC
LD A,D
OR E
Check DE against 0
53FD
If NZ is set, then LOCK was specified, so JUMP to 540CH to deal with that
53FF
LD HL,4296H
If we are here, then LOCK was not specified, so point HL to the routine for hashing the UNIVERSAL password
5402
LD DE,0000H
Get the SYS1 flag for a UNLOCK option. Yes, the command is just a LD DE with zero, but later routines save data to 5403-5404 which are the 2 bytes filled by 0000. It will ultimately be FFFFH if UNLOCK was specified
5405
5406
LD A,D
OR E
Check DE against 0
5407
If NZ is set, then UNLOCK was specified, so JUMP to 540CH to deal with that
5409
If we are here, then none of PASSWORD, LOCK, or UNLOCK were set, so JUMP back to SYS1/SYS for the next command

Subroutine inside PROT Routine: This is the jump point if the LOCK was specified

540C
LD (5430H),HL
Put the LOCK/UNLOCK password hash into 5430H (which is the 0000H of a LD DE,0000H command below)
540F
5412
LD A,(54BCH)
LD C,A
Fetch the drive number from 54BCH and put it into Register C
5413
GOSUB to 4B55H to get the director track number for the disk drive pointed to by Register C
5416
LD E,02H
We are going to need to read sector 2, so put a 2 into Register E
5418
LD HL,4200H
Put the destination buffer of 4200H into HL
541B
GOSUB to 4B35H to read track 11, sector 2 into a buffer at 4200H
541E
If NZ is set, then there was an error reading track 11, sector 2 so JUMP to the general purpose Disk I/O error routine at 554CH
5421
LD L,40H
We need to start to form the address of the third entry in the directory. Directory entries start at 00, 20, 40, 60, 80, A0, C0, and E0
5423
LD A,(HL)
Get the entry available/assigned byte from the buffer
5424
AND 0F8H
Mask Register A against 11111000 to keep only bits 3-7, signifying the available/assigned list value
5426
CP 10H
Compare the available/assigned list value against 10H to see if the entry is available
5428
If NZ is set, the entry was already assigned so we cannot use it. JUMP to 543AH
542A
LD A,L
If we are here, then we have found an unassigned entry, so get the LSB of the entry address
542B
ADD A,10H
Add 10H to that to get to the UPDATE password
542D
LD L,A
Put the location of the UPDATE password into Register L so Register Pair HL points to it
542E
PUSH DE
Save the track/sector number held in DE to the stack
542F
LD DE,0000H
Put the master password into Register Pair DE. Yes, the command is just a LD DE with zero, but 540CH, above, put HL into 5430-5431 which are the 2 bytes filled by 0000
5432
LD (HL),E
Put the LSB of the master password held in DE by virtue of 540C putting it there, into (HL) which is pointing to the LSB of the UPDATE password
5433
INC L
BUMP Register L to point to the next byte (the MSB of the UPDATE password)
5434
LD (HL),D
Put the MSB of the master password held in DE by virtue of 540C putting it there, into (HL) which is pointing to the MSB of the UPDATE password
5435
INC L
BUMP Register L to point to the next byte (the LSB of the ACCESS password)
5436
LD (HL),E
Put the LSB of the master password held in DE by virtue of 540C putting it there, into (HL) which is pointing to the LSB of the ACCESS password
5437
INC L
BUMP Register L to point to the next byte (the MSB of the ACCESS password)
5438
LD (HL),D
Put the MSB of the master password held in DE by virtue of 540C putting it there, into (HL) which is pointing to the MSB of the ACCESS password
5439
POP DE
Restore the track/sector number from the stack back into DE
543A
LD A,L
Prepare to move to the next entry by putting L into A
543B
AND 0E0H
Mask A against 1110 0000 to isolate the bits necessary to test if the end of sector has been reached
543D
ADD A,20H
Add 20H, which is a jump to the next entry, to the masked Register A
543F
LD L,A
Put that into Register L so that HL points to the next entry
5440
If NC is set, then we have not yet reached the end of the buffer, so LOOP back to 5423H
5442
LD HL,4200H
If we are here, then the end of the buffer was reached, so reform the buffer address in HL to 4200H
5445
GOSUB to 46EFH to write the updated sector back to diskette
5448
If NZ is set, then the write failed, so JUMP to the general purpose Disk I/O error routine at 554CH
544B
INC E
If we are here, then the write succeeded so BUMP Register E to point to the next sector
544C
LD A,E
Put that address into Register A for processing
544D
CP 0AH
Compare the available/assigned list value against 10H to see if we are at the end of the track
544F
If the CARRY FLAG is set, then we are not yet at the end of the track so JUMP back to 5418H
5451
If we are here, then we are at the end of the track, so jump back to SYS1/SYS for the next command

Subroutine inside the PROT routine to read the password from the keyboard

5454
LD B,08H
Set Register B to the maximum number of characters a password can have (i.e., 8)
5456
LD HL,5600H
Point Register Pair HL to the buffer at 5600H
5459
GOSUB to 0040H in the ROM to read user input with a wait
545C
EX DE,HL
Put the contents of HL into DE
545D
545F
LD H,00H
LD L,B
Set HL equal to the number of characters actually read from the keyboard
5460
ADD HL,DE
Calculate the end of the date in the buffer
5461
5463
5464
LD A,08H
SUB B
LD B,A
Then compute the number of bytes remaining in the buffer and then save it as a counter
5465
LD A,’ ‘
Since we need 8 characters, we have to fill the rest with blanks, so set Register A as a ” “
5467
LD (HL),A
Put the blank into the buffer
5468
INC HL
BUMP HL to the next space in the buffer
5469
LOOP back until 8 characters are there
546B
JUMP to the SYS2/SYS routine to hash a password

Subroutine inside the PROT routine to display the INVALID COMMAND DURING PROGRAM CHAINING message

546E
LD HL,5477H
Point HL to the INVALID COMMAND DURING PROGRAM CHAINING message
5471
GOSUB to 4467H to display the message pointed to by HL
5474
JUMP back to SYS1/SYS to get the next command

Subroutine inside the PROT routine to hold messages

5477
DEFB 0AH
Line Feed
5478
DEFM ‘INVALID COMMAND DURING PROGRAM CHAINING’
549F
DEFB 0DH
Carriage Return
54A0
DEFB 0AH
Line Feed
54A1
DEFM ‘MASTER PASSWORD? ‘
54B8
DEFB 03H
Message Terminator
54B9
DEFB 0AH
Line Feed
54BA
DEFM ‘NEW MASTER PASSWORD? ‘
54D1
DEFB 03H
Message Terminator
54D2
DEFM ‘INVALID MASTER PASSWORD’
54EA
DEFB 0DH
Carriage Return / Message Terminator

Subroutine inside the PROT routine to hold PROT parameters

54EB
DEFM ‘PW ‘
54F1
DEFW 53D9H
Address for the PW routine
54F3
DEFM ‘LOCK ‘
54F9
DEFB 53F9H
Address for the LOCK routine
54FB
DEFM ‘UNLOCK’
5501
DEFW 5403H
Address for the UNLOCK routine
5503
DEFB 00H
Text string terminator

5504H – VERIFY Command.

5504
GOSUB to the SYS1/SYS routine to check for ON/OFF
5507
LD HL,478BH
Point HL to the verify flag
550A
If Z is set, then we need VERIFY (OFF), so skip the next OPCODE and leave HL holding 478BH
550C
LD HL,47A8H
If we are here, then we need to process VERIFY (ON), so Point HL to the WRITE jump vector instead of 478BH
550F
LD (443AH),HL
Point the address of the VERIFY routine to the WRITE jump vector
5512
JUMP back to SYS1/SYS for the next command

5515H – General purpose subroutine to read the keyboard and test for SHIFT-@. If found, pause until another key is struck. But there’s more! For routines to also test for BREAK, Bit 5 is used. If Bit 5 is set in 430FH (the system condition flag), then test for BREAK and if found then return NZ. If no BREAK is found, then check the keyboard and if SHIFT-@ is not found, set Z. If Shift-@ is found, loop until we get a new key, and return NZ if break is active and Z if any other key is active.

5515
LD A,(430FH)
Read the system condition flag into Register A
5518
AND 20H
AND the system condition flag against 0010 0000 to isolate ONLY bit 5
551A
XOR 20H
XOR that masked Register A against 20H to test if the BREAK test flag is on
551C
RET Z
If the BREAK test flag is not active, then RETURN to caller
551D
LD A,(3840H)
If we are here, then the BREAK test flag is active, so we have to do a lot of processing. First poll the keyboard row with the BREAK key (i.e., 3840H) and put the results into Register A
5520
AND 04H
Mask the BREAK key row of the keyboard against 0000 0100 to isolate only the BREAK key
5522
RET NZ
If NZ is set, then the BREAK key is active, so RETURN
5523
If we are here then the BREAK key is not active, so GOSUB to 002BH in the ROM ($KBCHAR) to check the keyboard. That routine will return A with either the ASCII value of the key pressed or 00H if no key was pressed
5526
CP 60H
Test the keyboard strobe for SHIFT-@
5528
IF Z is set then SHIFT-@ was found, so JUMP to 552CH to process
552A
XOR A
Clear all flags so as to signal no activity
552B
RET
RETURN to caller

552CH – Subroutine in the General purpose subroutine to read the keyboard and test for SHIFT-@. If we are here, SHIFT-@ was found.

552C
LD A,(3840H)
Poll the keyboard row with the BREAK key (i.e., 3840H) and put the results into Register A
552F
AND 04H
Mask the BREAK key row of the keyboard against 0000 0100 to isolate only the BREAK key
5531
RET NZ
If NZ is set, then the BREAK key is active, so RETURN
5532
If we are here then the BREAK key is not active, so GOSUB to 002BH in the ROM ($KBCHAR) to check the keyboard. That routine will return A with either the ASCII value of the key pressed or 00H if no key was pressed
5535
OR A
Set the status flags for input
5536
LOOP back to 552CH
5538
XOR A
If we are here, then any key other than a BREAK was hit, so zero out the status bits
5539
RET
RETURN

553AH – Routine to display FILE SPEC REQUIRED error message and return to DOS.

553A
LD HL,5591H
Point HL to the “FILE SPEC REQUIRED” error message
553D
GOSUB to 4467H to display the message pointed to by HL
5540
JUMP back to SYS1/SYS to get the next command

5542H – Routine to display FILE SPEC REQUIRED error message and return to DOS

5543
LD HL,55A5H
Point HL to the “DEVICE SPEC REQUIRED” error message
5546
GOSUB to 4467H to display the message pointed to by HL
5549
JUMP back to SYS1/SYS to get the next command

554CH – General purpose subroutine for when a disk write (GAT/HIT) fails.

554C
OR 40H
Turn on the FILE ERROR bit in the error code held in Register A
554E
JUMP to 4409H in SYS4/SYS to display the error message

5551H – Message Storage Area

5551
DEFS 20H
Local DCB
5591
DEFB 0AH
Line Feed Character
5592
DEFM ‘FILE SPEC REQUIRED’
55A4
DEFB 0DH
Carriage Return / Message Terminator
55A5
DEFB 0AH
Line Feed Character
55A6
DEFM ‘DEVICE SPEC REQUIRED’
55BA
DEFB 0DH
Carriage Return / Message Terminator

5700H – APPEND Command (Part 1). This command puts file1 at the end of file2. Filename 1 is stored at 5551H and Filename 2 is stored at 5571H

5700
LD DE,5551H
Point DE to the local DCB area where the first filename will be stored
5703
GOSUB to 441CH to copy/edit a filename into DCB (SYSl, Code 4). This validates the filename, puts it into 5551H+, and returns NZ if there are illegal characters
5706
If NZ is set, we did not get a filename, but we did need one, so JUMP back to 553AH to display the FILE SPEC REQUIRED error message
5709
LD A,(DE)
If we are here, then we did get a filename, so fetch the current filename character and put it into Register A for processing
570A
CP ‘*’
Test for a “*” which would signify a special file
570C
If a “* was found, then JUMP to 553AH to display the FILE SPEC REQUIRED error message
570F
LD DE,5571H
Address of 2nd local DCB area where the second filename will be stored
5712
GOSUB to 441CH to copy/edit file into DCB (SYSl, Code 4). This validates the filename, puts it into 5571H+, and returns NZ if there are illegal characters
5715
If NZ is set, we did not get a filename, but we did need one, so JUMP back to 553AH to display the FILE SPEC REQUIRED error message
5718
LD A,(DE)
If we are here, then we did get a filename, so fetch the current filename character and put it into Register A for processing
5719
CP ‘*’
Test for a “*” which would signify a special file
571B
If a “* was found, then JUMP to 553AH to display the FILE SPEC REQUIRED error message
571E
LD B,00H
If we are here, then we have 2 good filenames. Set up some flags for I/O, starting with Register B saying that PHYSICAL I/O is required
5720
LD HL,5600H
Set a buffer for the 1st file, and hold in HL
5723
GOSUB to 4424H to open the 1st file
5726
If NZ is set, there was an error opening the file, so JUMP to the general purpose Disk I/O error routine at 554CH
5729
LD B,00H
If we are here, then the 1st file opened OK, so set up some flags for I/O, starting with Register B saying that PHYSICAL I/O is required
572B
LD DE,5551H
Point DE to the local DCB area where the first filename will be stored
572E
LD HL,6F00H
Set up a buffer at 6F00H to hold the first file
5731
GOSUB to 4424H to open the second file
5734
If NZ is set, there was an error opening the second file, so JUMP to the general purpose Disk I/O error routine at 554CH
5737
LD DE,5571H
DCB address for 2nd file
573A
GOSUB to 4448H to skip to end of file on 2nd file
573D
NOP
573E
NOP
573F
NOP
5740
NOP
5741
NOP
5742
NOP
5743
NOP
5744
NOP
5745
NOP
5746
NOP
5747
NOP
5748
NOP
5749
NOP
574A
NOP
574B
NOP
574C
JUMP to 57B6H to copy file 1 onto end of file 2. Why? Looks like APPEND was an after-thought and they needed to patch it in, so it is broken into 2 parts

574FH – COPY Command.

574F
LD DE,5551H
Point DE to the local DCB area of the first filename
5752
GOSUB to 441CH in SYSl (Entry Code 4) to copy/edit the first file filename. This routine also validates the filname and returns NZ if the filename is bad
5755
If the filename is bad, JUMP to 553AH to error out
5758
LD DE,5571H
Set DE to point to the local DCB area of the second filename
575B
GOSUB to 441CH in SYSl (Entry Code 4) to copy/edit the second file filename. This routine also validates the filname and returns NZ if the filename is bad
575E
If the filename is bad, JUMP to 553AH to error out
5761
LD B,00H
Set Register B to flag that physical I/O is needed for the source file
5763
LD DE,5551H
Point DE to the local DCB area of the first filename
5766
LD HL,5600H
Point HL to a buffer to use
5769
GOSUB to 4424H to open the source file
576C
If NZ is set then there was an error in opening the source file, so JUMP to the general purpose Disk I/O error routine at 554CH
576F
LD B,00H
If we are here, then the first file opened fine, so Set Register B to flag that physical I/O is needed for the destination file
5771
LD DE,5571H
Point DE to the local DCB area of the destination filename
5774
LD HL,5600H
Point HL to a buffer at 5600H
5777
GOSUB to 4420H to run an INIT call for the destination file
577A
If NZ is returned, there was an error in the processing of the INIT on the destination file, so JUMP to JUMP to the general purpose Disk I/O error routine at 554CH
577D
LD DE,5551H
Point DE to the local DCB area of the first (source) filename
5780
GOSUB to 4436H to read a sector from the source file
5783
IF Z is set, then there was no error, so JUMP to 5790H to continue processing
5785
CP 1CH
If we are here then we have an error, but we need to see what happened. First, test for EOF on source file
5787
If Z is set, then we hit the EOF, so JUMP to 57A1H
5789
CP 1DH
If we are here, we have an error, and it isn’t EOF, so now test for RECORD NOT FOUND
578B
If Z is set, then we have a RECORD NOT FOUND error, so JUMP to 479BH to deal with that
578D
If we are here then we have an error, and it wasn’t EOF and it wasn’t RECORD NOT FOUND, so JUMP to JUMP to the general purpose Disk I/O error routine at 554CH
5790
LD DE,5571H
If there was no problem on the INIT of the destination file, 5783H jumped here so let’s continue by pointing DE to the local DCB area of the second filename
5793
GOSUB to 4439H to write the sector which was just read into the DESTINATION file (pointed to by DE)
5796
If Z is set, then there was no error, so loop back to 577DH until we are done
5798
If we are here then there was an error, so JUMP to the general purpose Disk I/O error routine at 554CH

579BH – Subroutine in the COPY command. This routine is called when we have a RECORD NOT FOUND error

579B
LD HL,(5559H)
Get the record number at issue from the source DCB and put it into Register Pair HL
579E
LD (5579H),HL
Put that record into the destination DCB
57Al
LD DE,557lH
Point DE to the local DCB area of the destination filename
57A4
GOSUB to 4428H to CLOSE the destination file
57A7
If NZ is set then there was an error closing the destination file, so JUMP to the general purpose Disk I/O error routine at 554CH
57AA
LD DE,5551H
Point DE to the local DCB area of the first filename
57AD
GOSUB to 4428H to CLOSE the source file
5780
If NZ is set then there was an error closing the source file, so JUMP to the general purpose Disk I/O error routine at 554CH
5783
Return to SYSl wait for next command

57B6H – APPEND Command (Part 2).

57B6
LD DE,555lH
Point DE to the local DCB area of the first filename
57B9
GOSUB to 0013H of the ROM to read a character from 1st file
57BC
If Z is set then there was no error, so JUMP to 57C5H
57BE
CP 1CH
If we are here, then there was an error reading the character from the first file, so we need to see what it was. First check against 1CH to see if it was an END OF FILE
57C0
If Z is set, then we hit the EOF on the source file so JUMP to 57AlH of the copy command to close the files and return to DOS
57C2
If we are here, then we have an error but it wasn’t EOF, so JUMP to the general purpose Disk I/O error routine at 554CH
57C5
LD B,A
Save the current character in Register B so we can use Register A
57C6
GOSUB to 5515H to read the keyboard and test for SHIFT-@
57C9
If that routine returns NZ then the BREAK key is active, so abort the APPEND
57CB
LD A,B
Now that we finished testing for a BREAK, put the character back into Register A to continue
57CC
LD DE,557lH
Point DE to the local DCB area of the second filename
57CF
GOSUB to 001BH of the ROM to write the character held in Register A to DE (i.e., the second file)
57D2
If NZ is set, then we had an error while writing, so JUMP to the general purpose Disk I/O error routine at 554CH
57D5
Otherwise, LOOP back to the start of this Part 2 until we hit the EOF on source file

57D7H – DUMP Command.

57D7
LD BC,7000H
Default START address DUMP
57DA
LD (5868H),BC
Initialize START address location
57DE
LD (586EH),BC
Initialize END address location
57E2
LD BC,402DH
Set the default TRANSFER address
57E5
LD (58ABH),BC
Initialize the TRANSFER address location
57E9
LD DE,5551H
Point DE to the local DCB area
57EC
GOSUB to 441CH to copy/edit a filename into the DCB (SYSl, Code 4). This validates the filename, puts it into 5551H+, and returns NZ if there are illegal characters
57EF
If NZ is returned, the filename is bad so JUMP to 553AH to deal with that
57F2
LD A,(DE)
If there is no error in the filename, then start the process to test for a special character by putting (DE) into A
57F3
CP “*”
Compare that character with a “*”
57F5
If “*” is found, then JUMP to 553AH
57F8
LD DE,58F5H
If we are here, then we have a good filename! So set DE to the address of START text
57FB
GOSUB to 4476H (SYSl/SYS, Code 6) to search for the word START
57FE
LD DE,590EH
Point DE to a local buffer
5801
LD HL,5551H
Point HL to the local DCB area
5804
LD B,06H
We need to set up for a DJNZ loop of 6 characters. First, set Register B with the maximum number of chars to copy
5806
LD A,(HL)
Get a character from the file name
5807
CP 30H
Test for special character (end of file name)
5809
If the CARRY FLAG is set, then we have the end of the filename, so JUMP to 581EH
5808
CP 3AH
Test the character for numeric 0-9
580D
If the CARRY FLAG is set, then we have 0-9, so JUMP to 5817H to continue the COPY
580F
CP 41H
Test for special char 3A-3F
58ll
If the CARRY FLAG is set then we have 3A-3F, so JUMP to 581EH and end the COPY
5813
CP 5BH
Test for upper case letters
5815
If the CARRY FLAG is NOT set, then upper case was found, so JUMP to 581EH and end the COPY
5817
LD (DE),A
If we are here, then we have characters between A-Z and 0-9, so lets get to work. First, put cthe character into the local buffer pointed to be DE
5818
INC HL
Short list (590E) then bump
5819
INC DE
Fetch and stare address
581A
Loop till 6 chars copied or end of name found
58lC
If we are here, then 6 characters were copied, so JUMP to 5824H to skip the blank file

581EH – Subroutine in the DUMP command. This routine is called if less than 6 characters and we need to fill in blanks

581E
LD A,20H
Put an ASCII blank into Register Ato fill short list
5820
LD (DE),A
Put the blank where (DE) is pointing
5821
INC DE
Bump DE to point to the next character
5822
Loop back to 581EH until the 6 char name blanked
5824
LD DE,5551H
Point DE to the local DCB area for the DUMP file
5827
LD HL,58F2H
Point HL to the address of CIM
582A
GOSUB to 4473H (SYS1/SYS, Code 5) to add the message pointed to in HL (i.e., add the CIM extension)
582D
LD B,00H
Set Register B to flag that physical I/O is needed for the destination file
582F
LD HL,5600H
Point Register Pair HL to the buffer at 5600H
5832
GOSUB to 4420H to run an INIT call for the file
5835
If NZ is returned, there was an error in the processing of the INIT on the destination file, so JUMP to the general purpose Disk I/O error routine at 554CH
5838
LD A,05H
Put the control code for file name into Register A
583A
GOSUB to 001BH of the ROM to write the character held in Register A to the disk file
583D
LD A,06H
Put the number of characters in the filename in Register A
583F
GOSUB to 001BH of the ROM to write the character held in Register A to the disk file
5842
LD B,06H
Set up for a DJNZ loop. Put the number of characters in the filename in Register B
5844
LD HL,590EH
Point HL to the buffer holding the filename
5847
LD A,(HL)
Put a character from the filename buffer into Register A
5848
INC HL
BUMP HL to the next character in the filename buffer
5849
GOSUB to 001BH of the ROM to write the character held in Register A to the disk file
584C
Loop until the full 6 character filename has been written
584E
LD HL,(586EH)
Load the END address given in DUMP command into HL
5851
LD BC,(5868H)
Load the START address given in DUMP command into BC
5855
XOR A
Clear the CARRY FLAG because we about to use it
5856
SBC HL,BC
Subtract the START ADDRESS from the END ADDRESS
5858
LD HL,58C4H
Point HL to the END LESS THAN START error message
5858
If the subtraction triggered the CARRY FLAG, then the END ADDRESS was less than the START ADDRESS, so JUMP to 58BEH to error our
585D
LD HL,6FFFH
We need to test for a START address over 7000H so put 6FFFH into Register Pair HL
5860
SBC HL,BC
Compute 7000 minus START address
5862
LD HL,58D9H
Point HL to the START LESS THAN 7000 error message
5865
If NC is set, then the START is less than 7000, so JUMP to 58BEH to error out
5867
LD HL,0000H
Set HL to the START ADDRESS. 5868-5869 will be filled in by SYS1/SYS at 57FBH
586A
PUSH HL
Save current START address to the stack
5868
586C
LD B,H
LD C,L
BC=HL
586D
LD HL,0000H
Set HL to the END ADDRESS. 586E-586F will be filled in by SYS1/SYS at 57FBH
5870
INC HL
BUMP HL by 1 so that the END address has the true byte count
5871
XOR A
Clear the CARRY FLAG because we are about to use it
5872
SBC HL,BC
Calculate the number of bytes which need to be written by subtracting the START and END + 1
5874
If Z is set, then we are done copying, so JUMP out to 589FH
5876
LD B,0FEH
If we are here, then we are not done, and need to break the transfer into 254 byte blocks (as the maximum bytes between control codes), so set Register B to 254
5878
LD A,H
Test byte count for transfer
5879
OR A
Get status for upper 8 bits
587A
If the transfer count > 255, JUMP down to 5882H
587C
LD A,L
If we are here then the transfer count is NOT > 255, so put L into Register A for testing
5870
CP 0FFH
Test A against 255
587F
If NC is set, then it is greater than 255, so skip the next instruction by JUMPing to 5882H
5881
LD B,L
Since the move count is < 255 we will use the actual value
5882
POP HL
Restore the START address from the stack into HL
5883
LD A,01H
Put the special code for “LOAD DATA FOLLOWS” into Register A
5885
GOSUB to 001BH of the ROM to write the character held in Register A to the disk file
5888
LD A,B
Put the current count into Register A
5889
ADD A,02H
Add the two bytes of overhead
588B
GOSUB to 001BH of the ROM to write the character held in Register A to the disk file
588E
LD A,L
Next, we write the LSB of the load address to disk by first putting it into Register A
588F
GOSUB to 001BH of the ROM to write the character held in Register A to the disk file
5892
LD A,H
Next, we write the MSB of the load address to disk by first putting it into Register A
5893
GOSUB to 001BH of the ROM to write the character held in Register A to the disk file
5896
LD A,(HL)
This is where we write the core image; so put the character pointed to by (HL) into Register A
5897
INC HL
BUMP HL to point to the next character
5898
GOSUB to 001BH of the ROM to write the character held in Register A to the disk file
5898
Loop back 3 instructions (to 5896H) to keep writing the core image until HL hits zero
589D
If we are here, then we wrote a block, so we need to JUMP to 586AH to see if ALL the blocks were written or not

Routine within DUMP routine. This is jumped to by 5874H once the copying is done

589F
POP HL
Clear the STACK
58A0
LD A,02H
Next we need to write the TRANSFER ADDRESS, so set Register A with the control code 02H
58A2
GOSUB to 001BH of the ROM to write the character held in Register A to the disk file
S8A5
LD A,02H
Next, the byte count for the address must be written, so set Register A with 02H
58A7
GOSUB to 001BH of the ROM to write the character held in Register A to the disk file
S8AA
LD HL,0000H
Load HL with 0000H which will actually be populated with the TRANSFER ADDRESS by SYS1/SYS from 57F8H
58AD
LD A,L
Put the LSB of the TRANSFER ADDRESS into Register A
S8AE
GOSUB to 001BH of the ROM to write the character held in Register A to the disk file
58B1
LD A,H
Put the MSB of the TRANSFER ADDRESS into Register A
58B2
GOSUB to 001BH of the ROM to write the character held in Register A to the disk file
58B5
GOSUB to 4428H to CLOSE the file
58B8
If NZ is set then there was an error closing the file, so JUMP to the general purpose Disk I/O error routine at 554CH
58BB
If we are here, there was no error closing the file, so JUMP back to SYS1/SYS for the next command

Routine within DUMP routine. This is jumped to when there is an error, such as an END address lower than a START address, or a START address above 7000H

58BE
GOSUB to 4467H to display the message pointed to by HL
58C1
JUMP to 4030H to go back to SYS1/SYS with an OPTION 2 set

Routine within DUMP routine. Error message location

58C4
DEFB 0AH
Line feed
58C5
DEFM ‘END LESS THAN START’
58D8
DEFB 0DH
Carriage Return / Message terminator
58D9
DEFB 0AH
Line feed
58DA
DEFM ‘START LESS THAN X’7000”
58Fl
DEFB 0DH
Carriage Return / Message terminator
58F2
DEFM ‘CIM’
Extension for DUMP file name

Routine within DUMP routine. Parameter Text String location

58F5
DEFM ‘START ‘
58FA
DEFW 5BFAH
Location for START address
SBFD
DEFM ‘END ‘
5902
DEFW 586EH
Location for END addresss
5905
DEFM ‘TRA ‘
590A
DEFW 58ABH
Location for TRA address
590D
DEFB 00
List terminator
590E
DEFS 6
Temporary buffer area

5914H – KILL Command

5914
LD DE,5551H
Put the local DCB address (i.e., 5551H) into Register DE
5917
GOSUB to 441CH to copy/edit a filename into DCB (SYSl, Code 4). This validates the filename, puts it into 5551H+, and returns NZ if there are illegal characters
591A
If NZ is set, we did not get a filename, but we did need one, so JUMP back to 553AH to display the FILE SPEC REQUIRED error message
591D
GOSUB to 4424H to open the file
5920
If NZ is set, then there was an error opening the file, so JUMP to the general purpose Disk I/O error routine at 554CH
5923
GOSUB to 442CH to KILL the file
5926
If NZ is set, there was an error killing the file, so JUMP to the general purpose Disk I/O error routine at 554CH
5929
JUMP back to SYS1/SYS for the next command

592CH – LIST Command

592C
LD BC,0000H
First, we need to signal that no LINE option was chosen, so we load 0000H into BC
592F
LD (5954H),BC
And implement that by zero’ing 5954H
5933
LD DE,5551H
Put the local DCB address (i.e., 5551H) into Register DE
5936
GOSUB to 441CH to copy/edit a filename into DCB (SYSl, Code 4). This validates the filename, puts it into 5551H+, and returns NZ if there are illegal characters
5939
If NZ is set, we did not get a filename, but we did need one, so JUMP back to 553AH to display the FILE SPEC REQUIRED error message
593C
LD A,(DE)
If we are here, then we did get a filename, so fetch the current filename character and put it into Register A for processing
593D
CP ‘*’
Test for a “*” which would signify a special file
593F
If a “* was found, then JUMP to 553AH to display the FILE SPEC REQUIRED error message
5942
LD BC,5988H
If we are here, then we have a valid filename, so now point BC at the address of the LINE text
5945
GOSUB to 4476H in SYS1/SYS to compare against LINE
5948
LD B,00H
Set Register B to flag that physical I/O is needed for the source file
594A
LD HL,5600H
Point Register Pair HL to the buffer at 5600H
594D
GOSUB to 4424H to open the file to be LISTed
5950
If NZ is set, there wasn an error opening the file, so JUMP to the general purpose Disk I/O error routine at 554CH
5953
LD BC,0000H
We need to set the LINE option flag, so first ZERO BC out
5956
5957
LD A,B
OR C
Z-80 One-Two to check BC against 0
5958
If BC was 0000 then JUMP forward to 5967H since LINE option was not given. That routine will just write without checking for LINE count
595A
GOSUB to 0013H of the ROM to read a character from the file
595D
CP 0DH
Check the character read against the 0DH delimeter
595F
If NZ is set then it wasn’t an 0DH, so LOOP back to 595AH
5961
DEC C
If we are here then we got an 0DH, so we need to deal with that. DECrement the line count held in BC
5962
If that DECrement didn’t hit zero, then LOOP back to 595AH to keep reading and displaying
5964
DEC B
DECrement B too
5965
LOOP back to 595AH to keep reading and displaying
5967
LD DE,5551H
Put the local DCB address (i.e., 5551H) into Register DE
596A
GOSUB to 0013H of the ROM to read a character from the file
596D
If that ROM routine returned a NZ, then we have a problem so JUMP to 597EH to test for EOF
596F
GOSUB to 0033H in the ROM to display the ASCII character to the device type
5972
CP 0DH
Test for end of line
5974
If not end an end of Line, loop back to 5967H until the EOF
5976
GOSUB to 5515H to read the keyboard and test for SHIFT-@
5979
If that routine returns NZ then the BREAK key is active, so abort the LIST and JUMP to 4030H to go back to SYS1/SYS with an OPTION 2 set
597C
If no BREAK was hit, then JUMP back to 5967H to keep reading until we hit EOF

Routine within LIST routine. This checks to see if we hit EOF

597E
CP 1CH
Compare Register A with 1CH to test for EOF
5980
If we have an EOF then jump back to SYS1/SYS for the next command
5983
CP 1DH
If not, then test Register A with 1DH to see if we have a record not found error
5985
If we have a RECORD NOT FOUND then jump back to SYS1/SYS for the next command
5988
If we are here, then we have a general error that wasn’t EOF or RECORD NOT FOUND, so JUMP to the general purpose Disk I/O error routine at 554CH

Routine within LIST routine. LIST Parameter Text List

59BB
DEFM ‘LINE’
5991
DEFW 5991H
Address of LIST command routine
5993
DEFB 00H
List terminator

5994H – LOAD Command

5994
LD DE,5551H
Put the local DCB address (i.e., 5551H) into Register DE
5997
GOSUB to 441CH to copy/edit a filename into DCB (SYSl, Code 4). This validates the filename, puts it into 5551H+, and returns NZ if there are illegal characters
599A
If NZ is set, we did not get a filename, but we did need one, so JUMP back to 553AH to display the FILE SPEC REQUIRED error message
599D
LD A,(DE)
If there is no error in the filename, then start the process to test for a special character by putting (DE) into A
599E
CP ‘*’
Test for a “*” which would signify a special file
59A0
If a “* was found, then JUMP to 553AH to display the FILE SPEC REQUIRED error message
59A3
GOSUB to 4430H to load the file
59A6
If Z is set, then there was no error, so jump back to SYS1/SYS for the next command
59A9
If we are here then there was an error, so JUMP to the general purpose Disk I/O error routine at 554CH

59ACH – PRINT Command

59AC
LD DE,5551H
Put the local DCB address (i.e., 5551H) into Register DE
59AF
GOSUB to 441CH to copy/edit a filename into DCB (SYSl, Code 4). This validates the filename, puts it into 5551H+, and returns NZ if there are illegal characters
59B2
If NZ is set, we did not get a filename, but we did need one, so JUMP back to 553AH to display the FILE SPEC REQUIRED error message
59B5
LD A,(DE)
If there is no error in the filename, then start the process to test for a special character by putting (DE) into A
59B6
CP ‘*’
Test for a “*” which would signify a special file
59B8
If a “* was found, then JUMP to 553AH to display the FILE SPEC REQUIRED error message
59BB
LD B,00H
Set Register B to flag that physical I/O is needed for the source file
59BD
LD HL,5600H
Point Register Pair HL to the buffer at 5600H
59C0
GOSUB to 4424H to open the file
59C3
If NZ is set, then there was an error opening the file, so JUMP to the general purpose Disk I/O error routine at 554CH
59C6
LD DE,5551H
Put the local DCB address (i.e., 5551H) into Register DE
59C9
GOSUB to 0013H of the ROM to read a character from the file
59CC
If the ROM routine returns a NZ then we have a problem, so JUMP to 59DAH to test for EOF and RECORD NOT FOUND
59CE
GOSUB to 003BH in the ROM to send the character held in Register A to the printer
59D1
GOSUB to the general purpose subroutine to read the keyboard and test for SHIFT-@ and BREAK
59D4
If NZ is returned, then we have a BREAK, so JUMP back to DOS
59D7
LOOP back to 59C6H and keep reading characters and printing them!

Routine within PRINT routine. Check for EOF or RECORD NOT FOUND

59DA
PUSH AF
Save the disk status (the character in A, really) to the stack
59D8
LD A,0DH
Put a carriage return into Register A to terminate the current line
59DD
GOSUB to 003BH in the ROM to send the character held in Register A to the printer
59E0
POP AF
Restore the disk status from the stack
59E1
CP 1CH
Compare Register A with 1CH to test for EOF
59E3
If we have an EOF then jump back to SYS1/SYS for the next command
59E6
CP 1DH
If not, then test Register A with 1DH to see if we have a record not found error
59EB
If we have a RECORD NOT FOUND then jump back to SYS1/SYS for the next command
59E8
If we are here, then we have a general error that wasn’t EOF or RECORD NOT FOUND, so JUMP to the general purpose Disk I/O error routine at 554CH

5B00H – ATTRIB Command

5B00
LD DE,5551H
Put the local DCB address (i.e., 5551H) into Register DE
5B03
GOSUB to 441CH to copy/edit a filename into DCB (SYSl, Code 4). This validates the filename, puts it into 5551H+, and returns NZ if there are illegal characters
5B06
If NZ is set, we did not get a filename, but we did need one, so JUMP back to 553AH to display the FILE SPEC REQUIRED error message
5B09
LD A,(DE)
If there is no error in the filename, then start the process to test for a special character by putting (DE) into A
5B0A
CP ‘*’
Test for a “*” which would signify a special file
5B0C
If a “* was found, then JUMP to 553AH to display the FILE SPEC REQUIRED error message
5B0F
PUSH HL
Save HL (the address of the parameters for the command) to the stack
5B10
LD B,00H
Set Register B to flag that physical I/O is needed for the source file
5B12
LD HL,4D00H
Point Register Pair HL to the buffer at 4D00H
5B15
GOSUB to 4424H to open the file
5B18
If NZ is set, then there was an error opening the file, so JUMP to the general purpose Disk I/O error routine at 554CH
5B1B
POP HL
Restore the address of the parameters for the command from the stack to HL
5B1C
LD A,(5552H)
Fetch the permission flags for the file and put them into Register A
5B1F
AND 07H
MASK the permission flags held in A against 00000111 to isolate the access flags held in bits 0-2
5B21
LD A,37H
Load Register A with a restricted access, invisible, occupied value
5B23
If NZ is set then permission is required, so JUMP to the general purpose Disk I/O error routine at 554CH
5B26
XOR A
Clear Register A for filling into various permissions
5B27
LD (5C05H),A
Put a ZERO into the ACCESS attribute
5B2A
LD (5C0DH),A
Put a ZERO into the INVISIBLE attribute
5B2D
LD A,(HL)
Get the next character from the passed command string
5B2E
CP “(“
Compare it to “(“
5B30
If it was a “( then start testing for parameters
5B32
CP 20H
If we are here it wasn’t a “(” so test for a ” “
5B34
IF NZ is set then it wasn’t a “(” or a ” ” so ignore the command and JUMP to 5268H
5B37
INC HL
We’re going to skip it, so BUMP HL by one to point to the next character
5B38
Loop through the command until a “(” or end of command is found

Routine within ATTRIB routine. We found a “(” so its time to handle parameters.

5B3A
INC HL
Bump past the “(” (current character)
5B38
LD A,(HL)
Get the next character from the command line and put it into Register A
5B3C
CP “I”
Test for “I”
5B3E
If it was an “I”, then JUMP to 5B97H
5B40
CP “A”
Test for a “A”
5B42
If it was a “A” JUMP to 5BA7H
5B44
CP “U”
Test for a “U”
5B46
If it was a “A” JUMP to 5BBCH
5B48
CP “P”
Test for a “P”
5B4A
If its not a “P” then we struck out, so JUMP to 5C39H to display an ATTRIBUTE error message
5B4D
If we’re here then it was a “P” so GOSUB to 5BD1H to parse the PROT command parameter
5B50
If Z is set then it was not KILL/RENAME/WRITE, READ/WRITE, or PROT, so we have an error, so JUMP to 5C39H to display an ATTRIBUTE error message
5B53
PUSH HL
Save HL (the address of the parameters for the command) to the stack
5B54
LD B,07H
Set B with the number of entries to compare, which is 7
5B56
LD DE,(5155H)
Put the first 2 characters of the PROT parameter into DE
5B5A
LD HL,5C61H
Point HL to the list of possible valid parameters
5B5D
LD A,(HL)
Get one character from the list of possible valid parameters
5B5E
INC HL
BUMP HL to point to the next character in the list of possible parameters
5B5F
CP E
Compare the character of the parameter to the list
5B60
If that character matches, JUMP to 5B69H to see if others match
5B63
INC HL
If the character doesn’t match, then we need to BUMP to the next character in the list of possible parameters
5B64
LOOP back to 5B5DH until all options have been compared
5B66
If we are here then we ran out of options for a PROT command and have an error, so JUMP to 5C39H

Routine within ATTRIB routine. Parsing the PROT parameter list. If we are here, we had a single character match

5B69
LD A,(HL)
Fetch a second character from the command line
5B6A
CP D
Compare the character of the parameter to the list
5B6B
RET NZ
If they are not equal, then RETURN to the caller to try the next option
5B6C
POP AF
If we are here, we have had a 2 character match, so first clear the stack
5B6D
LD A,B
Put the number of options remaining in the list in Register A
5B6E
DEC A
DECrement the number of remaining options in the list
5B6F
CP 05H
Compare the number of options to 5
5B71
If NZ is flagged, then we are not at RE (for READ or RENAME), so JUMP to 5B7EH
5B73
LD A,(5157H)
If we are here then we are working on “RE”, so we need to get the 3rd character of the PROT parameter
5B76
CP “N”
Test that 3rd character against a N (for RENAME)
5B78
LD A,05H
Set A to the access flag for READ
5B7A
If the character wasn’t an “N” then we are assuming we have a “READ” so JUMP to 5B7EH to handle READ
5B7C
LD A,02H
Set A to the access flag for RENAME
5B7E
LD (5C0BH),A
Save the access flag held in Register A to the permission for PROT
5B81
POP HL
Restore the command line string address to HL
5B82
LD B,01H
Set Register B for KILL/RENAME/READ/WRITE/EXECUTE access
5B84
LD A,(5C05H)
Get byte 0 of the directory entry with access field 0 into Register A
5B87
OR B
Merge that access field with the 01H held in B to merge them
5B55
LD (5C05H),A
Save the updated access field to the directory entry
5B5B
LD A,(HL)
Get next char from the command string
5B8C
CP “)”
Test to see if the next character is a “)”
5B8E
If it is then we have found the end of the command, so JUMP to 5BF7H
5B90
CP “,”
OK, it wasn’t a “)” so let’s check to see if it is a “,”
5B92
If it is a “,” then that means we have more parameters to check so JUMP to 5B3AH
5B94
If we are here then we didn’t get a “)” or a “,” so we have an error in the attribute spec. JUMP to 5C39H to deal with it

Routine within ATTRIB routine. Process the “I” command

5897
GOSUB to 58D1H to parse rest of command
589A
If NZ is returned then then command string contains more than a “)”, so JUMP to 5C39H to deal with it
5890
LD A,(5C0DH)
Get the access permission from the directory (5C0DH) and put it into Register A
5BA0
OR 05H
OR Register A against 00000101 to set the invisible flag
5BA2
LD (5C0DH),A
Put the updated access permission flag back into (5C0DH)
5BA5
JUMP to 5B84H to test for a closing “)” and write the updated directory entry

Routine within ATTRIB routine. Process the “ACC” command

5BA7
GOSUB to 58D1H to parse rest of command
5BAA
If NZ is returned then nothing followed the “A” so we have an error, so JUMP to 5C39H to deal with it
5BAD
PUSH HL
Save HL (the address of the parameters for the command) to the stack
5BAE
LD DE,5155H
Put the address of the ACCESS password into DE
5BB1
GOSUB to 50D1H to get the hash of the ACCESS password
5BB4
LD (516AH),HL
Save the hashed password to (516AH)
5BB7
POP HL
Restore the command string address back to HL
5BB8
LD B,02H
Put the parameter for RENAME/WRITE/READ/EXECUTE access into Register B
5BBA
JUMP to 5BB4H to update the access permission field in the directory

Routine within ATTRIB routine. Process the “UPD” command

5BBC
GOSUB to 5BD1H to parse the PROT command parameter
5B8F
If nothing follows the “U” then we have an error, so JUMP to 5C39H to display an ATTRIBUTE error message
5BC2
PUSH HL
Save HL (the address of the parameters for the command) to the stack
5BC3
LD DE,5155H
Put the local DCB address (i.e., 5551H) into Register DE
5BC6
GOSUB to the SYS2/SYS routine to hash a password (in this case, the UPDATE password)
5BC9
LD (516BH),HL
Put the hash of the UPDATE password into 516BH
5BCC
POP HL
Restore the command string address
5BCD
LD B,04H
Set Register B to the value for WRITE/READ/EXECUTE access
5BCF
JUMP to 5B84H to update the access permission in the directory sector

Routine within ATTRIB routine. Process the PROT Parameters

5BD1
INC HL
BUMP HL to point to the next character in the command
5BD2
LD A,(HL)
Put the next character from the command into A
5BD3
CP 0DH
Compare that next character against 0DH (i.e., end of line)
5BD5
RET Z
If Z is set, we have end of line, so RETURN
5BD6
CP “)”
Compare that next character against “)”
5BD8
RET Z
If Z is set, we have a “)”, so RETURN
5BD9
CP “,”
Compare that next character against “)”
5BD8
RET Z
If Z is set, we have a “,”, so RETURN
5BDC
CP 3DH
Compare that next character against “=”
5BDE
If NZ is set, we do NOT have a “=” and have run out of valid characters so LOOP back to 5BD1 and keep going
5BE0
INC HL
If we are here, then we have an “=” so first BUMP HL to point to the next character after the “=”
5BEl
LD DE,5155H
Put the local DCB address (i.e., 5551H) into Register DE
5BE4
LD B,08H
Set Register B to the number of buffer bytes to initialize
5BE6
PUSH DE
Save the local DCB address from Register DE to the stack
5BE7
PUSH BC
Save the maximum number of bytes (held in B) to the stack
5BEB
LD A,20H
Put a ” ” into Register A
5BEA
LD (DE),A
Set the buffer byte to ” “
5BEB
INC DE
Bump to the next buffer byte
5BEC
LOOP back to 58EAH until the entire buffer has been filled with ” “
5BEE
POP BC
Restore the maximum number of bytes (held in B) from the stack
5BEF
POP DE
Restore the local DCB address from Register DE from the stack
5BF0
GOSUB to 508lH to copy the password to the buffer pointed to by DE. This uses SYS2/SYS
5BF3
DEC HL
Back up the pointer to the next character in the command by 1
58F4
OR 01H
Set the flags to indicate that a password was found
58F6
RET
RETURN out of the routine

Routine within ATTRIB routine. Jumped to by 5B8E once the end of the PROT command has been found

5BF7
LD BC,(5557H)
Put the directory sector pointer in the DCB (held in 5557H) into BC
5BF8
GOSUB to 4AC1H to read the directory sector pointed to by BC into the buffer
5BFE
If there was an error during the read, JUMP to the general purpose Disk I/O error routine at 554CH
5C01
LD A,(HL)
Put a byte of the directory entry into Register A
5C02
AND 0F8H
MASK the byte against 11111000 to clear the access permissions (i.e., the lowest 3 bits)
5C04
LD D,00H
Put the new access permission to Register D
5C06
BIT 00H,D
Test to see if all permissions have been granted
5C0B
If not all permissions were granted (i.e., Bit 0 is 0), then skip the next instruction
5C0A
OR 00H
Combine the access permission bits with the visibility attribute. Note: This may be 00H but 5C0BH is populated by the command at 5B7EH
5C0C
OR 00H
Combine the access permission bits with the visibility attribute. Note: This may be 00H but 5C0DH is populated by the command at 5B2AH
5C0E
LD (HL),A
Save the updated access permissions back to the DCB of the directory entry
5C0F
LD A,L
Put the UPDATE access password location into Register A
5C10
ADD A,l0H
A=A+10H to skip to the UPDATE access password location in the directory entry
5Cl2
LD L,A
Put the location of the UPDATE access password back into Register L
5C13
BIT 02H,D
Test to see if the UPDATE password was specified
5Cl5
If the UPDATE password was not specified, JUMP to 5C21H
5Cl7
LD A,(5168H)
If we are here then the UPDATE password was specified, so put the first byte of the passwords 2 byte hash hash (held at 5168H) into Register A
5ClA
LD (HL),A
Put the first byte of the UPDATE password’s hash into the DCB of the directory entry
5ClB
LD A,(5169H)
Put the second byte of the UPDATE password’s 2 byte hash hash (held at 5169H) into Register A
5C1E
INC HL
Bump the DCB pointer so as to point to the second byte of the UPDATE password
5ClF
LD (HL),A
Put the second byte of the UPDATE password’s hash into the DCB of the directory entry
5C20
DEC HL
We are about to do a routine which starts by BUMPing HL, so we need to DECrement HL by 1 first
5C21
5C22
INC HL
INC HL
BUMP HL twice to point to the starting position of the UPDATE password in the directory entry DCB
5C23
BIT 01H,D
Test for KILL/RENAME/READ WRITE/EXECUTE access
5C25
If all options are allowed (i.e., Bit 1 was set), then JUMP down to 5C30H
5C27
LD A,(516AH)
If all options are not allowed, then get the first byte (LSB) of the ACCESS password hash
5C2A
LD (HL),A
Put the first byte of the ACCESS password’s hash into the DCB of the directory entry
5C2B
LD A,(516BH)
Get the second byte (MSB) of the ACCESS password hash
5C2E
INC HL
Bump HL to point to the second byte of the ACCESS password in the DCB
5C2F
LD (HL),A
Put the second byte (MSB) of the ACCESS password hash into the DCB
5C30
GOSUB to 4AD6H to write the updated directory sector
5C33
If NZ is set, then there was an error during the write, so JUMP to the general purpose Disk I/O error routine at 554CH
5C36
If we are here, then we are done. JUMP back to SYS1/SYS for the next command

Routine within ATTRIB routine. Display the ATTRIBUTE SPECIFICATION ERROR message

5C39
LD HL,5C42H
Point HL to the test of the ATTRIBUTE SPECIFICATION ERROR message
5C3C
GOSUB to 4467H to display the message pointed to by HL
5C3F
JUMP to 4030H to go back to SYS1/SYS with an OPTION 2 set
5C42
DEFB 0AH
Line feed
5C43
DEFM ‘ATTRIBUTE SPECIFICATION ERROR’
5C60
DEFB 0DH
Carriage Return / Message terminator

Routine within ATTRIB routine. This is the PROT parameter list for processing of the attribute

5C61
DEFM ‘EXREWR NAKIFU’

5C6FH – DIR Command

5C6F
LD BC,0000H
We are going to need to clear a bunch of memory locations, so fill BC with 0’s
5C72
LD (5D9BH),BC
Put a zero in the “A” option flag (i.e., not selected)
5C76
LD (5D0BH),BC
Put a zero in the “I” option flag (i.e., not selected)
5C7A
LD (5CFDH),BC
Put a zero in the “S” option flag (i.e., not selected)
5C7E
LD C,00H
Put a default drive number of 0 into Register C
5C80
LD A,(HL)
Put the next character from the command line into Register A
5C81
CP ‘:’
Check to see if that character is a “:”
5C83
If it is not a colon, then we have no drive specified, so no need to process a drive number. Skip down to 5C8BH
5C85
INC HL
BUMP HL to point to the next character from the command line
5C86
LD A,(HL)
Put the next character from the command line into Register A
5C87
INC HL
BUMP HL to point to the next character from the command line
5C88
SUB ‘0’
SUBtract 30H from A to convert the drive number from the command line to binary
5C8A
LD C,A
Replace the default drive number with the one provided, held in A
5C8B
PUSH BC
Save the drive number to the stack
5C8C
LD A,C
Put the drive number to be used into Register A
5C8D
ADD A,’0′
ADD a “0” to Register A to effectively convert it from binary to ASCII
5C8F
LD (5E9EH),A
Put the drive number (in ASCII) into 5E9EH, which is the title message
5C92
LD DE,5E6AH
Put the address of the DIR options I,S, and A into DE
5C95
GOSUB to 4476H in SYS1/SYS to compare the rest of the command line to the option list pointed to by DE
5C98
LD HL,5E83H
Put the address of the DIR title line into DE
5C9B
GOSUB to 4467H display the title line pointed to by DE
5C9E
POP BC
Restore the Stack into Register BC
5C9F
PUSH BC
Save the contents of Register BC to the stack
5CA0
GOSUB to 4B55H to get the directory track number for the disk drive pointed to by Register C
5CA3
LD E,00H
Register E will hold the sector number, so put a 00H into Register E
5CA5
LD HL,4200H
Point Register Pair HL to a buffer starting at 4200H
5CA8
Read the sector held in Register E of track 11 into the buffer pointed to by HL
5CAB
If NZ is set, then there was an error in that diskette I/O, so JUMP to the general purpose Disk I/O error routine at 554CH
5CAE
LD HL,42D0H
Point HL to the address of the disk name in the GAT sector buffer
5CB1
LD DE,5EA1H
Point DE to the address of the disk name in third title line (i.e., “NNNNNNNN — MM/DD/YY”)
5CB4
LD BC,0008H
Set BC to the number of bytes in a diskette name
5CB7
LDIR
Move the disk name from the GAT buffer to the third title line (i.e., “NNNNNNNN — MM/DD/YY”). LDIR moves BC number of bytes from the memory location held in HL into the memory location held in DE
5CB9
LD DE,5EADH
Point DE to the address of the date in the third title line (i.e., “NNNNNNNN — MM/DD/YY”)
5CBC
LD BC,0008H
Set BC to the number of bytes in a date
5CBF
LDIR
Move the date from the GAT buffer to the third title line (i.e., “NNNNNNNN — MM/DD/YY”). LDIR moves BC number of bytes from the memory location held in HL into the memory location held in DE
5CC1
LD HL,5EA1H
Point HL to the address of the third title line (i.e., “NNNNNNNN — MM/DD/YY”)
5CC4
GOSUB to 4467H display the third title line (i.e., “NNNNNNNN — MM/DD/YY”)
5CC7
POP BC
Restore the stack to Register Pair BC
5CC8
LD B,00H
Setup for reading the first directory sector
5CCA
LD DE,6100H
Point DE to a buffer starting at 6100H
5CCD
Read a sector of the directory file into 4200H
5CD0
If NZ is set, then there was an error in that diskette I/O, so JUMP to the general purpose Disk I/O error routine at 554CH
5CD3
LD L,00H
Force HL to 4200H, which is the sector buffer start address
5CD5
PUSH BC
Save the contents of Register Pair BC to the stack
5CD6
LD BC,0100H
Load BC with the number of bytes to move (here, 256)
5CD9
LDIR
Copy the buffer at 4200H to the buffer at 6100H. The LDIR command moves BC number of bytes from the memory location held in HL into the memory location held in DE
5CDB
POP BC
Restore the sector/drive number from the stack into Register Pair BC
5CDC
INC B
Bump the sector number by 1
5CDD
LD A,B
Put the bumped sector number into Register A for processing
5CDE
CP 08H
Compare Register A (the bumped sector number) against 08H to see if we read the last directory sector or not
5CE0
If NZ is set, then we did NOT reach the end, so JUMP back to 5CCDH
5CE2
LD HL,6100H
If we are here then all sectors have been read, so now we need to display them. First, point HL to a buffer starting at 6100H
5CE5
LD A,0CH
Set Register A to the number of lines to display before it pauses
5CE7
LD (5DABH),A
Put that maximum line count into 5DABH (which is the line counter)
5CEA
LD B,03H
Set Register B to the number of files to display per line (i.e., 3)
5CEC
LD A,(HL)
Get the access control byte from the directory
5CED
PUSH HL
Save the directory address for the current file to the stack
5CEE
BIT 4,A
Test Bit 4 of Register A (the access control byte) to see if the entry is occupied
5CF0
If the Z Flag is SET then the entry is NOT occupied, so JUMP to 5DBFH to move to the next entry
5CF3
BIT 7,A
If we are here, then the entry is occuped so we now test Bit 7 of Register A (the access control byte) to see if it is a primary entry or an overflow entry
5CF5
If NZ is set then this is an overflow entry, so JUMP to 5DBFH to move to the next entry
5CF8
BIT 6,A
If we are here then the entry is occupied and it is not an overflow entry, so now we test Bit 6 of Register A (the access control byte) to see if it is a USER or SYSTEM file
5CFA
If the Z Flag is SET then it is a SYSTEM file, so JUMP to 5D06H
5CFC
LD DE,0000H
If we are here then the file is a USER file, so set DE to 0000H in preparation for testing to see if S option was specified or not
5CFF
5D00
LD A,D
OR E
Standard Z-80 combination to test DE against 00
5D01
If the Z Flag is SET then DE was 0000H and the S option was NOT selected, so JUMP to 5DBFH
5D04
If we are here, then DE was FFFF and the “S” option was selected, so JUMP to 5D12H to display the file
5D06
BIT 3,A
Test Bit 3 of Register A (the access control byte) to see if the file is INVISIBLE
5D08
If the Z Flag is SET then it is not invisible and can be displayed so JUMP to 5D12H
5D0A
LD DE,0000H
Begin the test to see if the user selected “I”. First, set DE to 0000H. This value (5D0B-5D0C) will be modified by SYS1/SYS if the user selected “I”
5D0D
5D0E
LD A,D
OR E
Standard Z-80 combination to test DE against 00
5D0F
If the Z Flag is SET then I was not selected so JUMP to 5DBFH
5D12
PUSH BC
If we are here then we haven invisible file AND the “I” option was chosen,Save the file’s line count and drive number to the stack
5D13
LD A,L
Put the LSB of the current entries address into Register A
5D14
ADD A,05H
Add 5 to that address to now point to the filename address
5D16
LD L,A
Put the address of the filename into Register L
5D17
LD C,11H
Set Register C to the maximum number of characters in a filename/EXT (i.e., 17)
5D19
LD B,08H
Set Register B to the maximum number of characters in a filename (i.e., 8)
5D1B
LD A,(HL)
Get a character from the filename pointed to by Register Pair HL
5D1C
INC HL
BUMP Register Pair HL to point to the next character of the filename
5D1D
CP ‘ ‘
Check to see if the filename character is a ” “
5D1F
If the Z Flag is SET then it is a space and we have run out of letters so then JUMP to 5D29H to process the extension
5D21
GOSUB to 0033H in the ROM to send the character held in Register A to the current device
5D24
DEC C
Reduce the number of characters to display by 1
5D25
LOOP back to 5D1BH until B (maximum number of characters in a filename) is zero
5D27
If we are here, then we have displayed as much of the filename as we have, so JUMP to 5D2DH to process the display of the extension

If we are here then we have run out of letters in the filename before we hit 8.

5D29
LD A,L
Put the LSB of the current address in the directory buffer into Register A
5D2A
ADD A,B
Add the remaining number of bytes in the filename to get to the extension + 1
5D2B
DEC A
Subtract 1 from A to now point to the extension
5D2C
LD L,A
Put the modified Register L (held in A) back into Register L so that L now points to the extension

Now we process the filename’s extension

5D2D
LD A,(HL)
Put the character pointed to by HL into Register A
5D2E
CP ‘ ‘
Compare the character held in Register A against a space
5D30
If the Z Flag is SET then we have no extension, so JUMP to 5D46H
5D32
LD A,’/’
If we are here, then we have an extension so load up the “/” into Register A since that has to be next character displayed
5D34
GOSUB to 0033H in the ROM to send the character held in Register A to the current device
5D37
DEC C
DECrement Register C by 1 (the maximum number of characters we should display for a given filename + extension) to reflect that we just displayed a character (in this case “/”)
5D38
LD B,03H
Set Register B to the maximum length of an extension (i.e., 3 characters)
5D3A
LD A,(HL)
Put the character pointed to by HL into Register A – in this case, one of the extension characters
5D3B
INC HL
Bump HL to point to the next character in the extension
5D3C
CP ‘ ‘
Compare the character held in Register A against a space to see if we have run out of characters
5D3E
If the Z Flag is SET then we have run out of characters before we hit 3 so then JUMP to 5D46H
5D40
If we are here, then we have a non-blank extension character so GOSUB to 0033H in the ROM to send the character held in Register A to the current device
5D43
DEC C
DECrement Register C by 1 to indicate that we have just displayed a character
5D44
LOOP back to 5D3AH until B is zero

If we are here, then we have finished displaying the extension (including if there was no extension at all, we ran out of characters before 3, or we displayed 3)

5D46
LD A,’ ‘
Put a ” ” into Register A
5D48
Display the ” ” by GOSUB to 0033H in the ROM to send the character held in Register A to the current device
5D4B
DEC C
DECrement Register C (the maximum number of characters we should display for a given filename + extension) by 1 since we just displayed a ” “
5D4C
LD A,L
Put Register L (the LSB of current file entry) into Register A for processing
5D4D
AND 0E0H
MASK Register A against 1110 0000 to keep only bits 5-7. This forces the LSB to be the beginning of a file
5D4F
LD L,A
Put the modified Register L (held in A) back into Register L
5D50
LD B,(HL)
Put the access flag for the file into Register B
5D51
LD A,’S’
Put a “S” into Register A for displaying
5D53
BIT 6,B
Test Bit 6 of Register B to see if the file is a SYSTEM file
5D55
If the file is a SYSTEM file then JUMP to 5D59H
5D57
LD A,’ ‘
Swap out the “S” for a ” ” since it isn’t a SYSTEM file
5D59
GOSUB to 0033H in the ROM to send the character held in Register A to the current device
5D5C
LD A,’I’
Put a “I” into Register A for displaying
5D5E
BIT 3,B
Test Bit 3 of Register B to see if the file is INVISIBLE
5D60
If the file is an INVISIBLE file then JUMP to 5D64H
5D62
LD A,’ ‘
Swap out the “I” for a ” ” since it isn’t an INVISIBLE file

If we are here, then we have determined that the file is invisible.

5D64
GOSUB to 0033H in the ROM to send the character held in Register A to the current device
5D67
PUSH HL
Save Register Pair HL (currently holding the beginning address of the file entry) to the Stack
5D68
LD A,L
Put Register L (currently the LSB of the file’s entry address) into Register A for processing
5D69
ADD A,10H
Move down 16 characters to now point to the UPDATE password
5D6B
LD L,A
Put the modified Register L (held in A) back into Register L
5D6C
LD E,(HL)
Put the LSB of the UPDATE PASSWORD into Register E
5D6D
INC L
BUMP L by 1 to point to the next byte in the password
5D6E
LD D,(HL)
Put the MSB of the UPDATE PASSWORD into Register D
5D6F
PUSH HL
Save Register Pair HL (the address of the UPDATE PASSWORD) to the Stack
5D70
LD HL,4296H
Set HL to 4296H which is the value of a universal password
5D73
SBC HL,DE
Test to see if the file is password protected or not
5D75
POP HL
Restore the address of the UPDATE PASSWORD from the Stack to Register Pair HL
5D76
If the Z Flag is SET then the file has no password so JUMP to 5D8CH
5D78
LD A,B
If we are here then the file has a password, so get the access flags (currently held in Register B) and put them into Register A for processing
5D79
AND 07H
MASK Register A against 0000 0111 to keep only bits 0-2, thus isolating the access control flags
5D7B
LD A,’P’
Put a “P” into Register A
5D7D
If the mask results in NZ being set, then we do not have unrestricted access to the file and JUMP to 5D8EH
5D7F
INC L
BUMP L by 1 to point to the LSB of the ACCESS password
5D80
LD E,(HL)
Put the LSB of the ACCESS PASSWORD into Register E
5D81
INC L
BUMP L by 1 to point to the MSB of the ACCESS password
5D82
LD D,(HL)
Put the MSB of the ACCESS PASSWORD into Register E
5D83
LD HL,4296H
Set HL to 4296H which is the value of a universal password
5D86
SBC HL,DE
Test to see if the file has an ACCESS PASSWORD or not
5D88
LD A,’P’
Put a “P” into Register A
5D8A
If that test shows that the file has an ACCESS PASSWORD, then JUMP to 4D8EH to display the “P” and continue processing

If we are here, then it has been determined that the file has no password.

5D8C
LD A,’ ‘
Put a ” ” into Register A to overwrite the “P” that may already be there
5D8E
GOSUB to 0033H in the ROM to send the character held in Register A (which may be a “P” or a ” “) to the current device
5D91
POP HL
Restore the beginning address of the file entry into Register Pair HL

Fill in the remainder of the field

5D92
LD A,’ ‘
Put a ” ” into A since we are going to pad the rest of the field
5D94
GOSUB to 0033H in the ROM to send the character held in Register A to the current device
5D97
DEC C
DECrement Register C (the maximum number of characters we should display for a given filename + extension) by 1 since we just displayed a ” “
5D98
LOOP back to 4D92H until we have padded out to reach 17 characters per filename
5D9A
LD DE,0000H
Set Register Pair DE to 0000H. If the user had included an “A” option, then SYS1/SYS will have filled bytes 5D9B-5D9C with “FFFF” instead
5D9D
5D9E
LD A,D
OR E
Common set of instructions to test DE against 0
5D9F
POP BC
Restore the files/line count and drive number from the stack into Register Pair BC
5DA0
If DE is NOT zero, then “A” was chosen as an option, so JUMP to 5DF1H to display the file size
5DA3
Reduce B by 1 (as we just displayed a file), and JUMP back to 5DBFH if there is room for more files to be displayed on this line
5DA5
LD A,0DH
If we are here, then we have displayed enough files on a line to merit a new line. Put a CARRIAGE RETURN into Register A
5DA7
GOSUB to 0033H in the ROM to send the character held in Register A to the current device
5DAA
LD A,00H
Put a 0 into Register A to set the maximum number of lines per screen

Check to see if we have hit the maximum number of lines per screen and if so, wait for user key press

5DAC
DEC A
DECrement that line count by 1
5DAD
JUMP back to 5DB4H to put up another line until the maximum number of lines per screen has been exhausted
5DAF
If we are here, then the screen is full, so GOSUB to 0049H to the ROM to wait for a key press
5DB2
LD A,0CH
Put the maximum number of lines per screen into Register A (i.e., 17)
5DB4
LD (5DABH),A
… and put that into the line/screen counter held at 5DABH
5DB7
GOSUB to 5515H to read the keyboard and test for SHIFT-@ and BREAK
5DBA
If NZ is set, then the BREAK key was pressed, so JUMP to 5DDBH to zero out the buffer (for security) and return to DOS
5DBD
LD B,03H
Set Register B to the number of files per line (i.e., 3)
5DBF
POP HL
Restore the beginning address of the current directory entry into Register Pair HL
5DC0
INC H
BUMP Register H by 1 to point to the next sector
5DC1
LD A,H
Put the contents of Register H into Register A for processing/testing
5DC2
CP 69H
Compare Register A against 105 to see if 8 sectors have been processed
5DC4
If 8 sectors have NOT been processed (i.e., NZ is set) then JUMP to 4CECH to process the next entry from the next sector
5DC8
LD H,61H
Prepare HL to point to a buffer at 61xxH by setting the MSB (H) to 61H
5DC9
LD A,L
Put Register L (the beginning address for the last entry) into Register A for processing
5DCA
ADD A,20H
Bump 20 bytes forward to as to calculate the beginning address
5DCC
LD L,A
Put the modified Register L (held in A) back into Register L
5DCD
If NC is set, then all entries have NOT been processed, so JUMP back to 4CECH to process the next entry
5DD0
GOSUB to 5DE1H to zero out the sector buffers. This is done to protect passwords
5DD3
LD A,0DH
Put a CARRIAGE RETURN into Register A
5DD5
GOSUB to 0033H in the ROM to send the character held in Register A to the current device
5DD8
JUMP back to SYS1/SYS for the next command

If the BREAK key was pressed, we jump here to zero out the buffer (for security) and return to DOS with OPTION 2

5DDB
GOSUB to 5DE1H to zero out the sector buffers. This is done to protect passwords
5DDE
JUMP to 4030H to go back to SYS1/SYS with an OPTION 2 set

This routine in the DIR function zeroes out the 8 sector buffers (6100H, 6200H … 6800H) to protect the passwords

5DE1
LD HL,6100H
Point HL to a buffer starting at 6100H
5DE4
LD B,00H
Set B to 00H (the fill character to zero out a memory byte))
5DE6
LD (HL),B
Put a 00H into the buffer pointed at by HL
5DE7
INC L
BUMP L by 1 to point to the next character in the buffer
5DE8
Jump back to 5DE6H to keep zeroing out bytes until the count rolls over (i.e., 256)
5DEA
INC H
At this point, we looped to fill a sector worth of buffer, so BUMP Register H by 1 to point to the next sector in the buffer
5DEB
LD A,H
Put the contents of Register H into Register A for processing/testing
5DEC
CP 69H
Compare Register A against 105 to see if 8 sectors have been processed
5DEE
If 8 sectors have NOT been processed (i.e., NZ is set), then JUMP back to 5DE6H to erase 256 bytes
5DF0
RET
RETURN

This routine is called from 5DA0H if “A” was chosen as an option so as to display the file size

5DF1
PUSH HL
Save Register Pair HL (holding the beginning address of the file entry) to the Stack
5DF2
5DF3
5DF4
INC L
INC L
INC L
BUMP L by 3 so as to point to the address of the EOF sector
5DF5
LD A,(HL)
Put the character pointed to by HL (the EOF byte offset) into Register A
5DF6
LD (5E69H),A
Put the the EOF byte offset into 5E69H for temporary storage
5DF9
INC L
BUMP L by 1 to so that L now points to the logical record length (LRL) in the directory
5DFA
PUSH HL
Save Register Pair HL (the address of the LRL) to the Stack
5DFB
LD L,(HL)
Put the logical record length into Register L
5DFC
LD A,L
Put Register L (the logical record length) into Register A for processing
5DFD
LD (5E1FH),A
Put the logical record length into 5E1FH for temporary storage
5DF0
SUB 01H
Subtract 1 from the logical record length to set the CARRY FLAG if the LRL was 256
5DF2
LD A,00H
Put a 0 into Register A, maintaining the CARRY FLAG
5DF4
ADC A,00H
Add with carry to 00H again. We now have A set as zeros with CARRY maintained
5DF6
LD H,A
Put that into Register H
5DF7
LD DE,5EBBH
Load Register Pair DE with 5EBBH (the address of th LRL in the display line)
5DFA
GOSUB to 606CH to convert Register DEs contents (the LRL) to ASCII and display it
5E0A
POP HL
Restore the address of the LRL from the stack into Register Pair HL
5E0D
LD A,L
Put Register L (the LSB of the address of the LRL) into Register A for processing
5E0E
ADD A,10H
Set A to be 16 bytes past the LSB of the address of the LRL so as to point to the byte containing the EOF sector number
5E0F
LD L,A
Put the modified Register L (held in A) back into Register L so that HL will point to the EOF sector
5E11
LD A,(HL)
Put the character pointed to by HL (the LSB of ending sector number) into Register A
5E12
LD (5E68H),A
Put the the LSB of ending sector number into 5E68H for temporary storage
5E13
INC L
BUMP L by 1 to point to the MSB of ending sector number
5E16
LD A,(HL)
Put the character pointed to by HL (the MSB of ending sector number) into Register A
5E17
LD (5E67H),A
Put the the MSB of ending sector number into 5E67H for temporary storage
5E18
LD HL,5E67H
XX
Set HL to point to the address of the ending sector number in binary
5E1B
LD C,00H
Set Register C to the LRL. This may be 00H here, but the instruction at 5DFDH modifies it
5E20
GOSUB to 60A7H to divide the number of records by record size
5E23
EX DE,HL
Swap DE and HL so that the quotient of that division is now in Register Pair HL
5E24
LD DE,5EC7H
Load DE with the address of the ending sector number in display
5E27
GOSUB to 606CH to convert Register DEs contents (the ending sector number) to ASCII and display it
5E2A
POP HL
Restore the address of the LRL into Register Pair HL
5E2B
GOSUB to 5E3EH to compute the number of granules assigned to the file. Results stored in DE
5E2E
EX DE,HL
Swap DE and HL so that HL holds the number of granules assigned to the file
5E2F
LD DE,5ED4H
Load DE with the address of the number of granules assigned to the file in the display line
5E32
GOSUB to 606CH to convert Register DEs contents (the number of granules assigned to the file) to ASCII and display it
5E35
LD HL,5EB7H
Load HL with the address of the LRL of the file in the display line
5E38
GOSUB to 4467H to display the message pointed to by HL
5E3B
LD B,01H
Set B (the line counter) to 1, as there is only one file/line to display if we are here
5E3D
RET
RETURN

Routine inside DIR to compute the number of granules assigned to the file. Results stored in DE.

5E3E
LD DE,0000H
Zero up Register Pair DE since it will be the accumulator for the math
5E41
LD A,L
Put Register L (the LSB of LRL) into Register A for processing
5E42
ADD A,16H
Set A to be 32 bytes later than the the LSB of LRL so as to point to the GAP
5E44
LD L,A
Put the modified Register L (held in A) back into Register L, so that HL points to the GAP’s address
5E45
LD A,(HL)
Put the character pointed to by HL (a byte of the GAP) into Register A
5E46
INC L
BUMP L by 1 to point to the next character, which is the granule count
5E47
CP 0FEH
Compare Register A against 0FEH to see if we have either the end of the GAP or there is an overflow entry
5E49
If NC is set, then we have an end of the gap or there is an overflow entry, so JUMP out of this LOOP to the next routine. This is the LOOP exit
5E4B
LD A,(HL)
Put the character pointed to by HL (the granule count) into Register A
5E4C
INC L
BUMP L by 1 to point to the next GAP
5E4D
AND 1FH
AND the granule count by 1FH to isolate the granule count – 1
5E4F
INC A
BUMP Register A by 1 to get to the true granule count
5E50
ADD A,E
Add Register E to Register A
5E51
LD E,A
Copy the result of that math back into Register E because DE is tracking the math
5E52
If the NC is set, then the LSB has not yet overflowed, so skip the next instruction
5E54
INC D
If we are here, then the LSB overflowed, so we need to BUMP Register D (the MSB of the granule count) by 1
5E55
LOOP back to the top of this routine (5E45H). This LOOP will keep going until 5E49 exits the loop because FF (end of GAP) was found

If the above routine (computing the number of granules) hits an end of the gap or there is an overflow entry, it jumps here

5E57
RET NZ
If the NZ flag is set then it found an END OF GAP, so RETURN to the caller
5E58
LD B,(HL)
If we are here, then we hit an overflow entry, so put the memory contents of HL, which is the pointer to the overflow entry, into Register B
5E59
LD A,B
Put the pointer to the overflow entry held in Register B into Register A for processing/testing
5E5A
AND 07H
MASK Register A against 0000 0111 to keep only bits 0-2, which is the sector number
5E5C
ADD A,61H
Form the address of the sector buffer by prepending with “61xxH”
5E5E
LD H,A
Put the 61H into the MSB of the sector buffer
5E5F
LD A,B
Put the pointer to the overflow entry into Register A
5E60
AND 0E0H
MASK Register A against 1110 0000 to keep only bits 5-7, which form the offset to the file entry
5E62
ADD A,16H
Add an offset of 32 bytes to offset to the GAP’s
5E64
LD L,A
Put the modified Register L (held in A) back into Register L
5E65
JUMP back to 5E45H to continue counting grans until the end of the GAP’s are found

Next is storage

5E67
DEFB 0
Memory location to hold the MSB of the EOF Sector
5E68
DEFB 0
Memory location to hold the LSB of the EOF Sector
5E69
DEFB 0
Memory location to hold the EOF byte offset

… DIR Option Text List (A, I, and S)

5E6A
DEFM ‘A ‘
XX
5E71
DEFW 5D9BH
Code address for the “A” Option
5E72
DEFM ‘I ‘
XX
5E78
DEFW 5D0BH
Code address for the “I” Option
5E7A
DEFM ‘S ‘
XX
5E81
DEFW 5CFDH
Code address for the “S” Option
5E82
DEFB 00H
XX

… DIR Screen Displays

5E83
DEFB 1CH
ASCII character value to clear the screen
5E84
DEFB 1FH
ASCII character value to home the cursor
5E85
DEFM ‘FILE DIRECTORY — DRIVE X’
5E9F
DEFB C5H
ASCII Compression Code for 5 Blanks
5EA0
DEFB 03H
Message Terminator
5EA1
DEFM ‘NNNNNNNN — MM/DD/YY’
5EB5
DEFB 0AH
ASCII character value for LINE FEED
5EB6
DEFB 0DH
ASCII character value for CARRIAGE RETURN / Message Terminator
5EB7
DEFM ‘LRL= / EOF= / SIZE= GRANS’
5EDF
DEFB 03H
Message Terminator

5EE0H – FREE Command.

5EE0
LD C,00H
Set a default drive number and put it into Register C
5EE2
LD A,03H
Put an illegal character into Register A
5EE4
LD DE,5551H
Put the local DCB address (i.e., 5551H) into Register DE
5EE7
LD (DE),A
Put the value held in Register A (which is an illegal character) into the memory location pointed to by DE
5EE8
GOSUB to 4424H to open the file. Since there is an illegal characters, this will really just load SYS2/SYS into 4E00H
5EEB
PUSH BC
Save the drive number held in Register Pair BC to the stack
5EEC
GOSUB to 50FDH to see if the drive is available. This uses SYS2/SYS
5EEF
JUMP to 5F58H if the drive is not available
5EF1
LD A,C
Put Register C (the drive number) into Register A for processing/testing
5EF2
ADD A,30H
Convert the number to ASCII by adding 30H to it (30H=ASCII ‘0’, 31H=ASCII ‘1’, …)
5EF4
LD (5F68H),A
Put the ASCII version of the drive number into 5F68H (which is where the display line is stored)
5EF7
GOSUB to 4AF0H to read the GAT sector for the specified drive
5EFA
If NZ is set, then there was an error in that diskette I/O, so JUMP to the general purpose Disk I/O error routine at 554CH
5EFD
LD HL,4DD0H
Put the address of the disk name in the GAT sector into HL
5F00
LD DE,5F6EH
Put the location of the disk name for the display into DE
5F03
LD BC,0008H
Put the number of bytes in a disk name into BC
5F06
LDIR
Put the disk name from the disk onto the display via LDIR. LDIR moves BC number of bytes from the memory location held in HL into the memory location held in DE
5F08
LD DE,5F79H
Put the address of the creation date on the display into register DE
5F0B
LD BC,0008H
Put the number of bytes in a date into register BC
5F0E
LDIR
Move the date from the GAT sector to the display via LDIR. LDIR moves BC number of bytes from the memory location held in HL into the memory location held in DE
5F10
LD HL,4D00H
Put the start address of the GAT table in the GAT sector
5F13
LD DE,0000H
We need to add the number of free granules, so set DE to 0000 for math
5F16
LD B,23H
Set B to the maximum number of GAT entries to examine
5F18
LD A,(HL)
Put GAT enty into Register A
5F19
SCF
Set the CARRY FLAG, so that bit 1 is forced to bit 7
5F1A
RRA
Set the bit 0 (granule) to the carry flag
5F1B
If the CARRY is set then the current track is assigned, so JUMP to 5F1EH
5F1D
INC DE
If the track is not assigned, the granule is free so BUMP DE which is counting the granules
5F1E
CP 0FFH
Next, test if bit 1 (gran 1) is available
5F20
If granule 1 is available, then JUMP to 5F19H
5F22
INC L
BUMP Register L by 1 to point to the next track in the GAT
5F23
LOOP back to until all tracks are tested (B is zero)
5F25
EX DE,HL
SWAP Register Pair DE with Register Pair HL holds the count of available grans
5F26
LD DE,5F90H
Point Register Pair DE to the array address for the ASCII Value
5F29
GOSUB to 606CH to convert DE to ASCII and then put on the display
5F2C
POP BC
Restore the drive number from the stack into Register Pair BC
5F2D
PUSH BC
Save the drive number in Register Pair BC to the stack
5F2E
GOSUB to 512EH to read the HIT sector for the specified drive. This uses SYS2/SYS
5F31
If NZ is set, then there was an error in that diskette I/O, so JUMP to the general purpose Disk I/O error routine at 554CH
5F34
LD HL,4D40H
Set HL to point to the start of the HIT area for user files
5F37
LD DE,0000H
Zero out DE for math
5F3A
LD A,(HL)
Fetch the HIT index and put it into Register A
5F3B
OR A
Set the status flags
5F3C
If ther eis a file assigned to this slot then JUMP to 5F3FH
5F3E
INC DE
Otherwise, count it as available by BUMPing DE
5F3F
INC L
BUMP Register L by 1 to the next slot in the HIT
5F40
LD A,L
Put Register L (the next slot in the HIT) into Register A for processing/testing
5F41
AND 0E7H
AND it against the end of the slot range
5F43
CP L
Check to see if we reached the end of a slot range
5F44
If the Z Flag is SET, then JUMP to 5F3AH to continue searching
5F46
ADD A,20H
Otherwise, bump 32 bytes to the next slot area
5F48
LD L,A
Put the modified Register L (held in A) back into Register L to form HL to hold the next HIT address
5F49
LOOP back top 5F3AH if the end of the HIT is not reached
5F4B
EX DE,HL
If we are here, then the end of the HIT was reached, so SWAP Register Pair DE with Register Pair HL so that and HL holds the free HIT slots
5F4C
LD DE,5F83H
Point DE to the 5 byte array address for the ASCII HIT slots
5F4F
GOSUB to 606CH to convert DE to ASCII and then put on the display
5F52
LD HL,5F62H
Point HL to the address of the display line for DRIVE X
5F55
GOSUB to 4467H to display the message pointed to by HL
5F58
POP BC
Restore the drive number into Register Pair BC
5F59
INC C
BUMP Register C by 1 to point to the next drive
5F5A
LD A,C
Put Register C (the next drive) into Register A for processing/testing
5F5B
CP 04H
Compare the next drive number against 04H to see if we have exhausted the number of drives
5F5D
Jump to 5EEBH if there are more drives to process
5F5F
JUMP back to SYS1/SYS for the next command

Free Display Messages

5F62
DEFW “DRIVE X — NNNNNNNN MM/DD/YY FILES, “
XX
5F94
DEFW ” GRANS”,0DH
XX

5F9CH – RENAME Command.

5F9C
LD DE,5551H
Put the local DCB address (i.e., 5551H) into Register DE
5F9F
GOSUB to 441CH to copy/edit a filename into the DCB (SYS1/SYS, Code 4). This validates the filename, puts it into the DCB buffer pointed to by DE, and returns NZ if there are illegal characters
5FA2
If NZ is set, we did not get a filename, but we did need one, so JUMP back to 553AH to display the FILE SPEC REQUIRED error message
5FA5
LD A,(DE)
If we are here, then we have a filename, so put the character pointed to by (DE into A
5FA6
LD A,(DE)
If we are here, then we did get a filename, so fetch the current filename character and put it into Register A for processing
5FA8
CP ‘*’
Test for a “*” which would signify a special file
5FAB
If a “* was found, then JUMP to 553AH to display the FILE SPEC REQUIRED error message
5FAB
If we are here, then we have a good filename so GOSUB to 4424H to open the file
5FAE
If NZ is set, then there was an error in that diskette I/O, so JUMP to the general purpose Disk I/O error routine at 554CH
5FB1
LD DE,5571H
Put the local DCB address for the second filename into Register Pair DE
5FB4
GOSUB to 441CH to copy/edit a filename into the DCB (SYS1/SYS, Code 4). This validates the filename, puts it into the DCB buffer pointed to by DE, and returns NZ if there are illegal characters
5FB7
If NZ is set, we did not get a filename, but we did need one, so JUMP back to 553AH to display the FILE SPEC REQUIRED error message
5FBA
LD A,(5552H)
Get the access flags for the selected file
5FBD
AND 07H
MASK Register A against 0000 0111 to keep only bits 0-2 (i.e., the ACCESS permission)
5FBF
CP 03H
Compare the masked Register A against 03H to see if we have permission to RENAME
5FC1
LD A,25H
Put the error code for no permission to RENAME into Register A
5FC3
If NC is set then we do not have permission to RENAME, so JUMP to the general purpose Disk I/O error routine at 554CH
5FC6
LD HL,5571H
Put the local DCB address for the second filename into Register Pair HL
5FC9
LD A,(HL)
Put the character pointed to by HL into Register A
5FCA
CP “:”
If we have a drive number in the destination filename then we have a problem, so test for the “:” to see if that’s the case
5FCC
If the Z Flag is SET, then JUMP to 6028H because we have an error
5FCE
CP 20H
If we are here then there was no drive spec, so let’s test for a space (end of name)
5FD0
If C is set then we are at the end of the name, so JUMP to 5FD5H
5FD2
INC HL
Otherwise, Bump HL to point to the next character in the filename
5FD3
LOOP back to 5FC9H to keep reading filename characters
5FD5
LD (HL),”:”
If we are here, then the filename is completely read. Put in a “:”
5FD7
INC HL
Bump HL to point to the next character after the “:”
5FD8
LD A,(5557H)
Fetch the drive number from 5557H
5FDB
ADD A,30H
Convert the number to ASCII by adding 30H to it (30H=ASCII ‘0’, 31H=ASCII ‘1’, …)
5FDD
LD (HL),A
Put the ASCII converted drive number into HL
5FDE
INC HL
Bump HL to point to the next character
5FDF
LD (HL),03H
Put a 03H terminator into HL
5FE1
LD DE,5571H
Set DE to be the local DCB address for the second filename
5FE4
GOSUB to 4424H to open the file
5FE7
If the Z Flag is SET then the file already exists, which is an error, so JUMP to 604EH
5FEA
CP 18H
If we are here then the file doesn’t already exist but we do need to test for another error
5FEC
If NZ is set, then there was an error in that diskette I/O, so JUMP to the general purpose Disk I/O error routine at 554CH
5FEF
LD BC,(5557H)
Store the drive number in Register C and the directory sector number in Register B
5FF3
PUSH BC
Save the contents of Register Pair BC to the stack
5FF4
GOSUB to 4AC1H to read the directory sector pointed to by BC into the buffer
5FF7
If NZ is set, then there was an error in that diskette I/O, so JUMP to the general purpose Disk I/O error routine at 554CH
5FFA
LD D,H
All is good so we need to get DE to point to the address of the file. First, copy the MSB (H) into the MSB (D)
5FFB
LD A,L
Put Register L (LSB) into Register A for processing/testing
5FFC
ADD A,05H
Add 5 to the LSB
5FFE
LD E,A
Put Register A (The LSB+5) into Register E to finish forming DE
5FFF
LD HL,515DH
Point HL to the SYS2/SYS buffer for new filename
6002
LD BC,000BH
Set BC to be the maximum number of characters in a filename
6005
LDIR
Do a LDIR to copy the new filename from the SYS2/SYS buffer (pointed to by HL) to the to directory file name area (pointed to by DE)
6007
POP BC
Restore the directory sector/drive number from of the stack into Register Pair BC
6008
GOSUB to 4AD6H to rewrite the directory sector
600B
If NZ is set, then there was an error in that diskette I/O, so JUMP to the general purpose Disk I/O error routine at 554CH
600E
GOSUB to 512EH to read the HIT sector for the specified drive. This uses SYS2/SYS
6011
If NZ is set, then there was an error in that diskette I/O, so JUMP to the general purpose Disk I/O error routine at 554CH
6014
LD D,H
Put the MSB of HIT sector buffer (held in H) into D
6015
LD E,B
Put the directory sector number (held in B) into E so that DE will point to the address of the of HIT slot for this file
6016
PUSH BC
Save the directory sector/drive number (held in BC) to the stack
6017
LD HL,515DH
Point HL to the SYS2/SYS buffer for new filename
601A
GOSUB to 509BH to computer the hash code for the designated file pointed to by HL
601D
POP BC
Restore the directory sector/drive number from the stack into Register Pair BC
601E
LD (DE),A
Put the new filename has into the memory location pointed to by DE
601F
GOSUB to the SYS2 subroutine to write updated the HIT
6022
If NZ is set, then there was an error in that diskette I/O, so JUMP to the general purpose Disk I/O error routine at 554CH
6025
JUMP back to SYS1/SYS for the next command

5FCC jumps here if a drive number was found in the rename command

6028
LD HL,6031H
Point HL to the “DRIVE SPECIFICATION ILLEGAL” message
602B
GOSUB to 4467H to display the message pointed to by HL
602E
JUMP to 4030H to go back to SYS1/SYS with an OPTION 2 set

DRIVE SPECIFICATION ILLEGAL message storage area

6031
.TEXT 0AH,”DRIVE SPECIFICATION ILLEGAL”,0DH
XX

5FE7 jumps here if the destination file in the RENAME command already exists

604E
LD HL,6057H
Point HL to the “DUPLICATE FILE NAME” message
6051
GOSUB to 4467H to display the message pointed to by HL
6054
JUMP to 4030H to go back to SYS1/SYS with an OPTION 2 set

DUPLICATE FILE NAME message storage area

6057
DEFB 0AH
6058
DEFW ‘DUPLICATE FILE NAME’
606B
DEFB 0DH

606CH – This routine converts the value held in HL to decimal ASCII. Results stored where DE points.

606C
LD A,” “
Set up Register A with the padding character
606E
LD BC,2710H
Set up BC to 10,000
6071
GOSUB to 608CH to divide by the value in Register Pair BC
6074
LD BC,03E8H
Set up BC to 1,000
6077
GOSUB to 608CH to divide by the value in Register Pair BC
607A
LD BC,0064H
Set up BC to 100
607D
GOSUB to 608CH to divide by the value in Register Pair BC
6080
LD BC,000AH
Set up BC to 10
6083
GOSUB to 608CH to divide by the value in Register Pair BC
6086
LD A,L
Put Register L (the LSB of the value) into Register A for processing/testing
6087
ADD A,30H
Convert the number to ASCII by adding 30H to it (30H=ASCII ‘0’, 31H=ASCII ‘1’, …)
6089
LD (DE),A
Put the value held in Register A into the memory location pointed to by DE
608A
INC DE
BUMP DE to the next byte in the ASCII list
608B
RET
RETURN

This is the division routine for 606CH

608C
PUSH DE
Save the contents of Register Pair DE to the stack
608D
LD E,A
Put Register A (the padding character) into Register E
608E
LD D,0FFH
Since D will be the quotient of the division, initialize it to -1
6090
XOR A
Clear the CARRY flag
6091
INC D
BUMP the quotient (Register D) by 1
6092
SBC HL,BC
Subtract
6094
If NC is set, then the divisor is not greater than the dividend, so we can subtract again … loop back to 6091H
6096
ADD HL,BC
If we are here, the divisor is greater than the dividend so we need to stop subtracting. First, we need to make the dividend (the remainder) positive by undoing that last substraction
6097
LD A,E
Put the pad character into A
6098
LD B,D
Put the quotient for current division into B
6099
POP DE
Restore the storage address for ASCII equivalent of value from the stack into Register Pair DE
609A
LD (DE),A
Put the value held in Register A (the pad character) into the memory location pointed to by DE. This will be replaced with the quotient if the remainder is not zero
609B
INC B
BUMP Register B by 1 to set the status flag for the remainder
609C
DEC B
DECrement Register B by 1 because we only really wanted to set the flag
609D
If the Z Flag is SET then there was no remainder, so JUMP to 60A5H
609F
LD A,B
If we are here, then there was a remainder so we need to deal with it. First, put Register B (the quotient) into Register A for processing/testing
60A0
ADD A,30H
Convert the number to ASCII by adding 30H to it (30H=ASCII ‘0’, 31H=ASCII ‘1’, …)
60A2
LD (DE),A
Put the value held in Register A into the memory location pointed to by DE
60A3
LD A,30H
Put the padding character back into Register A
60A5
INC DE
Bump to the next address in the ASCII list
60A6
RET
RETURN

60A7H – This routine is called by 5E20 to divide the number of records by the record size.

60A7
LD DE,0000H
Set DE to 0000 for math
60AA
LD A,C
Put Register C (divisor) into Register A for processing/testing
60AB
OR A
Set the flags
60AC
If the Z Flag is SET then the divisor is ZERO (which is a no-no), so JUMP to 60C9H
60AE
XOR A
Clear the flags, including the CARRY flag which we will need shortly
60AF
LD B,03H
Set B with the number of bytes in the dividend
60B1
PUSH BC
BC is the number of bytes left to be divided; save that to the stack
60B2
PUSH HL
HL has the address of the current byte to divide; save that to the stack
60B3
LD H,(HL)
Fetch a byte to divide and put it into H
60B4
LD B,08H
Set B to be the number of bits to test in byte
60B6
EX DE,HL
SWAP Register Pair DE with Register Pair HL so that we can shift DE’s value left 1 bit
60B7
ADD HL,HL
Double HL to shift the quotient left
60B8
EX DE,HL
SWAP Register Pair DE with Register Pair HL so that DE holds the quotient
60B9
RLC H
Move the MSB of H to the CARRY flag
60BB
RLA
Take that an shift it into Register A to combine it with the other bits from the dividend
60BC
CP C
Compare the divisory (held in C) against A
60BD
If C is set then the dividend is less than the divisor, so JUMP to 60C1H
60BF
SUB A,C
Otherwise, adjust the dividend so that it is less than the divisor
60C0
INC DE
Bump the quotient by 1
60C1
LOOP back to 60B6H until B is zero (i.e., all bits in the dividend have been tested)
60C3
POP HL
Restore the address of the current byte of the dividend from the stack into Register Pair HL
60C4
INC HL
Bump HL to point to the next byte of the dividend
60C5
POP BC
Restore the quotient
60C6
LOOP back to 60B1H until B is zero
60C8
RET
RETURN

60AC jumps here if the divisor is zero

60C9
LD D,(HL)
Put the MSB of the dividend into D
60CA
INC HL
Bump HL to point to the next byte of the dividend
60CB
LD E,(HL)
Put the LSB of the dividend into E
60CC
RET
RETURN with the two most significant bytes of the dividend as the quotient

60CDH – VERIFY routine

60CD
LD HL,478BH
Point HL to the address of the WRITE routine contained in the nucleus
60D0
If Z is set, then the OFF option was selected, so JUMP to 60D5H to clear the verify flag
60D2
XOR A
Zero A, clear status flags
60D3
INC A
Load a 1 into A to signify AUTO VERIFY on writes
60D4
OR A,A
Set the status flags to non Z
60D5
LD (485EH),A
Save the verify flag to 485EH in nucleus
60D8
RET
RETURN