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

 
ORG 4E00H
4E00
AND 0F0H
MASK the value of Register A against 0F0H (1111 0000). This has the effect of turning off bits 3, 2, 1, and 0, leaving only bits 7, 6, 5, 4 active.
4E02
CP 90H
Compare the value held in Register A against 90H (1001 0000), which would be the “OPEN” function call. Results: If Register A equals 90H, the Z FLAG is set; otherwise the NZ FLAG is set.
4E04
If the Z FLAG (Zero) is set, JUMP to 4E12H.
4E07
CP 0A0H
Compare the value held in Register A against 0A0H (1010 0000), which would be the “INIT” function call. Results: If Register A equals 0A0H, the Z FLAG is set; otherwise the NZ FLAG is set.
4E09
If the Z FLAG (Zero) is set, JUMP to 4F23H.
4E0C
CP 0C0H
Compare the value held in Register A against 0C0H (1100 0000), which would be the “PASSWORD ENCODE” function call. Results: If Register A equals 0C0H, the Z FLAG is set; otherwise the NZ FLAG is set.
4E0E
If the Z FLAG (Zero) is set, JUMP to 5107H.
4E11
RET
RETurn to the caller.

4E12H – Main Overlay Function – “OPEN”. On entry, Register B should be holding the RECORD LENGTH of the file to OPEN.

4E12
GOSUB to 4885H (from SYS00/SYS) to set up for opening a file.
4E15
XOR A
Set Register A to ZERO and clear all Flags.
4E16
LD (4414H),A
Store the value held in Register A into the memory location 4414H.
NOTE: 4414H is the storage location for the NUMBER OF THE OVERLAY CURRENTLY IN MEMORY, so this will force the reload of the overlay.
4E19
LD A,B
LET Register A = Register B (the record length).
4E1A
LD (500EH),A
Store the value held in Register A into the memory location 500EH (which is actually in the middle of a LD A,nn OPCODE and which is the nn, designed to set the record length).
4E1D
LD (501FH),HL
Store the value held in Register HL into the memory location 501FH (which is actually in the middle of a LD DE,nnnn OPCODE and which is the nn).
4E20
4E22
PUSH IX
POP HL
Let Register Pair HL = Index Register IX (i.e., the DCB + 00H).
4E23
GOSUB to 5064H to extract the filespec from the DCB.
4E26
RET NZ
If the NZ FLAG (Not Zero) is set, then the CALL returned an ERROR, so RETurn to the caller with NZ set to indicate an error.
4E27
LD HL,5141H
LET Register Pair HL = 5141H (i.e., the memory location where the SELECTED FILENAME + EXTENSION is stored).
4E2A
GOSUB to 50E7H to generate a hash code for 11 characters (i.e., FILENAME + EXTENSION) pointed to by Register Pair HL and put the resulting hash code into Register A.
4E2D
LD (4E75H),A
Store the value held in Register A (the hash code) into the memory location 4E75H (which is actually in the middle of a CP nn OPCODE and which is the nn). The routine this affects is one which parses the HIT sector in RAM looking for that particular HIT Entry.
4E30
LD DE,5139H
LET Register Pair DE = 5139H, which will be a pointer to the PASSWORD.
4E33
GOSUB to 5107H to encode the password stored in the memory location pointed to by Register Pair DE; results in Register Pair HL.
4E36
LD (514CH),HL
Store the value held in Register HL into the memory location 514CH (the UPDATE password memory location).
4E39
LD (514EH),HL
Store the value held in Register HL into the memory location 514EH (the ACCESS password memory location).
4E3C
LD A,(5137H)
Fetch the value stored at memory location 5137H (the SIDE number) and put it into Register A.
4E3F
INC A
Bump the value stored in Register A by 1.
4E40
If the Z FLAG (Zero) is set, meaning that the SIDE number was FFH (there was a side set), skip the next 2 instructions which select side 0 and JUMP to 4E46H.
4E42
XOR A
Set Register A to ZERO and clear all Flags, so that a 0 can be put into the SIDE NUMBER memory location.
4E43
LD (4463H),A
Store the value held in Register A (which is a 0) into the memory location 4463H.
NOTE: 4463H is the storage location for the old system disk side number.
4E46
LD A,(5138H)
Fetch the value stored at memory location 5138H (i.e., the SELECTED DRIVE NUMBER) and put it into Register A.
4E49
LD C,A
LET Register C = Register A (the drive number).
4E4A
INC A
Bump the value stored in Register A by 1, so that only a FFH (no drives on system) would trigger a Z FLAG.
4E4B
If the NZ FLAG (Not Zero) is set then there is at least one drive on the system, so JUMP to 4E51H.
4E4D
LD A,(42B3H)
Fetch the value stored at memory location 42B3H (i.e., the master drive number) and put it into Register A.
4E50
LD C,A
LET Register C = Register A (i.e., the master drive number).
4E51
GOSUB to 4C6BH to start and check the disk drive stored in Register C.
4E54
If the NZ FLAG (Not Zero) is set, then that CALL returned with an error, so JUMP to 4E7BH.
4E56
GOSUB to 4ABAH (from SYS00/SYS) to read the HIT sector.
4E59
RET NZ
If the NZ FLAG (Not Zero) is set, then the CALL returned an ERROR, so RETurn to the caller with NZ set to indicate an error.
4E5A
PUSH BC
Save Register BC to the top of the stack in preparation for using BC in a LDIR.
4E5B
PUSH DE
Save Register DE to the top of the stack in preparation for using BC in a LDIR.
4E5C
PUSH HL
Save Register HL to the top of the stack in preparation for using BC in a LDIR.
4E5D
LD HL,4300H
LET Register Pair HL = 4300H, which is the memory buffer holding the HIT sector.
4E60
LD DE,4D00H
LET Register Pair DE = 4D00H, which is another memory buffer.
4E63
LD BC,0100H
LET Register Pair BC = 0100H, to move 256 bytes.
4E66
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
4E68
POP HL
Restore Register Pair HL from the top of the STACK.
4E69
POP DE
Restore Register Pair DE from the top of the STACK.
4E6A
POP BC
Restore Register Pair BC from the top of the STACK.
4E6B
LD B,50H
LET Register B = 50H (Decimal: 80) for an 80 iteration DJNZ LOOP.
4E6D
LD HL,4D00H
LET Register Pair HL = 4D00H, which the memory buffer we just copied the HIT sector to.

Beginning of a loop of 80 iterations, where the HIT Table in RAM (pointed to by HL) is checked, one at a time, for a matching HIT Entry.

4E70
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., in the HIT sector in RAM) and put it into Register A.
4E71
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
4E72
If the Z FLAG (Zero) is set, then the HIT entry is unused so JUMP to 4E78H.
4E74
CP nn
Compare the value held in Register A against nn (a value which was set in 4E2DH, which was a HIT Entry). Results: If Register A equals nn, the Z FLAG is set; otherwise the NZ FLAG is set.
4E76
If the Z FLAG (Zero) is set then we have a HIT entry match, so JUMP to 4E9CH.
4E78
INC L
Bump the value stored in Register L by 1 to move to the next HIT entry.
4E79
DJNZ 4E70H
LOOP back to 4E70H until Register B is ZERO.

End of HIT Table Lookup Loop. If we are here, then all 80 entries were checked, and we had no match.

