4E00H - Request Dispatcher
SYS2/SYS is loaded at 4E00H by the request handler of SYS0/SYS for every request code whose bits 3-0 are 4 (directory entry code 04H) and entered here with Register A = the request code. Bits 6-4 choose the function: 1 (94H, 4424H) open a file or device, 2 (A4H, 4420H) open or create, 4 (C4H, 44B8H) test a drive, 5 (D4H) the hash code of a file name, 6 (E4H) the hash code of a password. The other codes return at once. Registers BC, DE and HL hold the caller's values. The bytes 4E09H-4E0BH are part of the patch SYS2ABC, which the file carries in place (no patch record).
4E00
AND 70H E6 70
Mask Register A (the request code) to bits 6-4, the function number times 10H: 94H gives 10H, A4H 20H, C4H 40H, D4H 50H, E4H 60H.
4E02
CP 10H FE 10
Compare Register A (the function bits) against 10H, function 1, request 94H (4424H): open.
4E04
If the Z FLAG is set (request 94H), JUMP to 4E69H to open the file or device whose specification is in the control block at Register Pair DE.
4E07
CP 20H FE 20
Compare Register A (the function bits) against 20H, function 2, request A4H (4420H): open, or create when the file is not there.
4E09
If the Z FLAG is set (request A4H), JUMP to 4E61H. This jump is part of the patch SYS2ABC.
4E0C
CP 40H FE 40
Compare Register A (the function bits) against 40H, function 4, request C4H (44B8H): test a drive.
4E0E
If the Z FLAG is set (request C4H), JUMP to 5147H to test the drive in Register C.
4E11
CP 50H FE 50
Compare Register A (the function bits) against 50H, function 5, request D4H: the hash code of a name.
4E13
If the Z FLAG is set (request D4H), JUMP to 50CBH with Register Pair HL = the 11 characters of a name and extension.
4E16
CP 60H FE 60
Compare Register A (the function bits) against 60H, function 6, request E4H: the hash code of a password.
4E18
If the Z FLAG is set (request E4H), JUMP to 511EH with Register Pair DE = the 8 characters of a password.
4E1B
RET C9
RETURN to the request handler for any other function (84H, B4H, F4H) with Register A = the function bits and the NZ FLAG: nothing is done.
4E1CH - Open a Device
Reached from 4E7CH when the specification starts with an asterisk: bytes +01H and +02H of the control block are the device's two letters. The device control blocks KI (4015H), DO (401DH), PR (4025H) and those at 43C0H-43FFH (JL, SI, LO and five free ones) are searched by name (bytes +06H-+07H). When one matches, the caller's control block becomes a routed device control block: type 10H, the address of the device found, three bytes 00H and the name. 4E48H-4E60H are part of the patch SYS2ABC. Index Register IX = the caller's control block (49E9H).
4E1C
LD E,(IX+01H) DD 5E 01
Fetch byte +01H of the control block at Index Register IX into Register E: the first letter of the device's name, after the asterisk.
4E1F
LD D,(IX+02H) DD 56 02
Fetch byte +02H of the control block at Index Register IX into Register D: the second letter.
4E22
LD HL,4015H 21 15 40
Point Register Pair HL to 4015H, the device control block KI, the first one searched.
4E25
PUSH HL E5
Save Register Pair HL (the device control block) to the stack.
4E26
LD A,L 7D
Copy Register L (the low byte of the block) into Register A.
4E27
ADD A,06H C6 06
Add 06H to Register A: the place of the name in the block.
4E29
LD L,A 6F
Copy Register A into Register L: Register Pair HL = byte +06H of the block, the first letter of its name.
4E2A
LD A,(HL) 7E
Fetch the first letter of the block's name from Register Pair HL into Register A.
4E2B
INC L 2C
Increment Register L to byte +07H, the second letter. INC does not change the CARRY FLAG; the compare below sets the flags.
4E2C
CP E BB
Compare Register A (the block's first letter) against Register E (the first letter wanted).
4E2D
If the NZ FLAG is set (they differ), JUMP to 4E36H to try the next block.
4E2F
LD A,(HL) 7E
Fetch the second letter of the block's name from Register Pair HL into Register A.
4E30
CP D BA
Compare Register A (the block's second letter) against Register D (the second letter wanted).
4E31
If the NZ FLAG is set (they differ), JUMP to 4E36H to try the next block.
4E33
POP HL E1
Restore Register Pair HL from the stack: the device control block whose name matches.
4E34
JUMP to 4E48H to make the caller's control block a route to it.
4E36
POP AF F1
Restore Register Pair AF from the stack: it only takes the block's address, pushed at 4E25H, off the stack.
4E37
INC L 2C
Increment Register L from byte +07H to the first byte of the next block (8 bytes on).
4E38
If the NZ FLAG is set (Register L did not pass FFH), JUMP to 4E3EH.
4E3A
LD A,08H 3E 08
Load Register A with 08H, the error code DEVICE NOT AVAILABLE: the last block, 43F8H, has been searched.
4E3C
OR A B7
OR Register A with itself: the NZ FLAG is set.
4E3D
RET C9
RETURN with error 08H (through 4A0CH, which restores the caller's registers).
4E3E
LD A,L 7D
Copy Register L (the low byte of the next block) into Register A.
4E3F
CP 2DH FE 2D
Compare Register A against 2DH: 402DH, the address after the PR block, is not a device control block.
4E41
If the NZ FLAG is set (still a block), JUMP back to 4E25H to compare it.
4E43
LD HL,43C0H 21 C0 43
Point Register Pair HL to 43C0H, the device control block JL, where the second group of blocks starts.
4E46
JUMP back to 4E25H to compare the name of the block at Register Pair HL (43C0H).
4E48
LD B,H 44
Copy Register H (the high byte of the block found) into Register B.
4E49
LD C,L 4D
Copy Register L (the low byte of the block found) into Register C: Register Pair BC = the device control block.
4E4A
PUSH IX DD E5
Save Index Register IX (the caller's control block) to the stack.
4E4C
POP HL E1
Restore Register Pair HL from the stack: Register Pair HL = the caller's control block.
4E4D
PUSH HL E5
Save Register Pair HL (the control block) to the stack, to return it in Register Pair DE.
4E4E
LD (HL),10H 36 10
Store 10H to byte +00H of the control block at Register Pair HL: the type of a routed device.
4E50
INC HL 23
Increment Register Pair HL to byte +01H of the control block.
4E51
LD (HL),C 71
Store Register C (the low byte of the device control block) to byte +01H at Register Pair HL.
4E52
INC HL 23
Increment Register Pair HL to byte +02H of the control block.
4E53
LD (HL),B 70
Store Register B (the high byte of the device control block) to byte +02H at Register Pair HL: bytes +01H-+02H are the address the route leads to (SYS0/SYS 44C4H follows it).
4E54
INC HL 23
Increment Register Pair HL to byte +03H of the control block.
4E55
XOR A AF
Set Register A to 00H and set the Z FLAG (XOR A), the result of the open.
4E56
LD (HL),A 77
Store Register A (00H) to byte +03H at Register Pair HL.
4E57
INC HL 23
Increment Register Pair HL to byte +04H of the control block.
4E58
LD (HL),A 77
Store Register A (00H) to byte +04H at Register Pair HL.
4E59
INC HL 23
Increment Register Pair HL to byte +05H of the control block.
4E5A
LD (HL),A 77
Store Register A (00H) to byte +05H at Register Pair HL.
4E5B
INC HL 23
Increment Register Pair HL to byte +06H of the control block.
4E5C
LD (HL),E 73
Store Register E (the first letter of the name) to byte +06H at Register Pair HL.
4E5D
INC HL 23
Increment Register Pair HL to byte +07H of the control block.
4E5E
LD (HL),D 72
Store Register D (the second letter of the name) to byte +07H at Register Pair HL.
4E5F
POP DE D1
Restore Register Pair DE from the stack: the caller's control block.
4E60
RET C9
RETURN with the Z FLAG set and Register A = 00H: the device is open (through 4A0CH, which restores the caller's registers).
4E61H - Function 2 (A4H): Open or Create
Reached through 4420H. As the open below, but a file that is not in the directory is created: on the drive named, or on the first drive from 0 that is ready, not write protected and has a free directory record. A created file has full access. Returns the Z FLAG when the file was opened, the Z FLAG and the CARRY FLAG when it was created. 4E61H-4E68H are part of the patch SYS2ABC.
4E61
GOSUB to 49E9H (SYS0/SYS), the start of a file request without the test of the open bit: Index Register IX = the control block at Register Pair DE, the caller's registers are saved and 4A0CH will restore them.
4E64
XOR A AF
Set Register A to 00H (XOR A): access level 0, full access, for a file that is created.
4E65
JUMP to 4F5EH to store the access level and go on with the open.
4E68
NOP 00
No operation: a byte left over at the end of the patch SYS2ABC (4E61H-4E68H).
4E69H - Function 1 (94H): Open
Reached through 4424H (SYS0/SYS's program loader opens every program file through it, 4CE4H; the overlays are loaded without an open). Register Pair DE = a control block holding a specification as text (from SYS1/SYS 4FCEH), Register Pair HL = the sector buffer, Register B = the record length (00H = 256). The name is looked up in the hash index sector of each drive (or of the drive named) and then in the directory; the password given is checked and the control block is filled in from the directory record. Errors: 13H ILLEGAL FILE NAME, 20H ILLEGAL DRIVE NUMBER, 16H HIT READ ERROR, 11H DIRECTORY READ ERROR, 18H FILE NOT IN DIRECTORY, 19H FILE ACCESS DENIED.
4E69
GOSUB to 49E9H (SYS0/SYS), the start of a file request without the test of the open bit: Index Register IX = the control block at Register Pair DE, the caller's registers are saved and 4A0CH will restore them.
4E6C
LD A,(430FH) 3A 0F 43
Fetch the system flags from 430FH into Register A. Function 2 joins here (4F68H).
4E6F
LD (4F45H),A 32 45 4F
Store Register A (the system flags) to 4F45H, the operand of LD B,00H at 4F44H: bit 2 tells there whether a program is being loaded to run.
4E72
AND F9H E6 F9
Mask Register A to clear bits 2 and 1 (AND F9H): bit 2 a program is being loaded, bit 1 start it without DEBUG.
4E74
LD (430FH),A 32 0F 43
Store Register A (the flags without bits 2 and 1) to 430FH.
4E77
LD A,(IX+00H) DD 7E 00
Fetch byte +00H of the control block at Index Register IX into Register A: the first character of the specification.
4E7A
CP 2AH FE 2A
Compare Register A against 2AH, an asterisk: a device.
4E7C
If the Z FLAG is set (a device specification), JUMP to 4E1CH.
4E7E
LD A,B 78
Copy Register B (the record length) into Register A.
4E7F
LD (51FDH),A 32 FD 51
Store Register A (the record length) to 51FDH, for byte +09H of the control block and byte +04H of a new directory record.
4E82
LD (4FEAH),HL 22 EA 4F
Store Register Pair HL (the sector buffer) to 4FEAH-4FEBH, the operand of LD DE,0000H at 4FE9H, for bytes +03H-+04H of the control block.
4E85
PUSH IX DD E5
Save Index Register IX (the control block) to the stack.
4E87
POP HL E1
Restore Register Pair HL from the stack: Register Pair HL = the control block, the specification as text.
4E88
GOSUB to 5050H to split the specification at Register Pair HL into the name and extension (51E8H, 11 characters), the password (51E0H, 8 characters) and the drive (4E9FH).
4E8B
RET NZ C0
If the NZ FLAG is set (error 13H or 20H in Register A), RETURN with it.
4E8C
LD HL,51E8H 21 E8 51
Point Register Pair HL to 51E8H, the name and extension padded with spaces.
4E8F
GOSUB to 50CBH: the hash code of the 11 characters at Register Pair HL goes to 51DEH.
4E92
LD DE,51E0H 11 E0 51
Point Register Pair DE to 51E0H, the password padded with spaces.
4E95
GOSUB to 511EH: Register Pair HL = the hash code of the 8 characters at Register Pair DE.
4E98
LD (51F3H),HL 22 F3 51
Store Register Pair HL (the password's hash code) to 51F3H-51F4H: the update password of a directory record created here.
4E9B
LD (51F5H),HL 22 F5 51
Store Register Pair HL (the password's hash code) to 51F5H-51F6H: the access password of a created record, and the code checked against an existing one (4F10H).
4E9E
LD A,00H 3E 00
Load Register A with the drive named (operand 4E9FH: FFH when none, set by 5066H or 50A1H).
4EA0
LD C,A 4F
Copy Register A (the drive named, or FFH) into Register C, the drive to search.
4EA1
INC A 3C
Increment Register A: 00H and the Z FLAG when no drive was named (FFH).
4EA2
If the NZ FLAG is set (a drive was named), JUMP to 4EA5H with Register C = that drive.
4EA4
LD C,A 4F
Copy Register A (00H) into Register C: the search starts with drive 0.
4EA5
GOSUB to 5147H to test drive Register C: the Z FLAG is set when it is there and its diskette turns and can be read.
4EA8
If the NZ FLAG is set (the drive is not ready), JUMP to 4EBDH for the next drive.
4EAA
GOSUB to 51B5H to read the hash index sector (sector 1 of the directory cylinder) of drive Register C into 4200H.
4EAD
RET NZ C0
If the NZ FLAG is set (error 16H, HIT READ ERROR, in Register A), RETURN with it.
4EAE
LD A,(HL) 7E
Fetch a byte of the hash index from Register Pair HL (4200H-42FFH) into Register A. Its position (Register L) is the directory entry code of the record it stands for.
4EAF
OR A B7
OR Register A with itself: the Z FLAG is set for 00H, a free record.
4EB0
If the Z FLAG is set (a free record), JUMP to 4EBAH.
4EB2
PUSH HL E5
Save Register Pair HL (the place in the hash index) to the stack.
4EB3
LD HL,51DEH 21 DE 51
Point Register Pair HL to 51DEH, the hash code of the name wanted.
4EB6
CP (HL) BE
Compare Register A (the hash index byte) against the hash code at Register Pair HL (51DEH).
4EB7
POP HL E1
Restore Register Pair HL from the stack: the place in the hash index. POP does not change the flags.
4EB8
If the Z FLAG is set (the same hash code), JUMP to 4ED7H to read the directory record and compare the name.
4EBA
INC L 2C
Increment Register L to the next byte of the hash index.
4EBB
If the NZ FLAG is set (Register L did not pass FFH), JUMP back to 4EAEH.
4EBD
LD A,(4E9FH) 3A 9F 4E
Load Register A with the drive named (the operand 4E9FH of LD A at 4E9EH).
4EC0
INC A 3C
Increment Register A: 00H and the Z FLAG when no drive was named.
4EC1
If the NZ FLAG is set (a drive was named and the file is not on it), JUMP to 4EC9H.
4EC3
INC C 0C
Increment Register C to the next drive of the global search.
4EC4
LD A,C 79
Copy Register C (the next drive) into Register A.
4EC5
CP 08H FE 08
Compare Register A against 08H, the number of drives (the patch SYS2ABC gives this operand: drives 4-7 are searched too).
4EC7
If the C FLAG is set (drive 0-7), JUMP back to 4EA5H to search it.
4EC9
LD A,18H 3E 18
Load Register A with 18H, the error code FILE NOT IN DIRECTORY.
4ECB
OR A B7
OR Register A with itself: the NZ FLAG is set.
4ECC
RET C9
RETURN with error 18H (through 4A0CH, which restores the caller's registers).
4ECDH - A Record That Is Not the File
The hash code matched but the directory record is an extension record or holds another name. The hash index, which the directory read put out of the buffer, is read again and the search goes on after the byte that matched.
4ECD
POP BC C1
Restore Register Pair BC from the stack: the copy pushed at 4EE3H (Register B the entry code, Register C the drive).
4ECE
POP HL E1
Restore Register Pair HL from the stack: the directory record's address, pushed at 4EE2H, dropped.
4ECF
POP BC C1
Restore Register Pair BC from the stack: pushed at 4ED8H, Register C = the drive.
4ED0
GOSUB to 51B5H to read the hash index sector of drive Register C into 4200H again.
4ED3
POP HL E1
Restore Register Pair HL from the stack: the place in the hash index, pushed at 4ED7H. POP does not change the flags.
4ED4
RET NZ C0
If the NZ FLAG is set (error 16H), RETURN with it.
4ED5
JUMP back to 4EBAH to go on with the next byte of the hash index.
4ED7H - The Hash Code Matches
Register L = the directory entry code of the record (bits 4-0 its sector less 2, bits 7-5 its place in the sector), Register C = the drive. The record is read; an extension record (bit 7 of its attribute byte) is passed over; the 11 characters of the name and extension are compared.
4ED7
PUSH HL E5
Save Register Pair HL (the place in the hash index) to the stack.
4ED8
PUSH BC C5
Save Register Pair BC (Register C = the drive) to the stack.
4ED9
LD B,L 45
Copy Register L (the position in the hash index) into Register B: the directory entry code of the record.
4EDA
GOSUB to 4B10H (SYS0/SYS) to read the directory sector of entry Register B on drive Register C into 4200H: Register Pair HL = the record.
4EDD
If the Z FLAG is set (the directory sector was read), JUMP to 4EE2H.
4EDF
POP BC C1
Restore Register Pair BC from the stack: the copy pushed at 4ED8H. POP does not change the flags.
4EE0
POP HL E1
Restore Register Pair HL from the stack: the place in the hash index.
4EE1
RET C9
RETURN with error 11H, DIRECTORY READ ERROR, in Register A.
4EE2
PUSH HL E5
Save Register Pair HL (the directory record) to the stack.
4EE3
PUSH BC C5
Save Register Pair BC (Register B the entry code, Register C the drive) to the stack.
4EE4
BIT 7,(HL) CB 7E
Test bit 7 of the record's attribute byte at Register Pair HL: set in an extension record, which SYS8/SYS writes with the attribute 90H (its 4FB1H) and links from the last extent of the record before (its 4FDCH).
4EE6
If the NZ FLAG is set (an extension record), JUMP to 4ECDH: it holds no name.
4EE8
LD A,05H 3E 05
Load Register A with 05H, the place of the name in a directory record.
4EEA
ADD A,L 85
Add Register L (the low byte of the record) to Register A.
4EEB
LD L,A 6F
Copy Register A into Register L: Register Pair HL = byte +05H of the record, the name.
4EEC
LD DE,51E8H 11 E8 51
Point Register Pair DE to 51E8H, the name and extension wanted.
4EEF
LD B,0BH 06 0B
Load Register B with 0BH: 8 characters of the name and 3 of the extension.
4EF1
LD A,(DE) 1A
Fetch a character of the name wanted from Register Pair DE into Register A.
4EF2
CP (HL) BE
Compare Register A against the character of the record at Register Pair HL.
4EF3
If the NZ FLAG is set (they differ), JUMP to 4ECDH: another file with the same hash code.
4EF5
INC HL 23
Increment Register Pair HL to the next character of the record.
4EF6
INC DE 13
Increment Register Pair DE to the next character of the name wanted.
4EF7
Decrement Register B and JUMP back to 4EF1H while characters are left.
4EF9
POP BC C1
Restore Register Pair BC from the stack: Register B = the entry code, Register C = the drive the file is on.
4EFA
LD A,C 79
Copy Register C (the drive the file was found on) into Register A.
4EFB
LD (4E9FH),A 32 9F 4E
Store Register A (the drive) to 4E9FH, the operand of LD A at 4E9EH.
4EFE
POP HL E1
Restore Register Pair HL from the stack: the directory record.
4EFF
POP AF F1
Restore Register Pair AF from the stack: it takes off the copy of Register Pair BC pushed at 4ED8H.
4F00
POP AF F1
Restore Register Pair AF from the stack: it takes off the place in the hash index pushed at 4ED7H.
4F01
PUSH BC C5
Save Register Pair BC (Register B the entry code, Register C the drive) to the stack.
4F02
PUSH HL E5
Save Register Pair HL (the directory record) to the stack.
4F03H - Check the Password
The hash code of the password given (51F5H) is compared with the record's: a code of CAD2H, or the update password (+10H-+11H), opens the file with full access (level 0); the access password (+12H-+13H) opens it with the level in bits 2-0 of the attribute byte, unless that level is 7. Level 6 (execute only) is given as level 5 (read only) with BREAK left off after the overlay, and when a program is being loaded to run, bit 1 of 430FH makes SYS0/SYS start it without DEBUG. Anything else: error 19H, FILE ACCESS DENIED. No file without passwords is refused: its codes are those of 8 spaces (4296H), the code of a password not given.
4F03
LD A,(HL) 7E
Fetch the record's attribute byte from Register Pair HL into Register A.
4F04
LD (51F9H),A 32 F9 51
Store Register A (the attribute byte) to 51F9H. Nothing reads it after an open; a created file puts 10H there (4F71H).
4F07
AND 07H E6 07
Mask Register A to bits 2-0: the access level of the access password.
4F09
LD C,A 4F
Copy Register A (the access level) into Register C.
4F0A
LD B,00H 06 00
Load Register B with 00H. Nothing uses the value: 4F44H loads Register B again.
4F0C
LD A,10H 3E 10
Load Register A with 10H, the place of the update password's hash code in a directory record.
4F0E
ADD A,L 85
Add Register L (the low byte of the record) to Register A.
4F0F
LD L,A 6F
Copy Register A into Register L: Register Pair HL = byte +10H of the record.
4F10
LD DE,(51F5H) ED 5B F5 51
Fetch the hash code of the password given from 51F5H-51F6H into Register Pair DE.
4F14
PUSH HL E5
Save Register Pair HL (byte +10H of the record) to the stack.
4F15
LD HL,CAD2H 21 D2 CA
Load Register Pair HL with CAD2H, a hash code that opens every file with full access.
4F18
XOR A AF
Set Register A to 00H and clear the CARRY FLAG (XOR A), for the SBC below.
4F19
SBC HL,DE ED 52
SUBtract Register Pair DE (the code given) from Register Pair HL (CAD2H): the Z FLAG is set when they are equal.
4F1B
POP HL E1
Restore Register Pair HL from the stack: byte +10H of the record. POP does not change the flags.
4F1C
If the Z FLAG is set (the code is CAD2H), JUMP to 4F56H with Register A = 00H: full access.
4F1E
LD A,(HL) 7E
Fetch the low byte of the update password's code from Register Pair HL (+10H) into Register A.
4F1F
INC HL 23
Increment Register Pair HL to byte +11H of the directory record.
4F20
PUSH HL E5
Save Register Pair HL (byte +11H) to the stack.
4F21
LD H,(HL) 66
Fetch the high byte of the update password's code from Register Pair HL into Register H.
4F22
LD L,A 6F
Copy Register A (the low byte) into Register L: Register Pair HL = the update password's code.
4F23
XOR A AF
Set Register A to 00H and clear the CARRY FLAG (XOR A).
4F24
SBC HL,DE ED 52
SUBtract Register Pair DE (the code given) from Register Pair HL (the update password's code): the Z FLAG is set when they are equal.
4F26
POP HL E1
Restore Register Pair HL from the stack: byte +11H of the record. POP does not change the flags.
4F27
If the Z FLAG is set (the update password), JUMP to 4F56H with Register A = 00H: full access.
4F29
LD A,C 79
Copy Register C (the access level) into Register A.
4F2A
CP 07H FE 07
Compare Register A against 07H, the level that gives no access at all.
4F2C
If the Z FLAG is set (level 7), JUMP to 4F39H: the access password opens nothing.
4F2E
INC HL 23
Increment Register Pair HL to byte +12H of the record, the access password's code.
4F2F
LD B,C 41
Copy Register C (the access level) into Register B. Nothing uses it: 4F44H loads Register B again.
4F30
LD A,(HL) 7E
Fetch the low byte of the access password's code from Register Pair HL into Register A.
4F31
INC HL 23
Increment Register Pair HL to byte +13H of the directory record.
4F32
LD H,(HL) 66
Fetch the high byte of the access password's code from Register Pair HL into Register H.
4F33
LD L,A 6F
Copy Register A (the low byte) into Register L: Register Pair HL = the access password's code.
4F34
XOR A AF
Set Register A to 00H and clear the CARRY FLAG (XOR A).
4F35
SBC HL,DE ED 52
SUBtract Register Pair DE (the code given) from Register Pair HL (the access password's code): the Z FLAG is set when they are equal.
4F37
If the Z FLAG is set (the access password), JUMP to 4F3FH.
4F39
POP HL E1
Restore Register Pair HL from the stack: the directory record, pushed at 4F02H.
4F3A
POP BC C1
Restore Register Pair BC from the stack: pushed at 4F01H.
4F3B
LD A,19H 3E 19
Load Register A with 19H, the error code FILE ACCESS DENIED.
4F3D
OR A B7
OR Register A with itself: the NZ FLAG is set.
4F3E
RET C9
RETURN with error 19H (through 4A0CH, which restores the caller's registers).
4F3F
LD A,C 79
Copy Register C (the access level) into Register A.
4F40
CP 06H FE 06
Compare Register A against 06H, execute only.
4F42
If the NZ FLAG is set (another level), JUMP to 4F56H with Register A = the level.
4F44
LD B,00H 06 00
Load Register B with the system flags as they were at the open (operand 4F45H, stored at 4E6FH).
4F46
BIT 2,B CB 50
Test bit 2 of Register B: set when SYS0/SYS is loading a program to run it (4CCFH).
4F48
If the Z FLAG is set (not a program being run), JUMP to 4F4FH.
4F4A
LD HL,430FH 21 0F 43
Point Register Pair HL to 430FH, the system flags.
4F4D
SET 1,(HL) CB CE
Set bit 1 of the system flags at Register Pair HL (430FH): SYS0/SYS starts the program at once, not through DEBUG (4CDBH).
4F4F
LD HL,4C4DH 21 4D 4C
Point Register Pair HL to 4C4DH, the operand of LD A,00H at 4C4CH in SYS0/SYS, where the request handler keeps the BREAK vector byte to put back after the overlay.
4F52
LD (HL),C9H 36 C9
Store C9H to 4C4DH at Register Pair HL: BREAK stays off after this request.
4F54
LD A,05H 3E 05
Load Register A with 05H, the read only level: the loader (or the program that opened the file) may read it.
4F56
LD (4FDAH),A 32 DA 4F
Store Register A (the access level) to 4FDAH, the operand of LD A,00H at 4FD9H, for byte +01H of the control block.
4F59
POP HL E1
Restore Register Pair HL from the stack: the directory record.
4F5A
POP BC C1
Restore Register Pair BC from the stack: Register B = the entry code, Register C = the drive.
4F5B
JUMP to 4FCEH to fill in the control block from the record.
4F5EH - Open, or Create When the File Is Not There
Function 2 continued (from 4E65H). Register A = 00H, the access level a created file gets; 4F5EH-4F60H are part of the patch SYS2ABC. The open runs as a subroutine; only FILE NOT IN DIRECTORY (18H) goes on to create. The drives are taken from the one named, or from drive 0: one that is ready, not write protected and has a free record; a hash index that cannot be read ends the request with error 16H. The patch SYS2ABC gave 4F95H (drives 4-7 are tried) and 4F8BH and 4F9AH-4FA4H, so that write protected drives end in error 1AH.
4F5E
LD (4FDAH),A 32 DA 4F
Store Register A (00H) to 4FDAH, the operand of LD A,00H at 4FD9H: full access for a file that is created; an existing file gets its own level at 4F56H.
4F61
PUSH HL E5
Save Register Pair HL (the sector buffer) to the stack.
4F62
LD HL,430FH 21 0F 43
Point Register Pair HL to 430FH, the system flags.
4F65
RES 2,(HL) CB 96
Reset bit 2 of the system flags at Register Pair HL (430FH): this is not a program being loaded to run.
4F67
POP HL E1
Restore Register Pair HL from the stack: the sector buffer.
4F68
GOSUB to 4E6CH to open the file as function 1 does (the start of a file request has been made at 4E61H).
4F6B
RET Z C8
If the Z FLAG is set (the file or device is open), RETURN.
4F6C
CP 18H FE 18
Compare Register A (the error) against 18H, FILE NOT IN DIRECTORY.
4F6E
RET NZ C0
If the NZ FLAG is set (any other error), RETURN with it.
4F6F
LD A,10H 3E 10
Load Register A with 10H, the attribute byte of a new record: bit 4, the record is in use; bits 2-0 level 0.
4F71
LD (51F9H),A 32 F9 51
Store Register A (10H) to 51F9H, the first byte of the new record.
4F74
LD A,(4E9FH) 3A 9F 4E
Load Register A with the drive named (operand 4E9FH of LD A at 4E9EH: FFH when none).
4F77
LD C,A 4F
Copy Register A (the drive named, or FFH) into Register C, the drive to try.
4F78
INC A 3C
Increment Register A: 00H and the Z FLAG when no drive was named.
4F79
If the NZ FLAG is set (a drive was named), JUMP to 4F7CH with Register C = that drive.
4F7B
LD C,A 4F
Copy Register A (00H) into Register C: start with drive 0.
4F7C
GOSUB to 5147H to test drive Register C: the Z FLAG when it is ready, with the CARRY FLAG when the diskette is write protected.
4F7F
If the NZ FLAG is set (not ready), JUMP to 4F8CH for the next drive.
4F81
If the C FLAG is set (write protected), JUMP to 4F8CH for the next drive.
4F83
GOSUB to 51B5H to read the hash index sector of drive Register C into 4200H.
4F86
RET NZ C0
If the NZ FLAG is set (error 16H, HIT READ ERROR, in Register A), RETURN with it.
4F87
GOSUB to 50DDH to find a free record in the hash index: Register Pair HL = its byte, Register L = its entry code.
4F8A
If the Z FLAG is set (a free record), JUMP to 4F9CH to create the file there.
4F8C
LD A,(4E9FH) 3A 9F 4E
Load Register A with the drive named (operand 4E9FH of LD A at 4E9EH).
4F8F
INC A 3C
Increment Register A: 00H and the Z FLAG when no drive was named.
4F90
If the NZ FLAG is set (the drive named cannot take the file), JUMP to 4F98H.
4F92
INC C 0C
Increment Register C to the next drive that may take the new file.
4F93
LD A,C 79
Copy Register C (the next drive) into Register A.
4F94
CP 08H FE 08
Compare Register A against 08H, the number of drives (an operand from the patch SYS2ABC).
4F96
If the C FLAG is set (drive 0-7), JUMP back to 4F7CH to try it.
4F98
LD A,1AH 3E 1A
Load Register A with 1AH, the error code FULL OR WRITE PROTECTED DISK.
4F9A
OR A B7
OR Register A with itself: the NZ FLAG is set.
4F9B
RET C9
RETURN with error 1AH (through 4A0CH, which restores the caller's registers).
4F9CH - Create the Directory Record
Register L = the free record's entry code, Register Pair HL its byte in the hash index, Register C the drive. The hash code of the name goes into the hash index, which is written back; then the record is made in its directory sector: the attribute byte 10H, the record length, the name and extension, the password's code as both passwords, no extents. The control block is filled in from it and the CARRY FLAG set, the mark of a new file.
4F9C
LD B,L 45
Copy Register L (the free record's entry code) into Register B.
4F9D
LD A,(51DEH) 3A DE 51
Fetch the hash code of the name from 51DEH into Register A.
4FA0
LD (HL),A 77
Store Register A (the hash code) to the byte of the hash index at Register Pair HL: the record is taken.
4FA1
GOSUB to 51C7H to write the hash index sector back to drive Register C and read it back: the Z FLAG when it is good.
4FA4
If the Z FLAG is set (written), GOSUB to 4B10H (SYS0/SYS) to read the directory sector of entry Register B: Register Pair HL = the record.
4FA7
RET NZ C0
If the NZ FLAG is set (error 17H, HIT WRITE ERROR, or 11H), RETURN with it.
4FA8
PUSH HL E5
Save Register Pair HL (the record) to the stack.
4FA9
PUSH BC C5
Save Register Pair BC (Register B the entry code, Register C the drive) to the stack.
4FAA
EX DE,HL EB
Exchange Register Pair DE with Register Pair HL: Register Pair DE = the record, the destination of the copies.
4FAB
LD BC,0005H 01 05 00
Load Register Pair BC with 0005H: bytes +00H-+04H of the record.
4FAE
LD HL,51F9H 21 F9 51
Point Register Pair HL to 51F9H: the attribute byte 10H, 00H, 00H, 00H (the end of file offset) and the record length (51FDH).
4FB1
LDIR ED B0
Copy 5 bytes from Register Pair HL (51F9H) to Register Pair DE (the record) with LDIR: bytes +00H-+04H. Register Pair BC ends at 0000H.
4FB3
LD BC,0011H 01 11 00
Load Register Pair BC with 0011H: bytes +05H-+15H of the record, 17 bytes.
4FB6
LD HL,51E8H 21 E8 51
Point Register Pair HL to 51E8H: the name and extension (11), the update and access codes (51F3H-51F6H) and 0000H (51F7H-51F8H, the ending record number).
4FB9
LDIR ED B0
Copy 17 bytes from Register Pair HL (51E8H) to Register Pair DE (byte +05H of the record) with LDIR, Register Pair BC the count. Register Pair DE ends at byte +16H.
4FBB
EX DE,HL EB
Exchange Register Pair DE with Register Pair HL: Register Pair HL = byte +16H of the record, the extents.
4FBC
LD B,0AH 06 0A
Load Register B with 0AH: the 10 bytes of the five extents.
4FBE
LD (HL),FFH 36 FF
Store FFH to the byte at Register Pair HL: no extent.
4FC0
INC HL 23
Increment Register Pair HL to the next byte of the extents.
4FC1
Decrement Register B and JUMP back to 4FBEH while bytes are left.
4FC3
POP BC C1
Restore Register Pair BC from the stack: Register B = the entry code, Register C = the drive.
4FC4
GOSUB to 4B1FH (SYS0/SYS) to write the directory sector of entry Register B back to drive Register C and read it back.
4FC7
POP HL E1
Restore Register Pair HL from the stack: the record. POP does not change the flags.
4FC8
RET NZ C0
If the NZ FLAG is set (error 12H or 0FH), RETURN with it.
4FC9
GOSUB to 4FCEH to fill in the control block from the new record.
4FCC
SCF 37
Set the CARRY FLAG: the file has been created.
4FCD
RET C9
RETURN with the Z FLAG (from 4FCEH) and the CARRY FLAG set.
4FCEH - Fill In the Control Block
Register Pair HL = the directory record, Register B = its entry code, Register C = the drive, Index Register IX = the control block. The 32 bytes are written: +00H 80H (open); +01H the access level, 20H, 80H when the record length is not 256, 08H when the specification ended with an exclamation mark; +02H 00H; +03H-+04H the buffer; +05H 00H; +06H the drive; +07H the entry code; +08H the end of file offset (record +03H); +09H the record length given; +0AH-+0BH 0000H; +0CH-+0DH the ending record number (record +14H-+15H); +0EH-+0FH the first extent (record +16H-+17H); +10H-+1FH up to four more extents, each with the count of granules before it.
4FCE
EX DE,HL EB
Exchange Register Pair DE with Register Pair HL: Register Pair DE = the directory record.
4FCF
PUSH IX DD E5
Save Index Register IX (the control block) to the stack.
4FD1
POP HL E1
Restore Register Pair HL from the stack: Register Pair HL = the control block.
4FD2
LD (HL),80H 36 80
Store 80H to byte +00H of the control block at Register Pair HL: bit 7, the file is open.
4FD4
INC HL 23
Increment Register Pair HL to byte +01H of the control block.
4FD5
LD A,(51FDH) 3A FD 51
Fetch the record length from 51FDH into Register A.
4FD8
OR A B7
OR Register A with itself: the Z FLAG is set for 00H, records of 256 bytes.
4FD9
LD A,00H 3E 00
Load Register A with the access level (operand 4FDAH: stored at 4F56H or 4F5EH). LD does not change the flags.
4FDB
If the Z FLAG is set (record length 256), JUMP to 4FDFH.
4FDD
OR 80H F6 80
OR Register A with 80H: bit 7, record mode (a record length other than 256).
4FDF
OR 20H F6 20
OR Register A with 20H: bit 5, the first sector must be read before the first byte.
4FE1
OR 00H F6 00
OR Register A with the operand 4FE2H: 08H (bit 3, the directory is written after every sector) when the specification ended with an exclamation mark, else 00H (50ADH).
4FE3
LD (HL),A 77
Store Register A to byte +01H of the control block at Register Pair HL.
4FE4
INC HL 23
Increment Register Pair HL to byte +02H of the control block.
4FE5
LD (HL),00H 36 00
Store 00H to byte +02H of the control block at Register Pair HL.
4FE7
INC HL 23
Increment Register Pair HL to byte +03H of the control block.
4FE8
PUSH DE D5
Save Register Pair DE (the directory record) to the stack.
4FE9
LD DE,0000H 11 00 00
Load Register Pair DE with the sector buffer (operand 4FEAH-4FEBH, stored at 4E82H; 0000H in the file).
4FEC
LD (HL),E 73
Store Register E (the low byte of the buffer) to byte +03H at Register Pair HL.
4FED
INC HL 23
Increment Register Pair HL to byte +04H of the control block.
4FEE
LD (HL),D 72
Store Register D (the high byte of the buffer) to byte +04H at Register Pair HL.
4FEF
INC HL 23
Increment Register Pair HL to byte +05H of the control block.
4FF0
POP DE D1
Restore Register Pair DE from the stack: the directory record.
4FF1
LD (HL),00H 36 00
Store 00H to byte +05H of the control block at Register Pair HL: the offset in the buffer.
4FF3
INC HL 23
Increment Register Pair HL to byte +06H of the control block.
4FF4
LD (HL),C 71
Store Register C (the drive) to byte +06H at Register Pair HL.
4FF5
INC HL 23
Increment Register Pair HL to byte +07H of the control block.
4FF6
LD (HL),B 70
Store Register B (the directory entry code) to byte +07H at Register Pair HL.
4FF7
INC HL 23
Increment Register Pair HL to byte +08H of the control block.
4FF8
LD A,03H 3E 03
Load Register A with 03H, the place of the end of file offset in a directory record.
4FFA
ADD A,E 83
Add Register E (the low byte of the record) to Register A.
4FFB
LD E,A 5F
Copy Register A into Register E: Register Pair DE = byte +03H of the record.
4FFC
LD A,(DE) 1A
Fetch the end of file offset from Register Pair DE (record +03H) into Register A.
4FFD
LD (HL),A 77
Store Register A (the end of file offset) to byte +08H of the control block at Register Pair HL.
4FFE
INC HL 23
Increment Register Pair HL to byte +09H of the control block.
4FFF
INC DE 13
Increment Register Pair DE to byte +04H of the record.
5000
LD A,(51FDH) 3A FD 51
Fetch the record length given from 51FDH into Register A (the record's own +04H is not used).
5003
LD (HL),A 77
Store Register A (the record length) to byte +09H of the control block at Register Pair HL.
5004
INC HL 23
Increment Register Pair HL to byte +0AH of the control block.
5005
LD (HL),00H 36 00
Store 00H to byte +0AH of the control block at Register Pair HL: the next record number, low byte.
5007
INC HL 23
Increment Register Pair HL to byte +0BH of the control block.
5008
LD (HL),00H 36 00
Store 00H to byte +0BH of the control block at Register Pair HL: the next record number, high byte.
500A
INC HL 23
Increment Register Pair HL to byte +0CH of the control block.
500B
LD A,10H 3E 10
Load Register A with 10H, the distance from byte +04H to byte +14H of the record.
500D
ADD A,E 83
Add Register E (the low byte of the record pointer) to Register A.
500E
LD E,A 5F
Copy Register A into Register E: Register Pair DE = byte +14H of the record, the ending record number.
500F
LD A,(DE) 1A
Fetch the low byte of the ending record number from Register Pair DE into Register A.
5010
LD (HL),A 77
Store Register A to byte +0CH of the control block at Register Pair HL.
5011
INC HL 23
Increment Register Pair HL to byte +0DH of the control block.
5012
INC DE 13
Increment Register Pair DE to byte +15H of the record.
5013
LD A,(DE) 1A
Fetch the high byte of the ending record number from Register Pair DE into Register A.
5014
LD (HL),A 77
Store Register A to byte +0DH of the control block at Register Pair HL.
5015
INC HL 23
Increment Register Pair HL to byte +0EH of the control block.
5016
INC DE 13
Increment Register Pair DE to byte +16H of the record, the first extent.
5017
LD A,(DE) 1A
Fetch the cylinder of the first extent from Register Pair DE into Register A.
5018
LD (HL),A 77
Store Register A to byte +0EH of the control block at Register Pair HL.
5019
INC HL 23
Increment Register Pair HL to byte +0FH of the control block.
501A
INC DE 13
Increment Register Pair DE to byte +17H of the record.
501B
LD A,(DE) 1A
Fetch the granule byte of the first extent from Register Pair DE into Register A (bits 7-5 the first granule, bits 4-0 the granules less one).
501C
LD (HL),A 77
Store Register A to byte +0FH of the control block at Register Pair HL.
501D
INC HL 23
Increment Register Pair HL to byte +10H, the second extent.
501E
AND 1FH E6 1F
Mask Register A (the granule byte) to bits 4-0: the granules of the extent less one.
5020
INC A 3C
Increment Register A: the granules of the first extent.
5021
LD C,A 4F
Copy Register A into Register C: Register Pair BC counts the granules before the next extent.
5022
LD B,00H 06 00
Load Register B with 00H, the high byte of the count.
5024
LD A,04H 3E 04
Load Register A with 04H: four more extents in the control block.
5026H - The Other Extents
Each of the four extents of the control block gets the count of granules before it (2 bytes), then the cylinder and the granule byte from the record. A cylinder of FEH or FFH in the record ends the copy: FFH is no extent, FEH the link that SYS8/SYS puts in the last extent to an extension record (its 4FDCH). The extents left are filled with FFH.
5026
PUSH AF F5
Save Register Pair AF (Register A = the extents left) to the stack.
5027
INC DE 13
Increment Register Pair DE to the next extent of the record, its cylinder byte.
5028
LD A,(DE) 1A
Fetch the cylinder of the extent from Register Pair DE into Register A.
5029
CP FEH FE FE
Compare Register A (the cylinder byte of the extent) against FEH.
502B
If the NC FLAG is set (FEH or FFH: no more extents here), JUMP to 5045H.
502D
LD (HL),C 71
Store Register C (the low byte of the granules before) to the control block at Register Pair HL.
502E
INC HL 23
Increment Register Pair HL to the next byte of the control block.
502F
LD (HL),B 70
Store Register B (the high byte of the granules before) to the control block at Register Pair HL.
5030
INC HL 23
Increment Register Pair HL to the next byte of the control block.
5031
LD A,(DE) 1A
Fetch the cylinder of the extent from Register Pair DE into Register A again.
5032
LD (HL),A 77
Store Register A (the cylinder) to the control block at Register Pair HL.
5033
INC HL 23
Increment Register Pair HL to the next byte of the control block.
5034
INC DE 13
Increment Register Pair DE to the granule byte of the extent in the record.
5035
LD A,(DE) 1A
Fetch the granule byte from Register Pair DE into Register A.
5036
LD (HL),A 77
Store Register A (the granule byte) to the control block at Register Pair HL.
5037
INC HL 23
Increment Register Pair HL to the next extent of the control block.
5038
AND 1FH E6 1F
Mask Register A (the granule byte) to bits 4-0: the granules of the extent less one.
503A
INC A 3C
Increment Register A: the granules of the extent.
503B
ADD A,C 81
Add Register C (the low byte of the count) to Register A.
503C
LD C,A 4F
Copy Register A (the new low byte) into Register C.
503D
ADC A,B 88
Add Register B and the CARRY FLAG to Register A (ADC): Register A = the low byte plus the high byte plus the carry.
503E
SUB C 91
SUBtract Register C (the low byte) from Register A: Register A = the high byte plus the carry.
503F
LD B,A 47
Copy Register A into Register B: Register Pair BC = the granules before the next extent.
5040
POP AF F1
Restore Register Pair AF from the stack: Register A = the extents left.
5041
DEC A 3D
Decrement Register A, the extents of the control block still to fill.
5042
If the NZ FLAG is set (extents left), JUMP back to 5026H.
5044
RET C9
RETURN with the Z FLAG set and Register A = 00H: the control block is filled in.
5045
POP AF F1
Restore Register Pair AF from the stack: Register A = the extents of the control block not filled (1-4).
5046
RLCA 07
Rotate Register A left: two times the number.
5047
RLCA 07
Rotate Register A left again: four times the number, the bytes left.
5048
LD B,A 47
Copy Register A (the bytes left) into Register B.
5049
LD (HL),FFH 36 FF
Store FFH to the byte of the control block at Register Pair HL: no extent.
504B
INC HL 23
Increment Register Pair HL to the next byte of the control block.
504C
Decrement Register B and JUMP back to 5049H while bytes are left.
504E
XOR A AF
Set Register A to 00H and set the Z FLAG (XOR A).
504F
RET C9
RETURN with the Z FLAG set and Register A = 00H: the control block is filled in.
5050H - Split a File Specification
Register Pair HL = a specification as text (name/ext.password:drive and an exclamation mark, ended by 03H). The name goes to 51E8H-51EFH and the extension to 51F0H-51F2H, padded with spaces, the password to 51E0H-51E7H, the drive to 4E9FH (FFH when there is none), and 08H to 4FE2H when the specification ends with an exclamation mark. Each field must start with a letter. Returns the Z FLAG, or the NZ FLAG with 13H (ILLEGAL FILE NAME: no name) or 20H (ILLEGAL DRIVE NUMBER: a drive other than 0-7).
5050
LD B,0BH 06 0B
Load Register B with 0BH: 11 bytes, the name and extension.
5052
LD DE,51E8H 11 E8 51
Point Register Pair DE to 51E8H, the name and extension.
5055
LD A,20H 3E 20
Load Register A with 20H, a space, the byte the fields are padded with.
5057
LD (DE),A 12
Store Register A (a space) to Register Pair DE.
5058
INC DE 13
Increment Register Pair DE to the next byte of the name and extension.
5059
Decrement Register B and JUMP back to 5057H while bytes are left: 51E8H-51F2H are spaces.
505B
LD B,08H 06 08
Load Register B with 08H: 8 bytes, the password.
505D
LD DE,51E0H 11 E0 51
Point Register Pair DE to 51E0H, the password.
5060
LD (DE),A 12
Store Register A (a space) to Register Pair DE.
5061
INC DE 13
Increment Register Pair DE to the next byte of the password.
5062
Decrement Register B and JUMP back to 5060H while bytes are left: 51E0H-51E7H are spaces.
5064
LD A,FFH 3E FF
Load Register A with FFH, the mark that no drive is named.
5066
LD (4E9FH),A 32 9F 4E
Store Register A (FFH) to 4E9FH, the operand of LD A at 4E9EH: every drive is searched.
5069
LD DE,51E8H 11 E8 51
Point Register Pair DE to 51E8H, where the name goes.
506C
LD B,08H 06 08
Load Register B with 08H: the name has at most 8 characters.
506E
GOSUB to 50B1H to copy the name from Register Pair HL to Register Pair DE: Register A = the character after it, Register B = 08H less the characters copied.
5071
LD C,A 4F
Copy Register A (the character after the name) into Register C.
5072
LD A,B 78
Copy Register B (what is left of the 8) into Register A.
5073
CP 08H FE 08
Compare Register A against 08H: nothing was copied.
5075
If the NZ FLAG is set (a name), JUMP to 507BH.
5077
LD A,13H 3E 13
Load Register A with 13H, the error code ILLEGAL FILE NAME.
5079
OR A B7
OR Register A with itself: the NZ FLAG is set.
507A
RET C9
RETURN with error 13H (through 4A0CH, after the RET NZ at 4E8BH).
507B
LD A,C 79
Copy Register C (the character after the name) into Register A.
507C
CP 2FH FE 2F
Compare Register A against 2FH, a slash: an extension follows.
507E
LD DE,51F0H 11 F0 51
Point Register Pair DE to 51F0H, where the extension goes. LD does not change the flags.
5081
LD B,03H 06 03
Load Register B with 03H: the extension has at most 3 characters.
5083
If the Z FLAG is set (a slash), GOSUB to 50B1H to copy the extension: Register A = the character after it.
5086
CP 2EH FE 2E
Compare Register A (the character after the name or the extension) against 2EH, a period: a password follows.
5088
LD DE,51E0H 11 E0 51
Point Register Pair DE to 51E0H, where the password goes. LD does not change the flags.
508B
LD B,08H 06 08
Load Register B with 08H: the password has at most 8 characters.
508D
If the Z FLAG is set (a period), GOSUB to 50B1H to copy the password: Register A = the character after it.
5090
CP 3AH FE 3A
Compare Register A (the character after the last field) against 3AH, a colon: a drive follows.
5092
If the NZ FLAG is set (no drive), JUMP to 50A6H to look for an exclamation mark.
5094
LD A,(HL) 7E
Fetch the drive's character from Register Pair HL into Register A.
5095
SUB 30H D6 30
SUBtract 30H from Register A: the digit's value.
5097
If the C FLAG is set (below the digit 0), JUMP to 509DH: not a drive.
5099
CP 08H FE 08
Compare Register A (the drive) against 08H, one more than the last drive.
509B
If the C FLAG is set (drive 0-7), JUMP to 50A1H.
509D
LD A,20H 3E 20
Load Register A with 20H, the error code ILLEGAL DRIVE NUMBER.
509F
OR A B7
OR Register A with itself: the NZ FLAG is set.
50A0
RET C9
RETURN with error 20H (through 4A0CH, after the RET NZ at 4E8BH).
50A1
LD (4E9FH),A 32 9F 4E
Store Register A (the drive) to 4E9FH, the operand of LD A at 4E9EH: only this drive is searched.
50A4
INC HL 23
Increment Register Pair HL past the drive's digit.
50A5
LD A,(HL) 7E
Fetch the character after the drive from Register Pair HL into Register A.
50A6
SUB 21H D6 21
SUBtract 21H from Register A: 00H and the Z FLAG for an exclamation mark.
50A8
LD A,08H 3E 08
Load Register A with 08H, bit 3 of byte +01H of the control block. LD does not change the flags.
50AA
If the Z FLAG is set (an exclamation mark), JUMP to 50ADH to store 08H.
50AC
XOR A AF
Set Register A to 00H and set the Z FLAG (XOR A): no exclamation mark.
50AD
LD (4FE2H),A 32 E2 4F
Store Register A (08H or 00H) to 4FE2H, the operand of OR 00H at 4FE1H.
50B0
RET C9
RETURN with the Z FLAG set: the specification is good.
50B1H - Copy a Field
Register Pair HL = the text, Register Pair DE = the destination, Register B = the most characters. 50B1H takes the first character, which must be a letter; 50B5H the others, letters or digits. The copy stops at the first other character, which comes back in Register A with Register Pair HL past it, or after Register B characters, when the next character comes back the same way. Register B returns the characters not used.
50B1
LD A,(HL) 7E
Fetch the first character of the field from Register Pair HL into Register A.
50B2
INC HL 23
Increment Register Pair HL past the first character of the field.
50B3
JUMP to 50BEH: the first character must be a letter.
50B5
LD A,(HL) 7E
Fetch the next character of the field from Register Pair HL into Register A.
50B6
INC HL 23
Increment Register Pair HL past the character of the field.
50B7
CP 30H FE 30
Compare Register A (the character) against 30H, the digit 0.
50B9
RET C D8
If the C FLAG is set (below the digit 0), RETURN with Register A = that character.
50BA
CP 3AH FE 3A
Compare Register A against 3AH, the character after 9.
50BC
If the C FLAG is set (a digit), JUMP to 50C4H to copy it.
50BE
CP 41H FE 41
Compare Register A against 41H, the letter A.
50C0
RET C D8
If the C FLAG is set (below A), RETURN with Register A = that character.
50C1
CP 5BH FE 5B
Compare Register A against 5BH, the character after Z.
50C3
RET NC D0
If the NC FLAG is set (above Z), RETURN with Register A = that character.
50C4
LD (DE),A 12
Store Register A (the letter or digit) to Register Pair DE.
50C5
INC DE 13
Increment Register Pair DE to the next byte of the destination.
50C6
Decrement Register B and JUMP back to 50B5H while characters may be taken.
50C8
LD A,(HL) 7E
Fetch the character after a full field from Register Pair HL into Register A.
50C9
INC HL 23
Increment Register Pair HL past the character after the field.
50CA
RET C9
RETURN with Register A = the character after the field and Register B = 00H.
50CBH - Function 5 (D4H): The Hash Code of a Name
Register Pair HL = the 11 characters of a name and extension, padded with spaces. Each character is exclusive ORed into Register A, which is rotated left after each; a result of 00H is made 01H, since 00H marks a free record in the hash index. Returns Register A = the code, Register H and Register L both = the code, and the code at 51DEH and 51DFH. SYS6/SYS asks for it through request D4H.
50CB
LD B,0BH 06 0B
Load Register B with 0BH: 11 characters, the name and the extension.
50CD
XOR A AF
Set Register A to 00H (XOR A), the code so far.
50CE
XOR (HL) AE
Exclusive OR Register A with the character at Register Pair HL.
50CF
INC HL 23
Increment Register Pair HL to the next character.
50D0
RLCA 07
Rotate Register A (the code so far) left, bit 7 into bit 0.
50D1
Decrement Register B and JUMP back to 50CEH while characters are left.
50D3
OR A B7
OR Register A (the code) with itself: the Z FLAG is set for 00H.
50D4
If the NZ FLAG is set (not 00H), JUMP to 50D7H.
50D6
INC A 3C
Increment Register A from 00H to 01H, a code the hash index can hold.
50D7
LD L,A 6F
Copy Register A (the code) into Register L, the low byte of the pair.
50D8
LD H,A 67
Copy Register A (the code) into Register H, the high byte of the pair.
50D9
LD (51DEH),HL 22 DE 51
Store Register Pair HL to 51DEH-51DFH: the code in both bytes; 51DEH is the byte compared with the hash index (4EB6H) and put into it (4F9DH).
50DC
RET C9
RETURN with Register A = the code (and Register H and Register L).
50DDH - Find a Free Record in the Hash Index
The hash index of drive Register C is at 4200H. The records of the directory sectors (sector 2 up, as many as the cylinder has sectors less 2) are searched from a place chosen by the tick counter 4040H to the end, then from the start. The first two records of sectors 2-9 (entry codes 00H-07H and 20H-27H) are kept for the system files and never taken. Returns the Z FLAG with Register Pair HL on the free byte (Register L = its entry code), or the NZ FLAG when every record is taken. 50FDH and 510EH are bytes of the patch SYS2ABC, which stops the search from running on without end when the directory is full.
50DD
LD A,(4040H) 3A 40 40
Fetch the tick counter from 4040H into Register A: a starting place that changes from one creation to the next.
50E0
PUSH AF F5
Save Register Pair AF (Register A = the tick) to the stack.
50E1
LD A,07H 3E 07
Load Register A with 07H, the place in a drive code table of the byte that gives the sectors.
50E3
GOSUB to 4797H (SYS0/SYS) to fetch byte +07H of the drive code table of drive Register C into Register A: bits 4-0 the highest sector number of a track, bits 7-5 the count less one that multiplies it.
50E6
PUSH DE D5
Save Register Pair DE (the caller's) to the stack.
50E7
LD D,A 57
Copy Register A (byte +07H of the drive code table) into Register D.
50E8
AND 1FH E6 1F
Mask Register A to bits 4-0: the highest sector number.
50EA
LD E,A 5F
Copy Register A (the highest sector number) into Register E.
50EB
INC E 1C
Increment Register E: the sectors of a track.
50EC
XOR D AA
Exclusive OR Register A with Register D (byte +07H): Register A = bits 7-5 alone.
50ED
RLCA 07
Rotate Register A left (bits 7-5 move toward bits 0-2).
50EE
RLCA 07
Rotate Register A (bits 7-5 of byte +07H) left again.
50EF
RLCA 07
Rotate Register A left again: bits 7-5 are now bits 2-0, the count less one.
50F0
INC A 3C
Increment Register A: the count that multiplies the sectors of a track.
50F1
GOSUB to 4B6CH (SYS0/SYS): Register A = Register A x Register E, the sectors of a cylinder.
50F4
POP DE D1
Restore Register Pair DE from the stack: the caller's.
50F5
SUB 02H D6 02
SUBtract 02H from Register A: the sectors of directory records (the allocation table and the hash index take sectors 0 and 1).
50F7
LD (510CH),A 32 0C 51
Store Register A to 510CH, the operand of CP 00H at 510BH: the sector numbers allowed are below it.
50FA
POP AF F1
Restore Register Pair AF from the stack: Register A = the tick.
50FB
LD L,A 6F
Copy Register A (the tick) into Register L: the first entry code looked at. Register H is 42H (the hash index at 4200H).
50FC
GOSUB to 5103H to search from there to the end.
50FF
RET Z C8
If the Z FLAG is set (a free record), RETURN with Register Pair HL on it.
5100
LD L,3FH 2E 3F
Load Register L with 3FH, so that the increment below starts the second search at 40H, record 2 of the first directory sector.
5102
INC L 2C
Increment Register L: record 0 of the next sector (or 40H on the second search).
5103
LD A,L 7D
Copy Register L (the entry code) into Register A.
5104
AND D8H E6 D8
Mask Register A to bits 7, 6, 4 and 3: 00H for records 0 and 1 of sectors 2-9.
5106
If the Z FLAG is set (a record kept for the system), JUMP to 5112H to pass over it.
5108
LD A,L 7D
Copy Register L (the entry code) into Register A.
5109
AND 1FH E6 1F
Mask Register A to bits 4-0: the directory sector less 2.
510B
CP 00H FE 00
Compare Register A against the sectors of directory records (operand 510CH, stored at 50F7H).
510D
If the NC FLAG is set (past the last directory sector), JUMP to 511CH to return with the NZ FLAG.
510F
LD A,(HL) 7E
Fetch the hash index byte of the record from Register Pair HL into Register A.
5110
OR A B7
OR Register A with itself: the Z FLAG is set for 00H, a free record.
5111
RET Z C8
If the Z FLAG is set (free), RETURN with Register Pair HL on it.
5112
LD A,L 7D
Copy Register L (the entry code) into Register A.
5113
ADD A,20H C6 20
Add 20H to Register A: the next record of the same sector.
5115
LD L,A 6F
Copy Register A (the entry code of the next record) into Register L.
5116
If the NC FLAG is set (record 1-7, no carry out of bit 7), JUMP back to 5103H to test it.
5118
CP 1FH FE 1F
Compare Register A (the entry code of record 0 again, after the carry) against 1FH, the last sector number the code can hold.
511A
If the NZ FLAG is set (not the last), JUMP back to 5102H for the next sector.
511C
OR A B7
OR Register A with itself: the NZ FLAG is set (Register A holds a sector number other than 00H).
511D
RET C9
RETURN with the NZ FLAG: no free record from here.
511EH - Function 6 (E4H): The Hash Code of a Password
Register Pair DE = 8 characters, padded with spaces. The characters are taken from the last to the first and mixed into Register Pair HL, which starts at FFFFH, with exclusive ORs and shifts only. Returns Register Pair HL = the code. 8 spaces give 4296H, the code of a file with no password. FORMAT/CMD (its 6DF1H), BACKUP/CMD and SYS6/SYS ask for it through request E4H.
511E
LD HL,FFFFH 21 FF FF
Load Register Pair HL with FFFFH, the code before the first character.
5121
LD B,08H 06 08
Load Register B with 08H: the 8 characters of the password.
5123
LD A,E 7B
Copy Register E (the low byte of the password's address) into Register A.
5124
ADD A,07H C6 07
Add 07H to Register A: the low byte of the last character's address.
5126
LD E,A 5F
Copy Register A into Register E: Register Pair DE = the last character.
5127
LD A,(DE) 1A
Fetch the character from Register Pair DE into Register A.
5128
PUSH DE D5
Save Register Pair DE (the place of the character) to the stack.
5129
LD D,A 57
Copy Register A (the character) into Register D.
512A
LD E,H 5C
Copy Register H (the high byte of the code) into Register E.
512B
LD A,L 7D
Copy Register L (the low byte of the code) into Register A.
512C
AND 07H E6 07
Mask Register A (the low byte of the code) to bits 2-0.
512E
RRCA 0F
Rotate Register A right (bits 2-0 move toward bits 7-5).
512F
RRCA 0F
Rotate Register A (bits 2-0 of the low byte) right again.
5130
RRCA 0F
Rotate Register A right again: bits 2-0 of Register L are now bits 7-5.
5131
XOR L AD
Exclusive OR Register A with Register L: Register A = Register L with its bits 2-0 exclusive ORed into bits 7-5.
5132
LD L,A 6F
Copy Register A (the mixed low byte) into Register L.
5133
LD H,00H 26 00
Load Register H with 00H: Register Pair HL = that byte.
5135
ADD HL,HL 29
Add Register Pair HL to itself: 2 times the mixed byte.
5136
ADD HL,HL 29
Add Register Pair HL to itself: 4 times the mixed byte.
5137
ADD HL,HL 29
Add Register Pair HL to itself: 8 times the mixed byte.
5138
ADD HL,HL 29
Add Register Pair HL to itself: 16 times, the byte shifted left 4 bits.
5139
XOR H AC
Exclusive OR Register A (the byte) with Register H (its bits 7-4).
513A
XOR D AA
Exclusive OR Register A with Register D (the character).
513B
LD D,A 57
Copy Register A into Register D: the new high byte of the code.
513C
LD A,L 7D
Copy Register L (the byte shifted left 4 bits, low part) into Register A.
513D
ADD HL,HL 29
Add Register Pair HL to itself: the byte shifted left 5 bits.
513E
XOR H AC
Exclusive OR Register A with Register H (bits 7-3 of the byte).
513F
XOR E AB
Exclusive OR Register A with Register E (the old high byte of the code).
5140
LD E,A 5F
Copy Register A into Register E: the new low byte of the code.
5141
EX DE,HL EB
Exchange Register Pair DE with Register Pair HL: Register Pair HL = the new code.
5142
POP DE D1
Restore Register Pair DE from the stack: the place of the character.
5143
DEC DE 1B
Decrement Register Pair DE to the character before.
5144
Decrement Register B and JUMP back to 5127H while characters are left.
5146
RET C9
RETURN with Register Pair HL = the hash code of the password.
5147H - Function 4 (C4H): Test a Drive
Reached through 44B8H, and from 4EA5H and 4F7CH. Register C = the drive. A drive whose table does not start with C3H (JP) is not there: the NZ FLAG. A rigid disk (bit 3 of byte +03H) is taken as ready. A floppy drive is selected and must show the index hole of its diskette, going and coming, within 11 ticks (275 ms); then the allocation table (sector 0 of the directory cylinder) is read and its bytes CCH-CDH set the last cylinder (+06H) and the two sides bit (+04H bit 5) of the drive code table. Returns the Z FLAG and Register A = 00H when the drive is ready, with the CARRY FLAG set when the diskette is write protected; the NZ FLAG when not. SYS6/SYS calls 44B8H too.
5147
PUSH IY FD E5
Save Index Register IY (the caller's) to the stack.
5149
GOSUB to 478FH (SYS0/SYS): Index Register IY = the drive code table of drive Register C.
514C
LD A,(IY+00H) FD 7E 00
Fetch byte +00H of the drive code table at Index Register IY into Register A.
514F
CP C3H FE C3
Compare Register A against C3H, the JP of a drive that is there (C9H when not).
5151
If the NZ FLAG is set (no drive), JUMP to 51A1H to return with the NZ FLAG.
5153
LD A,(IY+03H) FD 7E 03
Fetch byte +03H of the drive code table at Index Register IY into Register A.
5156
CPL 2F
Complement Register A: bit 3 becomes 0 for a rigid disk.
5157
AND 08H E6 08
Mask Register A to bit 3: the Z FLAG is set for a rigid disk; AND also clears the CARRY FLAG.
5159
If the Z FLAG is set (a rigid disk), JUMP to 51A1H to return with the Z FLAG, Register A = 00H, not write protected.
515B
PUSH DE D5
Save Register Pair DE (the caller's) to the stack.
515C
LD D,(IY+05H) FD 56 05
Fetch byte +05H of the drive code table at Index Register IY into Register D: the cylinder the head is on.
515F
LD E,00H 1E 00
Load Register E with 00H, sector 0, for the seek below.
5161
GOSUB to 475EH (SYS0/SYS) to select drive Register C and seek to cylinder Register D, where the head is already: the drive is selected and its motor started.
5164
GOSUB to 4759H (SYS0/SYS) to wait until the controller is not busy.
5167
LD A,(4040H) 3A 40 40
Fetch the tick counter from 4040H into Register A (40 ticks a second).
516A
ADD A,0BH C6 0B
Add 0BH to Register A (the tick): 11 ticks, 275 ms, from now.
516C
LD D,A 57
Copy Register A (the tick of the time out) into Register D.
516D
GOSUB to 51A4H: the Z FLAG is set while the index hole is not under the sensor (status bit 1 clear).
5170
If the NZ FLAG is set (the hole is there), JUMP back to 516DH to wait until it has gone.
5172
GOSUB to 51A4H to test the index hole again, with the same time out in Register D.
5175
If the Z FLAG is set (no hole), JUMP back to 5172H to wait for the next one: the diskette turns.
5177
PUSH AF F5
Save Register Pair AF (Register A = the controller's status, with bit 6 WRITE PROTECT) to the stack.
5178
GOSUB to 4B65H (SYS0/SYS): Register D = the directory cylinder of drive Register C.
517B
LD HL,4200H 21 00 42
Point Register Pair HL to 4200H, the sector buffer.
517E
LD E,00H 1E 00
Load Register E with 00H: sector 0 of the directory cylinder, the allocation table.
5180
GOSUB to 4B45H (SYS0/SYS) to read the directory sector at Register D, Register E of drive Register C into 4200H.
5183
If the NZ FLAG is set (it could not be read), JUMP to 51B0H to return with the NZ FLAG.
5185
LD DE,(42CCH) ED 5B CC 42
Fetch bytes CCH-CDH of the allocation table from 42CCH into Register Pair DE: Register E = the cylinders past 35, Register D = bits 2-0 the granules of a cylinder less one, bit 5 two sides.
5189
LD A,22H 3E 22
Load Register A with 22H, cylinder 34, the last of 35.
518B
ADD A,E 83
Add Register E (the cylinders past 35) to Register A: the last cylinder of this diskette.
518C
LD (IY+06H),A FD 77 06
Store Register A (the last cylinder) to byte +06H of the drive code table at Index Register IY.
518F
RES 5,(IY+04H) FD CB 04 AE
Reset bit 5 of byte +04H of the drive code table at Index Register IY: one side.
5193
BIT 5,D CB 6A
Test bit 5 of Register D (byte CDH of the allocation table): two sides.
5195
If the Z FLAG is set (one side), JUMP to 519BH.
5197
SET 5,(IY+04H) FD CB 04 EE
Set bit 5 of byte +04H of the drive code table at Index Register IY: two sides.
519B
POP AF F1
Restore Register Pair AF from the stack: Register A = the status saved at 5177H.
519C
RLCA 07
Rotate Register A left: bit 6 (WRITE PROTECT) moves to bit 7.
519D
AND 80H E6 80
Mask Register A to bit 7, the WRITE PROTECT bit of the status.
519F
ADD A,A 87
Add Register A to itself: Register A = 00H with the Z FLAG set, and bit 7 (write protected) goes into the CARRY FLAG.
51A0
POP DE D1
Restore Register Pair DE from the stack: the caller's. POP does not change the flags.
51A1
POP IY FD E1
Restore Index Register IY from the stack: the caller's.
51A3
RET C9
RETURN with the Z FLAG (ready, the CARRY FLAG set when write protected) or the NZ FLAG (not ready).
51A4H - Read the Index Hole With a Time Out
Register D = the tick at which to give up. Returns the Z FLAG when status bit 1 (INDEX) is clear and the NZ FLAG when it is set. At the time out it does not return to its caller: it ends the test of the drive with the NZ FLAG.
51A4
LD A,(4040H) 3A 40 40
Fetch the tick counter from 4040H into Register A.
51A7
CP D BA
Compare Register A against Register D, the tick of the time out.
51A8
If the Z FLAG is set (time is up), JUMP to 51B0H.
51AA
GOSUB to 4759H (SYS0/SYS) to wait until the controller is not busy: Register A = its status.
51AD
BIT 1,A CB 4F
Test bit 1 of Register A (the status), INDEX: set while the index hole is under the sensor.
51AF
RET C9
RETURN with the Z FLAG (no hole) or the NZ FLAG (the hole).
51B0
POP AF F1
Restore Register Pair AF from the stack: the return address of the CALL 51A4H at a time out, or the status pushed at 5177H after a read error. Either way it is dropped.
51B1
OR 01H F6 01
OR Register A with 01H: the NZ FLAG is set whatever Register A held.
51B3
JUMP to 51A0H to restore Register Pair DE and Index Register IY and return with the NZ FLAG: the drive is not ready.
51B5H - Read the Hash Index Sector
Register C = the drive. Reads sector 1 of the directory cylinder into 4200H. Returns the Z FLAG when it was read, the NZ FLAG when not; Register A = 16H (HIT READ ERROR) either way, Register Pair HL = 4200H. Registers BC and DE are kept.
51B5
PUSH BC C5
Save Register Pair BC (Register C the drive) to the stack.
51B6
PUSH DE D5
Save Register Pair DE (the caller's) to the stack.
51B7
GOSUB to 4B65H (SYS0/SYS): Register D = the directory cylinder of drive Register C.
51BA
LD E,01H 1E 01
Load Register E with 01H: sector 1, the hash index.
51BC
LD HL,4200H 21 00 42
Point Register Pair HL to 4200H, the sector buffer.
51BF
GOSUB to 4B45H (SYS0/SYS) to read the directory sector at Register D, Register E of drive Register C into 4200H: the Z FLAG when read.
51C2
POP DE D1
Restore Register Pair DE from the stack: the caller's.
51C3
POP BC C1
Restore Register Pair BC from the stack: Register C = the drive.
51C4
LD A,16H 3E 16
Load Register A with 16H, the error code HIT READ ERROR. LD does not change the flags of the read.
51C6
RET C9
RETURN with the Z FLAG (read) or the NZ FLAG (error 16H).
51C7H - Write the Hash Index Sector
Register C = the drive. Writes 4200H to sector 1 of the directory cylinder with the data mark FAH and reads it back. Returns the Z FLAG when it is good, the NZ FLAG when not; Register A = 17H (HIT WRITE ERROR) either way.
51C7
PUSH BC C5
Save Register Pair BC (Register C the drive) to the stack.
51C8
PUSH DE D5
Save Register Pair DE (the caller's) to the stack.
51C9
GOSUB to 4B65H (SYS0/SYS): Register D = the directory cylinder of drive Register C.
51CC
LD E,01H 1E 01
Load Register E with 01H: sector 1, the hash index.
51CE
LD HL,4200H 21 00 42
Point Register Pair HL to 4200H, the hash index in the sector buffer.
51D1
GOSUB to 4768H (SYS0/SYS) to write the sector at Register D, Register E of drive Register C from Register Pair HL with the data mark FAH.
51D4
If the Z FLAG is set (written), GOSUB to 4772H (SYS0/SYS) to read the sector back without storing it.
51D7
CP 06H FE 06
Compare Register A against 06H: the read back of a sector with the data mark FAH ends with error 06H, which means the write is good.
51D9
LD A,17H 3E 17
Load Register A with 17H, the error code HIT WRITE ERROR. LD does not change the flags.
51DB
POP DE D1
Restore Register Pair DE from the stack: the caller's.
51DC
POP BC C1
Restore Register Pair BC from the stack: Register C = the drive.
51DD
RET C9
RETURN with the Z FLAG (good) or the NZ FLAG and error 17H.
51DEH - Work Areas
51DEH-51F6H are not in the file: SYS2/SYS fills them at each open. 51F7H-51FDH are loaded with 00H. 51E8H-51F8H hold the bytes +05H-+15H of a new directory record and 51F9H-51FDH its bytes +00H-+04H, so that two LDIRs make it (4FAEH-4FB9H).
51DE-51DF
DEFS 2
The hash code of the name (50D9H), in both bytes. 51DEH is compared with the hash index (4EB6H) and put into it for a new file (4F9DH).
51E0-51E7
DEFS 8
The password given, padded with spaces (5050H-5062H, 508DH); its hash code goes to 51F3H and 51F5H.
51E8-51EF
DEFS 8
The name, padded with spaces (5057H, 506EH): compared with bytes +05H-+0CH of the directory records (4EEFH) and copied into a new one (4FB9H).
51F0-51F2
DEFS 3
The extension, padded with spaces (5083H): compared with bytes +0DH-+0FH of the records and copied into a new one.
51F3-51F4
DEFS 2
The hash code of the password given (4E98H): the update password (+10H-+11H) of a new record.
51F5-51F6
DEFS 2
The hash code of the password given (4E9BH): compared with an existing record's passwords (4F10H) and the access password (+12H-+13H) of a new record.
51F7-51F8
DEFW 0000H 00 00
Bytes +14H-+15H of a new record: the ending record number 0000H, an empty file.
51F9
DEFB 00H 00
Byte +00H of a new record, the attribute byte: 10H (in use, level 0) stored at 4F71H; an open stores the found record's attribute here (4F04H).
51FA-51FB
DEFB 00H,00H 00 00
Bytes +01H-+02H of a new directory record, copied in as 00H and 00H (4FB1H).
51FC
DEFB 00H 00
Byte +03H of a new record: the end of file offset 00H.
51FD
DEFB 00H 00
The record length given to the open in Register B (4E7FH): byte +09H of the control block (5000H) and byte +04H of a new record.