DOSPLUS 3.5 for the Model III - SYS2/SYS Disassembled

Page Customization

Introduction/Summary

DOSPLUS 3.5 SYS2/SYS Disassembly - OPEN@ and INIT@ (Model III)

SYS2/SYS is the low overlay that opens files: OPEN@ (request code 13H) and INIT@ (14H), with the routines they share and that other overlays request: the password code (15H, used by SYS14/SYS), the filling of a file control block from a directory entry (16H), the hash index code of a name (17H, used by SYS15/SYS), the address of the name buffer (18H, used by SYS15/SYS) and the drive of the last specification (19H). SYS0/SYS loads it at 4E00H over the low overlay before it.

The file is a load module of 5 blocks, 973 bytes, from 4E00H to 51CCH, with the transfer address 4E00H, and a 07H record. The fifth block (50FDH-5103H) is a patch over the fourth: it reorders the tests of the name character routine (50F0H) so that < and >, which are in its table, are taken in a name; before it, every character from 3AH to 40H ended the name. The page shows the patched bytes and gives the old instructions on the rows. The work area after the file, 51CDH-51EEH, is shown as DEFS rows (51CDH).

The Parts of SYS2/SYS

AddressContents
4E00H-4E11HThe routine table (routines 2-9) and routine 2 (4E00H, 4E10H).
4E12H-4F3FHOPEN@: devices, the file search through the hash index table of each drive, the name compare and the password check (4E12H, 4EF2H).
4F40H-4FC0HINIT@: a free hash index entry, the new directory entry (4F40H).
4FC1H-5068HThe file control block from the directory entry (4FC1H).
5069H-511EHThe specification parser and the name character copier (5069H, 50F0H).
511FH-519CHThe hash index code, upper case, routines 8 and 9, the free entry search, the password code (511FH, 513FH, 516EH).
519DH-51CCHReading and writing the hash index table and reading the GAT (519DH).

Opening a File

OPEN@ runs inside SYS0/SYS's file routine wrapper (448BH, a JP to 4CE9H), which puts the file control block in Index Register IX and keeps the caller's registers. A specification that starts with @ names a device: its two character name is looked up in the DCB table (44A6H), and the control block becomes 90H (open, with the FORCE flag) followed by the device's DCB address and filter table address, so character I/O on it goes to the device. For a file the name, extension, password and drive are taken apart (5069H); the name's hash index code (511FH) is looked for in the hash index table of the drive named, or of each ready drive from 0 to 7 in turn. The position of a matching byte in the table is the logical file number of the directory entry, whose name is then compared; extension entries are passed over.

The access a file is opened with depends on the password (4EF2H). Its code (516EH) is compared with CAA5H, a fixed code that opens any file with full access; then a file of protection level 7 is refused; then the code is compared with the diskette's master password code (GAT +CEH), with the entry's +10H code (the update password) and with its +12H code (the access password). The first three give access level 0, the access password gives the file's protection level, anything else error 19H. An empty password is eight spaces, whose code is 4296H.

INIT@ opens the file in the same way and, when it is not in the directory, creates it on the drive named or on the first drive that is ready and not write protected. The search for a free byte of the hash index table (513FH) starts at a place picked with the refresh register. The new entry is active with protection level 0, the logical record length, the name, and the code of the password given as both its update and its access password. The C FLAG returns set when the file was created.

The File Control Block

OffsetContents (from [4FC1H])
+00H80H, an open file (90H for a device).
+01HBits 2-0 the access level, bit 5 set (the buffer is to be read), bit 7 set when the logical record length is not 256.
+02HBit 7 of the entry's +01H.
+03H-04HThe buffer.
+05HThe position in the buffer, 00H.
+06HThe drive.
+07HThe logical file number.
+08HThe end of file byte.
+09HThe logical record length.
+0AH-0BHThe next record number, 0000H.
+0CH-0DHThe ending record number: the sector count, less 1 when the end of file byte is not 00H.
+0EH-0FHThe first extent of the entry.
+10H-1FHFour elements: the granules before the extent (2 bytes) and the extent (2 bytes); FFH when there are fewer extents.

Differences from the Manual

The manual does not give the fixed password code CAA5H, which opens every file, including files of protection level 7. Its table of the directory entry does not say which of +10H and +12H is which password: +10H is the update password (full access) and +12H the access password (4F14H, 4F25H).

Variables

Memory Outside SYS2/SYS

Address
Size
Contents
4300H-43FFH
256 bytes
System Sector Buffer
The GAT (51BDH), the hash index table (519DH) and directory sectors.
43CEH-43CFH
2 bytes
Master Password Code
In the GAT (4E95H).
44A6H
66 bytes
DCB Table
Device names at +09H (4E32H).
44E8H
32 bytes
DCTTBL
Drive names at +02H (50BBH).

The Work Area (51CDH-51EEH)

Address
Size
Contents
51CDH
1 byte
Drive
51CDH
51CEH
1 byte
Access Level
51CEH
51CFH
1 byte
Protection Level
51CFH
51D0H
1 byte
Hash Index Code
51D0H
51D1H
1 byte
Logical Record Length
51D1H
51D2H-51D3H
2 bytes
Buffer
51D2H
51D4H-51D5H
2 bytes
Master Password Code
51D4H
51D6H-51DDH
8 bytes
Password
51D6H
51DEH-51DFH
2 bytes
Drive or Device Name
51DEH
51E0H-51EAH
11 bytes
Name and Extension
51E0H
51EBH-51EEH
4 bytes
Password Codes
51EBH, 51EDH

Tables

Address
Size
Contents
4E00H-4E0FH
16 bytes
Routine Table
4E00H
5118H-511EH
7 bytes
Name Characters
5118H

Outside Routines

AddressContents
448BHSYS0/SYS: the file routine wrapper (a JP to 4CE9H), entered after its open test (4E12H, 4F40H).
4488HSYS0/SYS: DISKIO%, functions 0 (DCHECK), 6 (SREAD) and 7 (SWRITE).
44A3HSYS0/SYS: LOCDCT% (4F64H).
449AH, 449DHSYS0/SYS: read and write the directory sector of a logical file number.
4494HSYS0/SYS: 8 bit divide (514CH).

Disassembly

4E00H - The Routine Table

Data: SYS2/SYS's table of routines 2-9, one word each, used by SYS0/SYS's overlay request handler (its 49D3H-49E6H) for the request codes 12H-19H. OPEN@ (4424H) requests 13H and INIT@ (4420H) 14H; SYS14/SYS requests 15H (its 553DH), SYS15/SYS 18H and 17H (its 56BDH, 56C0H).

4E00-4E01
DEFW 4E10H 10 4E
Routine 2: 4E10H, XOR A and RET, which SYS0/SYS's record locator requests when it loads SYS2/SYS back (its 4D5FH-4D6CH).
4E02-4E03
DEFW 4E12H 12 4E
Routine 3: 4E12H, OPEN@, which opens the file or device named in the file control block at Register Pair DE.
4E04-4E05
DEFW 4F40H 40 4F
Routine 4: 4F40H, INIT@, which opens the file and creates it when it is not in the directory.
4E06-4E07
DEFW 516EH 6E 51
Routine 5: 516EH, which returns in Register Pair HL the password code of the 8 characters at Register Pair DE.
4E08-4E09
DEFW 4FC1H C1 4F
Routine 6: 4FC1H, which fills the file control block at Index Register IX from the directory entry at Register Pair HL.
4E0A-4E0B
DEFW 511FH 1F 51
Routine 7: 511FH, which returns in Register A the hash index code of the 11 characters of a name and extension at Register Pair HL.
4E0C-4E0D
DEFW 5136H 36 51
Routine 8: 5136H, which returns Register Pair HL = 51E0H, the name and extension buffer of SYS2/SYS.
4E0E-4E0F
DEFW 513AH 3A 51
Routine 9: 513AH, which returns in Register A and Register C the drive byte at 51CDH.

4E10H - Routine 2

Nothing to do when SYS0/SYS's record locator brings SYS2/SYS back.

4E10
XOR A AF
Set Register A to 00H by XORing it with itself, and set the Z FLAG: routine 2 has no work to do.
4E11
RET C9
RETurn to SYS0/SYS's overlay request handler (49E7H) with Register A = 00H.

4E12H - OPEN@ - Open a File or a Device

Routine 3, requested by OPEN@ (4424H) with Register Pair DE pointing to a file control block that holds a file specification (as FSPEC@ leaves it), Register Pair HL to a 256 byte buffer and Register B the logical record length. A device specification (@ and a two character name) makes the control block point to the device's DCB. A file is looked for in the hash index table of the drive named, or of drives 0-7 in turn; when its name is found and a password gives access, the control block is filled from the directory entry. Register A returns 00H with the Z FLAG, or an error code with the NZ FLAG.