4E7B
LD A,(5138H)
Fetch the value stored at memory location 5138H (i.e., the SELECTED DRIVE NUMBER) and put it into Register A.
4E7E
INC A
Bump the value stored in Register A by 1.
4E7F
If the NZ FLAG (Not Zero) is set then we have scanned all drives (and found nothing), so JUMP to 4E88H.
4E81
INC C
Bump the value stored in Register C (i.e., the drive number we are testing) by 1.
4E82
LD A,(4413H)
Fetch the value stored at memory location 4413H and put it into Register A.
NOTE: 4413H is the storage location for the NUMBER OF DISK DRIVES in the system.
4E85
CP C
Compare the value held in Register A (i.e., the number of disk drives in the system) against the value held in Register C (i.e., the disk drive we are testing). Results:
  • If Register A equals C, the Z FLAG is set.
  • If A < C, the CARRY FLAG will be set.
  • if A >= C, the NO CARRY FLAG will be set.
4E86
If the NC FLAG (No Carry) is set, then A >= C, LOOP back to 4E51H to test the next drive.

If we are here, we have tested all the available drives, and found no HIT entry match.

4E88
LD A,18H
LET Register A = 18H, to prepare for a FILE NOT FOUND error.
4E8A
PUSH AF
Save Register AF (i.e., the error number) to the top of the stack. Note that this is a common jump point when errors are found; it is not just a flow down.
4E8B
LD C,00H
LET Register C = 00H, so as to select drive :0 in the next instruction.
4E8D
GOSUB to 44D4H.
NOTE: 44D4H is the routine which handles DRIVE SELECT (Register C holds the drive number to be used).
4E90
POP AF
Restore Register Pair AF (i.e., the error number) from the top of the STACK.
4E91
RET
RETurn to the caller.

4E92H – Set up for a DRIVE NOT ON SYSTEM error.

4E92
LD A,02H
LET Register A = 02H, to prepare for a DRIVE NOT ON SYSTEM error.
4E94
JUMP to 4E8AH to select drive 0 and RETurn.

4E96H – Restore Register Pair BC and HL, and continue checking HIT entries.

4E96
POP BC
Clear the top entry of the STACK.
4E97
POP HL
Clear the top entry of the STACK.
4E98
POP BC
Restore Register Pair BC from the top of the STACK.
4E99
POP HL
Restore Register Pair HL from the top of the STACK.
4E9A
JUMP to 4E78H to continue checking HIT entries in the RAM buffer of 4D00H.

4E9CH – Continuation of Routine, jumped to if we have found the HIT entry match in the HIT Entry Stored in the RAM Buffer at 4D00H.

4E9C
PUSH HL
Save Register HL to the top of the stack.
4E9D
PUSH BC
Save Register BC to the top of the stack.
4E9E
LD B,L
LET Register B = Register L (i.e., the LOGICAL FILE NUMBER).
4E9F
GOSUB to 4A67H of SYS00/SYS to READ the Directory Entry into Buffer # 1.
4EA2
If the Z FLAG (Zero) is set, then that CALL returned NO ERROR, so continue with 4EA7H.
4EA4
POP BC
Clear the top entry of the STACK.
4EA5
POP HL
Clear the top entry of the STACK.
4EA6
RET
RETurn to the caller.

4EA7H – Continuation of Routine. Jumped to if we have matched the HIT Entry AND Read the Directory Entry into Buffer 1.

4EA7
PUSH HL
Save Register HL to the top of the stack.
4EA8
PUSH BC
Save Register BC to the top of the stack.
4EA9
LD A,05H
LET Register A = 05H to acct as an offset for HL, to get to the FILENAME in the DIRECTORY ENTRY in RAM.
4EAB
ADD A,L
ADD the value held in Register L to Register A (Results held in Register A) to now be 5 bytes in.
4EAC
LD L,A
LET Register L = Register A (i.e., the pointer to the Filename, so now HL points to the FILENAME in the DIRECTORY ENTRY in RAM.
4EAD
LD DE,5141H
LET Register Pair DE = 5141H (i.e., the memory location where the SELECTED FILENAME + EXTENSION is stored).
4EB0
LD B,0BH
LET Register B = 0BH (Decimal: 11) to prepare for a DJNZ loop of 11 bytes.

Top of a loop of 11 characters to compare for a filename match.

4EB2
LD A,(DE)
Fetch the value stored at memory location pointed to by Register Pair DE (i.e., the memory location where the FILENAME TO OPEN is stored) and put it into Register A.
4EB3
CP (HL)
Compare the value held in Register A against the value held in the memory location (HL) (i.e., the FILENAME in the DIRECTORY ENTRY in RAM). Results: If Register A equals (HL), the Z FLAG is set; otherwise the NZ FLAG is set.
4EB4
If the NZ FLAG (Not Zero) is set, then the current character of the filename in RAM didn’t match the current character of the filename we wanted so, JUMP to 4E96H to clear the stack, restore BC and HL, and JUMP to 4E78H.
4EB6
INC HL
Bump the value stored in Register Pair HL by 1 to point to the next byte of the FILENAME in the DIRECTORY ENTRY in RAM.
4EB7
INC DE
Bump the value stored in Register Pair DE by 1 to pointo the next byte of the FILENAME in the FILENAME TO OPEN.
4EB8
DJNZ 4EB2H
LOOP back to 4EB2H until Register B is ZERO.

Bottom of a loop of 11 characters to compare for a filename match. If we’re here then we must have had a filename match, because mismatches JUMP back to the HIT scanning routine above

4EBA
POP BC
Restore Register Pair BC from the top of the STACK.
4EBB
LD A,C
LET Register A = Register C (i.e., the DRIVE NUMBER).
4EBC
LD (5138H),A
Store the value held in Register A into the memory location 5138H (i.e., the SELECTED DRIVE NUMBER).
4EBF
LD IYL,0FFH
Let IYL = FFH.
4EC2
POP HL
Restore Register Pair HL from the top of the STACK.
4EC3
POP AF
Restore Register Pair AF from the top of the STACK.
4EC4
POP AF
Restore Register Pair AF from the top of the STACK.
4EC5
LD IYH,42H
Let IYH = 42H, so now IY = 42FFH.
4EC8
PUSH BC
Save Register BC to the top of the stack.
4EC9
PUSH HL
Save Register HL to the top of the stack.
4ECA
LD B,00H
LET Register B = 00H in preparation to set the access level; starting with FULL.
4ECC
BIT 0,(IY+00H)
Test Bit 0 of Register (IY+00H) to see if we are to skip the password check.
4ED0
RES 0,(IY+00H)
RESet (i.e., set as 0) BIT 0 of Register (IY+00H) to clear the password check flag.
4ED4
If the NZ FLAG (Not Zero) is set then JUMP to 4F1AH to skip the password check.
4ED6
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., the FILE ACCESS BYTE) and put it into Register A.
4ED7
AND 07H
MASK the value of Register A against 07H (0000 0111). This has the effect of turning off bits 7, 6, 5, 4, 3, leaving only bits 2, 1, 0 active.
4ED9
CP 07H
Compare the value held in Register A against 07H. Results: If Register A equals 07H, the Z FLAG is set; otherwise the NZ FLAG is set.
4EDB
If the Z FLAG (Zero) is set then NO ACCESS PERMITTED, so JUMP to 4F14H for a FILE ACCESS DENIED eror.
4EDD
LD C,A
LET Register C = Register A (i.e., the masked FILE ACCESS BYTE).
4EDE
LD A,10H
LET Register A = 10H, to move HL 10H bytes forward.
4EE0
ADD A,L
ADD the value held in Register L to Register A (Results held in Register A).
4EE1
LD L,A
LET Register L = Register A (i.e., put the offset Register L back into Register L).
4EE2
LD DE,(514EH)
Fetch the value stored at memory location 514EH (i.e., the given password) and put it into Register DE.
4EE6
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (the LSB of the actual file password) and put it into Register A.
4EE7
INC HL
Bump the value stored in Register Pair HL by 1 to now point to the MSB of the actual file password.
4EE8
PUSH HL
Save Register HL (i.e., the pointer to the MSB of the actual file password) to the top of the stack.
4EE9
LD H,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., the the MSB of the actual file password) and put it into Register H.
4EEA
LD L,A
LET Register L = Register A (i.e., the LSB of the actual file password), so now HL contains the actual file password.
4EEB
OR A
Set FLAGS based on the contents of Register A to clear the CARRY FLAG.
4EEC
SBC HL,DE
Subtracts the value stored in Register Pair DE (i.e., the given password) and the carry flag from the value stored in Register Pair HL (i.e., the actual file password).
4EEE
POP HL
Restore Register Pair HL from the top of the STACK (i.e., the pointer to the MSB of the actual file password).
4EEF
If the Z FLAG (Zero) is set then the ACTUAL FILE PASSWORD matched the GIVEN PASSWORD, so JUMP to 4F1AH.
4EF1
INC HL
Bump the value stored in Register Pair HL by 1, so that HL now points to the ACCESS PASSWORD.
4EF2
LD B,C
LET Register B = Register C (i.e., the masked FILE ACCESS BYTE).
4EF3
PUSH AF
Save Register AF to the top of the stack since we’re going to need to use Register A for the next 4 instructions.

Just as above, the next 4 instructions copy the ACCESS FILE PASSWORD (initially pointed at by Register Pair HL) into Register Pair HL.

4EF4
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL and put it into Register A.
4EF5
INC HL
Bump the value stored in Register Pair HL by 1.
4EF6
LD H,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL and put it into Register H.
4EF7
LD L,A
LET Register L = Register A.
4EF8
POP AF
Restore Register Pair AF from the top of the STACK.
4EF9
OR A
Set FLAGS based on the contents of Register A.
4EFA
SBC HL,DE
Subtracts the value stored in Register Pair DE (i.e., the given password) and the carry flag from the value stored in Register Pair HL (i.e., the actual ACCESS FILE PASSWORD).
4EFC
If the NZ FLAG (Not Zero) is set then there was NO match, so no access will be granted; JUMP to 4F14H for a FILE ACCESS DENIED.
4EFE
LD A,(427AH)
Fetch the value stored at memory location 427AH (the EXECUTE FILE FLAG) and put it into Register A.
4F01
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
4F02
If the NZ FLAG (Not Zero) is set, then we are OK to execute, so JUMP to 4F1AH.
4F04
LD A,B
LET Register A = Register B (i.e., the masked FILE ACCESS BYTE = the FILE ACCESS LEVEL PERMITTED).
4F05
CP 06H
Compare the value held in Register A against 06H. Results:
  • If Register A equals 06H, the Z FLAG is set.
  • If A < 06H, the CARRY FLAG will be set.
  • if A >= 06H, the NO CARRY FLAG will be set.
4F07
If the C FLAG (Carry) is set, then the FILE ACCESS LEVEL PERMITTED byte is LOWER than EXECUTE, so JUMP to 4F1AH.
4F09
DEC B
DECrement the value stored in Register B by 1, so that it is now set to READ.
4F0A
XOR A
Set Register A to ZERO and clear all Flags.
4F0B
LD (5200H),A
Store the value held in Register A (a 00H) into the memory location 5200H.
4F0E
DEC A
DECrement the value stored in Register A by 1.
4F0F
LD (5201H),A
Store the value held in Register A (a FFH) into the memory location 5201H.
4F12
JUMP to 4F1AH.

4F14H – This routine is jumped to if it is determined that NO ACCESS is PERMITTED.

4F14
POP HL
Restore Register Pair HL from the top of the STACK.
4F15
POP BC
Restore Register Pair BC from the top of the STACK.
4F16
LD A,19H
LET Register A = 19H, to prepare for a FILE ACCESS DENIED error.
4F18
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A; which we know will be NZ (since A is 19H), signifying an ERROR.
4F19
RET
RETurn to the caller.

4F1AH – This routine is jumped to if we are OK with the access level permitted.

4F1A
POP HL
Restore Register Pair HL from the top of the STACK.
4F1B
LD A,B
LET Register A = Register B (i.e., the access code).
4F1C
LD (5011H),A
Store the value held in Register A (i.e., the access code) into the memory location 5011H (which is actually in the middle of a LD A,nn OPCODE and which is the nn, designed to set the ACCESS CODE).
4F1F
POP BC
Restore Register Pair BC from the top of the STACK.
4F20
JUMP to 5006H.

4F23H – Main Overlay Function – “INIT”.

4F23
GOSUB to 4885H to set up.
4F26
GOSUB to 4E15H (i.e., the “OPEN” routine) to try to open the file.
4F29
If the NZ FLAG (Not Zero) is set, then that routine returned an ERROR, so JUMP to 4F3FH.

The next 3 instructionsset the EOF to ZERO.

4F2B
LD (IX+0CH),00H
Store the value held in Register 00H into the memory location IX+0CH.
4F2F
LD (IX+0DH),00H
Store the value held in Register 00H into the memory location IX+0DH.
4F33
LD (IX+08H),00H
Store the value held in Register 00H into the memory location IX+08H.
4F37
LD A,(500EH)
Fetch the value stored at memory location 500EH (which is actually in the middle of a LD A,nn OPCODE and which is the nn, designed to set the record length) and put it into Register A.
4F3A
LD (IX+09H),A
Store the value held in Register A into the memory location IX+09H (i.e., the the LOGICAL RECORD LENGTH in the DCB).
4F3D
XOR A
Set Register A to ZERO and clear all Flags to indicate NO ERROR.
4F3E
RET
RETurn to the caller.

4F3FH – Continuation of INIT routine, where the OPEN attempt returned an ERROR.

4F3F
CP 18H
Compare the value held in Register A against 18H to see if we got a FILE NOT FOUND error. Results:
  • If Register A equals 18H, the Z FLAG is set.
  • If A < 18H, the CARRY FLAG will be set.
  • if A >= 18H, the NO CARRY FLAG will be set.
4F41
RET NZ
If the NZ FLAG (Not Zero) is set, then the file was found, which is a bad thing on an INIT, so RETurn to the caller with NZ set indicating an error.
4F42
LD A,10H
LET Register A = 10H (0001 0000) to indicate a USER FILE/VISIBLE.
4F44
LD (4FCFH),A
Store the value held in Register A (i.e., the code to indicate a USER FILE/VISIBLE) into the memory location 4FCFH.
NOTE: 4FCFH is the middle of a LD (HL),nn OPCODE.
4F47
LD A,(5138H)
Fetch the value stored at memory location 5138H (i.e., the SELECTED DRIVE NUMBER) and put it into Register A.
4F4A
LD C,A
LET Register C = Register A (i.e., the SELECTED DRIVE NUMBER).
4F4B
INC A
Bump the value stored in Register A by 1, so that only a FFH (no drives on system) would trigger a Z FLAG.
4F4C
If the NZ FLAG (Not Zero) is set then there is at least one drive on the system, so JUMP to 4F52H.
4F4E
LD A,(42B3H)
Fetch the value stored at memory location 42B3H (i.e., the master drive number) and put it into Register A.
4F51
LD C,A
LET Register C = Register A (i.e., the master drive number).
4F52
GOSUB to 4C6BH to start the disk drive pointed to by Register C.
4F55
If the NZ FLAG (Not Zero) is set then the CALL returned an error (i.e., there is no diskette), so JUMP to 4F86H.
4F57
If the C FLAG (Carry) is set then the prior routine returned an error (i.e., there is no diskette), so JUMP to 4F86H.
4F59
GOSUB to 4A93H to READ THE GAT SECTOR into a Buffer at 4D00H.
4F5C
RET NZ
If the NZ FLAG (Not Zero) is set, then the CALL returned an ERROR, so RETurn to the caller with NZ set to indicate an error.
4F5D
LD HL,4D00H
LET Register Pair HL = 4D00H (i.e., the start of the RAM buffer holding the GAT sector).
4F60
LD B,28H
LET Register B = 28H (Decimal: 40) to set up for a DJNZ loop of 40 iterations (since the GAT sector has 40 entries).
4F62
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (a GAT entry) and put it into Register A.
4F63
CP 3FH
Compare the value held in Register A against 3FH (i.e., TRACK FULL). Results: If Register A equals 3FH, the Z FLAG is set; otherwise the NZ FLAG is set.
4F65
If the NZ FLAG (Not Zero) is set, then the track is NOT full, so JUMP to 4F6CH.
4F67
INC HL
Bump the value stored in Register Pair HL by 1 to point to the next GAT entry.
4F68
DJNZ 4F62H
LOOP back to 4F62H until Register B is ZERO.
4F6A
If we are here then all we got was TRACK FULL, so the diskette is full. JUMP to 4F86H to try the next disk drive.