4E12
GOSUB to 448BH, the SYS0/SYS entry point that jumps to 4CE9H, the file routine wrapper entered after its open test: it loads Index Register IX with the file control block at Register Pair DE, saves Register Pairs BC, DE, HL and Index Registers IX and IY, and returns here with Register A = 00H; this routine's RET goes through 4CFAH, which restores them.
4E15
LD A,(IX+00H) DD 7E 00
Load Register A with the first character of the specification at Index Register IX+00H (the file control block). INIT@ comes in here too (4F43H).
4E18
CP 40H FE 40
Compare Register A against 40H (@, the start of a device specification).
4E1A
If the NZ FLAG is set (a file), JUMP to 4E61H.
4E1C
PUSH IX DD E5
Save Index Register IX, the file control block, to the top of the stack, for the end at 4E52H.
4E1E
PUSH IX DD E5
Save Index Register IX to the top of the stack again.
4E20
POP HL E1
Restore Register Pair HL from the top of the stack: Register Pair HL = the file control block.
4E21
INC HL 23
INCrement Register Pair HL by 1 to the device name after the @.
4E22
LD DE,51DEH 11 DE 51
Point Register Pair DE to 51DEH, the two byte name buffer.
4E25
LD A,20H 3E 20
Load Register A with 20H, a space, to clear the name buffer with.
4E27
LD (DE),A 12
Store Register A (a space) to the first byte of the name buffer at Register Pair DE (51DEH).
4E28
INC DE 13
INCrement Register Pair DE by 1 to 51DFH, the second byte of the name buffer.
4E29
LD (DE),A 12
Store Register A (a space) to the second byte at Register Pair DE (51DFH): a one character name is padded with a space.
4E2A
DEC DE 1B
DECrement Register Pair DE by 1, back to 51DEH.
4E2B
PUSH DE D5
Save Register Pair DE (51DEH) to the top of the stack.
4E2C
LD B,02H 06 02
Load Register B with 02H, the most characters of a device name.
4E2E
GOSUB to 50F0H to copy up to Register B (2) name characters from Register Pair HL to Register Pair DE (51DEH).
4E31
POP HL E1
Restore Register Pair HL from the top of the stack: 51DEH, the device name.
4E32
LD IX,44A6H DD 21 A6 44
Point Index Register IX to 44A6H, the DCB table of SYS0/SYS.
4E36
LD DE,000BH 11 0B 00
Load Register Pair DE with 000BH, the length of an entry of the DCB table.
4E39
LD B,06H 06 06
Load Register B with 06H, the number of entries (KI, DO, PR, RS, U1, U2).
4E3B
LD A,(IX+09H) DD 7E 09
Load Register A with the first character of the entry's name at Index Register IX+09H.
4E3E
CP (HL) BE
Compare Register A against the first character of the device name at Register Pair HL (51DEH).
4E3F
If the NZ FLAG is set (they differ), JUMP to 4E49H for the next entry.
4E41
LD A,(IX+0AH) DD 7E 0A
Load Register A with the second character of the entry's name at Index Register IX+0AH.
4E44
INC HL 23
INCrement Register Pair HL by 1 to 51DFH, the second character of the device name.
4E45
CP (HL) BE
Compare Register A against the second character at Register Pair HL (51DFH).
4E46
DEC HL 2B
DECrement Register Pair HL by 1 back to 51DEH; the flags stay as the compare set them.
4E47
If the Z FLAG is set (both characters agree), JUMP to 4E52H with Index Register IX at the entry.
4E49
ADD IX,DE DD 19
ADD Register Pair DE (11) to Index Register IX: the next entry of the DCB table.
4E4B
DECrement Register B and loop back to 4E3BH while Register B is not zero.
4E4D
POP AF F1
Restore Register Pair AF from the top of the stack: it drops the file control block saved at 4E1CH.
4E4E
LD A,29H 3E 29
Load Register A with 29H, the error code Device not available.
4E50
OR A B7
OR Register A with itself to set the NZ FLAG.
4E51
RET C9
RETurn (through the wrapper at 4CFAH, or to INIT@ at 4F46H) with Register A = 29H and the NZ FLAG set.
4E52
POP HL E1
Restore Register Pair HL from the top of the stack: the file control block.
4E53
LD (HL),90H 36 90
Store 90H to the type byte at Register Pair HL: bit 7 an open control block and bit 4 the FORCE flag, so SYS0/SYS's character I/O (456CH) sends every character to the DCB at +01H-02H.
4E55
INC HL 23
INCrement Register Pair HL by 1 to the control block's +01H.
4E56
PUSH IX DD E5
Save Index Register IX, the DCB table entry that matched, to the top of the stack.
4E58
POP DE D1
Restore Register Pair DE from the top of the stack: Register Pair DE = the entry.
4E59
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the entry, Register Pair DE = the control block's +01H.
4E5A
LD BC,0004H 01 04 00
Load Register Pair BC with 0004H, the two words to copy.
4E5D
LDIR ED B0
Copy Register Pair BC (4) bytes from Register Pair HL (the entry's DCB address and filter table address) to Register Pair DE (control block +01H-04H).
4E5F
XOR A AF
Set Register A to 00H by XORing it with itself, and set the Z FLAG: the device is open.
4E60
RET C9
RETurn (through the wrapper at 4CFAH, or to INIT@ at 4F46H) with Register A = 00H.
4E61
LD (51D2H),HL 22 D2 51
A file: store Register Pair HL, the caller's buffer, to 51D2H-51D3H.
4E64
LD A,B 78
Load Register A with Register B, the caller's logical record length (00H for 256).
4E65
LD (51D1H),A 32 D1 51
Store Register A, the logical record length, to 51D1H.
4E68
GOSUB to 5069H to take the name, extension, password and drive from the file control block at Register Pair DE into 51E0H, 51E8H, 51D6H and 51CDH. The NZ FLAG returns set with an error code in Register A.
4E6B
RET NZ C0
If the NZ FLAG is set, RETurn (through the wrapper at 4CFAH, or to INIT@ at 4F46H) with the error code in Register A.
4E6C
LD HL,51E0H 21 E0 51
Point Register Pair HL to 51E0H, the name and extension (11 characters, padded with spaces).
4E6F
GOSUB to 511FH to compute the hash index code of the 11 characters at Register Pair HL (51E0H) into Register A.
4E72
LD (51D0H),A 32 D0 51
Store Register A, the hash index code, to 51D0H.
4E75
LD DE,51D6H 11 D6 51
Point Register Pair DE to 51D6H, the password (8 characters, padded with spaces).
4E78
GOSUB to 516EH to compute the password code of the 8 characters at Register Pair DE (51D6H) into Register Pair HL.
4E7B
LD (51EBH),HL 22 EB 51
Store Register Pair HL, the password code, to 51EBH-51ECH.
4E7E
LD (51EDH),HL 22 ED 51
Store Register Pair HL, the password code, to 51EDH-51EEH as well, the second password a new file gets (4FA3H).
4E81
LD A,(51CDH) 3A CD 51
Load Register A with the drive byte at 51CDH: 00H-07H for a drive named, FFH for none.
4E84
OR A B7
OR Register A (the drive byte) with itself to test bit 7, set for FFH.
4E85
If the P FLAG is set (a drive was named), JUMP to 4E89H with Register A = the drive.
4E88
XOR A AF
No drive named: set Register A to 00H by XORing it with itself, so the search starts with drive 0.
4E89
LD C,A 4F
Load Register C with Register A, the drive to search.
4E8A
LD A,00H 3E 00
Load Register A with 00H, the DCHECK function of DISKIO%.
4E8C
GOSUB to 4488H (DISKIO%) to check drive Register C. The NZ FLAG returns set when the drive is not ready.
4E8F
If the NZ FLAG is set (not ready), JUMP to 4EABH for the next drive.
4E91
GOSUB to 51BDH to read the GAT (directory sector 0) of drive Register C into 4300H. The NZ FLAG returns set with error 14H.
4E94
RET NZ C0
If the NZ FLAG is set, RETurn (through the wrapper at 4CFAH, or to INIT@ at 4F46H) with Register A = 14H.
4E95
LD L,CEH 2E CE
Load Register L with CEH: Register Pair HL = 43CEH, the diskette's master password code in the GAT at 4300H.
4E97
LD E,(HL) 5E
Load Register E with the low byte of the master password code at Register Pair HL (43CEH).
4E98
INC HL 23
INCrement Register Pair HL by 1 to 43CFH, the high byte of the code.
4E99
LD D,(HL) 56
Load Register D with the high byte at Register Pair HL (43CFH): Register Pair DE = the master password code.
4E9A
LD (51D4H),DE ED 53 D4 51
Store Register Pair DE, the master password code of drive Register C, to 51D4H-51D5H.
4E9E
GOSUB to 519DH to read the hash index table (directory sector 1) of drive Register C into 4300H; Register Pair HL returns 4300H. The NZ FLAG returns set with error 16H.
4EA1
RET NZ C0
If the NZ FLAG is set, RETurn (through the wrapper at 4CFAH, or to INIT@ at 4F46H) with Register A = 16H.
4EA2
LD A,(51D0H) 3A D0 51
Load Register A with the file's hash index code at 51D0H.
4EA5
CP (HL) BE
Compare Register A against the hash index table's byte at Register Pair HL; its position (Register L) is the logical file number of the entry.
4EA6
If the Z FLAG is set (the same code), JUMP to 4EC6H to read that entry and compare the name.
4EA8
INC L 2C
INCrement Register L by 1 to the next byte of the hash index table.
4EA9
If the NZ FLAG is set (Register L has not come back to 00H), JUMP back to 4EA2H.
4EAB
LD A,(51CDH) 3A CD 51
Not on this drive: load Register A with the drive byte at 51CDH.
4EAE
OR A B7
OR Register A (the drive byte) with itself to test bit 7, set for FFH.
4EAF
If the P FLAG is set (a drive was named), JUMP to 4EB8H: the file is not there.
4EB2
LD A,07H 3E 07
Load Register A with 07H, the last drive that is searched.
4EB4
INC C 0C
INCrement Register C, the drive, by 1 to the next drive.
4EB5
CP C B9
Compare Register A (7) against Register C. The NC FLAG is set while Register C is 7 or less.
4EB6
If the NC FLAG is set, JUMP back to 4E8AH to search drive Register C.
4EB8
LD A,18H 3E 18
Load Register A with 18H, the error code File not in directory.
4EBA
OR A B7
OR Register A with itself to set the NZ FLAG.
4EBB
RET C9
RETurn (through the wrapper at 4CFAH, or to INIT@ at 4F46H) with Register A = 18H. INIT@ creates the file on this error (4F47H).
4EBC
POP BC C1
Not this entry: restore Register Pair BC from the top of the stack (Register B the logical file number, Register C the drive).
4EBD
POP HL E1
Restore Register Pair HL from the top of the stack: the entry's address in the buffer, no longer needed.
4EBE
POP BC C1
Restore Register Pair BC from the top of the stack, saved at 4EC7H (Register C the drive).
4EBF
GOSUB to 519DH to read the hash index table of drive Register C into 4300H again: the directory sector was read over it. Error 16H returns with the NZ FLAG.
4EC2
POP HL E1
Restore Register Pair HL from the top of the stack: the position in the hash index table saved at 4EC6H.
4EC3
RET NZ C0
If the NZ FLAG is set, RETurn (through the wrapper at 4CFAH, or to INIT@ at 4F46H) with Register A = 16H.
4EC4
JUMP back to 4EA8H to go on with the next byte of the hash index table.
4EC6
PUSH HL E5
Save Register Pair HL, the position in the hash index table, to the top of the stack.
4EC7
PUSH BC C5
Save Register Pair BC (Register C the drive) to the top of the stack.
4EC8
LD B,L 45
Load Register B with Register L, the position in the hash index table: the logical file number of the entry.
4EC9
GOSUB to 449AH in SYS0/SYS to read the directory sector of logical file number Register B on drive Register C into 4300H. Register Pair HL returns the entry's address; the NZ FLAG is set with error 11H.
4ECC
If the Z FLAG is set (the sector was read), JUMP to 4ED1H to check the entry.
4ECE
POP BC C1
Restore Register Pair BC from the top of the stack.
4ECF
POP HL E1
Restore Register Pair HL from the top of the stack.
4ED0
RET C9
RETurn (through the wrapper at 4CFAH, or to INIT@ at 4F46H) with Register A = 11H and the NZ FLAG set.
4ED1
PUSH HL E5
Save Register Pair HL, the directory entry, to the top of the stack.
4ED2
PUSH BC C5
Save Register Pair BC (Register B the logical file number, Register C the drive) to the top of the stack.
4ED3
BIT 7,(HL) CB 7E
Test bit 7 of the entry's first byte at Register Pair HL, the extension entry flag (FXDE).
4ED5
If the NZ FLAG is set (an extension entry, which holds no name), JUMP to 4EBCH for the next byte of the hash index table.
4ED7
LD A,05H 3E 05
Load Register A with 05H, the offset of the name in a directory entry.
4ED9
ADD A,L 85
ADD Register L to Register A: the low byte of the entry + 5.
4EDA
LD L,A 6F
Load Register L with Register A: Register Pair HL = the entry's name.
4EDB
LD B,0BH 06 0B
Load Register B with 0BH, the 11 characters of name and extension.
4EDD
LD DE,51E0H 11 E0 51
Point Register Pair DE to 51E0H, the name and extension of the file to open.
4EE0
LD A,(DE) 1A
Load Register A with the character of the file's name at Register Pair DE.
4EE1
CP (HL) BE
Compare Register A against the character of the entry's name at Register Pair HL.
4EE2
If the NZ FLAG is set (they differ), JUMP to 4EBCH for the next byte of the hash index table.
4EE4
INC HL 23
INCrement Register Pair HL by 1 to the next character of the entry.
4EE5
INC DE 13
INCrement Register Pair DE by 1 to the next character of the file's name.
4EE6
DECrement Register B and loop back to 4EE0H while Register B is not zero.
4EE8
POP BC C1
The names agree: restore Register Pair BC from the top of the stack (Register B the logical file number, Register C the drive).
4EE9
POP HL E1
Restore Register Pair HL from the top of the stack: the directory entry.
4EEA
POP AF F1
Restore Register Pair AF from the top of the stack: it drops Register Pair BC saved at 4EC7H.
4EEB
POP AF F1
Restore Register Pair AF from the top of the stack: it drops the hash index table position saved at 4EC6H.
4EEC
LD A,(HL) 7E
Load Register A with the entry's first byte at Register Pair HL.
4EED
AND 07H E6 07
AND Register A with 07H: bits 2-0, the protection level of the file.
4EEF
LD (51CFH),A 32 CF 51
Store Register A, the protection level, to 51CFH.

4EF2H - The Password Check

Sets the access level the file control block gets: 0 (everything) when the password code is CAA5H, the diskette's master password code (GAT +CEH) or the entry's +10H code; the file's protection level when it is the entry's +12H code. A file of protection level 7 opens only with CAA5H. Any other password gives error 19H.

4EF2
PUSH HL E5
Save Register Pair HL, the directory entry, to the top of the stack.
4EF3
LD DE,(51EBH) ED 5B EB 51
Load Register Pair DE with the password code at 51EBH-51ECH.
4EF7
LD HL,CAA5H 21 A5 CA
Load Register Pair HL with CAA5H, a fixed password code that opens every file.
4EFA
XOR A AF
Set Register A to 00H by XORing it with itself, which also clears the C FLAG for the subtraction; Register A is the access level 0 if this code matches.
4EFB
SBC HL,DE ED 52
SUBtract Register Pair DE (the password code) from Register Pair HL (CAA5H) with the carry. The Z FLAG is set when they are equal.
4EFD
If the Z FLAG is set, JUMP to 4F39H with Register A = 00H: full access.
4EFF
LD A,(51CFH) 3A CF 51
Load Register A with the protection level of the file at 51CFH.
4F02
CP 07H FE 07
Compare Register A against 07H, the level that gives no access.
4F04
If the Z FLAG is set (level 7), JUMP to 4F34H for error 19H.
4F06
LD DE,(51EBH) ED 5B EB 51
Load Register Pair DE with the password code at 51EBH-51ECH.
4F0A
LD HL,(51D4H) 2A D4 51
Load Register Pair HL with the diskette's master password code at 51D4H-51D5H.
4F0D
XOR A AF
Set Register A to 00H by XORing it with itself and clear the C FLAG: Register A is the access level 0 if this code matches.
4F0E
SBC HL,DE ED 52
SUBtract Register Pair DE (the password code) from Register Pair HL (the master code) with the carry. The Z FLAG is set when they are equal.
4F10
If the Z FLAG is set (the master password), JUMP to 4F39H with Register A = 00H: full access.
4F12
POP HL E1
Restore Register Pair HL from the top of the stack: the directory entry.
4F13
PUSH HL E5
Save Register Pair HL, the directory entry, to the top of the stack again.
4F14
LD DE,0010H 11 10 00
Load Register Pair DE with 0010H, the offset of the entry's first password code.
4F17
ADD HL,DE 19
ADD Register Pair DE (10H) to Register Pair HL: Register Pair HL = the entry's +10H.
4F18
LD E,(HL) 5E
Load Register E with the low byte of the code at Register Pair HL (entry +10H).
4F19
INC HL 23
INCrement Register Pair HL by 1 to the entry's +11H.
4F1A
LD D,(HL) 56
Load Register D with the high byte at Register Pair HL: Register Pair DE = the entry's +10H code, the update password.
4F1B
PUSH HL E5
Save Register Pair HL (entry +11H) to the top of the stack.
4F1C
LD HL,(51EBH) 2A EB 51
Load Register Pair HL with the password code at 51EBH-51ECH.
4F1F
XOR A AF
Set Register A to 00H by XORing it with itself and clear the C FLAG: Register A is the access level 0 if this code matches.
4F20
SBC HL,DE ED 52
SUBtract Register Pair DE (the update password code) from Register Pair HL (the password code) with the carry. The Z FLAG is set when they are equal.
4F22
POP HL E1
Restore Register Pair HL from the top of the stack: the entry's +11H. The flags stay as the subtraction set them.
4F23
If the Z FLAG is set (the update password), JUMP to 4F39H with Register A = 00H: full access.
4F25
INC HL 23
INCrement Register Pair HL by 1 to the entry's +12H.
4F26
LD E,(HL) 5E
Load Register E with the low byte of the code at Register Pair HL (entry +12H).
4F27
INC HL 23
INCrement Register Pair HL by 1 to the entry's +13H.
4F28
LD D,(HL) 56
Load Register D with the high byte at Register Pair HL: Register Pair DE = the entry's +12H code, the access password.
4F29
LD HL,(51EBH) 2A EB 51
Load Register Pair HL with the password code at 51EBH-51ECH.
4F2C
XOR A AF
Set Register A to 00H by XORing it with itself and clear the C FLAG for the subtraction.
4F2D
SBC HL,DE ED 52
SUBtract Register Pair DE (the access password code) from Register Pair HL (the password code) with the carry. The Z FLAG is set when they are equal.
4F2F
LD A,(51CFH) 3A CF 51
Load Register A with the protection level of the file at 51CFH, the access this password gives; the flags stay as the subtraction set them.
4F32
If the Z FLAG is set (the access password), JUMP to 4F39H with Register A = the protection level.
4F34
LD A,19H 3E 19
Load Register A with 19H, the error code File access denied due to password protection.
4F36
POP HL E1
Restore Register Pair HL from the top of the stack: the directory entry.
4F37
OR A B7
OR Register A with itself to set the NZ FLAG.
4F38
RET C9
RETurn (through the wrapper at 4CFAH, or to INIT@ at 4F46H) with Register A = 19H and the NZ FLAG set.
4F39
POP HL E1
Restore Register Pair HL from the top of the stack: the directory entry.
4F3A
LD (51CEH),A 32 CE 51
Store Register A, the access level the password gives (0 or the protection level), to 51CEH.
4F3D
JUMP to 4FC1H to fill the file control block at Index Register IX from the directory entry at Register Pair HL; its RET goes through the wrapper at 4CFAH, or back to INIT@ at 4F46H.

4F40H - INIT@ - Open or Create a File

Routine 4, requested by INIT@ (4420H) with the same registers as OPEN@. The file is opened as by OPEN@; when it is not in the directory (error 18H) it is created on the drive named, or on the first of drives 0-7 that is ready and not write protected and has a free directory entry: the hash index code goes into a free byte of the hash index table, the entry gets the name, the logical record length and the password code as both passwords, and the file control block is filled. The C FLAG returns set when the file was created.

4F40
GOSUB to 448BH, the SYS0/SYS entry point that jumps to 4CE9H, the file routine wrapper: Index Register IX = the file control block at Register Pair DE, Register Pairs BC, DE, HL and Index Registers IX and IY are saved, and this routine's RET goes through 4CFAH, which restores them.
4F43
GOSUB to 4E15H, OPEN@ after its wrapper call, to open the file or device. Register A returns 00H with the Z FLAG or the error code with the NZ FLAG.
4F46
RET Z C8
If the Z FLAG is set (it was opened), RETurn through the wrapper (4CFAH) with Register A = 00H and the C FLAG clear.
4F47
CP 18H FE 18
Compare Register A, the error code, against 18H, File not in directory.
4F49
RET NZ C0
If the NZ FLAG is set (any other error), RETurn through the wrapper (4CFAH) with the error code in Register A.
4F4A
XOR A AF
Set Register A to 00H by XORing it with itself.
4F4B
LD (51CEH),A 32 CE 51
Store Register A (00H) to the access level at 51CEH: the creator of a file has full access to it.
4F4E
LD A,(51CDH) 3A CD 51
Load Register A with the drive byte at 51CDH (00H-07H, or FFH when no drive was named), as OPEN@'s parser left it.
4F51
OR A B7
OR Register A (the drive byte) with itself to test bit 7, set for FFH.
4F52
If the P FLAG is set (a drive was named), JUMP to 4F56H with Register A = the drive.
4F55
XOR A AF
No drive named: set Register A to 00H by XORing it with itself, so drive 0 is tried first.
4F56
LD C,A 4F
Load Register C with Register A, the drive to try.
4F57
LD A,00H 3E 00
Load Register A with 00H, the DCHECK function of DISKIO%.
4F59
GOSUB to 4488H (DISKIO%) to check drive Register C: the NZ FLAG is set when it is not ready, the C FLAG when it is write protected.
4F5C
If the C FLAG is set (write protected), JUMP to 4F6CH for the next drive.
4F5E
If the NZ FLAG is set (not ready), JUMP to 4F6CH for the next drive.
4F60
GOSUB to 519DH to read the hash index table of drive Register C into 4300H; Register Pair HL returns 4300H. Error 16H returns with the NZ FLAG.
4F63
RET NZ C0
If the NZ FLAG is set, RETurn through the wrapper (4CFAH) with Register A = 16H.
4F64
GOSUB to 44A3H (LOCDCT%) to load Index Register IY with the drive control table of drive Register C, whose DCT+0EH (the directory length) 513FH needs.
4F67
GOSUB to 513FH to find a free byte of the hash index table at 4300H. The Z FLAG returns set with Register Pair HL pointing to it.
4F6A
If the Z FLAG is set (a free entry), JUMP to 4F7DH.
4F6C
LD A,(51CDH) 3A CD 51
Load Register A with the drive byte at 51CDH.
4F6F
OR A B7
OR Register A (the drive byte) with itself to test bit 7, set for FFH.
4F70
If the P FLAG is set (a drive was named), JUMP to 4F79H: it has no room.
4F73
LD A,07H 3E 07
Load Register A with 07H, the last drive that is tried.
4F75
INC C 0C
INCrement Register C, the drive, by 1 to the next drive.
4F76
CP C B9
Compare Register A (7) against Register C. The NC FLAG is set while Register C is 7 or less.
4F77
If the NC FLAG is set, JUMP back to 4F57H to try drive Register C.
4F79
LD A,1AH 3E 1A
Load Register A with 1AH, the error code Directory space full.
4F7B
OR A B7
OR Register A with itself to set the NZ FLAG.
4F7C
RET C9
RETurn through the wrapper (4CFAH) with Register A = 1AH and the NZ FLAG set.
4F7D
PUSH HL E5
Save Register Pair HL, the free byte of the hash index table, to the top of the stack.
4F7E
LD A,(51D0H) 3A D0 51
Load Register A with the file's hash index code at 51D0H.
4F81
LD (HL),A 77
Store Register A, the hash index code, to the free byte at Register Pair HL: the entry is taken.
4F82
GOSUB to 51ADH to write the hash index table at 4300H back to drive Register C. Error 17H returns with the NZ FLAG.
4F85
POP HL E1
Restore Register Pair HL from the top of the stack: the byte of the hash index table.
4F86
RET NZ C0
If the NZ FLAG is set, RETurn through the wrapper (4CFAH) with Register A = 17H.
4F87
LD B,L 45
Load Register B with Register L, the byte's position: the logical file number of the new entry.
4F88
GOSUB to 449AH in SYS0/SYS to read the directory sector of logical file number Register B on drive Register C into 4300H; Register Pair HL returns the entry's address. Error 11H returns with the NZ FLAG.
4F8B
RET NZ C0
If the NZ FLAG is set, RETurn through the wrapper (4CFAH) with Register A = 11H.
4F8C
PUSH HL E5
Save Register Pair HL, the directory entry, to the top of the stack.
4F8D
LD (HL),10H 36 10
Store 10H to the entry's +00H at Register Pair HL: an active entry, not a system file, protection level 0.
4F8F
INC HL 23
INCrement Register Pair HL by 1 to the entry's +01H.
4F90
LD (HL),00H 36 00
Store 00H to the entry's +01H at Register Pair HL: no date.
4F92
INC HL 23
INCrement Register Pair HL by 1 to the entry's +02H.
4F93
LD (HL),00H 36 00
Store 00H to the entry's +02H at Register Pair HL: no date.
4F95
INC HL 23
INCrement Register Pair HL by 1 to the entry's +03H.
4F96
LD (HL),00H 36 00
Store 00H to the entry's +03H at Register Pair HL, the end of file byte: the file is empty.
4F98
INC HL 23
INCrement Register Pair HL by 1 to the entry's +04H.
4F99
LD A,(51D1H) 3A D1 51
Load Register A with the logical record length at 51D1H.
4F9C
LD (HL),A 77
Store Register A, the logical record length, to the entry's +04H at Register Pair HL.
4F9D
INC HL 23
INCrement Register Pair HL by 1 to the entry's +05H, the name.
4F9E
PUSH BC C5
Save Register Pair BC (Register B the logical file number, Register C the drive) to the top of the stack.
4F9F
LD BC,000FH 01 0F 00
Load Register Pair BC with 000FH: the 11 characters of name and extension and the two password codes.
4FA2
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the entry's +05H.
4FA3
LD HL,51E0H 21 E0 51
Point Register Pair HL to 51E0H, the name and extension, followed by the password code at 51EBH and its copy at 51EDH.
4FA6
LDIR ED B0
Copy Register Pair BC (15) bytes from Register Pair HL (51E0H-51EEH) to Register Pair DE: the entry's name and extension (+05H-+0FH), update password code (+10H-+11H) and access password code (+12H-+13H).
4FA8
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the entry's +14H.
4FA9
LD (HL),00H 36 00
Store 00H to the entry's +14H at Register Pair HL, the low byte of the sector count.
4FAB
INC HL 23
INCrement Register Pair HL by 1 to the entry's +15H.
4FAC
LD (HL),00H 36 00
Store 00H to the entry's +15H at Register Pair HL, the high byte of the sector count.
4FAE
INC HL 23
INCrement Register Pair HL by 1 to the entry's +16H, the extents.
4FAF
LD B,0AH 06 0A
Load Register B with 0AH, the 10 bytes +16H-+1FH.
4FB1
LD (HL),FFH 36 FF
Store FFH to the entry byte at Register Pair HL: no extent.
4FB3
INC HL 23
INCrement Register Pair HL by 1 to the next byte.
4FB4
DECrement Register B and loop back to 4FB1H while Register B is not zero.
4FB6
POP BC C1
Restore Register Pair BC from the top of the stack (Register B the logical file number, Register C the drive).
4FB7
GOSUB to 449DH in SYS0/SYS to write the directory sector at 4300H of logical file number Register B back to drive Register C. Error 12H returns with the NZ FLAG.
4FBA
POP HL E1
Restore Register Pair HL from the top of the stack: the directory entry.
4FBB
RET NZ C0
If the NZ FLAG is set, RETurn through the wrapper (4CFAH) with Register A = 12H.
4FBC
GOSUB to 4FC1H to fill the file control block at Index Register IX from the new entry at Register Pair HL. It returns Register A = 00H with the Z FLAG.
4FBF
SCF 37
Set the C FLAG: the file was created, not found (the Z FLAG stays set).
4FC0
RET C9
RETurn through the wrapper (4CFAH) with Register A = 00H, the Z FLAG and the C FLAG set.

4FC1H - Fill the File Control Block

Routine 6, also the end of OPEN@ and INIT@. Index Register IX points to the file control block, Register Pair HL to the directory entry, Register B is the logical file number and Register C the drive; 51CEH holds the access level, 51D1H the logical record length and 51D2H the buffer. The block gets the open flags, the buffer, drive and logical file number, the end of file byte, the record length, the next record number 0, the ending record number and the extents of the entry: the first at +0EH-+0FH and up to four more as 4 byte elements (the granules before the extent, then the extent), with FFH in the rest.

4FC1
PUSH IX DD E5
Save Index Register IX, the file control block, to the top of the stack.
4FC3
LD (IX+00H),80H DD 36 00 80
Store 80H to the type byte at Index Register IX+00H: an open file.
4FC7
LD A,(51CEH) 3A CE 51
Load Register A with the access level at 51CEH (0-7).
4FCA
SET 5,A CB EF
Set bit 5 of Register A, the flag that the buffer does not hold the current sector, so the first read fills it.
4FCC
LD (IX+01H),A DD 77 01
Store Register A to the control block's +01H at Index Register IX+01H: bits 2-0 the access level, bit 5 set.
4FCF
LD A,(51D1H) 3A D1 51
Load Register A with the logical record length at 51D1H.
4FD2
OR A B7
OR Register A with itself to test it for 00H, a record of 256 bytes.
4FD3
If the Z FLAG is set (256 byte records), JUMP to 4FD9H.
4FD5
SET 7,(IX+01H) DD CB 01 FE
Set bit 7 of the control block's +01H at Index Register IX+01H: the records are shorter than a sector.
4FD9
INC HL 23
INCrement Register Pair HL by 1 to the entry's +01H.
4FDA
LD A,(HL) 7E
Load Register A with the entry's +01H at Register Pair HL.
4FDB
AND 80H E6 80
AND Register A with 80H to keep bit 7, the flag of a file that may not shrink.
4FDD
LD (IX+02H),A DD 77 02
Store Register A to the control block's +02H at Index Register IX+02H.
4FE0
LD DE,(51D2H) ED 5B D2 51
Load Register Pair DE with the buffer address at 51D2H-51D3H.
4FE4
LD (IX+03H),E DD 73 03
Store Register E, the low byte of the buffer address, to the control block's +03H at Index Register IX+03H.
4FE7
LD (IX+04H),D DD 72 04
Store Register D, the high byte, to the control block's +04H at Index Register IX+04H.
4FEA
LD (IX+05H),00H DD 36 05 00
Store 00H to the control block's +05H at Index Register IX+05H, the position of the next byte in the buffer.
4FEE
LD (IX+06H),C DD 71 06
Store Register C, the drive, to the control block's +06H at Index Register IX+06H.
4FF1
LD (IX+07H),B DD 70 07
Store Register B, the logical file number, to the control block's +07H at Index Register IX+07H.
4FF4
INC HL 23
INCrement Register Pair HL by 1 to the entry's +02H.
4FF5
INC HL 23
INCrement Register Pair HL by 1 to the entry's +03H, the end of file byte.
4FF6
LD A,(HL) 7E
Load Register A with the end of file byte at Register Pair HL (entry +03H).
4FF7
LD (IX+08H),A DD 77 08
Store Register A, the end of file byte, to the control block's +08H at Index Register IX+08H.
4FFA
LD A,(51D1H) 3A D1 51
Load Register A with the logical record length at 51D1H.
4FFD
LD (IX+09H),A DD 77 09
Store Register A, the logical record length, to the control block's +09H at Index Register IX+09H.
5000
LD (IX+0AH),00H DD 36 0A 00
Store 00H to the control block's +0AH at Index Register IX+0AH, the low byte of the next record number.
5004
LD (IX+0BH),00H DD 36 0B 00
Store 00H to the control block's +0BH at Index Register IX+0BH, the high byte of the next record number.
5008
LD DE,0011H 11 11 00
Load Register Pair DE with 0011H, the distance from the entry's +03H to its +14H.
500B
ADD HL,DE 19
ADD Register Pair DE (11H) to Register Pair HL (entry +03H): Register Pair HL = the entry's +14H, the sector count.
500C
LD E,(HL) 5E
Load Register E with the low byte of the sector count at Register Pair HL.
500D
INC HL 23
INCrement Register Pair HL by 1 to the entry's +15H.
500E
LD D,(HL) 56
Load Register D with the high byte at Register Pair HL: Register Pair DE = the sector count of the file.
500F
INC HL 23
INCrement Register Pair HL by 1 to the entry's +16H, the first extent.
5010
LD A,(IX+08H) DD 7E 08
Load Register A with the end of file byte at Index Register IX+08H.
5013
OR A B7
OR Register A with itself to test it for 00H.
5014
If the Z FLAG is set (the last sector is full), JUMP to 5017H: the ending record number is the sector count.
5016
DEC DE 1B
DECrement Register Pair DE by 1: the last sector is partly used, so the ending record number is one less.
5017
LD (IX+0CH),E DD 73 0C
Store Register E, the low byte of the ending record number, to the control block's +0CH at Index Register IX+0CH.
501A
LD (IX+0DH),D DD 72 0D
Store Register D, the high byte, to the control block's +0DH at Index Register IX+0DH.
501D
LD A,(HL) 7E
Load Register A with the cylinder of the first extent at Register Pair HL (entry +16H).
501E
INC L 2C
INCrement Register L by 1 to the entry's +17H (an entry does not cross a 256 byte page).
501F
LD (IX+0EH),A DD 77 0E
Store Register A, the first extent's cylinder, to the control block's +0EH at Index Register IX+0EH.
5022
LD A,(HL) 7E
Load Register A with the first extent's granule byte at Register Pair HL (entry +17H): bits 7-5 the first granule, bits 4-0 the granules less 1.
5023
INC L 2C
INCrement Register L by 1 to the entry's +18H, the second extent.
5024
LD (IX+0FH),A DD 77 0F
Store Register A, the granule byte, to the control block's +0FH at Index Register IX+0FH.
5027
AND 1FH E6 1F
AND Register A with 1FH: the number of granules of the first extent less 1.
5029
INC A 3C
INCrement Register A by 1: the granules of the first extent.
502A
LD E,A 5F
Load Register E with Register A, the granules so far.
502B
LD D,00H 16 00
Load Register D with 00H: Register Pair DE = the granules before the next extent.
502D
LD B,04H 06 04
Load Register B with 04H, the four elements of the control block (+10H-+1FH).
502F
LD A,(HL) 7E
Load Register A with the cylinder byte of the next extent at Register Pair HL.
5030
CP FEH FE FE
Compare Register A against FEH. The NC FLAG is set for FEH (a link to an extension entry) or FFH (no more extents).
5032
If the NC FLAG is set, JUMP to 5059H to mark the elements left as empty.
5034
LD (IX+10H),E DD 73 10
Store Register E, the low byte of the granules before this extent, to the element's +00H at Index Register IX+10H.
5037
LD (IX+11H),D DD 72 11
Store Register D, the high byte, to the element's +01H at Index Register IX+11H.
503A
LD A,(HL) 7E
Load Register A with the extent's cylinder at Register Pair HL.
503B
INC HL 23
INCrement Register Pair HL by 1 to its granule byte.
503C
LD (IX+12H),A DD 77 12
Store Register A, the extent's cylinder, to the element's +02H at Index Register IX+12H.
503F
LD A,(HL) 7E
Load Register A with the extent's granule byte at Register Pair HL.
5040
INC HL 23
INCrement Register Pair HL by 1 to the next extent.
5041
LD (IX+13H),A DD 77 13
Store Register A, the granule byte, to the element's +03H at Index Register IX+13H.
5044
PUSH HL E5
Save Register Pair HL, the next extent of the entry, to the top of the stack.
5045
AND 1FH E6 1F
AND Register A with 1FH: the granules of this extent less 1.
5047
INC A 3C
INCrement Register A by 1: the granules of this extent.
5048
LD L,A 6F
Load Register L with Register A, the granules of this extent.
5049
LD H,00H 26 00
Load Register H with 00H: Register Pair HL = the granules of this extent.
504B
ADD HL,DE 19
ADD Register Pair DE (the granules before it) to Register Pair HL: the granules up to the end of this extent.
504C
LD DE,0004H 11 04 00
Load Register Pair DE with 0004H, the length of an element.
504F
ADD IX,DE DD 19
ADD Register Pair DE (4) to Index Register IX: Index Register IX+10H is the next element.
5051
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the granules before the next extent.
5052
POP HL E1
Restore Register Pair HL from the top of the stack: the next extent of the entry.
5053
DECrement Register B and loop back to 502FH while Register B is not zero.
5055
POP IX DD E1
Restore Index Register IX from the top of the stack: the file control block.
5057
XOR A AF
Set Register A to 00H by XORing it with itself, and set the Z FLAG: the control block is ready.
5058
RET C9
RETurn with Register A = 00H and the Z FLAG set.
5059
SLA B CB 20
Shift Register B left: the elements left times 2.
505B
SLA B CB 20
Shift Register B left again: the elements left times 4, the bytes of the control block to mark.
505D
LD (IX+10H),FFH DD 36 10 FF
Store FFH to the control block byte at Index Register IX+10H: no extent there.
5061
INC IX DD 23
INCrement Index Register IX by 1 to the next byte.
5063
DECrement Register B and loop back to 505DH while Register B is not zero.
5065
POP IX DD E1
Restore Index Register IX from the top of the stack: the file control block.
5067
XOR A AF
Set Register A to 00H by XORing it with itself, and set the Z FLAG: the control block is ready.
5068
RET C9
RETurn with Register A = 00H and the Z FLAG set.

5069H - Take the File Specification Apart

Called by OPEN@ (4E68H) with Register Pair DE pointing to the file control block that holds the specification. The name (up to 8 characters) goes to 51E0H, the extension after a slash (3) to 51E8H, the password after a period (8) to 51D6H, all padded with spaces; a drive name after a colon is looked up in DCTTBL (44E8H) and its number goes to 51CDH (FFH when no drive is given). Register A returns 00H with the Z FLAG, or 13H (no name) or 20H (no such drive) with the NZ FLAG.

5069
LD B,0BH 06 0B
Load Register B with 0BH, the 11 bytes of the name and extension buffer.
506B
LD HL,51E0H 21 E0 51
Point Register Pair HL to 51E0H, the name and extension buffer.
506E
LD (HL),20H 36 20
Store 20H (a space) to the byte at Register Pair HL.
5070
INC HL 23
INCrement Register Pair HL by 1 to the next byte of the buffer.
5071
DECrement Register B and loop back to 506EH while Register B is not zero: 51E0H-51EAH are spaces.
5073
LD B,0AH 06 0A
Load Register B with 0AH, the 10 bytes of the password and drive name buffers.
5075
LD HL,51D6H 21 D6 51
Point Register Pair HL to 51D6H, the password buffer, followed by the drive name buffer at 51DEH.
5078
LD (HL),20H 36 20
Store 20H (a space) to the byte at Register Pair HL.
507A
INC HL 23
INCrement Register Pair HL by 1 to the next byte.
507B
DECrement Register B and loop back to 5078H while Register B is not zero: 51D6H-51DFH are spaces.
507D
LD B,08H 06 08
Load Register B with 08H, the most characters of a name.
507F
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the specification in the file control block.
5080
LD DE,51E0H 11 E0 51
Point Register Pair DE to 51E0H, where the name goes.
5083
GOSUB to 50F0H to copy up to Register B (8) name characters from Register Pair HL to Register Pair DE (51E0H). Register A returns the character after them and Register B the room left.
5086
LD C,A 4F
Load Register C with Register A, the character after the name.
5087
LD A,B 78
Load Register A with Register B, the room left in the name.
5088
CP 08H FE 08
Compare Register A against 08H: all 8 places left means no character was copied.
508A
If the NZ FLAG is set (there is a name), JUMP to 5090H.
508C
LD A,13H 3E 13
Load Register A with 13H, the error code Improper file name.
508E
OR A B7
OR Register A with itself to set the NZ FLAG.
508F
RET C9
RETurn with Register A = 13H and the NZ FLAG set.
5090
LD A,C 79
Load Register A with Register C, the character after the name.
5091
CP 2FH FE 2F
Compare Register A against 2FH (a slash, before an extension).
5093
If the NZ FLAG is set (no extension), JUMP to 509DH.
5095
LD B,03H 06 03
Load Register B with 03H, the most characters of an extension.
5097
LD DE,51E8H 11 E8 51
Point Register Pair DE to 51E8H, the extension's place in the buffer.
509A
GOSUB to 50F0H to copy up to Register B (3) characters of the extension from Register Pair HL to Register Pair DE (51E8H). Register A returns the character after them.
509D
CP 2EH FE 2E
Compare Register A, the character after the name or extension, against 2EH (a period, before a password).
509F
If the NZ FLAG is set (no password), JUMP to 50A9H.
50A1
LD B,08H 06 08
Load Register B with 08H, the most characters of a password.
50A3
LD DE,51D6H 11 D6 51
Point Register Pair DE to 51D6H, the password buffer.
50A6
GOSUB to 50F0H to copy up to Register B (8) characters of the password from Register Pair HL to Register Pair DE (51D6H). Register A returns the character after them.
50A9
CP 3AH FE 3A
Compare Register A, the character after the specification so far, against 3AH (a colon, before a drive name).
50AB
LD C,FFH 0E FF
Load Register C with FFH, the drive byte for no drive named; the flags stay as the compare set them.
50AD
If the NZ FLAG is set (no drive), JUMP to 50EAH to store Register C (FFH).
50AF
LD DE,51DEH 11 DE 51
Point Register Pair DE to 51DEH, the drive name buffer.
50B2
PUSH DE D5
Save Register Pair DE (51DEH) to the top of the stack.
50B3
LD B,02H 06 02
Load Register B with 02H, the most characters of a drive name.
50B5
GOSUB to 50F0H to copy up to Register B (2) characters of the drive name from Register Pair HL to Register Pair DE (51DEH).
50B8
POP HL E1
Restore Register Pair HL from the top of the stack: 51DEH, the drive name.
50B9
PUSH IX DD E5
Save Index Register IX, the file control block, to the top of the stack.
50BB
LD IX,44E8H DD 21 E8 44
Point Index Register IX to 44E8H, DCTTBL, the drive table of SYS0/SYS.
50BF
LD DE,0004H 11 04 00
Load Register Pair DE with 0004H, the length of a DCTTBL entry.
50C2
LD C,00H 0E 00
Load Register C with 00H, drive 0, the number of the first entry.
50C4
LD A,(IX+00H) DD 7E 00
Load Register A with the low byte of the entry's drive control table address at Index Register IX+00H.
50C7
AND (IX+01H) DD A6 01
AND Register A with the high byte at Index Register IX+01H: Register A = FFH only when the address is FFFFH (no drive).
50CA
INC A 3C
INCrement Register A by 1. The Z FLAG is set when the entry has no drive.
50CB
If the Z FLAG is set, JUMP to 50DBH for the next entry.
50CD
LD A,(IX+02H) DD 7E 02
Load Register A with the first character of the entry's name at Index Register IX+02H.
50D0
CP (HL) BE
Compare Register A against the first character of the drive name at Register Pair HL (51DEH).
50D1
If the NZ FLAG is set (they differ), JUMP to 50DBH for the next entry.
50D3
LD A,(IX+03H) DD 7E 03
Load Register A with the second character of the entry's name at Index Register IX+03H.
50D6
INC HL 23
INCrement Register Pair HL by 1 to 51DFH, the second character of the drive name.
50D7
CP (HL) BE
Compare Register A against the second character at Register Pair HL (51DFH).
50D8
DEC HL 2B
DECrement Register Pair HL by 1 back to 51DEH; the flags stay as the compare set them.
50D9
If the Z FLAG is set (the names agree), JUMP to 50E8H with Register C = the drive.
50DB
ADD IX,DE DD 19
ADD Register Pair DE (4) to Index Register IX: the next entry of DCTTBL.
50DD
LD A,07H 3E 07
Load Register A with 07H, the number of the last DCTTBL entry.
50DF
INC C 0C
INCrement Register C, the drive number, by 1 to the next entry.
50E0
CP C B9
Compare Register A (7) against Register C. The NC FLAG is set while Register C is 7 or less.
50E1
If the NC FLAG is set, JUMP back to 50C4H for the next entry.
50E3
POP AF F1
Restore Register Pair AF from the top of the stack: it drops Index Register IX saved at 50B9H; the wrapper of OPEN@ restores Index Register IX at the end.
50E4
LD A,20H 3E 20
Load Register A with 20H, the error code Improper drive number.
50E6
OR A B7
OR Register A with itself to set the NZ FLAG.
50E7
RET C9
RETurn with Register A = 20H and the NZ FLAG set.
50E8
POP IX DD E1
Restore Index Register IX from the top of the stack: the file control block.
50EA
LD A,C 79
Load Register A with Register C, the drive number (FFH when none was named).
50EB
LD (51CDH),A 32 CD 51
Store Register A, the drive number or FFH, to the drive byte at 51CDH.
50EE
XOR A AF
Set Register A to 00H by XORing it with itself, and set the Z FLAG: the specification is taken.
50EF
RET C9
RETurn with Register A = 00H and the Z FLAG set.

50F0H - Copy Name Characters

Copies the characters at Register Pair HL that a name may hold (letters, made upper case, digits and the characters # $ % & + < >) to Register Pair DE, at most Register B of them. Register A returns the first other character, or the character after a full field, and Register Pair HL points past it. The fifth load block of the file (50FDH-5103H) is a patch: before it, 50FDH-5102H were CP 41H / RET C / CP 5BH / JR C,5111H, so the characters 3AH-40H ended the field and < and > in the table at 5118H were never taken.

50F0
LD A,(HL) 7E
Load Register A with the character at Register Pair HL.
50F1
GOSUB to 512DH to make Register A upper case when it is a lower case letter.
50F4
INC HL 23
INCrement Register Pair HL by 1 past the character in Register A.
50F5
CP 30H FE 30
Compare Register A against 30H, the character 0. The C FLAG is set below it.
50F7
If the C FLAG is set, JUMP to 5104H to look Register A up in the table of name characters.
50F9
CP 3AH FE 3A
Compare Register A against 3AH, one past the character 9. The C FLAG is set for a digit.
50FB
If the C FLAG is set (a digit), JUMP to 5111H to store it.
50FD
CP 5BH FE 5B
Compare Register A against 5BH, one past the character Z (patched by the fifth load block: CP 41H in the first).
50FF
RET NC D0
If the NC FLAG is set (5BH or above), RETurn with Register A = the character that ends the field (patched: RET C in the first block).
5100
CP 41H FE 41
Compare Register A against 41H, the character A (patched: CP 5BH in the first block).
5102
If the NC FLAG is set (a letter), JUMP to 5111H to store it (patched: JR C,5111H in the first block).
5104
PUSH BC C5
Save Register Pair BC (Register B the room left) to the top of the stack.
5105
PUSH HL E5
Save Register Pair HL, the text, to the top of the stack.
5106
LD HL,5118H 21 18 51
Point Register Pair HL to 5118H, the table of name characters.
5109
LD BC,0007H 01 07 00
Load Register Pair BC with 0007H, the seven characters of the table.
510C
CPIR ED B1
Compare Register A with the bytes at Register Pair HL (5118H), INCrementing Register Pair HL and DECrementing Register Pair BC (7), until one agrees (the Z FLAG) or Register Pair BC is zero.
510E
POP HL E1
Restore Register Pair HL from the top of the stack: the text.
510F
POP BC C1
Restore Register Pair BC from the top of the stack: Register B the room left.
5110
RET NZ C0
If the NZ FLAG is set (not a name character), RETurn with Register A = the character that ends the field.
5111
LD (DE),A 12
Store Register A, the character, to Register Pair DE.
5112
INC DE 13
INCrement Register Pair DE by 1 to the next place.
5113
DECrement Register B and loop back to 50F0H while Register B is not zero: there is room for more.
5115
LD A,(HL) 7E
The field is full: load Register A with the character after it at Register Pair HL.
5116
INC HL 23
INCrement Register Pair HL by 1 past that character.
5117
RET C9
RETurn with Register A = the character after the field and Register B = 00H.
5118-511E
DEFB 23H,24H,25H,26H,2BH,3CH,3EH 23 24 25 26 2B 3C 3E
Data: the seven characters 5104H accepts in a name besides letters and digits: # $ % & + < >.

511FH - The Hash Index Code

Routine 7, used by OPEN@ (4E6FH). Register A returns the code of the 11 characters of name and extension at Register Pair HL, the byte the hash index table holds for the file: each character is XORed into the code, which is then rotated left. A code of 00H, which marks a free entry, becomes 01H.

511F
LD BC,0B00H 01 00 0B
Load Register Pair BC with 0B00H: Register B = 11 characters, Register C = 00H, the code so far.
5122
LD A,(HL) 7E
Load Register A with the character at Register Pair HL.
5123
INC HL 23
INCrement Register Pair HL by 1 to the next character.
5124
XOR C A9
XOR Register A (the character) with Register C, the code so far.
5125
RLCA 07
Rotate Register A left, bit 7 into bit 0 and the C FLAG.
5126
LD C,A 4F
Load Register C with Register A, the new code.
5127
DECrement Register B and loop back to 5122H while Register B is not zero.
5129
OR A B7
OR Register A, the code, with itself to test it for 00H.
512A
RET NZ C0
If the NZ FLAG is set, RETurn with Register A = the hash index code.
512B
INC A 3C
INCrement Register A by 1: a code of 00H becomes 01H, since 00H marks a free entry of the table.
512C
RET C9
RETurn with Register A = 01H, the hash index code.

512DH - Upper Case

Makes a lower case letter in Register A upper case; any other character is returned as it is.

512D
CP 61H FE 61
Compare Register A against 61H, the character a. The C FLAG is set below it.
512F
RET C D8
If the C FLAG is set, RETurn with Register A as it is.
5130
CP 7BH FE 7B
Compare Register A against 7BH, one past the character z.
5132
RET NC D0
If the NC FLAG is set (above z), RETurn with Register A as it is.
5133
AND 5FH E6 5F
AND Register A with 5FH, clearing bits 7 and 5: the lower case letter becomes upper case.
5135
RET C9
RETurn with Register A = the upper case letter.

5136H - Routines 8 and 9

Routine 8 returns the address of the name buffer; routine 9 returns the drive found by the last specification.

5136
LD HL,51E0H 21 E0 51
Point Register Pair HL to 51E0H, the name and extension buffer.
5139
RET C9
RETurn to the overlay request handler (49E7H) with Register Pair HL = 51E0H.
513A
LD A,(51CDH) 3A CD 51
Load Register A with the drive byte at 51CDH (00H-07H, or FFH when no drive was named).
513D
LD C,A 4F
Load Register C with Register A, the drive byte.
513E
RET C9
RETurn to the overlay request handler (49E7H) with Register A and Register C = the drive byte.

513FH - Find a Free Entry of the Hash Index Table

Called by INIT@ (4F67H) with the hash index table at 4300H and Index Register IY pointing to the drive control table. The search starts at a place picked from the refresh register: one of the even entries 0, 2, 4 or 6 of a directory sector picked by the refresh register's value divided by the number of entry sectors. From there each entry of the sector is tried, then the next sector, to the last; then the search starts again at 00H. The Z FLAG returns set with Register Pair HL pointing to a free byte (00H); the NZ FLAG when there is none.

513F
PUSH DE D5
Save Register Pair DE to the top of the stack.
5140
LD A,R ED 5F
Load Register A with Register R, the refresh register, a value that changes all the time.
5142
LD E,A 5F
Load Register E with Register A, the refresh register's value.
5143
AND E0H E6 E0
AND Register A (the refresh value) with E0H to keep bits 7-5.
5145
ADD A,A 87
ADD Register A to itself: bits 6-5 move to bits 7-6 and the entry number within the sector becomes 0, 2, 4 or 6.
5146
LD D,A 57
Load Register D with Register A, the entry bits of the logical file number.
5147
LD A,(IY+0EH) FD 7E 0E
Load Register A with the directory length in sectors at Index Register IY+0EH (DCT+0EH).
514A
SUB 02H D6 02
SUBtract 02H from Register A: the sectors that hold entries (the GAT and the hash index table are the first two).
514C
GOSUB to 4494H in SYS0/SYS to divide Register E (the refresh value) by Register A (the entry sectors): Register E returns the remainder, the sector bits of the logical file number.
514F
LD A,E 7B
Load Register A with Register E, the sector bits (0 to the entry sectors less 1).
5150
OR D B2
OR Register A with Register D, the entry bits: Register A = the logical file number to start at.
5151
POP DE D1
Restore Register Pair DE from the top of the stack.
5152
LD L,A 6F
Load Register L with Register A: Register Pair HL = 4300H + the starting logical file number.
5153
GOSUB to 5159H to search from Register Pair HL. The Z FLAG returns set when a free byte was found.
5156
RET Z C8
If the Z FLAG is set, RETurn with Register Pair HL at the free byte.
5157
LD L,00H 2E 00
Load Register L with 00H: Register Pair HL = 4300H, the first byte, to search again from there.
5159
LD A,(HL) 7E
Load Register A with the byte of the hash index table at Register Pair HL.
515A
OR A B7
OR Register A with itself to test it for 00H, a free entry.
515B
RET Z C8
If the Z FLAG is set, RETurn with Register Pair HL at the free byte.
515C
LD A,20H 3E 20
Load Register A with 20H, the step to the next entry of the same sector (bits 7-5).
515E
ADD A,L 85
ADD Register L to Register A: the next entry of the sector. The C FLAG is set past the eighth.
515F
LD L,A 6F
Load Register L with Register A, the next logical file number.
5160
If the NC FLAG is set, JUMP back to 5159H to try it.
5162
LD A,(IY+0EH) FD 7E 0E
Load Register A with the directory length at Index Register IY+0EH (DCT+0EH).
5165
SUB 03H D6 03
SUBtract 03H from Register A: the sector bits of the last entry sector.
5167
INC L 2C
INCrement Register L by 1 to entry 0 of the next sector.
5168
CP L BD
Compare Register A against Register L. The NC FLAG is set while Register L is the last sector or before it.
5169
If the NC FLAG is set, JUMP back to 5159H to try it.
516B
OR FFH F6 FF
OR Register A with FFH: Register A = FFH and the NZ FLAG is set, no free entry from here on.
516D
RET C9
RETurn with the NZ FLAG set: the hash index table is full.

516EH - The Password Code

Routine 5, used by OPEN@ (4E78H). Register Pair HL returns the 16 bit code of the 8 characters at Register Pair DE (padded with spaces; letters are made upper case), taken from the last to the first, starting from FFFFH. Eight spaces give 4296H, the code DIR/SYS holds for a file without a password. Register Pair DE returns one byte before the first character.

516E
LD HL,FFFFH 21 FF FF
Load Register Pair HL with FFFFH, the starting code.
5171
LD B,08H 06 08
Load Register B with 08H, the 8 characters of the password.
5173
LD A,E 7B
Load Register A with Register E, the low byte of the password's address.
5174
ADD A,07H C6 07
ADD 07H to Register A: the low byte of the address of the last character.
5176
LD E,A 5F
Load Register E with Register A, the low byte.
5177
If the NC FLAG is set (no carry), JUMP to 517AH.
5179
INC D 14
INCrement Register D by 1, the carry into the high byte: Register Pair DE = the last character.
517A
LD A,(DE) 1A
Load Register A with the character of the password at Register Pair DE.
517B
GOSUB to 512DH to make Register A upper case when it is a lower case letter.
517E
PUSH DE D5
Save Register Pair DE, the place in the password, to the top of the stack.
517F
LD D,A 57
Load Register D with Register A, the character.
5180
LD E,H 5C
Load Register E with Register H, the high byte of the code so far.
5181
LD A,L 7D
Load Register A with Register L, the low byte of the code so far.
5182
AND 07H E6 07
AND Register A (the low byte of the code) with 07H to keep its bits 2-0.
5184
RRCA 0F
Rotate Register A right, the first of three rotations.
5185
RRCA 0F
Rotate Register A right, the second of three rotations.
5186
RRCA 0F
Rotate Register A right, the third: bits 2-0 of Register L are now bits 7-5.
5187
XOR L AD
XOR Register A with Register L, the low byte of the code: Register A = the low byte with its bits 7-5 changed by its bits 2-0.
5188
LD L,A 6F
Load Register L with Register A, the changed low byte of the code.
5189
LD H,00H 26 00
Load Register H with 00H: Register Pair HL = the changed low byte.
518B
ADD HL,HL 29
ADD Register Pair HL to itself: the value times 2.
518C
ADD HL,HL 29
ADD Register Pair HL to itself: the changed low byte times 4.
518D
ADD HL,HL 29
ADD Register Pair HL to itself: the changed low byte times 8.
518E
ADD HL,HL 29
ADD Register Pair HL to itself: times 16, so Register H = the value's bits 7-4 and Register L its bits 3-0 moved up.
518F
XOR H AC
XOR Register A (the value) with Register H (its high four bits).
5190
XOR D AA
XOR Register A with Register D, the character: the new high byte of the code.
5191
LD D,A 57
Load Register D with Register A, the new high byte.
5192
LD A,L 7D
Load Register A with Register L, the value's low four bits moved up.
5193
ADD HL,HL 29
ADD Register Pair HL to itself: the value times 32.
5194
XOR H AC
XOR Register A with Register H, the value's bits 7-3.
5195
XOR E AB
XOR Register A with Register E, the old high byte of the code: the new low byte.
5196
LD E,A 5F
Load Register E with Register A, the new low byte: Register Pair DE = the new code.
5197
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the new code.
5198
POP DE D1
Restore Register Pair DE from the top of the stack: the place in the password.
5199
DEC DE 1B
DECrement Register Pair DE by 1 to the character before.
519A
DECrement Register B and loop back to 517AH while Register B is not zero.
519C
RET C9
RETurn with Register Pair HL = the password code.

519DH - Reading and Writing the Directory's First Sectors

519DH reads the hash index table (directory sector 1), 51ADH writes it, 51BDH reads the GAT (sector 0), each into or from 4300H, on drive Register C. The Z FLAG returns set when the transfer worked; otherwise Register A holds 16H, 17H or 14H with the NZ FLAG.

519D
PUSH DE D5
Save Register Pair DE to the top of the stack.
519E
LD E,01H 1E 01
Load Register E with 01H, directory sector 1, the hash index table.
51A0
LD HL,4300H 21 00 43
Point Register Pair HL to 4300H, the system sector buffer.
51A3
LD A,06H 3E 06
Load Register A with 06H, the SREAD function of DISKIO%, which reads sector Register E of the directory cylinder.
51A5
GOSUB to 4488H (DISKIO%) to read the hash index table of drive Register C into the buffer at Register Pair HL (4300H).
51A8
POP DE D1
Restore Register Pair DE from the top of the stack.
51A9
RET Z C8
If the Z FLAG is set (read), RETurn with Register Pair HL = 4300H.
51AA
LD A,16H 3E 16
Load Register A with 16H, the error code Hit read error; the NZ FLAG stays set.
51AC
RET C9
RETurn with Register A = 16H and the NZ FLAG set.
51AD
PUSH DE D5
Save Register Pair DE to the top of the stack.
51AE
LD E,01H 1E 01
Load Register E with 01H, directory sector 1, the hash index table.
51B0
LD HL,4300H 21 00 43
Point Register Pair HL to 4300H, the buffer that holds the table.
51B3
LD A,07H 3E 07
Load Register A with 07H, the SWRITE function of DISKIO%, which writes sector Register E of the directory cylinder.
51B5
GOSUB to 4488H (DISKIO%) to write the buffer at Register Pair HL (4300H) to the hash index table of drive Register C.
51B8
POP DE D1
Restore Register Pair DE from the top of the stack.
51B9
RET Z C8
If the Z FLAG is set (written), RETurn with Register A = 00H.
51BA
LD A,17H 3E 17
Load Register A with 17H, the error code Hit write error; the NZ FLAG stays set.
51BC
RET C9
RETurn with Register A = 17H and the NZ FLAG set.
51BD
PUSH DE D5
Save Register Pair DE to the top of the stack.
51BE
LD E,00H 1E 00
Load Register E with 00H, directory sector 0, the GAT.
51C0
LD HL,4300H 21 00 43
Point Register Pair HL to 4300H, the system sector buffer.
51C3
LD A,06H 3E 06
Load Register A with 06H, the SREAD function of DISKIO%.
51C5
GOSUB to 4488H (DISKIO%) to read the GAT of drive Register C into the buffer at Register Pair HL (4300H).
51C8
POP DE D1
Restore Register Pair DE from the top of the stack.
51C9
RET Z C8
If the Z FLAG is set (read), RETurn with Register Pair HL = 4300H.
51CA
LD A,14H 3E 14
Load Register A with 14H, the error code Gat read error; the NZ FLAG stays set.
51CC
RET C9
RETurn with Register A = 14H and the NZ FLAG set. 51CCH is the last byte of SYS2/SYS.

51CDH - The Work Area

Not in the file: the bytes after SYS2/SYS that OPEN@ and INIT@ use, up to 51EEH below the end of the low overlay area.

51CD
DEFS 1
The drive: 00H-07H when the specification names one (stored at 50EBH), FFH when it does not. OPEN@ (4E81H, 4EABH) and INIT@ (4F4EH, 4F6CH) read it; routine 9 returns it (513AH).
51CE
DEFS 1
The access level the file control block gets: 0 or the file's protection level (4F3AH), 0 for a file INIT@ creates (4F4BH); 4FC7H puts it in FCB+01H.
51CF
DEFS 1
The protection level of the directory entry found, bits 2-0 of its first byte (4EEFH), read by the password check (4EFFH, 4F2FH).
51D0
DEFS 1
The hash index code of the file's name (4E72H), looked for in the hash index table (4EA2H) and stored there by INIT@ (4F7EH).
51D1
DEFS 1
The logical record length Register B brought to OPEN@ (4E65H), put in a new entry (4F99H) and the file control block (4FCFH, 4FFAH).
51D2-51D3
DEFS 2
The buffer address Register Pair HL brought to OPEN@ (4E61H), put in FCB+03H-04H (4FE0H).
51D4-51D5
DEFS 2
The master password code of the diskette, from the GAT at 43CEH (4E9AH), compared at 4F0AH.
51D6-51DD
DEFS 8
The password from the specification, padded with spaces (5075H, 50A3H), whose code 4E78H computes.
51DE-51DF
DEFS 2
The drive or device name from the specification, padded with a space (4E22H-4E2EH, 50AFH-50B5H).
51E0-51EA
DEFS 11
The name (51E0H-51E7H) and extension (51E8H-51EAH), padded with spaces (506BH-509AH): hashed at 4E6CH, compared with each entry (4EDDH) and put in a new entry (4FA3H). Routine 8 returns its address (5136H).
51EB-51EC
DEFS 2
The password code (4E7BH), compared at 4EF3H, 4F06H, 4F1CH and 4F29H, and a new entry's update password (4FA6H).
51ED-51EE
DEFS 2
A copy of the password code (4E7EH), a new entry's access password (4FA6H).