4F6CH – Continuation of INIT Routine. Jumped to if we have parsed the GAT and found a track which is not full.

4F6C
GOSUB to 4ABAH.
NOTE: 4ABAH is the SYS00/SYS routine to read the HIT sector into RAM.
4F6F
RET NZ
If the NZ FLAG (Not Zero) is set, then the CALL returned an ERROR, so RETurn to the caller with NZ set to indicate an error.

The next set of instructions save the registers used in a LDIR, sets up for a LDIR to move 256 bytes (i.e., a sector) from Memory Buffer 1 (i.e., 4300H) to Memory Buffer 2 (i.e., 4D00H), and restore the registers.

4F70
PUSH BC
Save Register BC to the top of the stack.
4F71
PUSH DE
Save Register DE to the top of the stack.
4F72
PUSH HL
Save Register HL to the top of the stack.
4F73
LD HL,4300H
LET Register Pair HL = 4300H (i.e., a memory buffer used to store a disk sector).
4F76
LD DE,4D00H
LET Register Pair DE = 4D00H (i.e., a memory buffer used to store a disk sector).
4F79
LD BC,0100H
LET Register Pair BC = 0100H (i.e., a 256 byte sector).
4F7C
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
4F7E
POP HL
Restore Register Pair HL from the top of the STACK.
4F7F
POP DE
Restore Register Pair DE from the top of the STACK.
4F80
POP BC
Restore Register Pair BC from the top of the STACK.
4F81
GOSUB to 50F7H to find an empty directory (i.e., HIT) entry.
4F84
If the Z FLAG (Zero) is set, then an empty HIT entry was found, so JUMP to 4F98H.
4F86
LD A,(5138H)
Fetch the value stored at memory location 5138H and put it into Register A.
NOTE: 5138H is the storage location for the SELECTED DRIVE NUMBER.
4F89
INC A
Bump the value stored in Register A by 1, so that only a FFH (no drives on system) would trigger a Z FLAG.
4F8A
If the NZ FLAG (Not Zero) is set then there is at least one drive on the system, so JUMP to 4F93H.
4F8C
INC C
Bump the value stored in Register C by 1 to go check the next disk drive.
4F8D
LD A,(4413H)
Fetch the value stored at memory location 4413H and put it into Register A.
NOTE: 4413H is the storage location for the NUMBER OF DISK DRIVES in the system.
4F90
CP C
Compare the value held in Register A (i.e., the NUMBER OF DISK DRIVES in the system) against the value held in Register C (i.e., the drive to test next). Results:
  • If Register A equals C, the Z FLAG is set.
  • If A < C, the CARRY FLAG will be set.
  • if A >= C, the NO CARRY FLAG will be set.
4F91
If the NC FLAG (No Carry) is set them if A >= C, so LOOP BACK to 4F52H to test the drive held in Register C.
4F93
LD A,1BH
LET Register A = 1BH to prepare for a DISK FULL error.
4F95
JUMP to 4E8AH to select drive 0 and RETurn.

4F98H – Continuation of INIT Routine. Jumped to if an empty HIT entry was found.

4F98
LD B,L
LET Register B = Register L (i.e., the LOGICAL FILE NUMBER).
4F99
LD A,(4E75H)
Fetch the value stored at memory location 4E75H (i.e., the HASH CODE) and put it into Register A.
4F9C
LD (HL),A
Store the value held in Register A into the memory location pointed to by Register Pair HL (i.e., an entry in the HIT TABLE).

The next set of instructions save the registers used in a LDIR, sets up for a LDIR to move 256 bytes (i.e., a sector) from Memory Buffer 2 (i.e., 4D00H) to Memory Buffer 1 (i.e., 4300H), and restore the registers.

4F9D
PUSH BC
Save Register BC to the top of the stack.
4F9E
PUSH DE
Save Register DE to the top of the stack.
4F9F
PUSH HL
Save Register HL to the top of the stack.
4FA0
LD HL,4D00H
LET Register Pair HL = 4D00H (0100 1101 0000 0000).
4FA3
LD DE,4300H
LET Register Pair DE = 4300H (0100 0011 0000 0000).
4FA6
LD BC,0100H
LET Register Pair BC = 0100H (0000 0001 0000 0000).
4FA9
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
4FAB
POP HL
Restore Register Pair HL from the top of the STACK.
4FAC
POP DE
Restore Register Pair DE from the top of the STACK.
4FAD
POP BC
Restore Register Pair BC from the top of the STACK.
4FAE
GOSUB to 4AC2H to save the HIT TABLE stored in 4300H- to the diskette.
4FB1
RET NZ
If the NZ FLAG (Not Zero) is set, then the CALL returned an ERROR, so RETurn to the caller with NZ set to indicate an error.
4FB2
GOSUB to 4A67H.
NOTE: 4A67H is the SYS00/SYS routine to read the directory entry into a memory buffer.
4FB5
RET NZ
If the NZ FLAG (Not Zero) is set, then the CALL returned an ERROR, so RETurn to the caller with NZ set to indicate an error.
4FB6
PUSH HL
Save Register HL (the pointer in the directory entry) to the top of the stack.
4FB7
LD HL,(514CH)
Fetch the value stored at memory location 514CH and put it into Register HL.
NOTE: 514CH is the storage location for the UPDATE PASSWORD.
4FBA
LD DE,5CEFH
LET Register Pair DE = 5CEFH (0101 1100 1110 1111), which would be a mask for a blank password.
4FBD
OR A
Set FLAGS based on the contents of Register A.
4FBE
SBC HL,DE
Subtracts the value stored in Register Pair DE (i.e., a blank password) and the carry flag from the value stored in Register Pair HL (i.e., the UPDATE PASSWORD).
4FC0
POP HL
Restore Register Pair HL from the top of the STACK.
4FC1
PUSH HL
Save Register HL to the top of the stack.
4FC2
If the Z FLAG (Zero) is set then the password was blank so we have full access. JUMP to 4FCEH.
4FC4
LD A,(4FCFH)
Fetch the value stored at memory location 4FCFH and put it into Register A.
NOTE: 4FCFH is the middle of a LD (HL),nn OPCODE.
4FC7
AND 0F8H
MASK the value of Register A against F8H (1111 1000). This has the effect of turning off bits 2, 1, 0 (which are the security code bits) leaving only bits 7, 6, 5, 4, 3 active.
4FC9
OR 06H
OR Register A against 06H (0000 0110). This has the effect of turning on bits 2 and 1 to enable READ ACCESS.
4FCB
LD (4FCFH),A
Store the value held in Register A into the memory location 4FCFH.
NOTE: 4FCFH is the middle of a LD (HL),nn OPCODE.
4FCE
LD (HL),nn
Store the value held at 4FCFH (which a number of locations in this Overlay use) into the memory location pointed to by Register Pair HL (which is the TYPE BYTE in the Directory).
4FD0
INC HL
Bump the value stored in Register Pair HL by 1 to the next byte of the directory entry.
4FD1
LD A,(421CH)
Fetch the value stored at memory location 421CH and put it into Register A.
NOTE: 421CH is the storage location for the Clock Data: Month.
4FD4
LD (HL),A
Store the value held in Register A (i.e., the current month) into the memory location pointed to by Register Pair HL (i.e., the MONTH byte of the directory entry).
4FD5
INC HL
Bump the value stored in Register Pair HL by 1 to the next byte of the directory entry.
4FD6
LD A,(421AH)
Fetch the value stored at memory location 421AH and put it into Register A.
NOTE: 421AH is the storage location for the Clock Data: Year.
4FD9
LD (HL),A
Store the value held in Register A (i.e., the current year) into the memory location pointed to by Register Pair HL (i.e., the YEAR byte of the directory entry).
4FDA
INC HL
Bump the value stored in Register Pair HL by 1 to the next byte of the directory entry.
4FDB
LD (HL),00H
Store the value held in Register 00H into the memory location pointed to by Register Pair HL (i.e., the EOF byte of the directory entry).
4FDD
INC HL
Bump the value stored in Register Pair HL by 1 to the next byte of the directory entry.
4FDE
LD A,(500EH)
Fetch the value stored at memory location 500EH (which is actually in the middle of a LD A,nn OPCODE and which is the nn, designed to set the record length) and put it into Register A.
4FE1
LD (HL),A
Store the value held in Register A into the memory location pointed to by Register Pair HL (i.e., the LOGICAL RECORD LENGTH byte of the directory entry).
4FE2
INC HL
Bump the value stored in Register Pair HL by 1 to the next byte of the directory entry.
4FE3
PUSH BC
Save Register BC to the top of the stack because we need to use it for something else.
4FE4
LD BC,000FH
LET Register Pair BC = 000FH (Decimal: 15), which is the number of bytes for Filename (8), Extension (3), and both Password hashes (2+2).
4FE7
EX DE,HL
EXchange the value stored in Register Pair HL (a location in the directory entry) with the value stored in Register Pair DE to set up for a LDIR.
4FE8
LD HL,5141H
LET Register Pair HL = 5141H (i.e., the memory location where the SELECTED FILENAME + EXTENSION is stored).
4FEB
LDIR
Move the filename and extension into the directory via LDIR which transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
4FED
EX DE,HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair DE.
4FEE
LD (HL),00H
Store the value held in Register 00H into the memory location pointed to by Register Pair HL (i.e., the EOF byte of the directory entry).
4FF0
INC HL
Bump the value stored in Register Pair HL by 1.
4FF1
LD (HL),00H
Store the value held in Register 00H into the memory location pointed to by Register Pair HL (i.e., the EOF byte of the directory entry).
4FF3
INC HL
Bump the value stored in Register Pair HL by 1 to point to the extents in the directory entry.
4FF4
LD B,1AH
LET Register B = 1AH (Decimal: 26) to prepare for a DJNZ loop to fill all 26 extents in the directory entry with FFH.
4FF6
LD (HL),0FFH
Store the value held in Register FFH (i.e., END of EXTENTS) into the memory location pointed to by Register Pair HL.
4FF8
INC HL
Bump the value stored in Register Pair HL by 1 to point to the next extent storage byte.
4FF9
DJNZ 4FF6H
LOOP back to 4FF6H until Register B is ZERO.
4FFB
POP BC
Restore Register Pair BC from the top of the STACK.
4FFC
GOSUB to 4A7BH to write the DIRECTORY ENTRY held in the memory buffer to diskette.
4FFF
POP HL
Restore Register Pair HL from the top of the STACK.
5000
RET NZ
If the NZ FLAG (Not Zero) is set, then the CALL returned an ERROR, so RETurn to the caller with NZ set to indicate an error.
5001
GOSUB to 5006H to construct an open DCB.
5004
SCF
Set the CARRY FLAG to indicate that the file was successfully created.
5005
RET
RETurn to the caller.

5006H – SUBroutine to Construct an Open File DCB.

5006
EX DE,HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair DE.
5007
5009
PUSH IX
POP HL
Let Register Pair HL = Index Register IX (i.e., the DCB + 00H).
500A
LD (HL),80H
Store 80H (1000 0000) into the memory location pointed to by Register Pair HL (i.e., the DCB + 00H). This will mark the file as being open.
500C
INC HL
Bump the value stored in Register Pair HL by 1 to point to DCB + 01H (i.e., the OPTIONS BYTE).
500D
LD A,nn
LET Register A = nn, where nn has been set by other portions of this Overlay. It is supposed to be holding the LOGICAL RECORD LENGTH.
500F
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A (i.e., the LOGICAL RECORD LENGTH).
5010
LD A,nn
LET Register A = nn, where nn has been set by other portions of this Overlay. It is supposed to be holding the ACCESS CODE. Note: The FLAGS will be set based on the LRL, since this LD doesn’t change flags.
5012
If the Z FLAG (Zero) is set, meaning that we are set for SECTOR I/O, JUMP to 5016H.
5014
OR 80H
OR Register A against 80H (1000 0000) to indicate NON-SECTOR I/O. This has the effect of turning on bits 7.
5016
OR 20H
OR Register A against 20H (0010 0000) to indicate CURRENT SECTOR NOT LOADED. This has the effect of turning on bit 5.
5018
LD (HL),A
Store the value held in Register A into the memory location pointed to by Register Pair HL.
5019
INC HL
Bump the value stored in Register Pair HL by 1 to point to DCB + 02H.
501A
LD (HL),00H
Store the value held in Register 00H into the memory location pointed to by Register Pair HL.
501C
INC HL
Bump the value stored in Register Pair HL by 1 to point to DCB + 03H.
501D
PUSH DE
Save Register DE to the top of the stack.
501E
LD DE,nnnn
LET Register Pair DE = nnnn, where nnnn has been set by other portions of this Overlay. It is supposed to be holding a buffer location.
5021
LD (HL),E
Store the value held in Register E (the LSB of the buffer) into the memory location pointed to by Register Pair HL.
5022
INC HL
Bump the value stored in Register Pair HL by 1 to point to DCB + 04H.
5023
LD (HL),D
Store the value held in Register D (the MSB of the buffer) into the memory location pointed to by Register Pair HL.
5024
INC HL
Bump the value stored in Register Pair HL by 1 to point to DCB + 05H.
5025
POP DE
Restore Register Pair DE from the top of the STACK (so DE should now contain the location of the directory byte).
5026
LD (HL),00H
Store the value held in Register 00H into the memory location pointed to by Register Pair HL so as to set the LSB of the next sector of the file to ZERO.
5028
INC HL
Bump the value stored in Register Pair HL by 1 to point to DCB + 06H.
5029
LD (HL),C
Store the value held in Register C (i.e., the DRIVE NUMBER) into the memory location pointed to by Register Pair HL (i.e., DCB + 06H).
502A
INC HL
Bump the value stored in Register Pair HL by 1 to point to DCB + 07H.
502B
LD (HL),B
Store the value held in Register B into the memory location pointed to by Register Pair HL.
502C
INC HL
Bump the value stored in Register Pair HL by 1 to point to DCB + 08H.
502D
LD A,03H
LET Register A = 03H, as the number of bytes in DE (the directory byte) to skip forward so as to point to the LSB of the end.
502F
ADD A,E
ADD the value held in Register E to Register A (Results held in Register A) to skip DE forward by 3.
5030
LD E,A
LET Register E = Register A to finalize the DE = DE + 3.
5031
LD A,(DE)
Fetch the value stored at memory location pointed to by Register Pair DE (i.e., the LSB of the end) and put it into Register A.
5032
LD (HL),A
Store the value held in Register A into the memory location pointed to by Register Pair HL.
5033
INC HL
Bump the value stored in Register Pair HL by 1 to point to DCB + 09H.
5034
INC DE
Bump the value stored in Register Pair DE by 1 to point to the directory byte + 04.
5035
LD A,(DE)
Fetch the value stored at memory location pointed to by Register Pair DE (i.e., the LOGICAL RECORD LENGTH) and put it into Register A.
5036
LD (HL),A
Store the value held in Register A (i.e., the LOGICAL RECORD LENGTH) into the memory location pointed to by Register Pair HL (i.e., the DCB + 09H).
5037
INC HL
Bump the value stored in Register Pair HL by 1 to point to DCB + 0AH.
5038
LD (HL),00H
Store the value held in Register 00H into the memory location pointed to by Register Pair HL (i.e., DCB + 0AH) so as to set the NMSB of the next to ZERO.
503A
INC HL
Bump the value stored in Register Pair HL by 1 to point to DCB + 0BH.
503B
LD (HL),00H
Store the value held in Register 00H into the memory location pointed to by Register Pair HL (i.e., DCB + 0BH) so as to set the MSB of the next to ZERO.
503D
INC HL
Bump the value stored in Register Pair HL by 1 to point to DCB + 0CH.
503E
LD A,10H
LET Register A = 10H (Decimal: 16) so as to push DE forward another 16 bytes.
5040
ADD A,E
ADD the value held in Register E to Register A (Results held in Register A).
5041
LD E,A
LET Register E = Register A so that DE = DE + 16.
5042
LD A,(DE)
Fetch the value stored at memory location pointed to by Register Pair DE (i.e., the NMSB of the end of the file) and put it into Register A.
5043
LD (HL),A
Store the value held in Register A (i.e., the NMSB of the end of the file) into the memory location pointed to by Register Pair HL (i.e., the DCB + 0CH).
5044
INC HL
Bump the value stored in Register Pair HL by 1 to point to DCB + 0DH.
5045
INC DE
Bump the value stored in Register Pair DE by 1 to point to the MSB of the end of the file.
5046
LD A,(DE)
Fetch the value stored at memory location pointed to by Register Pair DE (i.e., the MSB of the end of the file) and put it into Register A.
5047
LD (HL),A
Store the value held in Register A (i.e., the MSB of the end of the file) into the memory location pointed to by Register Pair HL (i.e., the DCB + 0DH).
5048
INC HL
Bump the value stored in Register Pair HL by 1 to point to DCB + 0EH.
5049
LD A,(4463H)
Fetch the value stored at memory location 4463H and put it into Register A.
NOTE: 4463H is the storage location for the disk side number.
504C
LD (HL),A
Store the value held in Register A (i.e., the disk side number) into the memory location pointed to by Register Pair HL (i.e., the DCB + 0EH).
504D
INC HL
Bump the value stored in Register Pair HL by 1 to point to DCB + 0FH.
504E
LD (HL),00H
Store the value held in Register 00H into the memory location pointed to by Register Pair HL (i.e., the DCB + 0FH).
5050
INC HL
Bump the value stored in Register Pair HL by 1 to point to DCB + 10H.
5051
INC DE
Bump the value stored in Register Pair DE by 1 to point to the EXTENTS information in the directory entry.
5052
EX DE,HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair DE to prepare for a LDIR to swap the directory entry with the DCB.
5053
LD BC,001AH
LET Register Pair BC = 001AH (Decimal: 26) to prepare for a move of the 26 bytes of a directory entry.
5056
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
5058
LD A,(IX+09H)
Fetch the value stored at memory location IX+09H (i.e., the LOGICAL RECORD LENGTH) and put it into Register A.
505B
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
505C
If the Z FLAG (Zero) is set then we are set for SECTOR I/O, so JUMP to 5062H.
505E
SET 7,(IX+01H)
SET (i.e., set as 1) BIT 7 of Register (IX+01H) so as to indicate that this is not a full sector.
5062
XOR A
Set Register A to ZERO and clear all Flags to indicate NO ERROR.
5063
RET
RETurn to the caller.

5064H – SUBroutine to extract the filespec from the DCB.

5064
LD A,0FFH
LET Register A = 0FFH, which will be stored in the SIDE NUMBER memory location.
5066
LD (5137H),A
Store the value held in Register A into the memory location 5137H.
NOTE: 5137H is the storage location for the SIDE number.

The next set of instructions initialize the FILENAME + EXTENSION (11 bytes) into SPACEs.

5069
LD B,0BH
LET Register B = 0BH (Decimal: 11) which is the length of a filename + extension, in preparation for a LDIR.
506B
LD DE,5141H
LET Register Pair DE = 5141H (i.e., the memory location where the SELECTED FILENAME + EXTENSION is stored).
506E
LD A,20H
LET Register A = 20H (ASCII: SPACE).
5070
LD (DE),A
Blank out the filename pointed to by (DE) by store the value held in Register A (i.e., a SPACE) into the memory location pointed to by Register Pair DE.
5071
INC DE
Bump the value stored in Register Pair DE by 1 to point to the next memory location where the FILENAME + EXTENSION will be stored.
5072
DJNZ 5070H
LOOP back to 5070H until Register B is ZERO and all 11 characters of the FILENAME + EXTENSION pointed to by Register Pair DE are converted to SPACEs.

The next set of instructions initialize the PASSWORD (8 bytes) into SPACEs.

5074
LD B,08H
LET Register B = 08H, which is the length of a password, in preparation for a LDIR.
5076
LD DE,5139H
LET Register Pair DE = 5139H (i.e., the memory location where the PASSWORD is stored).
5079
LD (DE),A
Blank out the filename pointed to by (DE) by store the value held in Register A (i.e., a SPACE) into the memory location pointed to by Register Pair DE.
507A
INC DE
Bump the value stored in Register Pair DE by 1.
507B
DJNZ 5079H
LOOP back to 5079H until Register B is ZERO and all 8 characters of the PASSWORD pointed to by Register Pair DE are converted to SPACEs.

The next set of instructions initialize the DRIVE NUMBER to -1.

507D
LD A,0FFH
LET Register A = 0FFH (Decimal: -1).
507F
LD (5138H),A
Store the value held in Register A (i.e., a -1) into the memory location 5138H.
NOTE: 5138H is the storage location for the SELECTED DRIVE NUMBER.

The next set of instructions move the filename to the workspace.

5082
LD DE,5141H
LET Register Pair DE = 5141H (i.e., the memory location where the SELECTED FILENAME + EXTENSION is stored).
5085
LD B,08H
LET Register B = 08H, for the 8 character filename
5087
GOSUB to 50CDH to get the filename, extension, and password (including validation) — routine checks the number of characters set in Register B starting at (HL) and if valid, puts that character into (DE).
508A
LD C,A
LET Register C = Register A (to save the character).
508B
LD A,B
LET Register A = Register B.
508C
CP 08H
Compare the value held in Register A against 08H. Results: If Register A equals 08H, the Z FLAG is set; otherwise the NZ FLAG is set.
508E
If the NZ FLAG (Not Zero) is set then the filename is NOT null, so JUMP to 5094H.
5090
LD A,13H
LET Register A = 13H to set up for a INVALID FILENAME error.
5092
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A. The NZ Flag will be set because we just put a 13H into Register A, so NZ will be set to indicate an error.
5093
RET
RETurn to the caller.

5094H – This is a continuation of the 5064H subroutine to extract the filespec from the DCB. We are here if the filename is NOT null.

5094
LD A,C
LET Register A = Register C (to restore the current character to Register A).
5095
CP 2FH
Compare the value held in Register A against 2FH (ASCII: /). Results: If Register A equals /, the Z FLAG is set; otherwise the NZ FLAG is set.
5097
If the NZ FLAG (Not Zero) is set, meaning that the character is not a / (so there is no need to process an extension), skip over the next instructions (which process an EXTENSION) and JUMP to 50A1H.
5099
LD DE,5149H
LET Register Pair DE = 5149H (i.e., the memory location holding the filename’s extension).
509C
LD B,03H
LET Register B = 03H, to signify that there are 3 bytes in an extension to deal with.
509E
GOSUB to 50CDH to get the filename, extension, and password (including validation) — routine checks the number of characters set in Register B starting at (HL) and if valid, puts that character into (DE).
50A1
CP 2EH
Compare the value held in Register A against 2EH (ASCII: .). Results: If Register A equals ., the Z FLAG is set; otherwise the NZ FLAG is set.
50A3
If the NZ FLAG (Not Zero) is set, meaning that the character is not a . (so there is no need to process a password), skip over the next instructions (which process a PASSWORD) and JUMP to 50ADH.
50A5
LD DE,5139H
LET Register Pair DE = 5139H (i.e., the memory location holding the filename’s password).
50A8
LD B,08H
LET Register B = 08H, to signify that there are 8 bytes in a password to deal with.
50AA
GOSUB to 50CDH to get the filename, extension, and password (including validation) — routine checks the number of characters set in Register B starting at (HL) and if valid, puts that character into (DE).
50AD
CP 3AH
Compare the value held in Register A against 2EH (ASCII: :). Results: If Register A equals :, the Z FLAG is set; otherwise the NZ FLAG is set.
50AF
If the NZ FLAG (Not Zero) is set, meaning that the character is not a . (so there is no need to process a DRIVE NUMBER), skip over the next instructions (which process a DRIVE NUMBER) and JUMP to 50C9H.
50B1
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., the drive number) and put it into Register A.
50B2
SUB 30H
SUBtract the value 30H from Register A to convert an ASCII rendition of a number to its numeric counterpart.
50B4
If the C FLAG (Carry) is set then the number was below 30H, meaning that it was not a number, so JUMP to 50BEH to deal with that error and exit.
50B6
LD C,A
LET Register C = Register A (i.e., the REQUESTED DRIVE NUMBER).
50B7
LD A,(4413H)
Fetch the value stored at memory location 4413H (i.e., the storage location for the NUMBER OF DISK DRIVES in the system) and put it into Register A.
50BA
CP C
Compare the value held in Register A (i.e., the storage location for the NUMBER OF DISK DRIVES in the system) against the value held in Register C (i.e., the REQUESTED DRIVE NUMBER). Results:
  • If the storage location for the NUMBER OF DISK DRIVES in the system (stored in Register A) equals the REQUESTED DRIVE NUMBER (stored in Register C), the Z FLAG is set.
  • If the storage location for the NUMBER OF DISK DRIVES in the system (stored in Register A) < the REQUESTED DRIVE NUMBER (stored in Register C), the CARRY FLAG will be set.
  • if the storage location for the NUMBER OF DISK DRIVES in the system (stored in Register A) >= the REQUESTED DRIVE NUMBER (stored in Register C), the NO CARRY FLAG will be set.
50BB
LD A,C
LET Register A = Register C (i.e., the REQUESTED DRIVE NUMBER).
50BC
If the NC FLAG (No Carry) is set, then drive REQUESTED DRIVE NUMBER is on the system, so JUMP to 50C3H to continue.
50BE
LD A,02H
LET Register A = 13H to set up for a DISK NOT ON SYSTEM error.
50C0
JUMP to 4E8AH to select drive 0 and RETurn.

50C3H – This is a continuation of the 5064H (and then 5094H) subroutine to extract the filespec from the DCB. We are here if the filename, extension, and password have been copied to the work area, and the drive number supplied is valid.

50C3
LD (5138H),A
Store the value held in Register A (i.e., the REQUESTED DRIVE NUMBER) into the memory location 5138H (i.e., the storage location for the SELECTED DRIVE NUMBER).
50C6
INC HL
Bump the value stored in Register Pair HL (i.e., the next character) by 1.
50C7
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., the next character) and put it into Register A.
50C8
INC HL
Bump the value stored in Register Pair HL by 1 (i.e., the next character).
50C9
CP 23H
Compare the value held in Register A against 23H (ASCII: #). Results: If Register A equals #, the Z FLAG is set; otherwise the NZ FLAG is set.
50CB
XOR A
Set Register A to ZERO and clear all Flags.
50CC
RET
RETurn to the caller.

50CDH – SUBroutine to get the filename, extension, and password (including validation). This routine checks the number of characters set in Register B starting at (HL) and if valid, puts that character into (DE).

50CD
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., a character) and put it into Register A.
50CE
INC HL
Bump the value stored in Register Pair HL by 1 to point to the next character to validate.
50CF
JUMP to 50DAH to Validate the number of characters set in Register B contained in the memory locations pointed to by Register Pair HL and put the valid characters into the memory locations pointed to by Register Pair DE. Note: This jumps into the middle of the validation routine because the FIRST character must be A-Z; so it skips the tests of 0-9, which come first in the routine, for the FIRST character.

50D1H – Validate the number of characters set in Register B contained in the memory locations pointed to by Register Pair HL and put the valid characters into the memory locations pointed to by Register Pair DE.

50D1
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., the current character) and put it into Register A.
50D2
INC HL
Bump the value stored in Register Pair HL by 1 to point to the next character.
50D3
CP 30H
Compare the value held in Register A against 30H (ASCII: 0). Results:
  • If Register A equals 0, the Z FLAG is set.
  • If A < 0, the CARRY FLAG will be set.
  • if A >= 0, the NO CARRY FLAG will be set.
50D5
RET C
If the C FLAG (Carry) is set, t hen the character is below a 0, which is an invalid character for a filename, extension, and/or password, so RETurn to the caller with so RETurn to the caller with the C FLAG and NZ FLAG both set.
50D6
CP 3AH
Compare the value held in Register A against 3AH (ASCII: 1 character above 9). Results:
  • If Register A equals one character above (ASCII: 1 character above 9, the Z FLAG is set.
  • If A < ASCII: 1 character above 9, the CARRY FLAG will be set.
  • if A >= ASCII: 1 character above 9, the NO CARRY FLAG will be set.
50D8
If the C FLAG (Carry) is set then the character isn’t a number or below so JUMP to 50E0H to make sure that it isn’t an alphabetical character.
50DA
CP 41H
Compare the value held in Register A against 41H (ASCII: A). Results:
  • If Register A equals A, the Z FLAG is set.
  • If A < A, the CARRY FLAG will be set.
  • if A >= A, the NO CARRY FLAG will be set.
50DC
RET C
If the C FLAG (Carry) is set then A < A, and would therefore be invalid, so RETurn to the caller with the C FLAG and NZ FLAG both set.
50DD
CP 5BH
Compare the value held in Register A against 5BH (ASCII: 1 character above Z). Results:
  • If Register A equals 1 character above Z, the Z FLAG is set.
  • If A < 1 character above Z, the CARRY FLAG will be set.
  • if , the NO CARRY FLAG will be set.
50DF
RET NC
If the NC FLAG (No Carry) is set, then A >= 1 character above Z, meaning we have an invalid character, so RETurn to the caller.
50E0
LD (DE),A
At this point, we have a character between 0-9 and A-Z, so … a valid character. Store the value held in Register A (i.e., the validated character) into the memory location pointed to by Register Pair DE.
50E1
INC DE
Bump the value stored in Register Pair DE by 1 to point to the next character SAVE location.
50E2
DJNZ 50D1H
LOOP back to 50D1H until Register B is ZERO.
50E4
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., the next character)and put it into Register A.
50E5
INC HL
Bump the value stored in Register Pair HL by 1 to point to the next character SOURCE location.
50E6
RET
RETurn to the caller.

50E7H – SUBroutine to Generate a HASH Code for 11 Characters pointed to by (HL) – Hash code returned in Register A.

50E7
LD B,0BH
LET Register B = 0BH (Decimal: 11), for a DJNZ loop of 11 characters.
50E9
LD C,00H
LET Register C = 00H so we start off with a clean slate.
50EB
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., the character of the 11 characters to hash) and put it into Register A.
50EC
INC HL
Bump the value stored in Register Pair HL by 1 to point to the next of the 11 characters to check.

The next 2 instructions are how a hash is calculated. The prior hash is XORed against the current character, and then the bits are rotated left.

50ED
XOR C
eXclusive OR Register C against Register A. The results are stored in Register A.
50EE
RLCA
Rotate the bits in A left (with Bit 7 going into both the CARRY and Bit 0).
50EF
LD C,A
LET Register C = Register A (i.e., the current hashed value).
50F0
DJNZ 50EBH
LOOP back to 50EBH until Register B is ZERO (meaning that 11 characters have been processed).
50F2
LD A,C
LET Register A = Register C (i.e., the FINAL hashed value).
50F3
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
50F4
RET NZ
If the NZ FLAG (Not Zero) is set, then we have SOME value in the hash, so RETurn to the caller.
50F5
INC A
If we are here then the hash was 0, and we don’t want a 0, so we bump the value stored in Register A by 1 to at least make it non-zero.
50F6
RET
RETurn to the caller.

50F7H – SUBroutine to find an empty directory (i.e., HIT) entry.

50F7
LD HL,4D00H
LET Register Pair HL = 4D00H as a buffer for the HIT table.
50FA
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., the hash code) and put it into Register A.
50FB
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
50FC
RET Z
If the Z FLAG (Zero) is set, then we have found an empty entry, so RETurn to the caller.
50FD
INC HL
Bump the value stored in Register Pair HL by 1 to point to the next HIT entry.
50FE
LD A,L
LET Register A = Register L (which is the LSB of the counter, which started at 00H, so L can be used as a bytes processed counter).
50FF
CP 51H
Compare the value held in Register A against 51H (Decimal: 80). 80 is the maximum number of HIT entries. Results:
  • If Register A equals 80, the Z FLAG is set.
  • If A < 80, the CARRY FLAG will be set.
  • if A >= 80, the NO CARRY FLAG will be set.
5101
If the C FLAG (Carry) is set then A < 80, so JUMP to 50FAH to process the next entry.
5103
LD A,1AH
LET Register A = 1AH to set up for a DIRECTORY FULL error.
5105
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A. The NZ Flag will be set because we just put a 13H into Register A, so NZ will be set to indicate an error.
5106
RET
RETurn to the caller.

5107H – MAIN ROUTINE – Password Encode. Encode the password stored in the memory location pointed to by Register Pair DE; results in Register Pair HL.

5107
LD HL,0FFFFH
LET Register Pair HL = 0FFFFH (Decimal: -1) as the default.
510A
LD B,08H
LET Register B = 08H since a password is 8 characters.

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

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

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

5113
LD A,(DE)
Fetch the value stored at memory location pointed to by Register Pair DE (i.e., 1 character of the 8 character password) and put it into Register A.
5114
PUSH DE
Save Register DE (i.e., the location in the password string where Register A got the character from) to the top of the stack.
5115
LD D,A
LET Register D = Register A (i.e., the password character pointed to by (DE)).
5116
LD E,H
LET Register E = Register H (i.e., the MSB of the password).
5117
LD A,L
LET Register A = Register L (i.e., the LSB of the password).
5118
AND 07H
MASK the value of Register A against 07H (0000 0111). This has the effect of turning off bits 7, 6, 5, 4, 3, leaving only bits 2, 1, 0 active.
511A
511B
511C
RRCA
RRCA
Move the bottom 3 bits (2, 1, and 0) to the top 3 bits (7, 6, and 5)
511D
XOR L
eXclusive OR Register L against Register A to merge the masked Register A with the LSB. The results are stored in Register A.
511E
LD L,A
LET Register L = Register A (i.e., the new LSB).
511F
LD H,00H
LET Register H = 00H so that the MSB = 0.
5121
SBC HL,DE
Let PASSWORD = PASSWORD – DE by subtracting the value stored in Register Pair DE and the carry flag from the value stored in Register Pair HL.
5123
ADD HL,HL
Let PASSWORD = PASSWORD * 2 by adding the value held in Register Pair HL to Register Pair HL. The results are held in Register Pair HL.
5124
ADD HL,HL
Let PASSWORD = PASSWORD * 4 by doing that again.
5125
XOR H
eXclusive OR Register H (i.e., the new MSB) against Register A (i.e., the old LSB). The results are stored in Register A.
5126
XOR D
eXclusive OR Register D (i.e., the character) against Register A (i.e., the old LSB / new MSB combination). The results are stored in Register A.
5127
LD D,A
LET Register D = Register A (i.e., the mishmash we just did).
5128
LD A,L
LET Register A = Register L (i.e., the new MSB).
5129
ADD HL,HL
Let PASSWORD = PASSWORD * 2 by adding the value held in Register Pair HL to Register Pair HL. The results are held in Register Pair HL.
512A
XOR H
eXclusive OR Register H (i.e., the NEWER MSB) against Register A (i.e., the prior new MSB). The results are stored in Register A.
512B
XOR E
eXclusive OR Register E (i.e., the old MSB) against Register A. The results are stored in Register A.
512C
LD E,A
LET Register E = Register A.
512D
EX DE,HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair DE so that Register Pair HL now contains the newly encoded password.
512E
POP DE
Restore Register Pair DE (i.e., the location in the pasword string for the character which was just processed) from the top of the STACK.
512F
DEC DE
DECrement the value stored in Register Pair DE by 1 to point to the previous character in the password string.
5130
LOOP back to 5113H until Register B is ZERO (i.e., all 8 characters of the password have been processed, in reverse).
5132
5133
LD A,H
OR L
The Z-80 does not have a way to check a register pair against 0 easily. So a common trick is to let Register A equal one part of the Register Pair and then to OR that against the other part of the Register Pair. Only if both parts of the register pair were 0 will A be 0.
5134
RET NZ
If the NZ FLAG (Not Zero) is set, then Register Pair HL (i.e., the password) was not 0, so RETurn to the caller.
5135
INC L
Bump the value stored in Register L by 1 so we don’t have a password of 0.
5136
RET
RETurn to the caller.

5137H – MEMORY STORAGE LOCATIONS.

5137
00
1 byte memory storage location for SELECTED SIDE (-1 = Any, 0-1=Side 0-1)
5138
00
1 byte memory storage location for SELECTED DRIVE (-1 = Any, 0-3=Drive 0-3)
5139
00 x 8
8 byte memory storage location for PASSWORD
5141
00 x 8
8 byte memory storage location for FILENAME
5149
00 00 00
3 byte memory storage location for EXTENSION
514C
00
1 byte memory storage location for ENCODED UPDATE PASSWORD
514E
00
1 byte memory storage location for ENCODED ACCESS PASSWORD
END 4E00H