5200H - The Diskette FCB
The first load record (5200H-521FH) is a 32-byte FCB that DIRCHECK hands to the DOS read routine at 4436H and the write routine at 443CH. It is set up as an open FCB with FCB+0 bit 1 set, so NEXT names a sector of the whole diskette (counted from 0) instead of a sector of a file. DIRCHECK stores the target drive at 5206H, the buffer address at 5203H-5204H and the sector to read or write at 520AH-520BH before each call.
5200
DEFB 82H 82
FCB+0, the FCB flags: 82H. Bit 7 set means the FCB is open (SYS0 4980H refuses an FCB without it); bit 1 set means NEXT and EOF count sectors of the whole diskette, not of a file. Bit 0 (write with the directory mark) is set at 591BH for each W or C write and cleared again at 5925H.
5201
DEFB 60H 60
FCB+1: 60H. Bit 6 set keeps the EOF field where it is when a sector is written (SYS0 4A51H); bit 5 set says the buffer does not hold the sector at NEXT. Bits 0-2 are the access level, 0 (FULL), so reading and writing are both allowed.
5202
DEFB 00H 00
FCB+2: 00H. Bit 5 would say that the file's directory entry has been marked updated; with FCB+0 bit 1 set there is no directory entry and SYS0 4A70H skips that step.
5203-5204
DEFW 0000H 00 00
FCB+3 and FCB+4, the buffer address: 0000H in the file. 5820H stores the buffer of each read here (61BAH, 62BAH, 63BAH or 64BAH), and 58E0H stores 61BAH for the W and C functions.
5205
DEFB 00H 00
FCB+5, the low byte of NEXT (the byte within the sector): 00H, never changed, because DIRCHECK always reads and writes whole sectors (FCB+1 bit 7, record mode, is clear).
5206
DEFB 00H 00
FCB+6, the drive number: 00H in the file. 52B4H stores the drive typed in answer to the drive question here.
5207
DEFB FFH FF
FCB+7, the DEC of the file's directory entry: FFH. It is not used, because FCB+0 bit 1 says the FCB addresses the whole diskette.
5208
DEFB 00H 00
FCB+8, the low byte of EOF: 00H. With EOF at FFFF00H no sector number reaches it.
5209
DEFB 00H 00
FCB+9, the logical record length: 00H (256). FCB+1 bit 7 is clear, so reads and writes move whole sectors.
520A-520B
DEFW 0000H 00 00
FCB+10 and FCB+11, the middle and high bytes of NEXT: the number of the diskette sector to read or write next, 0000H in the file. Stored at 52D2H (0, the BOOT sector), 5310H (the directory's first sector), 57F6H (an FDE sector), 58EBH and 591EH (W and C). 4436H adds 1 after each read.
520C-520D
DEFW FFFFH FF FF
FCB+12 and FCB+13, the middle and high bytes of EOF: FFFFH, also stored again at 52CCH. With EOF at the top of the range every sector number is below EOF, so SYS0 4A1EH never reports END OF FILE.
520E-5215
DEFB FFH, FFH, FFH, FFH, FFH, FFH, FFH, FFH FF FF FF FF FF FF FF FF
FCB+14 to FCB+21, the four extent elements of an ordinary FCB: all FFH (end of list). Not used while FCB+0 bit 1 is set.
5216-5217
DEFB FFH, FFH FF FF
FCB+22 and FCB+23, the granule count before the second extent group: FFH, FFH. Not used here.
5218-521F
DEFB FFH, FFH, FFH, FFH, FFH, FFH, FFH, FFH FF FF FF FF FF FF FF FF
FCB+24 to FCB+31, the second group of four extent elements: all FFH. Not used here.
5220H - Work Areas Not in the File
The file has no load record for 5220H-5275H, so these bytes hold whatever was in memory when DIRCHECK was loaded. Every one of them is written before it is read.
5220-525F
DEFS 64
The input line buffer: 64 bytes. 59B9H points Register Pair HL here and passes Register B = 40H (64) to the ROM's line input at 0040H; the typed line ends with 0DH. 529DH reads the drive number digits from here.
5260-5267
DEFS 8
A copy of 430AH-4311H, bytes 0-7 of the target drive's PDRIVE record, made at 52E8H after the BOOT sector read. 5260H = the directory's first lump (replaced at 52FFH by the value from the BOOT sector), 5261H = the number of lumps, 5262H = the PDRIVE flags, 5263H = the number of tracks, 5264H = the sectors per track, 5265H = the granules per lump, 5266H = the byte for the sector register, 5267H = the disk I/O flags.
5268
DEFS 1
The printer answer: 00H when the answer to OUTPUT TO PRINTER? was N, 0BH when it was Y (the character minus 4EH). Written at 528EH; read at 5383H, where a value other than 0 switches the output to the printer.
5269-526D
DEFS 5
The number buffer: 5B41H writes a number here as five decimal digits and 5B2BH blanks the leading zeros; 5B01H writes two hexadecimal digits at 5269H-526AH. The characters are printed from here by 599BH.
526E
DEFS 1
The unprotected directory flag: 00H until a directory sector is read without the directory mark, then 01H. Cleared at 52C6H, set at 5812H (the message at 5D06H is shown the first time), read at 580CH and 53B6H (the message is shown again after the listing).
526F
DEFS 1
The number of directory sectors: 10 plus the extra FDE sectors named by HIT byte 1FH, or 00H if that byte is bad. Written at 5354H; read at 58D2H by the W and C functions, which refuse to run when it is 00H.
5270-5271
DEFS 2
The number of granules on the diskette: tracks times sectors per track, divided by 5. Written at 5364H; read at 53CAH, 5473H, 5615H and 5720H.
5272
DEFS 1
The FDE sector (0 is the first sector after the HIT) held in the first FDE buffer at 61BAH. Set to 00H at 532BH and to the sector read at 5885H.
5273
DEFS 1
The FDE sector held in the second FDE buffer at 62BAH. Set to 01H at 5330H and to the sector read at 58B8H.
5274-5275
DEFS 2
The diskette sector number of the directory's first sector (the GAT): the directory lump times the sectors per lump. Written at 530DH; read at 57F2H and 58E3H.
5276H - Variables in the File
The last bytes of the second load record's lead-in (5276H-5280H) are variables that DIRCHECK changes while it runs. The program starts at 5281H, just after them.
5276
DEFB 00H 00
A printer option byte: when it is not 0, 59F5H outputs six carriage returns through 5A69H each time the page line count at 5277H runs out. It is 00H in the file and no instruction writes it, so the six lines are never sent.
5277
DEFB 00H 00
Lines left on the printer page, counted down at 59FCH for every line output while the printer is selected, and reloaded with 3CH (60) when it reaches 0. It is 00H in the file, so the first count wraps to FFH (255). Only the unreferenced routines at 59EFH and 5A1CH would use it for anything else.
5278
DEFB 00H 00
Character positions left on the output line: set to 40H (64) at 5A18H after every carriage return and counted down by 5A34H for every other character. 5A27H ends the line when it reaches 0; 59A3H uses it to move to a column; 5A7CH uses it to decide whether the display still needs the carriage return.
5279
DEFB 00H 00
The DEC (directory entry code) of the entry being examined in the directory passes at 543AH, 55A4H and 5625H. Bits 0-4 are the FDE sector (0 = the first after the HIT), bits 5-7 the entry within it. 58BDH steps it to the next entry.
527A
DEFB 00H 00
The DEC of the entry of the file's chain being examined: first the same DEC as 5279H, then the DEC of each FXDE the chain links to (54AAH, 55FDH). 579EH uses it as the offset of the entry's byte in the HIT.
527B
DEFB 00H 00
The DEC of the previous entry in a file's chain (54A4H), which an FXDE's byte 1 must match (54CDH); also the back link of a stand-alone FXDE (5500H). 5628H stores FFH here before the listing; nothing in the listing reads it.
527C
DEFB 00H 00
The HIT code computed from an FPDE's 11-character name and extension at 5786H; 579EH compares it with the HIT byte.
527D-527E
DEFW 0000H 00 00
The number of the granule being checked by 554EH (0 is the first granule of the diskette). Written at 5554H; read at 5596H, 55C9H and 5611H.
527F-5280
DEFW 0000H 00 00
The address of that granule's byte in the granule map at 65BAH. Written at 5558H; read at 559CH and 561DH, and at 5710H, where it still holds the map address of the last granule checked.
5281H - Entry Point: The Printer Question
DOS loads DIRCHECK/CMD and jumps to its transfer address 5281H. The reply I at the end (5958H) also comes back here. The program sets its own stack, then asks whether the output goes to the printer until exactly one character is typed and it is N or Y.
5281
LD SP,61BAH 31 BA 61
Load the Stack Pointer SP with 61BAH. The stack grows down from 61BAH into 60BAH-61B9H, below the first FDE buffer at 61BAH; 5941H resets SP to the same value at the reply prompt.
Printer Question Loop
Repeats until the reply is one character, N or Y.
5284
LD HL,5C75H 21 75 5C
Point Register Pair HL to 5C75H, the message OUTPUT TO PRINTER? (ended by 03H).
5287
GOSUB to 59B6H to display the message at Register Pair HL and read a line into 5220H. It returns with Register B = the number of characters typed, Register A = the first character (lower case changed to upper case) and Register Pair HL = 5220H.
528A
DECrement Register B (the number of characters typed) and, if it is not 0, LOOP BACK to 5284H to ask again: the reply must be exactly one character.
528C
SUB 4EH D6 4E
SUBtract 4EH (ASCII N) from Register A (the character typed). Register A becomes 00H for N and 0BH for Y; the Z FLAG is set for N.
528E
LD (5268H),A 32 68 52
Store Register A (00H for N, 0BH for Y, anything else for another character) at 5268H, the printer answer. 5383H switches the output to the printer when it is not 0.
5291
If the Z FLAG is set (Register A = 00H, the reply was N), JUMP to 5297H to ask for the drive.
5293
CP 0BH FE 0B
Compare Register A (the character minus 4EH) against 0BH, which is Y minus N. The Z FLAG is set if the reply was Y.
5295
If the NZ FLAG is set (Register A is not 0BH, so the reply was neither N nor Y), LOOP BACK to 5284H to ask again.
5297H - The Drive Question
The reply Y at the end (594BH) comes back here to check another diskette with the same printer answer. The drive number is typed in decimal; anything other than digits, or a value above 255, repeats the question.
Drive Question Loop
Repeats until the reply is a decimal number from 0 to 255.
5297
LD HL,5C89H 21 89 5C
Point Register Pair HL to 5C89H, the message WHICH DRIVE CONTAINS TARGET DISKETTE? (ended by 03H).
529A
GOSUB to 59B6H to display the message at Register Pair HL and read a line into 5220H. It returns with Register B = the number of characters typed and Register Pair HL = 5220H, the first character.
529D
EX DE,HL EB
Exchange Register Pairs DE and HL: DE now points to 5220H, the first typed character. Register Pair HL (the old DE) is not used.
529E
XOR A AF
Set Register A to 00H, the drive number built so far, and clear the flags.
Digit Loop
Register A = the number so far, Register Pair DE = the next character, Register B = the characters left.
529F
LD L,0AH 2E 0A
Load Register L with 0AH (10), the multiplier for the next decimal digit.
52A1
GOSUB to 5ACEH with Register A = the number so far and Register L = 0AH (Register H is cleared there). It returns the product in Register A (high byte, always 00H here since the most is 2,550) and Register Pair HL; Register H is not 00H once the product reaches 256.
52A4
OR H B4
OR Register H (the middle byte of the product) into Register A (its high byte). The NZ FLAG is set if the number times 10 is 256 or more.
52A5
If the NZ FLAG is set (the number is too large for one byte), LOOP BACK to 5297H to ask for the drive again.
52A7
LD A,(DE) 1A
Load Register A with the character at Register Pair DE (the next typed character; 0DH if the line is empty).
52A8
SUB 30H D6 30
SUBtract 30H (ASCII 0) from Register A, turning a digit character into its value 0-9.
52AA
CP 0AH FE 0A
Compare Register A (the character minus 30H) against 0AH. The CARRY FLAG is set only for a digit 0-9.
52AC
INC DE 13
INCrement Register Pair DE to point to the character after this one. INC DE does not change the flags.
52AD
If the NO CARRY FLAG is set (the character was not a digit), LOOP BACK to 5297H to ask again.
52AF
ADD A,L 85
ADD Register L (the low byte of the number times 10) to Register A (the digit value), giving the new number in Register A.
52B0
If the CARRY FLAG is set (the sum passed 255), LOOP BACK to 5297H to ask again.
52B2
DECrement Register B (the characters left to convert) and LOOP BACK to 529FH while it is not 0.
52B4
LD (5206H),A 32 06 52
Store Register A (the drive number typed) at 5206H, the drive byte (FCB+6) of the FCB at 5200H.
52B7H - Start a Check: Clear the Map and Read the BOOT Sector
The W and C functions come back here (592FH) to check the same diskette again after they have rewritten the directory. The granule map is cleared, the FCB is pointed at sector 0, and the BOOT sector is read into 63BAH.
52B7
LD BC,0600H 01 00 06
Load Register Pair BC with 0600H (1,536), the size of the granule map at 65BAH: one byte per granule.
52BA
LD HL,65BAH 21 BA 65
Point Register Pair HL to 65BAH, the first byte of the granule map.
Clear the Granule Map
Register Pair HL = the next map byte, Register Pair BC = the bytes left.
52BD
LD (HL),00H 36 00
Store 00H at the map byte at Register Pair HL: nothing is known yet about this granule.
52BF
INC HL 23
INCrement Register Pair HL to point to the next map byte.
52C0
DEC BC 0B
DECrement Register Pair BC (the bytes left). DEC BC does not set the flags.
52C1
LD A,B 78
Load Register A with Register B, the high byte of the count left.
52C2
OR C B1
OR Register C (the low byte of the count) into Register A. The Z FLAG is set only when Register Pair BC has reached 0000H.
52C3
If the NZ FLAG is set (bytes are left), LOOP BACK to 52BDH to clear the next one.
52C5
XOR A AF
Set Register A to 00H and clear the flags, for the flag at 526EH.
52C6
LD (526EH),A 32 6E 52
Store Register A (00H) at 526EH, the unprotected directory flag: no unprotected directory sector has been seen on this diskette yet.
52C9
LD HL,FFFFH 21 FF FF
Load Register Pair HL with FFFFH, the highest sector number, for the EOF field.
52CC
LD (520CH),HL 22 0C 52
Store Register Pair HL (FFFFH) at 520CH-520DH, the EOF field of the FCB, so that no sector number counts as past the end.
52CF
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H, the number of the BOOT sector (the first sector of the diskette).
52D2
LD (520AH),HL 22 0A 52
Store Register Pair HL (0000H) at 520AH-520BH, the NEXT sector field of the FCB.
52D5
LD HL,63BAH 21 BA 63
Point Register Pair HL to 63BAH, the buffer that later holds the GAT; the BOOT sector is read into it first.
52D8
GOSUB to 5820H to read the sector named by NEXT (0) of the drive at 5206H into the buffer at Register Pair HL (63BAH). It returns the DOS error code in Register A, with the Z FLAG set if there was no error.
52DB
If the NZ FLAG is set (the read failed), JUMP to 5ABEH to display the DOS error for the code in Register A and end with FUNCTION TERMINATED.
52DE
PUSH HL E5
Save Register Pair HL (63BAH, the BOOT sector) on the stack.
52DF
LD HL,430AH 21 0A 43
Point Register Pair HL to 430AH, the copy of bytes 0-7 of the current drive's PDRIVE record that SYS0 4776H made when the read selected the target drive.
52E2
LD DE,5260H 11 60 52
Point Register Pair DE to 5260H, DIRCHECK's copy of those eight bytes.
52E5
LD BC,0008H 01 08 00
Load Register Pair BC with 0008H, the number of bytes to copy.
52E8
LDIR ED B0
LDIR: copy Register Pair BC (8) bytes from Register Pair HL (430AH) to Register Pair DE (5260H), incrementing both: the target drive's directory lump, number of lumps, flags, tracks, sectors per track, granules per lump and two more bytes.
52EA
POP HL E1
Restore Register Pair HL from the stack: HL = 63BAH, byte 0 of the BOOT sector.
52EB
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, byte 0 of the BOOT sector (00H on a NEWDOS/80 diskette).
52EC
OR A B7
OR Register A with itself to set the flags: the Z FLAG is set if byte 0 is 00H.
52ED
INC HL 23
INCrement Register Pair HL to point to byte 1 of the BOOT sector. INC HL does not change the flags.
52EE
If the NZ FLAG is set (byte 0 is not 00H), JUMP to 52F7H: the sector is not a BOOT sector.
52F0
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, byte 1 of the BOOT sector.
52F1
CP FEH FE FE
Compare Register A (byte 1) against FEH. The Z FLAG is set if it is FEH, as on a BOOT sector.
52F3
INC HL 23
INCrement Register Pair HL to point to byte 2 of the BOOT sector. INC HL does not change the flags.
52F4
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, byte 2 of the BOOT sector: the lump where the directory starts. LD does not change the flags.
52F5
If the Z FLAG is set (bytes 0 and 1 were 00H and FEH), JUMP to 52FFH to use Register A (byte 2) as the directory lump.
52F7
LD HL,5CB0H 21 B0 5C
Point Register Pair HL to 5CB0H, the message that the diskette's first sector is not a BOOT sector and that the directory is assumed to start on lump 17.
52FA
GOSUB to 5977H to output the message at Register Pair HL and a carriage return.
52FD
LD A,11H 3E 11
Load Register A with 11H (17), the directory lump assumed.
52FFH - Read the GAT, the HIT and the First Two FDE Sectors
Register A holds the lump where the directory starts. The directory's first sector number is computed from it and saved, then the first four directory sectors are read: the GAT into 63BAH, the HIT into 64BAH, and FDE sectors 0 and 1 into the two FDE buffers 61BAH and 62BAH.
52FF
LD (5260H),A 32 60 52
Store Register A (the directory's first lump) at 5260H, over the PDRIVE value copied there.
5302
LD L,A 6F
Load Register L with Register A, the directory's first lump.
5303
LD A,(5265H) 3A 65 52
Load Register A with the byte at 5265H, the target drive's granules per lump (from PDRIVE byte 5).
5306
LD H,A 67
Load Register H with Register A, the granules per lump.
5307
RLCA 07
Rotate Register A (the granules per lump) left: Register A = granules per lump times 2.
5308
RLCA 07
Rotate Register A left again: Register A = granules per lump times 4.
5309
ADD A,H 84
ADD Register H (the granules per lump) to Register A: Register A = granules per lump times 5, the sectors per lump (a granule is 5 sectors).
530A
GOSUB to 5ACEH to multiply Register A (the sectors per lump) by Register L (the directory lump); Register H is cleared first. Register Pair HL returns the low 16 bits of the product: the diskette sector where the directory starts.
530D
LD (5274H),HL 22 74 52
Store Register Pair HL (the directory's first sector) at 5274H-5275H, where 57F2H and 58E3H find it again.
5310
LD (520AH),HL 22 0A 52
Store Register Pair HL (the directory's first sector) at 520AH-520BH, the NEXT field of the FCB, so the next read gets the GAT.
5313
LD HL,62BAH 21 BA 62
Point Register Pair HL to 62BAH, 256 bytes below the GAT buffer; the loop adds 100H before each read.
5316
LD B,02H 06 02
Load Register B with 02H: two sectors, the GAT and the HIT.
5318
INC H 24
INCrement Register H: Register Pair HL = 63BAH for the GAT, then 64BAH for the HIT.
5319
GOSUB to 5801H to read the sector at NEXT into the buffer at Register Pair HL. A directory sector must come back with error 06H (the directory mark); without it 5801H reports the unprotected directory once. 4436H adds 1 to NEXT.
531C
DECrement Register B (the sectors left) and LOOP BACK to 5318H while it is not 0.
531E
LD HL,60BAH 21 BA 60
Point Register Pair HL to 60BAH, 256 bytes below the first FDE buffer.
5321
LD B,02H 06 02
Load Register B with 02H: two FDE sectors, sectors 0 and 1 after the HIT.
5323
INC H 24
INCrement Register H: Register Pair HL = 61BAH for FDE sector 0, then 62BAH for FDE sector 1.
5324
GOSUB to 5801H to read the sector at NEXT into the buffer at Register Pair HL and check the directory mark; NEXT goes up by 1.
5327
DECrement Register B (the sectors left) and LOOP BACK to 5323H while it is not 0.
5329
LD A,00H 3E 00
Load Register A with 00H, the FDE sector now in the first FDE buffer.
532B
LD (5272H),A 32 72 52
Store Register A (00H) at 5272H, the FDE sector held at 61BAH.
532E
LD A,01H 3E 01
Load Register A with 01H, the FDE sector now in the second FDE buffer.
5330
LD (5273H),A 32 73 52
Store Register A (01H) at 5273H, the FDE sector held at 62BAH.
5333H - Directory Size and Diskette Size
HIT byte 1FH holds the number of extra FDE sectors (0, 5, 10, 15 or 20). From it DIRCHECK computes the number of directory sectors for the W and C functions, then the number of granules on the diskette from the PDRIVE tracks and sectors per track.
5333
LD A,(64D9H) 3A D9 64
Load Register A with the byte at 64D9H, byte 1FH of the HIT (64BAH + 1FH): the number of FDE sectors beyond the first eight.
5336
LD L,A 6F
Load Register L with Register A, the number of extra FDE sectors.
5337
LD H,00H 26 00
Load Register H with 00H, so Register Pair HL = the number of extra FDE sectors.
5339
GOSUB to 5AEEH to divide Register Pair HL by 5. It returns the quotient in Register Pair HL and the remainder in Register A, with the Z FLAG set if the remainder is 0.
533C
If the NZ FLAG is set (the number is not a multiple of 5), JUMP to 5345H to report a bad HIT byte.
533E
INC L 2C
INCrement Register L (the number of 5-sector groups).
533F
INC L 2C
INCrement Register L again: Register L = the groups plus 2 (the eight standard FDE sectors plus the GAT and HIT make two groups of five).
5340
LD A,L 7D
Load Register A with Register L, the directory size in groups of five sectors.
5341
CP 07H FE 07
Compare Register A (the groups) against 07H. The CARRY FLAG is set for 2 to 6 groups, that is 0 to 20 extra sectors.
5343
If the CARRY FLAG is set (the byte is valid), JUMP to 534EH with Register A = the groups.
5345
LD A,1FH 3E 1F
Load Register A with 1FH, the offset of the bad byte in the HIT, for the report.
5347
LD HL,5D6AH 21 6A 5D
Point Register Pair HL to 5D6AH, the message BAD "HIT" SECTOR BYTE.
534A
GOSUB to 583FH to output Register A (1FH) in hexadecimal, three spaces and the message at Register Pair HL.
534D
XOR A AF
Set Register A to 00H: the directory size is unknown, so it is taken as 0.
534E
LD L,05H 2E 05
Load Register L with 05H, the sectors in one group.
5350
GOSUB to 5ACEH to multiply Register A (the groups) by Register L (5); Register H is cleared first. Register L returns the product: the number of directory sectors (10 to 30), or 0.
5353
LD A,L 7D
Load Register A with Register L, the number of directory sectors.
5354
LD (526FH),A 32 6F 52
Store Register A (the number of directory sectors) at 526FH, used by the W and C functions.
5357
LD A,(5263H) 3A 63 52
Load Register A with the byte at 5263H, the number of tracks on the diskette (from PDRIVE byte 3).
535A
LD L,A 6F
Load Register L with Register A, the number of tracks.
535B
LD A,(5264H) 3A 64 52
Load Register A with the byte at 5264H, the sectors per track (from PDRIVE byte 4).
535E
GOSUB to 5ACEH to multiply Register A (the sectors per track) by Register L (the tracks); Register H is cleared first. Register Pair HL returns the number of sectors on the diskette.
5361
GOSUB to 5AEEH to divide Register Pair HL (the sectors on the diskette) by 5. Register Pair HL returns the number of granules on the diskette.
5364
LD (5270H),HL 22 70 52
Store Register Pair HL (the number of granules) at 5270H-5271H.
5367H - Is There a Lockout Table?
GAT bytes 60H-BFH hold the lockout (existence) table only when the diskette has 96 lumps or fewer and GAT byte 60H is not FFH; otherwise the allocation bits run on to byte BFH. The GAT check at 53C0H is patched to match: its instruction at 53E5H becomes LD A,17H (so the lockout test at 53E7H runs) or stays JR 53FEH (the lockout test is skipped), and the number of GAT bytes checked, the operand at 53E1H, becomes 60H or C0H.
5367
LD A,(5261H) 3A 61 52
Load Register A with the byte at 5261H, the number of lumps on the diskette (from PDRIVE byte 1).
536A
CP 61H FE 61
Compare Register A (the lumps) against 61H (97). The NO CARRY FLAG is set if the diskette has more than 96 lumps.
536C
If the NO CARRY FLAG is set (more than 96 lumps, so there is no room for a lockout table), JUMP to 5378H.
536E
LD A,(641AH) 3A 1A 64
Load Register A with the byte at 641AH, GAT byte 60H (63BAH + 60H): the first byte of the lockout table, or FFH if the diskette has none.
5371
INC A 3C
INCrement Register A (GAT byte 60H). The Z FLAG is set only if the byte was FFH.
5372
LD A,3EH 3E 3E
Load Register A with 3EH, the opcode of LD A,n, for 53E5H. LD does not change the flags.
5374
LD B,60H 06 60
Load Register B with 60H: 96 GAT bytes of allocation bits. LD does not change the flags.
5376
If the NZ FLAG is set (GAT byte 60H was not FFH, so there is a lockout table), JUMP to 537CH with Register A = 3EH and Register B = 60H.
5378
LD A,18H 3E 18
Load Register A with 18H, the opcode of JR, for 53E5H: no lockout table.
537A
LD B,C0H 06 C0
Load Register B with C0H: 192 GAT bytes of allocation bits.
537C
LD (53E5H),A 32 E5 53
Store Register A (3EH or 18H) at 53E5H, the opcode of the instruction at the start of the GAT check's granule loop.
537F
LD A,B 78
Load Register A with Register B, the number of GAT bytes to check (60H or C0H).
5380
LD (53E1H),A 32 E1 53
Store Register A (60H or C0H) at 53E1H, the operand of the CP at 53E0H that ends the GAT check.
5383H - Check the Directory and List It
The diskette's name and date are output, then the checks run in order: the GAT (53C0H), every directory entry (543AH), the HIT (5535H), every granule (554EH), the file list (5625H) and the free and locked-out counts (571BH).
5383
LD A,(5268H) 3A 68 52
Load Register A with the byte at 5268H, the printer answer (00H for N, 0BH for Y).
5386
OR A B7
OR Register A with itself: the NZ FLAG is set if the output is to go to the printer.
5387
If the NZ FLAG is set, GOSUB to 59DBH to send the output to the printer as well as the display.
538A
LD B,02H 06 02
Load Register B with 02H, the number of carriage returns.
538C
GOSUB to 597CH to output Register B (2) carriage returns.
538F
LD B,08H 06 08
Load Register B with 08H, the length of the diskette name.
5391
LD HL,648AH 21 8A 64
Point Register Pair HL to 648AH, GAT byte D0H (63BAH + D0H): the diskette name.
5394
GOSUB to 599BH to output Register B (8) characters from Register Pair HL (the name). HL returns at 6492H, GAT byte D8H.
5397
LD B,04H 06 04
Load Register B with 04H, the number of spaces.
5399
GOSUB to 59AEH to output Register B (4) spaces.
539C
LD B,08H 06 08
Load Register B with 08H, the length of the diskette date.
539E
GOSUB to 599BH to output Register B (8) characters from Register Pair HL (6492H, GAT bytes D8H-DFH: the date).
53A1
GOSUB to 597AH to output one carriage return.
53A4
GOSUB to 53C0H to check the GAT and mark allocated and locked-out granules in the granule map.
53A7
GOSUB to 543AH to check every directory entry and mark the granules each file owns.
53AA
GOSUB to 5535H to report HIT bytes that no entry accounted for.
53AD
GOSUB to 554EH to report every granule whose map byte shows a conflict.
53B0
GOSUB to 5625H to list the files, one line per FPDE in use.
53B3
GOSUB to 571BH to output the numbers of free and locked-out granules.
53B6
LD A,(526EH) 3A 6E 52
Load Register A with the byte at 526EH, the unprotected directory flag (01H if a directory sector was read without the directory mark).
53B9
OR A B7
OR Register A with itself: the NZ FLAG is set if a directory sector was unprotected.
53BA
If the NZ FLAG is set, GOSUB to 5815H to output the unprotected directory message a second time.
53BD
JUMP to 5932H to output FUNCTION COMPLETED and ask what to do next.
53C0H - Check the GAT
Called from 53A4H. The GAT (at 63BAH) has one byte per lump, one bit per granule (bit 0 = the lump's first granule). For every granule that exists on the diskette, the map byte at 65BAH gets bit 6 if the GAT marks it allocated and bit 7 if the lockout table (GAT byte + 60H) marks it locked out. Bits for granules that do not exist (past the lump's granules per lump, or past the end of the diskette) must be set in both tables; a clear one is reported as a bad GAT byte, with the offset of the byte in hexadecimal. The number of GAT bytes checked (the operand at 53E1H) and whether the lockout test runs (the opcode at 53E5H) were set at 5367H-5380H.
53C0
LD IX,63BAH DD 21 BA 63
Point Index Register IX to 63BAH, byte 0 of the GAT (the allocation byte of lump 0).
53C4
LD IY,65BAH FD 21 BA 65
Point Index Register IY to 65BAH, the granule map byte of granule 0.
53C8
LD L,00H 2E 00
Load Register L with 00H, the number of the lump being checked (also the offset of its GAT byte).
53CA
LD DE,(5270H) ED 5B 70 52
Load Register Pair DE with the value at 5270H, the number of granules on the diskette: the granules still to be accounted for.
Lump Loop
Register L = the lump, Index Register IX = its GAT byte, Index Register IY = the map byte of its first granule, Register Pair DE = the granules of the diskette not yet reached.
53CE
LD A,(5265H) 3A 65 52
Load Register A with the byte at 5265H, the granules per lump (from PDRIVE byte 5).
53D1
LD H,A 67
Load Register H with Register A: Register H = the granules of this lump that exist, at most the granules per lump.
53D2
LD A,D 7A
Load Register A with Register D, the high byte of the granules not yet reached.
53D3
OR A B7
OR Register A with itself: the NZ FLAG is set if 256 or more granules are left.
53D4
If the NZ FLAG is set (plenty of granules are left), JUMP to 53DBH with Register H = the granules per lump.
53D6
LD A,E 7B
Load Register A with Register E, the number of granules not yet reached (under 256).
53D7
CP H BC
Compare Register A (the granules left) against Register H (the granules per lump). The NO CARRY FLAG is set if a whole lump's worth is left.
53D8
If the NO CARRY FLAG is set, JUMP to 53DBH with Register H = the granules per lump.
53DA
LD H,E 63
Load Register H with Register E: the diskette ends inside this lump, so only Register E granules of it exist (0 when the lump is past the end).
53DB
LD B,08H 06 08
Load Register B with 08H: eight bits in the GAT byte.
53DD
LD C,01H 0E 01
Load Register C with 01H, the mask of bit 0, the lump's first granule.
53DF
LD A,L 7D
Load Register A with Register L, the lump number (the offset of its GAT byte).
53E0
CP 00H FE 00
Self-Modifying Code
Compare Register A (the lump number) against the operand at 53E1H: 00H in the file, set at 5380H to 60H (a lockout table follows the allocation bits) or C0H (no lockout table). The NO CARRY FLAG is set when every GAT byte has been checked.
53E2
RET NC D0
If the NO CARRY FLAG is set (Register A has reached the number of GAT bytes), RETURN to 53A7H.
53E3
XOR A AF
Set Register A to 00H, the error bits for this lump: bit 0 = the allocation byte is bad, bit 1 = the lockout byte is bad.
53E4
PUSH AF F5
Save Register Pair AF on the stack. Register A (the error bits) is the high byte of the saved word, so EX (SP),HL puts it into Register H at 53F1H and 540AH.
Granule Loop
Register C = the mask of the granule's bit, Register B = the bits left, Register H = the granules of the lump that still exist.
53E5
Self-Modifying Code
The opcode at 53E5H is 18H (JR 53FEH) in the file and is set at 537CH: 18H skips the lockout test when the GAT has no lockout table; 3EH turns this into LD A,17H (the displacement 17H becomes the operand), which changes nothing that matters because 53E7H loads Register A next, and execution falls into the lockout test.
53E7
LD A,(IX+60H) DD 7E 60
Load Register A with the byte at Index Register IX +60H, the lockout byte of this lump (GAT byte L + 60H).
53EA
INC H 24
INCrement Register H (the granules of the lump that still exist).
53EB
DEC H 25
DECrement Register H back to its value. The Z FLAG is set if Register H is 0: this granule does not exist.
53EC
If the NZ FLAG is set (the granule exists), JUMP to 53F7H to record whether it is locked out.
53EE
AND C A1
AND Register C (the granule's bit mask) with Register A (the lockout byte). The NZ FLAG is set if the bit is set, as it must be for a granule that does not exist.
53EF
If the NZ FLAG is set (the bit is set), JUMP to 53FEH to test the allocation bit.
53F1
EX (SP),HL E3
Exchange Register Pair HL with the word at the top of the stack (the Stack Pointer SP points at the saved error bits): Register H now holds the error bits and the saved word holds the lump number and count.
53F2
SET 1,H CB CC
Set bit 1 of Register H (the error bits): the lockout byte of this lump is bad.
53F4
EX (SP),HL E3
Exchange Register Pair HL with the word at the top of the stack again (the Stack Pointer SP still points at it): the error bits go back on the stack and Register Pair HL gets back the lump number (L) and granules left (H).
53F5
JUMP to 53FEH to test the allocation bit of the same granule.
53F7
AND C A1
AND Register C (the granule's bit mask) with Register A (the lockout byte). The Z FLAG is set if the granule is not locked out.
53F8
If the Z FLAG is set (not locked out), JUMP to 53FEH.
53FA
SET 7,(IY+00H) FD CB 00 FE
Set bit 7 of the map byte at Index Register IY +00H: this granule is locked out.
53FE
LD A,(IX+00H) DD 7E 00
Load Register A with the byte at Index Register IX +00H, the allocation byte of this lump (GAT byte L).
5401
INC H 24
INCrement Register H (the granules of the lump that still exist).
5402
DEC H 25
DECrement Register H back to its value. The Z FLAG is set if Register H is 0: this granule does not exist.
5403
If the NZ FLAG is set (the granule exists), JUMP to 540EH to record whether it is allocated.
5405
AND C A1
AND Register C (the granule's bit mask) with Register A (the allocation byte). The NZ FLAG is set if the bit is set, as it must be for a granule that does not exist.
5406
If the NZ FLAG is set (the bit is set), JUMP to 5419H for the next bit.
5408
EX (SP),HL E3
Exchange Register Pair HL with the word at the top of the stack (the Stack Pointer SP points at the saved error bits): Register H now holds the error bits.
5409
SET 0,H CB C4
Set bit 0 of Register H (the error bits): the allocation byte of this lump is bad.
540B
EX (SP),HL E3
Exchange Register Pair HL with the word at the top of the stack again (the Stack Pointer SP still points at it): the error bits go back and Register Pair HL gets back the lump number and granules left.
540C
JUMP to 5419H for the next bit, leaving Index Register IY and Register Pair DE as they are.
540E
AND C A1
AND Register C (the granule's bit mask) with Register A (the allocation byte). The Z FLAG is set if the granule is free.
540F
If the Z FLAG is set (the granule is free in the GAT), JUMP to 5415H.
5411
SET 6,(IY+00H) FD CB 00 F6
Set bit 6 of the map byte at Index Register IY +00H: the GAT marks this granule allocated.
5415
DEC DE 1B
DECrement Register Pair DE (the granules of the diskette not yet reached): this one has been handled.
5416
DEC H 25
DECrement Register H (the granules of this lump that still exist).
5417
INC IY FD 23
INCrement Index Register IY to the map byte of the next granule.
5419
RLC C CB 01
Rotate Register C (the bit mask) left, to the next granule's bit.
541B
DECrement Register B (the bits left) and LOOP BACK to 53E5H while it is not 0.
541D
LD A,L 7D
Load Register A with Register L, the lump number, which is the offset of its allocation byte in the GAT.
541E
POP BC C1
Restore Register Pair BC from the stack: Register B = the saved error bits of this lump, Register C = the saved flags, which are not used.
541F
BIT 0,B CB 40
Test bit 0 of Register B (the error bits): the NZ FLAG is set if the allocation byte is bad.
5421
If the NZ FLAG is set, GOSUB to 5431H to report Register A (the byte's offset) as a bad GAT byte. Register Pair BC is kept by 583FH.
5424
LD A,L 7D
Load Register A with Register L, the lump number.
5425
ADD A,60H C6 60
ADD 60H to Register A: the offset of the lump's lockout byte in the GAT.
5427
BIT 1,B CB 48
Test bit 1 of Register B (the error bits): the NZ FLAG is set if the lockout byte is bad.
5429
If the NZ FLAG is set, GOSUB to 5431H to report Register A (the lockout byte's offset) as a bad GAT byte.
542C
INC IX DD 23
INCrement Index Register IX to the next lump's allocation byte.
542E
INC L 2C
INCrement Register L, the lump number and offset of the next GAT byte.
542F
LOOP BACK to 53CEH for the next lump, with Register L = its number.
5431H - Report a Bad GAT Byte
Called from 5421H and 5429H with Register A = the offset of the bad byte in the GAT.
5431
PUSH HL E5
Save Register Pair HL (the lump number and granules left of the GAT check) on the stack.
5432
LD HL,5D52H 21 52 5D
Point Register Pair HL to 5D52H, the message BAD "GAT" SECTOR BYTE.
5435
GOSUB to 583FH to output Register A (the byte's offset) in hexadecimal, three spaces and the message at Register Pair HL, then a carriage return. Register Pair BC is kept.
5438
POP HL E1
Restore Register Pair HL (the lump number and granules left) from the stack.
5439
RET C9
RETURN to the GAT check at 5424H or 542CH with Register Pair HL restored.
543AH - Check Every Directory Entry
Called from 53A7H. Every DEC from 00H up is examined until 586AH reports that the entry's FDE sector is past the end of the directory. An FPDE in use must have its name's HIT code in the HIT (the HIT copy's byte is then cleared, so 5535H can report the bytes no entry claims); each of its extent elements must name granules that exist, and those granules are marked in the map (bit 5, and bit 4 when a second file claims one); an FEH element links to an FXDE, which must be in use, be an FXDE and link back. An FXDE met on its own is checked at 54E1H. Every complaint goes out through 582EH as the FPDE's name, its DEC in hexadecimal and a message.
543A
XOR A AF
Set Register A to 00H, the first DEC (FDE sector 0, entry 0), and clear the flags.
Entry Loop
Register A = the DEC to examine; 58BDH gives the next one at 54DBH.
543B
LD (5279H),A 32 79 52
Store Register A (the DEC to examine) at 5279H, the entry being examined.
543E
LD (527AH),A 32 7A 52
Store Register A (the same DEC) at 527AH, the entry of the chain being examined: the chain starts at this entry.
5441
GOSUB to 586AH to find the entry for the DEC in Register A, reading its FDE sector into the first FDE buffer (61BAH) if needed. It returns Index Register IY pointing to the entry and the Z FLAG set, or the NZ FLAG if the sector is past the directory.
5444
RET NZ C0
If the NZ FLAG is set (every entry of the directory has been examined), RETURN to 53AAH.
5445
LD A,(IY+00H) FD 7E 00
Load Register A with byte +00H of the entry at Index Register IY: its flags (bit 7 FXDE, bit 6 system file, bit 4 in use, bit 3 invisible, bits 0-2 access level).
5448
BIT 4,A CB 67
Test bit 4 of Register A (the entry's flags): the Z FLAG is set if the entry is not in use.
544A
If the Z FLAG is set (a free entry), JUMP to 54DBH to go on to the next DEC.
544D
BIT 7,A CB 7F
Test bit 7 of Register A (the entry's flags): the NZ FLAG is set if it is an FXDE, an extension entry.
544F
If the NZ FLAG is set, JUMP to 54E1H to check the FXDE on its own.
5452
GOSUB to 5786H to compute the HIT code of the FPDE's name and extension (bytes +05H to +0FH of the entry at Index Register IY) and store it at 527CH.
5455
GOSUB to 579EH, which points Register Pair HL to the HIT byte of the DEC at 527AH (64BAH + DEC) and compares it with the code at 527CH: the Z FLAG is set if they match.
5458
LD (HL),00H 36 00
Store 00H at the HIT byte at Register Pair HL (in DIRCHECK's copy only): this byte belongs to an entry, so 5535H will not report it. LD does not change the flags.
545A
If the Z FLAG is set (the HIT byte matches the name), JUMP to 5465H to check the extents.
545C
LD A,(5279H) 3A 79 52
Load Register A with the byte at 5279H, the DEC of this FPDE.
545F
DEC A 3D
DECrement Register A (the DEC). The Z FLAG is set only for DEC 01H, the first entry of FDE sector 1 (DIR/SYS on a NEWDOS/80 diskette), whose HIT byte is not checked.
5460
LD A,50H 3E 50
Load Register A with 50H (ASCII P), the letter that makes the message at 5F8AH read FPDE. LD does not change the flags.
5462
If the NZ FLAG is set (any DEC but 01H), GOSUB to 5829H to report FPDE HAS BAD CODE IN "HIT" SECTOR for this file.
5465
LD B,05H 06 05
Load Register B with 05H: five two-byte extent elements at bytes +16H to +1FH of an entry (the fifth is where the FEH link to an FXDE is kept).
Extent Element Loop
Index Register IY = the entry, moved up two bytes for each element; Register B = the elements left.
5467
LD A,(IY+16H) FD 7E 16
Load Register A with byte +16H of the entry at Index Register IY: byte 0 of the current extent element, the lump where it starts, or FEH (a link to an FXDE follows) or FFH (the end of the list).
546A
CP FEH FE FE
Compare Register A (the element's byte 0) against FEH. The NO CARRY FLAG is set for FEH or FFH.
546C
If the NO CARRY FLAG is set, JUMP to 549FH to handle the link or the end.
546E
GOSUB to 5758H with Register A = the starting lump to decode the element at Index Register IY: it returns Register Pair DE = the first granule, Register C = the number of granules, and the NZ FLAG; or the Z FLAG with Register Pair HL pointing to the message saying what is wrong.
5471
If the Z FLAG is set (the element is bad), JUMP to 549AH to report the message at Register Pair HL.
Granule Loop
Register Pair DE = the granule, Register C = the granules of the element left.
5473
LD HL,(5270H) 2A 70 52
Load Register Pair HL with the value at 5270H, the number of granules on the diskette.
5476
DEC HL 2B
DECrement Register Pair HL: the number of the diskette's last granule.
5477
OR A B7
OR Register A with itself to clear the CARRY FLAG for the subtraction.
5478
SBC HL,DE ED 52
SUBtract Register Pair DE (the granule) from Register Pair HL (the last granule). The CARRY FLAG is set if the granule is past the end of the diskette.
547A
LD HL,5EBEH 21 BE 5E
Point Register Pair HL to 5EBEH, the message EXTENT SPACE OVERFLOWS DISKETTE. LD does not change the flags.
547D
If the CARRY FLAG is set (the granule does not exist), JUMP to 549AH to report the message at Register Pair HL.
547F
LD HL,65BAH 21 BA 65
Point Register Pair HL to 65BAH, the granule map.
5482
ADD HL,DE 19
ADD Register Pair DE (the granule) to Register Pair HL: HL points to this granule's map byte.
5483
BIT 5,(HL) CB 6E
Test bit 5 of the map byte at Register Pair HL: the NZ FLAG is set if another file has already claimed this granule.
5485
If the Z FLAG is set (no file has claimed it yet), JUMP to 5489H.
5487
SET 4,(HL) CB E6
Set bit 4 of the map byte at Register Pair HL: the granule is claimed by more than one file.
5489
SET 5,(HL) CB EE
Set bit 5 of the map byte at Register Pair HL: the granule is claimed by a file.
548B
INC DE 13
INCrement Register Pair DE to the next granule of the element.
548C
DEC C 0D
DECrement Register C (the granules of the element left).
548D
If the NZ FLAG is set (granules are left), LOOP BACK to 5473H.
548F
INC IY FD 23
INCrement Index Register IY: first step to the next extent element.
5491
INC IY FD 23
INCrement Index Register IY again: Index Register IY +16H is now the next element.
5493
DECrement Register B (the elements left) and LOOP BACK to 5467H while it is not 0.
5495
LD HL,5EABH 21 AB 5E
All five elements were extents, with no FEH link or FFH end: point Register Pair HL to 5EABH, the message BAD EXTENT ELEMENT.
5498
JUMP to 54D8H to report the message at Register Pair HL and go on to the next DEC.
549A
GOSUB to 582EH to report the message at Register Pair HL for this file (name, DEC and message). Register Pair BC and Index Register IY are kept.
549D
JUMP to 548FH to go on with the next extent element.
549F
If the NZ FLAG is set (Register A is FFH, the end of the list), JUMP to 54DBH to go on to the next DEC.
54A1
LD A,(527AH) 3A 7A 52
Register A is FEH, a link to an FXDE. Load Register A with the byte at 527AH, the DEC of the entry holding the link.
54A4
LD (527BH),A 32 7B 52
Store Register A (that DEC) at 527BH, the previous entry of the chain, which the FXDE's back link must name.
54A7
LD A,(IY+17H) FD 7E 17
Load Register A with byte +17H of the entry at Index Register IY: byte 1 of the element, the DEC of the FXDE.
54AA
LD (527AH),A 32 7A 52
Store Register A (the FXDE's DEC) at 527AH, the entry of the chain now being examined.
54AD
GOSUB to 5893H to find the entry for the DEC in Register A, using the second FDE buffer (62BAH) if its sector is not in either buffer. It returns Index Register IY pointing to the FXDE and the Z FLAG, or the NZ FLAG if the sector is past the directory.
54B0
LD HL,5F31H 21 31 5F
Point Register Pair HL to 5F31H, the message BAD EXTENSION INDEX. LD does not change the flags.
54B3
If the NZ FLAG is set (the link names an entry past the directory), JUMP to 54D8H to report the message at Register Pair HL.
54B5
LD A,(IY+00H) FD 7E 00
Load Register A with byte +00H of the entry at Index Register IY, the linked entry's flags.
54B8
AND 90H E6 90
AND 90H with Register A: keep bit 7 (FXDE) and bit 4 (in use).
54BA
CP 90H FE 90
Compare Register A (the two bits) against 90H: the Z FLAG is set for an FXDE in use.
54BC
If the Z FLAG is set, JUMP to 54CAH to check its back link.
54BE
LD HL,5F4EH 21 4E 5F
Point Register Pair HL to 5F4EH, the message INACTIVE FXDE.
54C1
BIT 4,A CB 67
Test bit 4 of Register A (the in-use bit): the Z FLAG is set if the linked entry is not in use.
54C3
If the Z FLAG is set, JUMP to 54D8H to report the message at Register Pair HL.
54C5
LD HL,5F5CH 21 5C 5F
The linked entry is in use but is an FPDE: point Register Pair HL to 5F5CH, the message EXTENSION NOT FXDE.
54C8
JUMP to 54D8H to report the message at Register Pair HL.
54CA
LD HL,5F6FH 21 6F 5F
Point Register Pair HL to 5F6FH, the message FXDE HAS BAD BACK DEC CODE, in case the back link is wrong.
54CD
LD A,(527BH) 3A 7B 52
Load Register A with the byte at 527BH, the DEC of the entry that holds the link.
54D0
CP (IY+01H) FD BE 01
Compare Register A (that DEC) against byte +01H of the FXDE at Index Register IY, its back link. The Z FLAG is set if they match.
54D3
If the NZ FLAG is set (the back link is wrong), JUMP to 54D8H to report the message at Register Pair HL.
54D5
JUMP to 5465H to check the FXDE's extent elements, with Index Register IY on the FXDE.
54D8
GOSUB to 582EH to report the message at Register Pair HL for this file: the name of the entry at 5279H, its DEC and the message.
54DB
GOSUB to 58BDH to load Register A with the DEC after the one at 5279H.
54DE
JUMP to 543BH to examine the entry for the DEC in Register A.
54E1H - An FXDE on Its Own
Reached from 544FH with Index Register IY on an FXDE in use, found while stepping through the DECs. Its bytes +02H to +15H must be 0 (an FXDE holds only its flags, the back link and extent elements); its HIT byte must not be 0; its back link must name an entry in use whose FEH element links to this FXDE.
54E1
PUSH IY FD E5
Save Index Register IY (the FXDE's address) on the stack.
54E3
POP DE D1
Restore it into Register Pair DE: DE = the FXDE's address, byte +00H.
54E4
LD B,14H 06 14
Load Register B with 14H (20): the bytes +02H to +15H to test.
54E6
LD HL,5F45H 21 45 5F
Point Register Pair HL to 5F45H, the message BAD FXDE, in case one of the bytes is not 0.
54E9
INC DE 13
INCrement Register Pair DE to byte +01H of the FXDE.
Zero Byte Loop
Register Pair DE = the byte before the one to test, Register B = the bytes left.
54EA
INC DE 13
INCrement Register Pair DE to the next byte of the FXDE (+02H on the first pass).
54EB
LD A,(DE) 1A
Load Register A with the byte at Register Pair DE.
54EC
OR A B7
OR Register A with itself: the NZ FLAG is set if the byte is not 0.
54ED
If the NZ FLAG is set, JUMP to 54D8H to report the message at Register Pair HL (BAD FXDE).
54EF
DECrement Register B (the bytes left) and LOOP BACK to 54EAH while it is not 0.
54F1
GOSUB to 579EH to point Register Pair HL to the HIT byte of the DEC at 527AH (this FXDE's DEC). The compare with the code at 527CH that 579EH also makes is not used here.
54F4
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the FXDE's HIT byte.
54F5
OR A B7
OR Register A with itself: the Z FLAG is set if the HIT byte is 0.
54F6
LD (HL),00H 36 00
Store 00H at the HIT byte at Register Pair HL (in DIRCHECK's copy), so that 5535H does not report it. LD does not change the flags.
54F8
LD A,58H 3E 58
Load Register A with 58H (ASCII X), the letter that makes the message at 5F8AH read FXDE. LD does not change the flags.
54FA
If the Z FLAG is set (the HIT byte was 0), GOSUB to 5829H to report FXDE HAS BAD CODE IN "HIT" SECTOR with this entry's DEC.
54FD
LD A,(IY+01H) FD 7E 01
Load Register A with byte +01H of the FXDE at Index Register IY: the DEC of the entry it links back to.
5500
LD (527BH),A 32 7B 52
Store Register A (the back link's DEC) at 527BH.
5503
GOSUB to 5893H to find the entry for the DEC in Register A (the back link): Index Register IY points to it and the Z FLAG is set, or the NZ FLAG if its sector is past the directory.
5506
LD HL,5F6FH 21 6F 5F
Point Register Pair HL to 5F6FH, the message FXDE HAS BAD BACK DEC CODE. LD does not change the flags.
5509
If the NZ FLAG is set (the back link names an entry past the directory), JUMP to 54D8H to report it.
550B
BIT 4,(IY+00H) FD CB 00 66
Test bit 4 of byte +00H of the entry at Index Register IY (the back-linked entry's in-use bit).
550F
LD HL,5FACH 21 AC 5F
Point Register Pair HL to 5FACH, the message FXDE LINKS BACK TO INACTIVE FDE. LD does not change the flags.
5512
If the Z FLAG is set (that entry is not in use), JUMP to 54D8H to report it.
5514
LD B,05H 06 05
Load Register B with 05H: the five extent elements of the back-linked entry.
Link Search Loop
Looks for the FEH element of the back-linked entry. Index Register IY moves up two bytes per element; Register B = the elements left.
5516
LD A,(IY+16H) FD 7E 16
Load Register A with byte +16H of the entry at Index Register IY: byte 0 of the current element.
5519
CP FEH FE FE
Compare Register A (the element's byte 0) against FEH. The NO CARRY FLAG is set for FEH (link) or FFH (end).
551B
If the NO CARRY FLAG is set (FEH or FFH), JUMP to 5528H.
551D
INC IY FD 23
INCrement Index Register IY: first step to the next element.
551F
INC IY FD 23
INCrement Index Register IY again: Index Register IY +16H is now the next element.
5521
DECrement Register B (the elements left) and LOOP BACK to 5516H while it is not 0.
5523
LD HL,5FCEH 21 CE 5F
Point Register Pair HL to 5FCEH, the message FXDE LINKS BACK TO FDE NOT LINKING TO IT.
5526
JUMP to 54D8H to report the message at Register Pair HL.
5528
If the NZ FLAG is set (Register A is FFH: the back-linked entry has no link), JUMP to 5523H to report it.
552B
LD A,(527AH) 3A 7A 52
Load Register A with the byte at 527AH, the DEC of this FXDE.
552E
CP (IY+17H) FD BE 17
Compare Register A (this FXDE's DEC) against byte +17H of the entry at Index Register IY, the DEC the link names. The Z FLAG is set if it links to this FXDE.
5531
If the NZ FLAG is set (it links elsewhere), JUMP to 5523H to report it.
5533
JUMP to 54DBH: the FXDE is correct; go on to the next DEC.
5535H - Check the HIT
Called from 53AAH. The directory pass at 543AH cleared the HIT copy's byte of every entry it accounted for, so any byte still not 0 belongs to no entry and is reported with its offset in hexadecimal. Byte 1FH (the count of extra FDE sectors) is skipped.
5535
LD DE,64BAH 11 BA 64
Point Register Pair DE to 64BAH, byte 00H of DIRCHECK's copy of the HIT.
5538
LD B,00H 06 00
Load Register B with 00H, the offset of the byte being tested (256 bytes are tested).
HIT Byte Loop
Register Pair DE = the byte, Register B = its offset.
553A
LD A,(DE) 1A
Load Register A with the HIT byte at Register Pair DE.
553B
OR A B7
OR Register A with itself: the Z FLAG is set if the byte is 0 (free, or cleared by 543AH).
553C
INC DE 13
INCrement Register Pair DE to the next HIT byte. INC DE does not change the flags.
553D
If the Z FLAG is set (the byte is 0), JUMP to 554AH.
553F
LD A,B 78
Load Register A with Register B, the offset of the byte.
5540
CP 1FH FE 1F
Compare Register A (the offset) against 1FH: the Z FLAG is set for byte 1FH, the count of extra FDE sectors.
5542
If the Z FLAG is set, JUMP to 554AH: byte 1FH is not a name code.
5544
LD HL,5D6AH 21 6A 5D
Point Register Pair HL to 5D6AH, the message BAD "HIT" SECTOR BYTE.
5547
GOSUB to 583FH to output Register A (the offset) in hexadecimal, three spaces and the message at Register Pair HL. Register Pair BC is kept.
554A
INC B 04
INCrement Register B (the offset). The Z FLAG is set when it wraps to 00H after byte FFH.
554B
If the NZ FLAG is set, LOOP BACK to 553AH for the next byte.
554D
RET C9
RETURN to 53ADH, which goes on to check every granule.
554EH - Check Every Granule
Called from 53ADH. Each granule's map byte now holds bit 7 (locked out), bit 6 (allocated in the GAT), bit 5 (claimed by a file) and bit 4 (claimed by more than one file). A locked-out granule must be allocated and not claimed; any other granule must be allocated exactly when one file claims it. A granule that breaks the rule is reported as lump,granule in hexadecimal with a message, followed by every file whose extents include it.
554E
LD HL,65BAH 21 BA 65
Point Register Pair HL to 65BAH, the map byte of granule 0.
5551
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H, the number of granule 0.
Granule Loop
Register Pair DE = the granule, Register Pair HL = its map byte; both are also kept at 527DH and 527FH.
5554
LD (527DH),DE ED 53 7D 52
Store Register Pair DE (the granule's number) at 527DH-527EH.
5558
LD (527FH),HL 22 7F 52
Store Register Pair HL (the granule's map byte address) at 527FH-5280H.
555B
BIT 7,(HL) CB 7E
Test bit 7 of the map byte at Register Pair HL: the NZ FLAG is set if the granule is locked out.
555D
If the Z FLAG is set (not locked out), JUMP to 5579H.
555F
BIT 6,(HL) CB 76
Test bit 6 of the map byte at Register Pair HL: the NZ FLAG is set if the GAT marks the granule allocated.
5561
If the Z FLAG is set (locked out but free in the GAT), JUMP to 556DH.
5563
BIT 5,(HL) CB 6E
Test bit 5 of the map byte at Register Pair HL: the NZ FLAG is set if a file claims the granule.
5565
If the Z FLAG is set (locked out, allocated and not claimed: correct), JUMP to 5611H for the next granule.
5568
LD DE,5D82H 11 82 5D
Point Register Pair DE to 5D82H, the message GRANULE LOCKED OUT, BUT ASSIGNED TO FILE(S).
556B
JUMP to 5596H to report the granule with the message at Register Pair DE.
556D
LD DE,5E4DH 11 4D 5E
Point Register Pair DE to 5E4DH, the message GRANULE LOCKED OUT, BUT FREE.
5570
BIT 5,(HL) CB 6E
Test bit 5 of the map byte at Register Pair HL: the NZ FLAG is set if a file claims the granule.
5572
If the Z FLAG is set (not claimed), JUMP to 5596H to report the message at Register Pair DE.
5574
LD DE,5E70H 11 70 5E
Point Register Pair DE to 5E70H, the message GRANULE LOCKED OUT, BUT FREE AND ASSIGNED TO FILE(S).
5577
JUMP to 5596H to report the granule with the message at Register Pair DE.
5579
BIT 6,(HL) CB 76
Test bit 6 of the map byte at Register Pair HL: the NZ FLAG is set if the GAT marks the granule allocated.
557B
If the Z FLAG is set (free in the GAT), JUMP to 558EH.
557D
LD DE,5DB4H 11 B4 5D
Point Register Pair DE to 5DB4H, the message GRANULE ALLOCATED BUT NOT ASSIGNED TO ANY FILE.
5580
BIT 5,(HL) CB 6E
Test bit 5 of the map byte at Register Pair HL: the NZ FLAG is set if a file claims the granule.
5582
If the Z FLAG is set (allocated but not claimed), JUMP to 5596H to report the message at Register Pair DE.
5584
BIT 4,(HL) CB 66
Test bit 4 of the map byte at Register Pair HL: the NZ FLAG is set if more than one file claims the granule.
5586
If the Z FLAG is set (allocated and claimed by one file: correct), JUMP to 5611H for the next granule.
5589
LD DE,5E15H 11 15 5E
Point Register Pair DE to 5E15H, the message GRANULE ALLOCATED, BUT ASSIGNED TO MULTIPLE FILES.
558C
JUMP to 5596H to report the granule with the message at Register Pair DE.
558E
BIT 5,(HL) CB 6E
Test bit 5 of the map byte at Register Pair HL: the NZ FLAG is set if a file claims the granule.
5590
If the Z FLAG is set (free and not claimed: correct), JUMP to 5611H for the next granule.
5593
LD DE,5DE9H 11 E9 5D
Point Register Pair DE to 5DE9H, the message GRANULE FREE, BUT ASSIGNED TO FILE(S).
5596
LD HL,(527DH) 2A 7D 52
Load Register Pair HL with the value at 527DH, the number of the granule to report.
5599
GOSUB to 584DH to output Register Pair HL (the granule) as lump,granule, three spaces and the message at Register Pair DE, then a carriage return.
559C
LD HL,(527FH) 2A 7F 52
Load Register Pair HL with the value at 527FH, the granule's map byte address.
559F
BIT 5,(HL) CB 6E
Test bit 5 of the map byte at Register Pair HL: the NZ FLAG is set if any file claims the granule.
55A1
If the Z FLAG is set (no file claims it), JUMP to 560EH to end the report with a blank line.
55A4
XOR A AF
Set Register A to 00H, the first DEC, to search the whole directory for the files that claim the granule.
Owner Search Loop
Register A = the DEC to examine; the DEC is kept at 5279H and the chain entry at 527AH.
55A5
LD (5279H),A 32 79 52
Store Register A (the DEC to examine) at 5279H.
55A8
LD (527AH),A 32 7A 52
Store Register A (the same DEC) at 527AH, the chain entry.
55AB
GOSUB to 586AH to find the entry for the DEC in Register A: Index Register IY points to it and the Z FLAG is set, or the NZ FLAG if its sector is past the directory.
55AE
If the NZ FLAG is set (every entry has been searched), JUMP to 560EH.
55B1
LD A,(IY+00H) FD 7E 00
Load Register A with byte +00H of the entry at Index Register IY, its flags.
55B4
AND 90H E6 90
AND 90H with Register A: keep bit 7 (FXDE) and bit 4 (in use).
55B6
CP 10H FE 10
Compare Register A (the two bits) against 10H: the Z FLAG is set for an FPDE in use.
55B8
If the NZ FLAG is set (a free entry or an FXDE), JUMP to 5608H for the next DEC.
55BB
LD B,05H 06 05
Load Register B with 05H, the extent elements in one entry.
Element Loop
Index Register IY moves up two bytes per element; Register B = the elements left.
55BD
LD A,(IY+16H) FD 7E 16
Load Register A with byte +16H of the entry at Index Register IY: byte 0 of the element, the starting lump, or FEH (link) or FFH (end).
55C0
CP FEH FE FE
Compare Register A (the element's byte 0) against FEH. The NO CARRY FLAG is set for FEH or FFH.
55C2
If the NO CARRY FLAG is set (FEH or FFH), JUMP to 55F8H.
55C4
GOSUB to 5758H with Register A = the starting lump to decode the element at Index Register IY: Register Pair DE = its first granule, Register C = its number of granules, and the NZ FLAG; the Z FLAG if it is bad.
55C7
If the Z FLAG is set (a bad element, already reported), JUMP to 55D4H to skip it.
55C9
LD HL,(527DH) 2A 7D 52
Load Register Pair HL with the value at 527DH, the granule being reported.
55CC
RST 18H DF
RST 18H (the ROM's 16-bit compare): compare Register Pair HL (the granule reported) with Register Pair DE (a granule of the element). The Z FLAG is set if they are equal.
55CD
If the Z FLAG is set (this file claims the granule), GOSUB to 55DCH to output the file's DEC and name. All registers but Register Pair AF come back unchanged.
55D0
INC DE 13
INCrement Register Pair DE to the element's next granule.
55D1
DEC C 0D
DECrement Register C (the granules of the element left).
55D2
If the NZ FLAG is set (Register C shows granules left), LOOP BACK to 55CCH.
55D4
INC IY FD 23
INCrement Index Register IY: first step to the next element.
55D6
INC IY FD 23
INCrement Index Register IY again: Index Register IY +16H is now the next element.
55D8
DECrement Register B (the elements left) and LOOP BACK to 55BDH while it is not 0.
55DA
JUMP to 5608H for the next DEC: all five elements of this entry are searched.
55DCH - Output an Owner
Called from 55CDH when a file's extent includes the granule being reported. The registers are saved by 5A90H and restored at 5AADH, so the element loop continues where it was.
55DC
GOSUB to 5A90H, which saves Register Pairs HL, DE, BC and Index Registers IX and IY on the stack and continues at 55DFH; the JUMP to 5AADH at 55F5H restores them and returns to 55D0H.
55DF
LD B,0AH 06 0A
Load Register B with 0AH (10), the column to move to.
55E1
GOSUB to 59A3H to output spaces until the output line reaches column Register B (10).
55E4
LD A,(5279H) 3A 79 52
Load Register A with the byte at 5279H, the DEC of the file's FPDE.
55E7
GOSUB to 5B01H to output Register A (the DEC) as two hexadecimal digits.
55EA
LD B,03H 06 03
Load Register B with 03H, the number of spaces.
55EC
GOSUB to 59AEH to output Register B (3) spaces.
55EF
GOSUB to 57AEH to find the FPDE of the DEC at 5279H (Index Register IY is changed; 5AADH restores it) and output its name and extension.
55F2
GOSUB to 597AH to output a carriage return, ending the owner's line.
55F5
JUMP to 5AADH to restore Index Registers IY and IX and Register Pairs BC, DE and HL and return to 55D0H.
55F8
If the NZ FLAG is set (Register A is FFH, the end of the file's elements), JUMP to 5608H for the next DEC.
55FA
LD A,(IY+17H) FD 7E 17
Register A is FEH: load Register A with byte +17H of the entry at Index Register IY, the DEC of the FXDE it links to.
55FD
LD (527AH),A 32 7A 52
Store Register A (the FXDE's DEC) at 527AH, the chain entry.
5600
GOSUB to 5893H to find the FXDE for the DEC in Register A: Index Register IY points to it and the Z FLAG is set, or the NZ FLAG if its sector is past the directory.
5603
If the NZ FLAG is set (a bad link, already reported), JUMP to 5608H for the next DEC.
5606
LOOP BACK to 55BBH to search the FXDE's elements (it is not checked again here).
5608
GOSUB to 58BDH to load Register A with the DEC after the one at 5279H.
560B
JUMP to 55A5H to examine the entry for the DEC in Register A.
560E
GOSUB to 597AH to output a carriage return, leaving a blank line after the report.
5611
LD DE,(527DH) ED 5B 7D 52
Load Register Pair DE with the value at 527DH, the granule just checked.
5615
LD HL,(5270H) 2A 70 52
Load Register Pair HL with the value at 5270H, the number of granules on the diskette.
5618
INC DE 13
INCrement Register Pair DE: the next granule.
5619
DEC HL 2B
DECrement Register Pair HL: the number of the diskette's last granule.
561A
OR A B7
OR Register A with itself to clear the CARRY FLAG for the subtraction.
561B
SBC HL,DE ED 52
SUBtract Register Pair DE (the next granule) from Register Pair HL (the last granule). The NO CARRY FLAG is set while the next granule exists.
561D
LD HL,(527FH) 2A 7F 52
Load Register Pair HL with the value at 527FH, the map byte address of the granule just checked. LD does not change the flags.
5620
INC HL 23
INCrement Register Pair HL: the next granule's map byte. INC HL does not change the flags.
5621
If the NO CARRY FLAG is set (the next granule exists), JUMP to 5554H to check it with Register Pair DE and HL.
5624
RET C9
RETURN to 53B0H: every granule of the diskette has been checked.
5625H - List the Files
Called from 53B0H. One line per FPDE in use: the name/extension, S (system file) and I (invisible) at column 14, P= and the access level when the update password is not blank and either the access password is not blank or the level is not 0, EOF = sectors/bytes at column 21 (in decimal), the number of extent elements at column 38 with EXTS, and the sectors the extents cover at column 47.
5625
GOSUB to 597AH to output a carriage return before the list.
5628
LD A,FFH 3E FF
Load Register A with FFH, for the previous chain entry at 527BH.
562A
LD (527BH),A 32 7B 52
Store Register A (FFH) at 527BH, the previous chain entry. Nothing in the listing reads 527BH.
562D
XOR A AF
Set Register A to 00H, the first DEC (FDE sector 0, entry 0).
File Loop
Register A = the DEC to examine, kept at 5279H and 527AH.
562E
LD (5279H),A 32 79 52
Store Register A (the DEC to examine) at 5279H.
5631
LD (527AH),A 32 7A 52
Store Register A (the same DEC) at 527AH, the chain entry.
5634
GOSUB to 586AH to find the entry for the DEC in Register A: Index Register IY points to it and the Z FLAG is set, or the NZ FLAG if its sector is past the directory.
5637
If the NZ FLAG is set (every entry has been listed), JUMP to 597AH to output a carriage return; its RETURN goes back to 53B3H.
563A
LD A,(IY+00H) FD 7E 00
Load Register A with byte +00H of the entry at Index Register IY, its flags.
563D
AND 90H E6 90
AND 90H with Register A: keep bit 7 (FXDE) and bit 4 (in use).
563F
CP 10H FE 10
Compare Register A (the two bits) against 10H: the Z FLAG is set for an FPDE in use.
5641
If the NZ FLAG is set (a free entry or an FXDE), JUMP to 5715H for the next DEC.
5644
GOSUB to 57B1H to output the name and extension of the entry at Index Register IY (spaces left out, a / before the extension).
5647
LD B,0EH 06 0E
Load Register B with 0EH (14), the column for the attributes.
5649
GOSUB to 59A3H to output spaces until the output line reaches column Register B (14).
564C
LD A,53H 3E 53
Load Register A with 53H (ASCII S), shown for a system file.
564E
BIT 6,(IY+00H) FD CB 00 76
Test bit 6 of byte +00H of the entry at Index Register IY: the NZ FLAG is set for a system file.
5652
If the NZ FLAG is set, GOSUB to 5A27H to output Register A (S).
5655
LD A,49H 3E 49
Load Register A with 49H (ASCII I), shown for an invisible file.
5657
BIT 3,(IY+00H) FD CB 00 5E
Test bit 3 of byte +00H of the entry at Index Register IY: the NZ FLAG is set for an invisible file.
565B
If the NZ FLAG is set, GOSUB to 5A27H to output Register A (I).
565E
LD DE,4296H 11 96 42
Load Register Pair DE with 4296H, the code of a blank password.
5661
LD L,(IY+10H) FD 6E 10
Load Register L with byte +10H of the entry at Index Register IY, the low byte of the update password's code.
5664
LD H,(IY+11H) FD 66 11
Load Register H with byte +11H of the entry at Index Register IY: Register Pair HL = the update password's code.
5667
RST 18H DF
RST 18H (the ROM's 16-bit compare): compare Register Pair HL (the update password's code) with Register Pair DE (4296H). The Z FLAG is set if the update password is blank.
5668
If the Z FLAG is set (no update password), JUMP to 568EH without showing P=.
566A
LD L,(IY+12H) FD 6E 12
Load Register L with byte +12H of the entry at Index Register IY, the low byte of the access password's code.
566D
LD H,(IY+13H) FD 66 13
Load Register H with byte +13H of the entry at Index Register IY: Register Pair HL = the access password's code.
5670
RST 18H DF
RST 18H: compare Register Pair HL (the access password's code) with Register Pair DE (4296H). The Z FLAG is set if the access password is blank.
5671
If the NZ FLAG is set (an access password is given), JUMP to 567AH to show P=.
5673
LD A,(IY+00H) FD 7E 00
Load Register A with byte +00H of the entry at Index Register IY, its flags.
5676
AND 07H E6 07
AND 07H with Register A: bits 0-2, the access level for a user without the update password.
5678
If the Z FLAG is set (level 0, FULL), JUMP to 568EH without showing P=.
567A
LD A,50H 3E 50
Load Register A with 50H (ASCII P), the start of P= and the level.
567C
GOSUB to 5A27H to output Register A (50H, the letter P).
567F
LD A,3DH 3E 3D
Load Register A with 3DH (ASCII =), the second character of P=.
5681
GOSUB to 5A27H to output Register A (3DH, the = sign).
5684
LD A,(IY+00H) FD 7E 00
Load Register A with byte +00H of the entry at Index Register IY, its flags.
5687
AND 07H E6 07
AND 07H with Register A: the access level 0-7.
5689
ADD A,30H C6 30
ADD 30H to Register A, turning the level into its digit character.
568B
GOSUB to 5A27H to output Register A (the level digit).
568E
LD B,15H 06 15
Load Register B with 15H (21), the column for the EOF.
5690
GOSUB to 59A3H to output spaces until the output line reaches column Register B (21).
5693
LD HL,5FF9H 21 F9 5F
Point Register Pair HL to 5FF9H, the text EOF = (ended by 03H).
5696
GOSUB to 5984H to output the text at Register Pair HL.
5699
LD E,(IY+14H) FD 5E 14
Load Register E with byte +14H of the entry at Index Register IY, the middle byte of the file's EOF.
569C
LD D,(IY+15H) FD 56 15
Load Register D with byte +15H of the entry at Index Register IY: Register Pair DE = the middle and high bytes of the EOF.
569F
LD A,(IY+03H) FD 7E 03
Load Register A with byte +03H of the entry at Index Register IY, the low byte of the EOF (the byte within the last sector).
56A2
OR A B7
OR Register A with itself: the Z FLAG is set if the file ends on a sector boundary.
56A3
If the Z FLAG is set, JUMP to 56A6H with Register Pair DE unchanged.
56A5
DEC DE 1B
DECrement Register Pair DE: in a NEWDOS/80 entry the middle and high bytes are one higher when the low byte is not 0, so DE becomes the number of the sector the EOF is in.
56A6
GOSUB to 5B2BH to convert Register Pair DE (the EOF sector) to decimal. It returns Register Pair HL pointing to the first digit that is not a leading zero and Register B = the number of digits from there.
56A9
GOSUB to 599BH to output Register B digits from Register Pair HL.
56AC
LD A,2FH 3E 2F
Load Register A with 2FH (ASCII /), between the EOF sector and byte.
56AE
GOSUB to 5A27H to output Register A (2FH, the / character).
56B1
LD E,(IY+03H) FD 5E 03
Load Register E with byte +03H of the entry at Index Register IY, the low byte of the EOF (the byte within the sector).
56B4
GOSUB to 5B29H, which clears Register D and converts Register Pair DE (the byte) to decimal: Register Pair HL = its first digit, Register B = the number of digits.
56B7
GOSUB to 599BH to output Register B digits from Register Pair HL.
56BA
LD B,26H 06 26
Load Register B with 26H (38), the column for the number of extent elements.
56BC
GOSUB to 59A3H to output spaces until the output line reaches column Register B (38).
56BF
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H, the count of granules in the file's extents.
56C2
LD C,E 4B
Load Register C with Register E (00H), the count of extent elements.
Extent Count Loop
Index Register IY moves up two bytes per element; Register B = the elements left in this entry, Register C = the elements counted, Register Pair DE = the granules counted.
56C3
LD B,05H 06 05
Load Register B with 05H, the extent elements in one entry.
56C5
LD A,(IY+16H) FD 7E 16
Load Register A with byte +16H of the entry at Index Register IY: byte 0 of the element, or FEH (link) or FFH (end).
56C8
CP FEH FE FE
Compare Register A (the element's byte 0) against FEH. The NO CARRY FLAG is set for FEH or FFH.
56CA
If the NO CARRY FLAG is set (FEH or FFH), JUMP to 56E0H.
56CC
INC C 0C
INCrement Register C, the number of extent elements.
56CD
LD A,(IY+17H) FD 7E 17
Load Register A with byte +17H of the entry at Index Register IY, byte 1 of the element (bits 5-7 the first granule in the lump, bits 0-4 the number of granules minus 1).
56D0
AND 1FH E6 1F
AND 1FH with Register A: the element's number of granules minus 1.
56D2
INC A 3C
INCrement Register A: the element's number of granules.
56D3
ADD A,E 83
ADD Register E (the low byte of the granules counted) to Register A.
56D4
LD E,A 5F
Load Register E with Register A, the new low byte of the granules counted.
56D5
If the NO CARRY FLAG is set (no carry out of the low byte), JUMP to 56D8H.
56D7
INC D 14
INCrement Register D, the high byte of the granules counted.
56D8
INC IY FD 23
INCrement Index Register IY: first step to the next element.
56DA
INC IY FD 23
INCrement Index Register IY again: Index Register IY +16H is now the next element.
56DC
DECrement Register B (the elements left) and LOOP BACK to 56C5H while it is not 0.
56DE
JUMP to 56EAH to output the counts: all five elements of this entry were extents.
56E0
If the NZ FLAG is set (Register A is FFH, the end of the elements), JUMP to 56EAH to output the counts.
56E2
LD A,(IY+17H) FD 7E 17
Register A is FEH: load Register A with byte +17H of the entry at Index Register IY, the DEC of the FXDE it links to.
56E5
GOSUB to 5893H to find the FXDE for the DEC in Register A: Index Register IY points to it and the Z FLAG is set, or the NZ FLAG if its sector is past the directory.
56E8
If the Z FLAG is set, LOOP BACK to 56C3H to count the FXDE's elements too.
56EA
PUSH DE D5
Save Register Pair DE (the granules counted) on the stack.
56EB
LD E,C 59
Load Register E with Register C, the number of extent elements.
56EC
GOSUB to 5B29H, which clears Register D and converts Register Pair DE (the element count) to decimal: Register Pair HL = its first digit, Register B = the number of digits.
56EF
GOSUB to 599BH to output Register B digits from Register Pair HL.
56F2
LD HL,6000H 21 00 60
Point Register Pair HL to 6000H, the text EXTS with a leading space.
56F5
GOSUB to 5984H to output the text at Register Pair HL.
56F8
LD B,2FH 06 2F
Load Register B with 2FH (47), the column for the number of sectors.
56FA
GOSUB to 59A3H to output spaces until the output line reaches column Register B (47).
56FD
POP HL E1
Restore Register Pair HL from the stack: HL = the granules counted.
56FE
LD A,05H 3E 05
Load Register A with 05H, the sectors in a granule.
5700
GOSUB to 5AD0H to multiply Register Pair HL (the granules) by Register A (5). Register Pair HL returns the low 16 bits of the product: the sectors the extents cover.
5703
EX DE,HL EB
Exchange Register Pairs DE and HL: DE = the number of sectors.
5704
GOSUB to 5B2BH to convert Register Pair DE (the sectors) to decimal: Register Pair HL = its first digit, Register B = the number of digits.
5707
GOSUB to 599BH to output Register B digits from Register Pair HL.
570A
LD HL,6006H 21 06 60
Point Register Pair HL to 6006H, the text SECTORS with a leading space.
570D
GOSUB to 5977H to output the text at Register Pair HL and a carriage return.
5710
LD HL,(527FH) 2A 7F 52
Load Register Pair HL with the value at 527FH, which still holds the map byte address of the last granule checked by 554EH.
5713
SET 0,(HL) CB C6
Set bit 0 of the map byte at Register Pair HL. No instruction of DIRCHECK tests bit 0 of a map byte, so this has no effect on the output.
5715
GOSUB to 58BDH to load Register A with the DEC after the one at 5279H.
5718
JUMP to 562EH to list the entry for the DEC in Register A.
571BH - Count the Free and Locked-Out Granules
Called from 53B3H. Every granule's map byte is examined: a locked-out granule counts in Register Pair DE of the main register set, a granule that is neither locked out nor allocated counts in Register Pair DE of the alternate set. Both counts are output in decimal.
571B
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H: the count of locked-out granules, in the main register set.
571E
PUSH DE D5
Save Register Pair DE (0000H) on the stack, to start the other count with it.
571F
EXX D9
EXX: exchange Register Pairs BC, DE and HL with the alternate set. The main set's DE (the locked-out count, 0000H) is kept aside; the loop below uses the alternate set.
5720
LD BC,(5270H) ED 4B 70 52
Load Register Pair BC (alternate set) with the value at 5270H, the number of granules on the diskette.
5724
LD HL,65BAH 21 BA 65
Point Register Pair HL (alternate set) to 65BAH, the map byte of granule 0.
5727
POP DE D1
Restore Register Pair DE (alternate set) from the stack: DE = 0000H, the count of free granules.
Map Loop
The alternate set is active: Register Pair HL = the map byte, Register Pair BC = the granules left, Register Pair DE = the free count.
5728
BIT 7,(HL) CB 7E
Test bit 7 of the map byte at Register Pair HL: the NZ FLAG is set if the granule is locked out.
572A
If the NZ FLAG is set, JUMP to 5733H to count it as locked out.
572C
BIT 6,(HL) CB 76
Test bit 6 of the map byte at Register Pair HL: the NZ FLAG is set if the GAT marks it allocated.
572E
If the NZ FLAG is set (allocated), JUMP to 5736H without counting it.
5730
INC DE 13
INCrement Register Pair DE (alternate set), the count of free granules.
5731
JUMP to 5736H for the next granule, with the free count increased.
5733
EXX D9
EXX: switch from the alternate register set to the main set, where Register Pair DE holds the locked-out count.
5734
INC DE 13
INCrement Register Pair DE (main set), the count of locked-out granules.
5735
EXX D9
EXX: switch back to the alternate set for the loop.
5736
INC HL 23
INCrement Register Pair HL (alternate set) to the next map byte.
5737
DEC BC 0B
DECrement Register Pair BC (alternate set), the granules left. DEC BC does not set the flags.
5738
LD A,B 78
Load Register A with Register B, the high byte of the granules left.
5739
OR C B1
OR Register C (the low byte) into Register A. The Z FLAG is set when Register Pair BC is 0000H.
573A
If the NZ FLAG is set (granules are left), LOOP BACK to 5728H.
573C
GOSUB to 5B2BH to convert Register Pair DE (alternate set: the free count) to decimal: Register Pair HL = its first digit, Register B = the number of digits.
573F
GOSUB to 599BH to output Register B digits from Register Pair HL.
5742
LD HL,600FH 21 0F 60
Point Register Pair HL to 600FH, the text FREE GRANULES. with a leading space and five trailing spaces.
5745
GOSUB to 5984H to output the text at Register Pair HL.
5748
EXX D9
EXX: switch from the alternate register set to the main set, whose Register Pair DE holds the locked-out count.
5749
GOSUB to 5B2BH to convert Register Pair DE (the locked-out count) to decimal: Register Pair HL = its first digit, Register B = the number of digits.
574C
GOSUB to 599BH to output Register B digits from Register Pair HL.
574F
LD HL,6024H 21 24 60
Point Register Pair HL to 6024H, the text LOCKED-OUT GRANULES. with a leading space.
5752
GOSUB to 5977H to output the text at Register Pair HL and a carriage return.
5755
JUMP to 597AH to output one more carriage return; its RETURN goes back to 53B6H.
5758H - Decode an Extent Element
Called from 546EH and 55C4H with Register A = byte 0 of an extent element (the lump where it starts) and Index Register IY +16H/+17H on the element. Byte 1 holds the first granule within the lump in bits 5-7 and the number of granules minus 1 in bits 0-4. Returns Register Pair DE = the diskette granule number where the element starts, Register C = its number of granules and the NZ FLAG; or, for a bad element, Register A = 00H, the Z FLAG and Register Pair HL pointing to the message.
5758
LD HL,5261H 21 61 52
Point Register Pair HL to 5261H, the number of lumps on the diskette (from PDRIVE byte 1).
575B
CP (HL) BE
Compare Register A (the element's starting lump) against the byte at Register Pair HL (the number of lumps). The NO CARRY FLAG is set if the lump does not exist.
575C
LD E,A 5F
Load Register E with Register A, the starting lump. LD does not change the flags.
575D
LD HL,5EDEH 21 DE 5E
Point Register Pair HL to 5EDEH, the message EXTENT'S STARTING LUMP # TOO LARGE. LD does not change the flags.
5760
If the NO CARRY FLAG is set (the lump is past the diskette's last), JUMP to 5784H to return the Z FLAG with that message.
5762
LD A,(5265H) 3A 65 52
Load Register A with the byte at 5265H, the granules per lump.
5765
LD C,A 4F
Load Register C with Register A, the granules per lump.
5766
LD D,(IY+17H) FD 56 17
Load Register D with byte +17H of the element at Index Register IY, byte 1 of the element.
5769
LD A,D 7A
Load Register A with Register D, byte 1 of the element.
576A
AND E0H E6 E0
AND E0H with Register A: keep bits 5-7, the first granule within the lump.
576C
RLCA 07
Rotate Register A left: bits 5-7 move toward bits 0-2 (bit 7 goes to bit 0).
576D
RLCA 07
Rotate Register A left again (the second of three rotations).
576E
RLCA 07
Rotate Register A left a third time: Register A = the first granule within the lump, 0-7.
576F
LD HL,5F01H 21 01 5F
Point Register Pair HL to 5F01H, the message EXTENT'S STARTING GRAN'S OFFSET IN LUMP TOO BIG.
5772
CP C B9
Compare Register A (the first granule within the lump) against Register C (the granules per lump). The NO CARRY FLAG is set if it is too big.
5773
If the NO CARRY FLAG is set, JUMP to 5784H to return the Z FLAG with that message.
5775
LD L,A 6F
Load Register L with Register A, the first granule within the lump.
5776
LD H,00H 26 00
Load Register H with 00H: Register Pair HL = the first granule within the lump.
5778
LD A,D 7A
Load Register A with Register D, byte 1 of the element again.
5779
LD D,H 54
Load Register D with Register H (00H): Register Pair DE = the starting lump.
Lump Times Granules per Lump
Adds Register Pair DE (the lump) to Register Pair HL, Register C (the granules per lump) times.
577A
ADD HL,DE 19
ADD Register Pair DE (the starting lump) to Register Pair HL.
577B
DEC C 0D
DECrement Register C, the additions of the lump still to make.
577C
If the NZ FLAG is set, LOOP BACK to 577AH. Register Pair HL ends as the lump times the granules per lump plus the granule within the lump: the diskette granule number.
577E
EX DE,HL EB
Exchange Register Pairs DE and HL: DE = the element's first granule on the diskette.
577F
AND 1FH E6 1F
AND 1FH with Register A (byte 1 of the element): bits 0-4, the number of granules minus 1.
5781
LD C,A 4F
Load Register C with Register A, the number of granules minus 1.
5782
INC C 0C
INCrement Register C: the number of granules (1-32). The NZ FLAG is set, telling the caller the element is good.
5783
RET C9
RETURN with Register Pair DE = the first granule, Register C = the number of granules and the NZ FLAG.
5784
XOR A AF
Set Register A to 00H and set the Z FLAG: the element is bad, and Register Pair HL points to the message saying why.
5785
RET C9
RETURN to the caller with Register A = 00H and the Z FLAG (a bad element).
5786H - Compute an FPDE's HIT Code
Called from 5452H with Index Register IY on an FPDE. The 11 characters of the name and extension (bytes +05H to +0FH) are combined: A = 0, then for each character XOR it and rotate left; a result of 00H becomes 01H, because 00H in the HIT means a free entry. The code is stored at 527CH.
5786
PUSH IY FD E5
Save Index Register IY (the FPDE's address) on the stack; the loop moves it.
5788
PUSH BC C5
Save Register Pair BC (Register B is the caller's element count) on the stack.
5789
LD B,0BH 06 0B
Load Register B with 0BH (11), the characters of the name and extension.
578B
XOR A AF
Set Register A to 00H, the code built so far.
Code Loop
Index Register IY +05H = the next character, Register B = the characters left.
578C
XOR (IY+05H) FD AE 05
XOR the character at Index Register IY +05H into Register A (the code so far).
578F
RLCA 07
Rotate Register A (the code) left, bit 7 into bit 0.
5790
INC IY FD 23
INCrement Index Register IY, so that IY +05H is the next character.
5792
DECrement Register B (the characters left) and LOOP BACK to 578CH while it is not 0.
5794
If the NZ FLAG is set (the code in Register A is not 00H), JUMP to 5797H.
5796
INC A 3C
INCrement Register A: a code of 00H becomes 01H.
5797
LD (527CH),A 32 7C 52
Store Register A (the HIT code of the name) at 527CH.
579A
POP BC C1
Restore Register Pair BC (the caller's element count in Register B) from the stack.
579B
POP IY FD E1
Restore Index Register IY (the FPDE's address) from the stack.
579D
RET C9
RETURN to 5455H with the code stored at 527CH.
579EH - Compare the HIT Byte
Called from 5455H and 54F1H. Returns Register Pair HL pointing to the byte of DIRCHECK's HIT copy for the DEC at 527AH (the HIT byte's offset is the DEC), and the Z FLAG set if it equals the code at 527CH.
579E
LD A,(527AH) 3A 7A 52
Load Register A with the byte at 527AH, the DEC of the entry being examined.
57A1
LD HL,64BAH 21 BA 64
Point Register Pair HL to 64BAH, byte 00H of DIRCHECK's copy of the HIT.
57A4
ADD A,L 85
ADD Register L (BAH) to Register A (the DEC): the low byte of 64BAH + DEC.
57A5
LD L,A 6F
Load Register L with Register A, the low byte of the HIT byte's address.
57A6
If the NO CARRY FLAG is set (no carry into the high byte), JUMP to 57A9H.
57A8
INC H 24
INCrement Register H: Register Pair HL = 64BAH + DEC crosses into 65xxH.
57A9
LD A,(527CH) 3A 7C 52
Load Register A with the byte at 527CH, the HIT code computed from the FPDE's name.
57AC
CP (HL) BE
Compare Register A (the computed code) against the HIT byte at Register Pair HL. The Z FLAG is set if they are equal.
57AD
RET C9
RETURN with Register Pair HL on the HIT byte and the flags of the compare.
57AEH - Output the Name of the Entry at 5279H
57AEH first finds the entry for the DEC at 5279H (Index Register IY is changed); 57B1H outputs the name and extension of the entry at Index Register IY, leaving out spaces and putting a / before the extension when it is not blank.
57AE
GOSUB to 5867H to load Register A with the DEC at 5279H and find its entry: Index Register IY points to it.
57B1
PUSH IY FD E5
Save Index Register IY (the entry's address) on the stack; the loop moves it.
57B3
PUSH BC C5
Save Register Pair BC (Register B is the caller's count) on the stack.
57B4
LD B,08H 06 08
Load Register B with 08H, the characters of the name.
Name Loop
Index Register IY +05H = the next name character, Register B = the characters left.
57B6
LD A,(IY+05H) FD 7E 05
Load Register A with the character at Index Register IY +05H, a character of the name.
57B9
CP 20H FE 20
Compare Register A (the character) against 20H (a space). The Z FLAG is set for a space.
57BB
If the NZ FLAG is set (not a space), GOSUB to 5A27H to output Register A.
57BE
INC IY FD 23
INCrement Index Register IY, so that IY +05H is the next character.
57C0
DECrement Register B (the characters left) and LOOP BACK to 57B6H while it is not 0.
57C2
LD A,(IY+05H) FD 7E 05
Load Register A with the character at Index Register IY +05H: entry byte +0DH, the extension's first character.
57C5
CP 20H FE 20
Compare Register A (the extension's first character) against 20H: the Z FLAG is set if the extension is blank.
57C7
If the Z FLAG is set, JUMP to 57CEH without the /.
57C9
LD A,2FH 3E 2F
Load Register A with 2FH (ASCII /), put between the name and the extension.
57CB
GOSUB to 5A27H to output Register A (2FH, the / character).
57CE
LD B,03H 06 03
Load Register B with 03H, the characters of the extension.
Extension Loop
Index Register IY +05H = the next extension character, Register B = the characters left.
57D0
LD A,(IY+05H) FD 7E 05
Load Register A with the character at Index Register IY +05H, a character of the extension.
57D3
CP 20H FE 20
Compare Register A (the character) against 20H (a space). The Z FLAG is set for a space.
57D5
If the NZ FLAG is set, GOSUB to 5A27H to output Register A.
57D8
INC IY FD 23
INCrement Index Register IY, so that IY +05H is the next character.
57DA
DECrement Register B (the characters left) and LOOP BACK to 57D0H while it is not 0.
57DC
POP BC C1
Restore Register Pair BC (the caller's count in Register B) from the stack.
57DD
POP IY FD E1
Restore Index Register IY (the entry's address) from the stack.
57DF
RET C9
RETURN to the caller with Index Register IY unchanged.
57E0H - Read an FDE Sector
Called from 587EH and 58B1H with Register A = a DEC (bits 0-4 are its FDE sector) and Register Pair HL = the buffer. The FDE sector must exist: sectors 0-7 plus the extra sectors named by HIT byte 1FH. Returns the Z FLAG after reading the sector into the buffer, or the NZ FLAG (with the CARRY FLAG) if the sector is past the directory. Register Pairs BC and DE are kept.
57E0
PUSH DE D5
Save Register Pair DE (the caller's entry offset in Register E) on the stack.
57E1
PUSH BC C5
Save Register Pair BC (the caller's counts) on the stack.
57E2
AND 1FH E6 1F
AND 1FH with Register A (the DEC): bits 0-4, the FDE sector.
57E4
LD E,A 5F
Load Register E with Register A, the FDE sector.
57E5
LD D,00H 16 00
Load Register D with 00H: Register Pair DE = the FDE sector.
57E7
LD A,(64D9H) 3A D9 64
Load Register A with the byte at 64D9H, HIT byte 1FH: the number of extra FDE sectors.
57EA
ADD A,07H C6 07
ADD 07H to Register A: the number of the directory's last FDE sector.
57EC
CP E BB
Compare Register A (the last FDE sector) against Register E (the FDE sector wanted). The CARRY FLAG is set if the sector wanted is past the last.
57ED
If the CARRY FLAG is set, JUMP to 57FEH to return with the NZ FLAG.
57EF
INC DE 13
INCrement Register Pair DE (the FDE sector), the first of two steps past the GAT and HIT.
57F0
INC DE 13
INCrement Register Pair DE again: DE = the FDE sector plus 2, its position in the directory after the GAT and the HIT.
57F1
PUSH HL E5
Save Register Pair HL (the buffer) on the stack.
57F2
LD HL,(5274H) 2A 74 52
Load Register Pair HL with the value at 5274H, the diskette sector where the directory starts.
57F5
ADD HL,DE 19
ADD Register Pair DE (the position in the directory) to Register Pair HL: HL = the diskette sector to read.
57F6
LD (520AH),HL 22 0A 52
Store Register Pair HL (the diskette sector) at 520AH-520BH, the NEXT field of the FCB.
57F9
POP HL E1
Restore Register Pair HL (the buffer) from the stack.
57FA
GOSUB to 5801H to read the sector at NEXT into the buffer at Register Pair HL and check its directory mark.
57FD
XOR A AF
Set Register A to 00H and set the Z FLAG: the sector is in the buffer.
57FE
POP BC C1
Restore Register Pair BC (the caller's counts) from the stack.
57FF
POP DE D1
Restore Register Pair DE (the caller's entry offset) from the stack.
5800
RET C9
RETURN with the Z FLAG (sector read) or the NZ FLAG (no such sector).
5801H - Read a Directory Sector
Called with Register Pair HL = the buffer and NEXT set in the FCB. A directory sector is written with the directory mark, so its read must return error 06H. Any other error ends the function; a read without the error means the sector is unprotected, which is reported once per diskette.
5801
GOSUB to 5820H to read the sector at NEXT into the buffer at Register Pair HL. Register A returns the DOS error code, with the Z FLAG set for no error.
5804
If the Z FLAG is set (no error: the sector has no directory mark), JUMP to 580CH.
5806
CP 06H FE 06
Compare Register A (the error code) against 06H, the error for a sector with the directory mark.
5808
If the NZ FLAG is set (a real read error), JUMP to 5ABEH to display the DOS error for the code in Register A and end with FUNCTION TERMINATED.
580B
RET C9
RETURN with Register A = 06H and the Z FLAG set by the compare: the directory sector is protected as it should be.
580C
LD A,(526EH) 3A 6E 52
Load Register A with the byte at 526EH, the unprotected directory flag.
580F
OR A B7
OR Register A with itself: the NZ FLAG is set if the message has already been shown for this diskette.
5810
RET NZ C0
If the NZ FLAG is set (already reported), RETURN without the message.
5811
INC A 3C
INCrement Register A (00H) to 01H, the value that marks the diskette as unprotected.
5812
LD (526EH),A 32 6E 52
Store Register A (01H) at 526EH: an unprotected directory sector has been found.
5815
PUSH HL E5
Save Register Pair HL on the stack. 53BAH also calls this entry to show the message again after the list.
5816
PUSH BC C5
Save Register Pair BC (the caller's count in Register B) on the stack.
5817
LD HL,5D06H 21 06 5D
Point Register Pair HL to 5D06H, the message ATLEAST ONE DIRECTORY SECTOR UNPROTECTED.
581A
GOSUB to 5977H to output the message at Register Pair HL and a carriage return.
581D
POP BC C1
Restore Register Pair BC (the caller's count) from the stack.
581E
POP HL E1
Restore Register Pair HL (the caller's buffer address) from the stack.
581F
RET C9
RETURN to the caller: 531CH, 5327H or 57FDH after a read, or 53BDH after the second message.
5820H - Read a Sector
Called with Register Pair HL = the buffer. The sector named by NEXT (520AH-520BH) of the drive at 5206H is read through the DOS; NEXT goes up by 1 after a read with no error or with error 06H.
5820
LD (5203H),HL 22 03 52
Store Register Pair HL (the buffer) at 5203H-5204H, the buffer address of the FCB (FCB+3 and FCB+4).
5823
LD DE,5200H 11 00 52
Point Register Pair DE to 5200H, the FCB whose NEXT names the sector.
5826
JUMP to SYS0 4436H (READ) with Register Pair DE = the FCB: with FCB+0 bit 1 set, the sector named by NEXT is read into the buffer and NEXT is advanced. Its RETURN goes back to the caller of 5820H with Register A = the error code and the Z FLAG set for no error.
5829H - Report a Complaint About an Entry
5829H is entered with Register A = P or X: it completes the message at 5F8AH as FPDE or FXDE HAS BAD CODE IN "HIT" SECTOR. 582EH is entered with Register Pair HL on any message. The line is the name of the entry at 5279H, three spaces, its DEC in hexadecimal, three spaces and the message. 583FH is entered with Register A = a number to show in hexadecimal before the message.
5829
LD HL,5F8BH 21 8B 5F
Point Register Pair HL to 5F8BH, the second letter of the message at 5F8AH.
582C
LD (HL),A 77
Store Register A (50H P or 58H X) at the byte at Register Pair HL (5F8BH): the message now reads FPDE or FXDE.
582D
DEC HL 2B
DECrement Register Pair HL to 5F8AH, the start of the message.
582E
PUSH BC C5
Save Register Pair BC (Register B is the caller's element count) on the stack.
582F
PUSH IY FD E5
Save Index Register IY (the caller's entry pointer) on the stack.
5831
GOSUB to 57AEH to find the entry of the DEC at 5279H and output its name and extension. Register Pair HL (the message) is not changed.
5834
LD B,03H 06 03
Load Register B with 03H, the number of spaces.
5836
GOSUB to 59AEH to output Register B (3) spaces.
5839
POP IY FD E1
Restore Index Register IY (the caller's entry pointer) from the stack.
583B
POP BC C1
Restore Register Pair BC (the caller's count in Register B) from the stack.
583C
LD A,(5279H) 3A 79 52
Load Register A with the byte at 5279H, the DEC of the entry, to output in hexadecimal.
583F
PUSH BC C5
Save Register Pair BC on the stack; the GAT check at 541FH still needs Register B.
5840
GOSUB to 5B01H to output Register A (the DEC or byte offset) as two hexadecimal digits.
5843
LD B,03H 06 03
Load Register B with 03H, the number of spaces. 584DH continues here too.
5845
GOSUB to 59AEH to output Register B (3) spaces.
5848
GOSUB to 5977H to output the message at Register Pair HL and a carriage return.
584B
POP BC C1
Restore Register Pair BC (saved at 583FH or 584DH) from the stack.
584C
RET C9
RETURN to the caller with Register Pair HL past the message.
584DH - Report a Granule
Called from 5599H with Register Pair HL = the granule's number on the diskette and Register Pair DE = the message. The granule is shown as bb,r: the lump number in hexadecimal and the granule within the lump.
584D
PUSH BC C5
Save Register Pair BC on the stack; it is restored at 584BH.
584E
LD A,(5265H) 3A 65 52
Load Register A with the byte at 5265H, the granules per lump.
5851
GOSUB to 5AF0H to divide Register Pair HL (the granule's number) by Register A (the granules per lump): Register Pair HL returns the lump and Register A the granule within the lump.
5854
PUSH AF F5
Save Register Pair AF (Register A = the granule within the lump) on the stack.
5855
LD A,L 7D
Load Register A with Register L, the lump number (below 256).
5856
GOSUB to 5B01H to output Register A (the lump) as two hexadecimal digits.
5859
LD A,2CH 3E 2C
Load Register A with 2CH (ASCII comma), put between the lump and the granule.
585B
GOSUB to 5A27H to output Register A (the comma).
585E
POP AF F1
Restore Register Pair AF from the stack: Register A = the granule within the lump.
585F
ADD A,30H C6 30
ADD 30H to Register A, turning the granule (0-7) into its digit.
5861
GOSUB to 5A27H to output Register A (the digit).
5864
EX DE,HL EB
Exchange Register Pairs DE and HL: HL = the message address.
5865
JUMP to 5843H to output three spaces, the message at Register Pair HL and a carriage return, restore Register Pair BC and return.
5867H - Find the Entry for a DEC
5867H loads Register A from 5279H. 586AH and 5893H find the entry for the DEC in Register A (bits 0-4 the FDE sector, bits 5-7 the entry, so A AND E0H is the entry's offset in the sector). 586AH reads a missing sector into the first FDE buffer (61BAH); 5893H looks in both buffers and reads a missing sector into the second (62BAH), so an FPDE in the first buffer stays there while its FXDEs are read. Both return Index Register IY on the entry and the Z FLAG, or the NZ FLAG if the sector is past the directory. Register Pairs DE and HL are kept.
5867
LD A,(5279H) 3A 79 52
Load Register A with the byte at 5279H, the DEC of the entry being examined.
586A
PUSH DE D5
Save Register Pair DE (the caller's granule or count) on the stack.
586B
LD D,A 57
Load Register D with Register A, the DEC, to keep it while it is split.
586C
AND E0H E6 E0
AND E0H with Register A: bits 5-7, the entry number times 32, which is the entry's offset in its sector.
586E
LD E,A 5F
Load Register E with Register A, the entry's offset in the sector.
586F
LD A,D 7A
Load Register A with Register D, the DEC, to get its FDE sector.
5870
AND 1FH E6 1F
AND 1FH with Register A: bits 0-4, the FDE sector.
5872
LD D,A 57
Load Register D with Register A, the FDE sector.
5873
LD A,(5272H) 3A 72 52
Load Register A with the byte at 5272H, the FDE sector held in the first buffer.
5876
CP D BA
Compare Register A (the sector in the buffer) against Register D (the sector wanted). The Z FLAG is set if it is already there.
5877
If the Z FLAG is set, JUMP to 5888H to use the first buffer.
5879
PUSH HL E5
Save Register Pair HL (the caller's pointer) on the stack.
587A
LD A,D 7A
Load Register A with Register D, the FDE sector wanted.
587B
LD HL,61BAH 21 BA 61
Point Register Pair HL to 61BAH, the first FDE buffer.
587E
GOSUB to 57E0H to read the FDE sector in Register A into the buffer at Register Pair HL. The NZ FLAG is returned if the sector is past the directory.
5881
POP HL E1
Restore Register Pair HL (the caller's pointer) from the stack.
5882
If the NZ FLAG is set (no such sector), JUMP to 5891H to return with it.
5884
LD A,D 7A
Load Register A with Register D, the FDE sector just read.
5885
LD (5272H),A 32 72 52
Store Register A (the sector) at 5272H: the first buffer now holds it.
5888
LD IY,61BAH FD 21 BA 61
Point Index Register IY to 61BAH, the first FDE buffer.
588C
LD D,00H 16 00
Load Register D with 00H: Register Pair DE = the entry's offset in the sector.
588E
ADD IY,DE FD 19
ADD Register Pair DE (the entry's offset) to Index Register IY: IY points to the entry.
5890
XOR A AF
Set Register A to 00H and set the Z FLAG: the entry was found.
5891
POP DE D1
Restore Register Pair DE (the caller's value) from the stack.
5892
RET C9
RETURN with Index Register IY on the entry and the Z FLAG, or the NZ FLAG.
5893
PUSH DE D5
Save Register Pair DE (the caller's value) on the stack.
5894
LD D,A 57
Load Register D with Register A, the DEC, to keep it while it is split.
5895
AND E0H E6 E0
AND E0H with Register A: bits 5-7, the entry's offset in its sector.
5897
LD E,A 5F
Load Register E with Register A, the entry's offset.
5898
LD A,D 7A
Load Register A with Register D, the DEC, to get its FDE sector.
5899
AND 1FH E6 1F
AND 1FH with Register A: bits 0-4, the FDE sector.
589B
LD D,A 57
Load Register D with Register A, the FDE sector.
589C
LD A,(5272H) 3A 72 52
Load Register A with the byte at 5272H, the FDE sector held in the first buffer.
589F
CP D BA
Compare Register A (that sector) against Register D (the sector wanted). The Z FLAG is set if the first buffer holds it.
58A0
If the Z FLAG is set, JUMP to 5888H to use the first buffer.
58A2
LD IY,62BAH FD 21 BA 62
Point Index Register IY to 62BAH, the second FDE buffer.
58A6
LD A,(5273H) 3A 73 52
Load Register A with the byte at 5273H, the FDE sector held in the second buffer.
58A9
CP D BA
Compare Register A (that sector) against Register D (the sector wanted). The Z FLAG is set if the second buffer holds it.
58AA
If the Z FLAG is set, JUMP to 588CH to add the entry's offset to Index Register IY (62BAH).
58AC
PUSH HL E5
Save Register Pair HL (the caller's pointer) on the stack.
58AD
LD A,D 7A
Load Register A with Register D, the FDE sector wanted.
58AE
LD HL,62BAH 21 BA 62
Point Register Pair HL to 62BAH, the second FDE buffer.
58B1
GOSUB to 57E0H to read the FDE sector in Register A into the buffer at Register Pair HL. The NZ FLAG is returned if the sector is past the directory.
58B4
POP HL E1
Restore Register Pair HL (the caller's pointer) from the stack.
58B5
If the NZ FLAG is set (no such sector), JUMP to 5891H to return with it.
58B7
LD A,D 7A
Load Register A with Register D, the FDE sector just read.
58B8
LD (5273H),A 32 73 52
Store Register A (the sector) at 5273H: the second buffer now holds it.
58BB
JUMP to 588CH to add the entry's offset to Index Register IY (62BAH).
58BDH - The Next DEC
Returns Register A = the DEC after the one at 5279H: the next entry in the same FDE sector, or entry 0 of the next sector after entry 7. 586AH later finds whether that sector exists.
58BD
LD A,(5279H) 3A 79 52
Load Register A with the byte at 5279H, the DEC just examined.
58C0
ADD A,20H C6 20
ADD 20H to Register A: the next entry in bits 5-7. The CARRY FLAG is set if the entry number passed 7.
58C2
RET NC D0
If the NO CARRY FLAG is set, RETURN with Register A = the next entry of the same sector.
58C3
INC A 3C
INCrement Register A: entry 0 of the next FDE sector (bits 5-7 are 0 after the carry).
58C4
RET C9
RETURN with Register A = the next DEC (entry 0 of the next sector).
58C5H - The W and C Functions
Reached from 5950H (reply W) and 5955H (reply C) with Register A = the reply letter. Both need SYSTEM option BK = Y and a known directory size. Every directory sector of the last diskette checked is read and written back with the directory mark and a verify read, so that it reads as protected; for C, every FDE entry not in use is also cleared to zeros before the write (the GAT and HIT, the first two sectors, are left as they are). The check then runs again from 52B7H.
58C5
LD (58FBH),A 32 FB 58
Self-Modifying Code
Store Register A (57H W or 43H C, the reply) at 58FBH, the operand of the CP at 58FAH.
58C8
LD A,(436DH) 3A 6D 43
Load Register A with the byte at 436DH, SYS0's copy of system data sector byte F1H; bit 4 is SYSTEM option BK.
58CB
BIT 4,A CB 67
Test bit 4 of Register A: the Z FLAG is set if option BK is N.
58CD
LD A,37H 3E 37
Load Register A with 37H, the DOS error code DISKETTE ACCESS DENIED. LD does not change the flags.
58CF
If the Z FLAG is set (option BK = N), JUMP to 5ABEH to display the error for Register A (37H) and end with FUNCTION TERMINATED.
58D2
LD A,(526FH) 3A 6F 52
Load Register A with the byte at 526FH, the number of directory sectors (00H if HIT byte 1FH was bad).
58D5
OR A B7
OR Register A with itself: the Z FLAG is set if the size is unknown.
58D6
LD B,A 47
Load Register B with Register A, the number of directory sectors: the count for the loop. LD does not change the flags.
58D7
LD HL,5D35H 21 35 5D
Point Register Pair HL to 5D35H, the message DIRECTORY SIZE UNKNOWN. LD does not change the flags.
58DA
If the Z FLAG is set (the size is unknown), JUMP to 5AC5H to output the message at Register Pair HL and end with FUNCTION TERMINATED.
58DD
LD HL,61BAH 21 BA 61
Point Register Pair HL to 61BAH, the first FDE buffer, used as the buffer for every sector.
58E0
LD (5203H),HL 22 03 52
Store Register Pair HL (61BAH) at 5203H-5204H, the buffer address of the FCB.
58E3
LD HL,(5274H) 2A 74 52
Load Register Pair HL with the value at 5274H, the diskette sector where the directory starts (the GAT).
58E6
LD DE,5200H 11 00 52
Point Register Pair DE to 5200H, the FCB used for every read and write.
58E9
LD C,00H 0E 00
Load Register C with 00H, the directory sector being handled (0 = the GAT, 1 = the HIT).
Directory Sector Loop
Register Pair HL = the diskette sector, Register C = its position in the directory, Register B = the sectors left, Register Pair DE = the FCB.
58EB
LD (520AH),HL 22 0A 52
Store Register Pair HL (the diskette sector) at 520AH-520BH, the NEXT field of the FCB.
58EE
GOSUB to SYS0 4436H (READ) with Register Pair DE = the FCB to read the sector into 61BAH. Register A returns the error code, with the Z FLAG set for no error.
58F1
If the Z FLAG is set (read without the directory mark), JUMP to 58F8H.
58F3
CP 06H FE 06
Compare Register A (the error code) against 06H, the error for a sector with the directory mark.
58F5
If the NZ FLAG is set (a real read error), JUMP to 5ABEH to display the DOS error for Register A and end with FUNCTION TERMINATED.
58F8
LD A,43H 3E 43
Load Register A with 43H (ASCII C), to compare with the reply stored at 58FBH.
58FA
CP 00H FE 00
Self-Modifying Code
Compare Register A (C) against the operand at 58FBH: 00H in the file, the reply letter stored at 58C5H. The Z FLAG is set for the C function.
58FC
If the NZ FLAG is set (the W function), JUMP to 591AH to write the sector back unchanged.
58FE
LD A,C 79
Load Register A with Register C, the position of the sector in the directory.
58FF
CP 02H FE 02
Compare Register A against 02H. The CARRY FLAG is set for the GAT (0) and the HIT (1).
5901
If the CARRY FLAG is set, JUMP to 591AH: the GAT and HIT are written back unchanged.
5903
EXX D9
EXX: switch to the alternate register set, keeping Register Pairs BC (count and position), DE (FCB) and HL (sector) aside.
5904
LD HL,(5203H) 2A 03 52
Load Register Pair HL (alternate set) with the value at 5203H, the FCB's buffer address (61BAH): the first FDE entry of the sector.
5907
LD B,08H 06 08
Load Register B (alternate set) with 08H, the entries in an FDE sector.
Entry Clear Loop
Alternate set: Register Pair HL = the entry, Register B = the entries left.
5909
LD DE,0020H 11 20 00
Load Register Pair DE (alternate set) with 0020H (32), the length of an entry.
590C
BIT 4,(HL) CB 66
Test bit 4 of byte 0 of the entry at Register Pair HL: the NZ FLAG is set if it is in use.
590E
If the NZ FLAG is set (in use), JUMP to 5916H to step over it with Register Pair DE = 0020H.
5910
LD (HL),00H 36 00
Store 00H at the byte at Register Pair HL, one byte of the unused entry.
5912
DEC E 1D
DECrement Register E (alternate set), the bytes of the entry left.
5913
INC HL 23
INCrement Register Pair HL to the next byte. INC HL does not change the flags.
5914
If the NZ FLAG is set (bytes are left), LOOP BACK to 5910H. Register Pair HL ends on the next entry and Register Pair DE is 0000H.
5916
ADD HL,DE 19
ADD Register Pair DE to Register Pair HL: an entry in use is stepped over (DE = 0020H); after clearing, DE is 0000H and HL is already on the next entry.
5917
DECrement Register B (the entries left) and LOOP BACK to 5909H while it is not 0.
5919
EXX D9
EXX: switch from the alternate register set back to the main set: Register Pair HL = the sector, Register Pair DE = the FCB, Register Pair BC = the count and position.
591A
EX DE,HL EB
Exchange Register Pairs DE and HL: HL = 5200H, the FCB, and DE = the diskette sector.
591B
SET 0,(HL) CB C6
Set bit 0 of the byte at Register Pair HL (FCB+0): the next write uses the directory mark.
591D
EX DE,HL EB
Exchange Register Pairs DE and HL back: HL = the diskette sector, DE = the FCB.
591E
LD (520AH),HL 22 0A 52
Store Register Pair HL (the diskette sector) at 520AH-520BH again: the read advanced NEXT past it.
5921
GOSUB to SYS0 443CH (WRITE with verify) with Register Pair DE = the FCB: the buffer at 61BAH is written to the sector with the directory mark (FCB+0 bit 0), then read back to verify.
5924
EX DE,HL EB
Exchange Register Pairs DE and HL: HL = the FCB.
5925
RES 0,(HL) CB 86
Clear bit 0 of the byte at Register Pair HL (FCB+0): later writes use the normal mark. RES does not change the flags.
5927
EX DE,HL EB
Exchange Register Pairs DE and HL back: HL = the diskette sector, DE = the FCB.
5928
If the NZ FLAG is set (the write or verify failed), JUMP to 5ABEH to display the DOS error for Register A and end with FUNCTION TERMINATED.
592B
INC C 0C
INCrement Register C, the position of the next sector in the directory.
592C
INC HL 23
INCrement Register Pair HL, the next diskette sector.
592D
DECrement Register B (the directory sectors left) and LOOP BACK to 58EBH while it is not 0.
592F
JUMP to 52B7H to check the same diskette again, with the same drive and output answers.
5932H - Function Completed: What Next?
Reached from 53BDH at the end of a check. 5935H is also where every ending comes: 5ACBH jumps there after FUNCTION TERMINATED. The output goes back to the display only, and the REPLY menu is repeated until one of N, Y, W, C or I is typed.
5932
LD HL,5B71H 21 71 5B
Point Register Pair HL to 5B71H, the message FUNCTION COMPLETED.
5935
GOSUB to 59D1H to make the display the only output device (a carriage return ends the printer's line first if the printer was in use).
5938
GOSUB to 595FH to output the message at Register Pair HL, a carriage return and one more carriage return.
Reply Loop
Repeats until the first character typed is N, Y, W, C or I.
593B
LD HL,5BB0H 21 B0 5B
Point Register Pair HL to 5BB0H, the REPLY menu (N, Y, I, W and C, one per line).
593E
GOSUB to 59B6H to display the menu at Register Pair HL and read a line into 5220H. It returns Register A = the first character, in upper case.
5941
LD SP,61BAH 31 BA 61
Load the Stack Pointer SP with 61BAH, the top of DIRCHECK's stack: whatever was left on the stack by an ending in mid-routine is dropped.
5944
CP 4EH FE 4E
Compare Register A (the reply) against 4EH (ASCII N).
5946
If the Z FLAG is set (N), JUMP to 402DH, the DOS no-error exit, to end DIRCHECK.
5949
CP 59H FE 59
Compare Register A (the reply) against 59H (ASCII Y).
594B
If the Z FLAG is set (Y), JUMP to 5297H to ask for the drive of another diskette, keeping the printer answer.
594E
CP 57H FE 57
Compare Register A (the reply) against 57H (ASCII W).
5950
If the Z FLAG is set (W), JUMP to 58C5H with Register A = 57H to rewrite the directory sectors protected.
5953
CP 43H FE 43
Compare Register A (the reply) against 43H (ASCII C).
5955
If the Z FLAG is set (C), JUMP to 58C5H with Register A = 43H to clear the unused entries and rewrite the directory protected.
5958
CP 49H FE 49
Compare Register A (the reply) against 49H (ASCII I).
595A
If the NZ FLAG is set (none of the replies), LOOP BACK to 593BH to show the menu again.
595C
Reply I: JUMP to 5281H to start again with the printer question.
595FH - Output a Message and a Blank Line
Called from 5938H with Register Pair HL = a message ended by 03H.
595F
GOSUB to 5977H to output the message at Register Pair HL and a carriage return.
5962
JUMP to 597AH to output one more carriage return; its RETURN goes back to the caller.
5964H - Unreferenced Code: A Y or N Question
Nothing jumps to, calls or points to 5964H. The routine would display the message at Register Pair HL until exactly one character is typed and it is N (Z FLAG) or Y (NZ FLAG); the program asks its questions at 5281H and 593BH instead.
5964
PUSH HL E5
Save Register Pair HL (the question) on the stack. (Unreferenced code.)
5965
GOSUB to 59B6H to display the message at Register Pair HL and read a line: Register B = the characters typed, Register A = the first character in upper case. (Unreferenced code.)
5968
POP HL E1
Restore Register Pair HL (the question) from the stack. (Unreferenced code.)
5969
DECrement Register B (the characters typed) and LOOP BACK to 5964H unless it was 1. (Unreferenced code.)
596B
CP 4EH FE 4E
Compare Register A (the character) against 4EH (ASCII N). (Unreferenced code.)
596D
RET Z C8
If the Z FLAG is set (N), RETURN with it. (Unreferenced code.)
596E
CP 59H FE 59
Compare Register A (the character) against 59H (ASCII Y). (Unreferenced code.)
5970
If the NZ FLAG is set (neither N nor Y), LOOP BACK to 5964H to ask again. (Unreferenced code.)
5972
OR A B7
OR Register A (59H) with itself: the NZ FLAG is set. (Unreferenced code.)
5973
RET C9
RETURN with the NZ FLAG for Y. (Unreferenced code.)
5974H - Output Messages and Carriage Returns
5974H makes the display the only output device first. 5977H outputs a message ended by 03H and a carriage return; 597AH outputs one carriage return; 597CH outputs Register B carriage returns; 5984H outputs a message ended by 03H. Every character goes through 5A27H.
5974
GOSUB to 59D1H to make the display the only output device. 5AC5H comes here with Register Pair HL on a message.
5977
GOSUB to 5984H to output the message at Register Pair HL up to its 03H.
597A
LD B,01H 06 01
Load Register B with 01H: one carriage return.
597C
LD A,0DH 3E 0D
Load Register A with 0DH, a carriage return, the character to output.
597E
GOSUB to 5A27H to output Register A (0DH), which also counts the line and checks the BREAK, ENTER and up-arrow keys.
5981
DECrement Register B (the carriage returns left) and LOOP BACK to 597CH while it is not 0.
5983
RET C9
RETURN to the caller with Register B = 00H after the last carriage return.
5984
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the next character of the message.
5985
CP 03H FE 03
Compare Register A (the character) against 03H, the end of the message.
5987
INC HL 23
INCrement Register Pair HL past the character. INC HL does not change the flags.
5988
RET Z C8
If the Z FLAG is set (the 03H was reached), RETURN with Register Pair HL just past it.
5989
GOSUB to 5A27H to output Register A (the character).
598C
LOOP BACK to 5984H for the next character at Register Pair HL.
598EH - Unreferenced Code: Clear the Display
Nothing jumps to, calls or points to 598EH or 5996H. 598EH would output 1CH (cursor home) and then 1FH (clear to the end of the screen); 5996H would output only 1CH.
598E
GOSUB to 5996H to output 1CH, the cursor home code. (Unreferenced code.)
5991
LD A,1FH 3E 1F
Load Register A with 1FH, the code that clears to the end of the screen. (Unreferenced code.)
5993
JUMP to 5A27H to output Register A (1FH); its RETURN goes back to the caller. (Unreferenced code.)
5996
LD A,1CH 3E 1C
Load Register A with 1CH, the cursor home code. (Unreferenced code.)
5998
JUMP to 5A27H to output Register A (1CH); its RETURN goes back to the caller. (Unreferenced code.)
599BH - Output Characters, Move to a Column, Output Spaces
599BH outputs Register B characters from Register Pair HL. 59A3H outputs spaces until the line reaches column Register B (counted from 0), using the positions left at 5278H; nothing is output if the line is already there or past it. 59AEH outputs Register B spaces.
599B
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the next character to output.
599C
INC HL 23
INCrement Register Pair HL to the character after it.
599D
GOSUB to 5A27H to output Register A (the character).
59A0
DECrement Register B (the characters left) and LOOP BACK to 599BH while it is not 0.
59A2
RET C9
RETURN with Register Pair HL just past the last character output.
59A3
LD A,40H 3E 40
Load Register A with 40H (64), the characters a line holds.
59A5
SUB B 90
SUBtract Register B (the column wanted) from Register A: the positions that should be left on the line at that column.
59A6
LD B,A 47
Load Register B with Register A, those positions.
59A7
LD A,(5278H) 3A 78 52
Load Register A with the byte at 5278H, the positions now left on the line.
59AA
SUB B 90
SUBtract Register B (the positions left at the column wanted) from Register A: the spaces needed.
59AB
LD B,A 47
Load Register B with Register A, the number of spaces needed.
59AC
RET C D8
If the CARRY FLAG is set (the line is already past the column), RETURN without output.
59AD
RET Z C8
If the Z FLAG is set (the line is exactly at the column), RETURN without output.
59AE
LD A,20H 3E 20
Load Register A with 20H, a space, the character to output.
59B0
GOSUB to 5A27H to output Register A (the space).
59B3
DECrement Register B (the spaces left) and LOOP BACK to 59AEH while it is not 0.
59B5
RET C9
RETURN to the caller with Register B = 00H after the last space.
59B6H - Show a Question and Read the Reply
Called with Register Pair HL = the message. The reply is read into 5220H with the ROM's line input and changed to upper case. Returns Register Pair HL = 5220H, Register A = the first character, Register B = the number of characters typed, and the Z FLAG if the line is empty.
59B6
GOSUB to 5984H to output the message at Register Pair HL up to its 03H.
59B9
LD HL,5220H 21 20 52
Point Register Pair HL to 5220H, the input line buffer.
59BC
LD B,40H 06 40
Load Register B with 40H (64), the most characters the line may hold.
59BE
PUSH HL E5
Save Register Pair HL (5220H, the start of the buffer) on the stack.
59BF
GOSUB to the ROM's line input at 0040H with Register Pair HL = the buffer and Register B = 64. It echoes the keys and returns when ENTER or BREAK is pressed, with Register B = the number of characters typed and Register Pair HL = 5220H; after ENTER the line is followed by 0DH. The CARRY FLAG that BREAK sets is not tested.
Upper Case Loop
Register Pair HL = the next character; the loop ends after the 0DH.
59C2
LD A,(HL) 7E
Load Register A with the character at Register Pair HL.
59C3
GOSUB to 5AB5H to change Register A to upper case if it is a lower case letter.
59C6
CP 0DH FE 0D
Compare Register A (the character) against 0DH, the end of the line. The Z FLAG is set at the end.
59C8
LD (HL),A 77
Store Register A (the upper case character) back at Register Pair HL. LD does not change the flags.
59C9
INC HL 23
INCrement Register Pair HL to the next character. INC HL does not change the flags.
59CA
If the NZ FLAG is set (not the end of the line), LOOP BACK to 59C2H.
59CC
POP HL E1
Restore Register Pair HL from the stack: HL = 5220H, the start of the line.
59CD
LD A,(HL) 7E
Load Register A with the character at Register Pair HL, the first character of the reply.
59CE
CP 0DH FE 0D
Compare Register A (the first character) against 0DH: the Z FLAG is set if the line is empty.
59D0
RET C9
RETURN with Register A, Register B, Register Pair HL and the flags as described above.
59D1H - Choose the Output Devices
The displacement byte of the JR at 5A6CH (5A6DH) says where output goes: 05H skips the printer call at 5A6EH (display only, the value in the file); 00H falls into it (printer and display). 59D1H sets 05H, 59DBH sets 00H. When the setting changes, a carriage return first ends the line on the old devices. Register Pair AF is kept.
59D1
PUSH AF F5
Save Register Pair AF (the caller's Register A and flags) on the stack.
59D2
LD A,(5A6DH) 3A 6D 5A
Load Register A with the byte at 5A6DH, the output setting.
59D5
CP 05H FE 05
Compare Register A (the setting) against 05H: the Z FLAG is set if the output already goes to the display only.
59D7
LD A,05H 3E 05
Load Register A with 05H, the setting for the display only. LD does not change the flags.
59D9
JUMP to 59E3H to store Register A (05H) if the setting differs.
59DB
PUSH AF F5
Save Register Pair AF on the stack. 5387H calls here when the printer answer was Y.
59DC
LD A,(5A6DH) 3A 6D 5A
Load Register A with the byte at 5A6DH, the output setting.
59DF
CP 00H FE 00
Compare Register A (the setting) against 00H: the Z FLAG is set if the printer is already in use.
59E1
LD A,00H 3E 00
Load Register A with 00H, the setting for the printer and display. LD does not change the flags.
59E3
If the Z FLAG is set (the setting is already the one in Register A), JUMP to 59EDH to return without a change.
59E5
PUSH AF F5
Save Register Pair AF (Register A = the new setting) on the stack.
59E6
GOSUB to 597AH to output a carriage return with the old setting.
59E9
POP AF F1
Restore Register Pair AF from the stack: Register A = the new setting.
59EA
LD (5A6DH),A 32 6D 5A
Self-Modifying Code
Store Register A (05H display only, or 00H printer and display) at 5A6DH, the displacement of the JR at 5A6CH.
59ED
POP AF F1
Restore Register Pair AF (the caller's) from the stack.
59EE
RET C9
RETURN to the caller with Register Pair AF unchanged.
59EFH - Unreferenced Code: At the Top of a Page?
Nothing calls 59EFH except the unreferenced routine at 5A1CH. It would return the Z FLAG when the printer page line count at 5277H is 3CH (60), that is at the top of a page.
59EF
LD A,(5277H) 3A 77 52
Load Register A with the byte at 5277H, the lines left on the printer page. (Unreferenced code.)
59F2
CP 3CH FE 3C
Compare Register A (the lines left) against 3CH (60): the Z FLAG is set at the top of a page. (Unreferenced code.)
59F4
RET C9
RETURN with the flags of the compare. (Unreferenced code.)
59F5H - Count a Line
Called from 5A44H after every carriage return. With the printer in use, the page line count at 5277H goes down by 1; when it reaches 0 it is reloaded with 3CH (60), after six carriage returns if the byte at 5276H is not 0 (it is 00H and never written). In every case the positions left on the line (5278H) are set back to 40H (64).
59F5
LD A,(5A6DH) 3A 6D 5A
Load Register A with the byte at 5A6DH, the output setting.
59F8
CP 05H FE 05
Compare Register A (the setting) against 05H: the Z FLAG is set if the output goes to the display only.
59FA
If the Z FLAG is set, JUMP to 5A16H: only the line position is reset.
59FC
LD A,(5277H) 3A 77 52
Load Register A with the byte at 5277H, the lines left on the printer page.
59FF
DEC A 3D
DECrement Register A, the lines left. The Z FLAG is set when the page is full.
5A00
If the NZ FLAG is set (lines are left), JUMP to 5A13H to store Register A as the new count.
5A02
LD A,(5276H) 3A 76 52
Load Register A with the byte at 5276H, the option that asks for six blank lines between pages (00H).
5A05
OR A B7
OR Register A with itself: the Z FLAG is set if the option is off.
5A06
If the Z FLAG is set, JUMP to 5A11H to reload the page count.
5A08
LD B,06H 06 06
Load Register B with 06H, the number of blank lines.
5A0A
LD A,0DH 3E 0D
Load Register A with 0DH, a carriage return, for each blank line.
5A0C
GOSUB to 5A69H to send Register A (0DH) to the output devices.
5A0F
DECrement Register B (the blank lines left) and LOOP BACK to 5A0CH while it is not 0.
5A11
LD A,3CH 3E 3C
Load Register A with 3CH (60), the lines of a printer page.
5A13
LD (5277H),A 32 77 52
Store Register A (the lines left on the page) at 5277H.
5A16
LD A,40H 3E 40
Load Register A with 40H (64), the characters of a line.
5A18
LD (5278H),A 32 78 52
Store Register A (40H) at 5278H, the positions left on the new line.
5A1B
RET C9
RETURN to 5A47H, which checks the BREAK, ENTER and up-arrow keys.
5A1CH - Unreferenced Code: Feed to the Top of the Page
Nothing jumps to, calls or points to 5A1CH. It would output carriage returns until 59EFH reports the top of a printer page, or until Register C (a limit) runs out.
5A1C
GOSUB to 59EFH: the Z FLAG is set if the page line count at 5277H is 60, the top of a page. (Unreferenced code.)
5A1F
RET Z C8
If the Z FLAG is set, RETURN. (Unreferenced code.)
5A20
GOSUB to 597AH to output a carriage return. (Unreferenced code.)
5A23
DEC C 0D
DECrement Register C, the carriage returns still allowed. (Unreferenced code.)
5A24
If the NZ FLAG is set, LOOP BACK to 5A1CH. (Unreferenced code.)
5A26
RET C9
RETURN when Register C has reached 0. (Unreferenced code.)
5A27H - Output a Character
Every character DIRCHECK outputs comes here in Register A. A character other than 0DH goes out through 5A69H and uses up one of the 64 positions of the line (5278H); when none are left, or for 0DH, the line is ended: a space first if nothing was output on it, then 0DH, then 59F5H counts the line. After each line the keyboard is checked: BREAK waits until ENTER or up-arrow is pressed, and up-arrow ends the function with FUNCTION TERMINATED. Register Pairs AF, BC and HL are kept.
5A27
PUSH HL E5
Save Register Pair HL (the caller's pointer) on the stack.
5A28
PUSH BC C5
Save Register Pair BC (the caller's count in Register B) on the stack.
5A29
PUSH AF F5
Save Register Pair AF (Register A = the character) on the stack.
5A2A
LD HL,5278H 21 78 52
Point Register Pair HL to 5278H, the positions left on the output line.
5A2D
CP 0DH FE 0D
Compare Register A (the character) against 0DH, a carriage return.
5A2F
If the Z FLAG is set (a carriage return), JUMP to 5A37H to end the line.
5A31
GOSUB to 5A69H to send Register A (the character) to the output devices.
5A34
DEC (HL) 35
DECrement the byte at Register Pair HL (5278H), the positions left on the line.
5A35
If the NZ FLAG is set (positions are left), JUMP to 5A5DH to restore the registers and return.
5A37
LD A,40H 3E 40
Load Register A with 40H (64), the value 5278H holds when nothing has been output on the line.
5A39
CP (HL) BE
Compare Register A (40H) against the byte at Register Pair HL (5278H): the Z FLAG is set if the line is empty.
5A3A
LD A,20H 3E 20
Load Register A with 20H, a space. LD does not change the flags.
5A3C
If the Z FLAG is set (an empty line), GOSUB to 5A69H to send Register A (the space) to the output devices, so that the line is not empty.
5A3F
LD A,0DH 3E 0D
Load Register A with 0DH, a carriage return, to end the line.
5A41
GOSUB to 5A69H to send Register A (0DH) to the output devices. 5A73H does not send it to the display when the line was exactly 64 characters, since the display has already moved to the next line.
5A44
GOSUB to 59F5H to count the line on the printer page and set 5278H back to 64 positions.
5A47
LD A,(3840H) 3A 40 38
Load Register A with the byte at 3840H, keyboard row 6 (bit 0 ENTER, bit 2 BREAK, bit 3 up-arrow).
5A4A
AND 04H E6 04
AND 04H with Register A: keep bit 2, the BREAK key.
5A4C
If the Z FLAG is set (BREAK is not pressed), JUMP to 5A55H.
Pause Loop
Waits while BREAK paused the output, until ENTER or up-arrow is pressed.
5A4E
LD A,(3840H) 3A 40 38
Load Register A with the byte at 3840H, keyboard row 6.
5A51
AND 09H E6 09
AND 09H with Register A: keep bit 0 (ENTER) and bit 3 (up-arrow).
5A53
If the Z FLAG is set (neither is pressed), LOOP BACK to 5A4EH.
5A55
LD A,(3840H) 3A 40 38
Load Register A with the byte at 3840H, keyboard row 6.
5A58
AND 08H E6 08
AND 08H with Register A: keep bit 3, the up-arrow key.
5A5A
If the NZ FLAG is set (up-arrow is pressed), JUMP to 5A61H to end the function.
5A5D
POP AF F1
Restore Register Pair AF (Register A = the character) from the stack.
5A5E
POP BC C1
Restore Register Pair BC (the caller's count) from the stack.
5A5F
POP HL E1
Restore Register Pair HL (the caller's pointer) from the stack.
5A60
RET C9
RETURN to the caller with Register A = the character output.
Key Release Loop
Waits until no key of row 6 is held, so the up-arrow does not act on what follows.
5A61
LD A,(3840H) 3A 40 38
Load Register A with the byte at 3840H, keyboard row 6.
5A64
OR A B7
OR Register A with itself: the Z FLAG is set when no key of the row is pressed.
5A65
If the NZ FLAG is set (a key is still held), LOOP BACK to 5A61H.
5A67
JUMP to 5AC8H to output FUNCTION TERMINATED and ask what to do next. The Stack Pointer is reset at 5941H.
5A69H - Send a Character to the Output Devices
Called from 5A27H and 59F5H with Register A = the character. 5A90H saves Register Pairs HL, DE, BC and Index Registers IX and IY; the JUMP to 5AADH restores them. The printer gets every character (5A6EH) when the displacement at 5A6DH is 00H; the display gets every character except a carriage return that is not needed (5A73H).
5A69
GOSUB to 5A90H, which saves Register Pairs HL, DE, BC and Index Registers IX and IY on the stack and continues at 5A6CH.
5A6C
Self-Modifying Code
JUMP to 5A73H: the displacement at 5A6DH is 05H in the file and is stored at 59EAH. With 05H the printer call is skipped (display only); with 00H the JR goes to 5A6EH, the next instruction, and the character is printed first.
5A6E
PUSH AF F5
Save Register Pair AF (Register A = the character) on the stack.
5A6F
GOSUB to the ROM's printer routine at 003BH to print Register A (the character) through the printer DCB at 4025H.
5A72
POP AF F1
Restore Register Pair AF from the stack: Register A = the character again.
5A73
CP 0DH FE 0D
Compare Register A (the character) against 0DH, a carriage return.
5A75
If the NZ FLAG is set (any other character), JUMP to 5A8BH to display it.
5A77
LD A,40H 3E 40
Load Register A with 40H (64), the characters a line holds.
5A79
LD HL,5278H 21 78 52
Point Register Pair HL to 5278H, the positions left on the output line.
5A7C
SUB (HL) 96
SUBtract the byte at Register Pair HL (the positions left) from Register A: the characters output on the line.
5A7D
LD HL,5278H 21 78 52
Point Register Pair HL to 5278H again; the next two instructions repeat the same calculation.
5A80
LD A,40H 3E 40
Load Register A with 40H (64), the characters a line holds (again).
5A82
SUB (HL) 96
SUBtract the byte at Register Pair HL (5278H, the positions left) from Register A: A = the characters output on the line. The Z FLAG is set if there were none.
5A83
If the Z FLAG is set (nothing on the line), JUMP to 5A89H to display the carriage return.
5A85
AND 3FH E6 3F
AND 3FH with Register A (the characters on the line): the Z FLAG is set only for 64, a full line.
5A87
If the Z FLAG is set (a full line: the display has already moved to the next line), JUMP to 5AADH without displaying the carriage return.
5A89
LD A,0DH 3E 0D
Load Register A with 0DH, a carriage return, to display.
5A8B
GOSUB to the ROM's display routine at 0033H to display Register A (the character) at the cursor through the video DCB at 401DH.
5A8E
JUMP to 5AADH to restore the saved registers and return.
5A90H - Save the Registers and Continue
Called by a routine that wants its registers back when it ends: 5A90H takes the return address (the address after the CALL 5A90H), saves Register Pairs HL, DE, BC and Index Registers IX and IY, and jumps to that address. The routine ends by jumping to 5AADH, which restores them in the reverse order and returns to the routine's own caller. Used at 55DCH and 5A69H.
5A90
EX (SP),HL E3
Exchange Register Pair HL with the word at the top of the stack (the Stack Pointer SP points at the return address): HL = the address after the CALL 5A90H, and the stack holds the caller's HL.
5A91
LD (5A9DH),HL 22 9D 5A
Self-Modifying Code
Store Register Pair HL (the address after the CALL) at 5A9DH, the operand of the JP at 5A9CH.
5A94
POP HL E1
Restore Register Pair HL (the caller's HL) from the stack; the return address is now off the stack.
5A95
PUSH HL E5
Save Register Pair HL on the stack (restored at 5AB3H).
5A96
PUSH DE D5
Save Register Pair DE on the stack (restored at 5AB2H).
5A97
PUSH BC C5
Save Register Pair BC on the stack (restored at 5AB1H).
5A98
PUSH IX DD E5
Save Index Register IX on the stack (restored at 5AAFH).
5A9A
PUSH IY FD E5
Save Index Register IY on the stack (restored at 5AADH).
5A9C
JP 0000H C3 00 00
Self-Modifying Code
JUMP to the address stored at 5A9DH (0000H in the file): the instruction after the CALL 5A90H, with all registers as they were.
5A9F
POP HL E1
Restore Register Pair HL from the stack: the return address of a routine that would end here instead of at 5AADH. (Unreferenced code: nothing jumps to 5A9FH.)
5AA0
LD (5AABH),HL 22 AB 5A
Self-Modifying Code
Store Register Pair HL (that return address) at 5AABH, the operand of the JP at 5AAAH. (Unreferenced code.)
5AA3
POP IY FD E1
Restore Index Register IY from the stack. (Unreferenced code.)
5AA5
POP IX DD E1
Restore Index Register IX from the stack. (Unreferenced code.)
5AA7
POP BC C1
Restore Register Pair BC from the stack. (Unreferenced code.)
5AA8
POP DE D1
Restore Register Pair DE from the stack. (Unreferenced code.)
5AA9
POP HL E1
Restore Register Pair HL from the stack. (Unreferenced code.)
5AAA
JP 0000H C3 00 00
JUMP to the address stored at 5AABH (0000H in the file). (Unreferenced code.)
5AAD
POP IY FD E1
Restore Index Register IY from the stack (saved at 5A9AH). 55F5H, 5A87H and 5A8EH end here.
5AAF
POP IX DD E1
Restore Index Register IX from the stack (saved at 5A98H).
5AB1
POP BC C1
Restore Register Pair BC from the stack (saved at 5A97H).
5AB2
POP DE D1
Restore Register Pair DE from the stack (saved at 5A96H).
5AB3
POP HL E1
Restore Register Pair HL from the stack (saved at 5A95H).
5AB4
RET C9
RETURN to the caller of the routine that called 5A90H.
5AB5H - Upper Case
Called from 59C3H with Register A = a character; a lower case letter (61H-7AH) is changed to upper case by subtracting 20H.
5AB5
CP 61H FE 61
Compare Register A (the character) against 61H (ASCII a). The CARRY FLAG is set below a.
5AB7
RET C D8
If the CARRY FLAG is set, RETURN with Register A unchanged.
5AB8
CP 7BH FE 7B
Compare Register A (the character) against 7BH, the character after z. The NO CARRY FLAG is set above z.
5ABA
RET NC D0
If the NO CARRY FLAG is set, RETURN with Register A unchanged.
5ABB
SUB 20H D6 20
SUBtract 20H from Register A: the lower case letter becomes upper case.
5ABD
RET C9
RETURN to 59C6H with Register A in upper case.
5ABEH - End the Function
5ABEH is entered with a DOS error code in Register A: SYS0 4409H displays its message. 5AC5H is entered with Register Pair HL on a message to output. Both, and 5A67H, reach 5AC8H, which outputs FUNCTION TERMINATED and goes to the reply menu.
5ABE
OR C0H F6 C0
OR C0H into Register A (the DOS error code): bit 7 set makes 4409H display the message and return instead of ending the program; bit 6 is ignored by NEWDOS/80.
5AC0
GOSUB to SYS0 4409H to display the DOS error message for the code in Register A.
5AC3
JUMP to 5AC8H to output FUNCTION TERMINATED and show the reply menu.
5AC5
GOSUB to 5974H to make the display the only output device and output the message at Register Pair HL and a carriage return.
5AC8
LD HL,5B84H 21 84 5B
Point Register Pair HL to 5B84H, the message FUNCTION TERMINATED.
5ACB
JUMP to 5935H to output the message at Register Pair HL on the display and ask what to do next.
5ACEH - Multiply
5ACEH multiplies Register A by Register L (Register H is cleared); 5AD0H multiplies Register A by Register Pair HL. The 24-bit product is returned in Register A (high byte) and Register Pair HL (middle and low bytes). Register Pairs BC and DE are kept. The work is done by 5AD9H.
5ACE
LD H,00H 26 00
Load Register H with 00H, so Register Pair HL = Register L, the 8-bit multiplicand.
5AD0
PUSH BC C5
Save Register Pair BC (the caller's counts) on the stack.
5AD1
GOSUB to 5AD9H to multiply Register Pair HL by Register A: the product returns in Register H (high byte), Register L (middle byte) and Register C (low byte).
5AD4
LD A,H 7C
Load Register A with Register H, the product's high byte.
5AD5
LD H,L 65
Load Register H with Register L, the product's middle byte.
5AD6
LD L,C 69
Load Register L with Register C, the product's low byte: Register Pair HL = the low 16 bits of the product.
5AD7
POP BC C1
Restore Register Pair BC (the caller's counts) from the stack.
5AD8
RET C9
RETURN with the product in Register A and Register Pair HL.
5AD9
PUSH DE D5
Save Register Pair DE (the caller's value) on the stack.
5ADA
EX DE,HL EB
Exchange Register Pairs DE and HL: DE = the multiplicand.
5ADB
LD C,80H 0E 80
Load Register C with 80H: the low byte of the product, with a marker bit that falls out after eight shifts.
5ADD
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H, the high 16 bits of the product.
Multiply Loop
Eight passes, one per bit of Register A from bit 0; Register Pair HL and Register C hold the product, shifted right one bit per pass.
5AE0
RRCA 0F
Rotate Register A (the multiplier) right: its lowest bit goes into the CARRY FLAG (after eight passes Register A is back as it was).
5AE1
If the NO CARRY FLAG is set (the bit is 0), JUMP to 5AE4H without adding.
5AE3
ADD HL,DE 19
ADD Register Pair DE (the multiplicand) to Register Pair HL, the high part of the product.
5AE4
SRL H CB 3C
Shift Register H right (bit 0 goes to the CARRY FLAG), the top of the product.
5AE6
RR L CB 1D
Rotate Register L right through the CARRY FLAG: the bit from Register H goes in at the top.
5AE8
RR C CB 19
Rotate Register C right through the CARRY FLAG: the bit from Register L goes in at the top, and the marker bit comes out into the CARRY FLAG after the eighth pass.
5AEA
If the NO CARRY FLAG is set (the marker has not come out), LOOP BACK to 5AE0H.
5AEC
POP DE D1
Restore Register Pair DE (the caller's value) from the stack.
5AED
RET C9
RETURN with the product in Register H, Register L and Register C.
5AEEH - Divide
5AEEH divides Register Pair HL by 5; 5AF0H divides Register Pair HL by Register A. Register Pair HL returns the quotient and Register A the remainder, with the Z FLAG set if the remainder is 0. Register C is left holding the divisor and Register B holds 00H.
5AEE
LD A,05H 3E 05
Load Register A with 05H, the divisor (the sectors in a granule).
5AF0
LD C,A 4F
Load Register C with Register A, the divisor.
5AF1
LD B,10H 06 10
Load Register B with 10H (16), one pass per bit of Register Pair HL.
5AF3
XOR A AF
Set Register A to 00H, the remainder so far, and clear the flags.
Divide Loop
Register Pair HL is shifted left into Register A (the remainder); each quotient bit is put into bit 0 of Register L.
5AF4
ADD HL,HL 29
ADD Register Pair HL to itself: shift the dividend left; its top bit goes into the CARRY FLAG.
5AF5
RLA 17
Rotate Register A (the remainder) left through the CARRY FLAG, taking in that bit.
5AF6
If the CARRY FLAG is set (the remainder overflowed 8 bits, so it is surely at least the divisor), JUMP to 5AFBH to subtract.
5AF8
CP C B9
Compare Register A (the remainder) against Register C (the divisor). The CARRY FLAG is set if it is smaller.
5AF9
If the CARRY FLAG is set, JUMP to 5AFDH: this quotient bit is 0.
5AFB
SUB C 91
SUBtract Register C (the divisor) from Register A (the remainder).
5AFC
INC L 2C
INCrement Register L: set this quotient bit (bit 0, clear after the shift).
5AFD
DECrement Register B (the passes left) and LOOP BACK to 5AF4H while it is not 0.
5AFF
OR A B7
OR Register A (the remainder) with itself: the Z FLAG is set if it is 0.
5B00
RET C9
RETURN with the quotient in Register Pair HL and the remainder in Register A.
5B01H - Output a Byte in Hexadecimal
Called with Register A = the byte. The two digits are written at 5269H-526AH and output. Register Pairs BC and HL are kept.
5B01
PUSH HL E5
Save Register Pair HL (the caller's pointer) on the stack.
5B02
PUSH BC C5
Save Register Pair BC (the caller's count in Register B) on the stack.
5B03
LD HL,5269H 21 69 52
Point Register Pair HL to 5269H, the number buffer.
5B06
GOSUB to 5B13H to write Register A as two hexadecimal digits at Register Pair HL; HL returns two bytes higher, at 526BH.
5B09
DEC HL 2B
DECrement Register Pair HL to 526AH, the second digit.
5B0A
DEC HL 2B
DECrement Register Pair HL to 5269H, the first digit.
5B0B
LD B,02H 06 02
Load Register B with 02H, the number of digits.
5B0D
GOSUB to 599BH to output Register B (2) characters from Register Pair HL (5269H).
5B10
POP BC C1
Restore Register Pair BC (the caller's count) from the stack.
5B11
POP HL E1
Restore Register Pair HL (the caller's pointer) from the stack.
5B12
RET C9
RETURN to the caller after the two digits are output.
5B13
PUSH AF F5
Save Register Pair AF (Register A = the byte) on the stack.
5B14
RRCA 0F
Rotate Register A right: the first of four rotations that bring the high digit into bits 0-3.
5B15
RRCA 0F
Rotate Register A right, the second rotation.
5B16
RRCA 0F
Rotate Register A right, the third of the four rotations.
5B17
RRCA 0F
Rotate Register A right, the fourth: bits 0-3 of Register A now hold the byte's high digit.
5B18
GOSUB to 5B1CH to write the digit in bits 0-3 of Register A at Register Pair HL and step HL on.
5B1B
POP AF F1
Restore Register Pair AF from the stack: Register A = the byte, whose low digit is written next.
5B1C
AND 0FH E6 0F
AND 0FH with Register A: the digit value 0-15.
5B1E
CP 0AH FE 0A
Compare Register A (the digit) against 0AH. The CARRY FLAG is set for 0-9.
5B20
If the CARRY FLAG is set (a digit 0-9), JUMP to 5B24H.
5B22
ADD A,07H C6 07
ADD 07H to Register A, so that 0AH-0FH become the letters A-F after 30H is added.
5B24
ADD A,30H C6 30
ADD 30H to Register A: the digit's ASCII character.
5B26
LD (HL),A 77
Store Register A (the character) at the byte at Register Pair HL.
5B27
INC HL 23
INCrement Register Pair HL to the next position in the buffer.
5B28
RET C9
RETURN to 5B1BH, or to 5B09H after the second digit.
5B29H - Convert a Number to Decimal
5B29H clears Register D so Register E is converted; 5B2BH converts Register Pair DE (0-65535) to five digits at 5269H-526DH and changes the leading zeros (up to four) to spaces. Returns Register Pair HL = the first digit that is not a leading zero, Register B = the number of digits from there, and Register Pair DE = the caller's Register Pair HL.
5B29
LD D,00H 16 00
Load Register D with 00H, so Register Pair DE = Register E, the number to convert.
5B2B
PUSH HL E5
Save Register Pair HL on the stack; it comes back in Register Pair DE at 5B3FH.
5B2C
GOSUB to 5B41H to write Register Pair DE as five decimal digits at 5269H-526DH.
5B2F
LD B,04H 06 04
Load Register B with 04H, the most leading zeros to blank (the last digit is always shown).
5B31
LD HL,5269H 21 69 52
Point Register Pair HL to 5269H, the first digit.
5B34
LD A,30H 3E 30
Load Register A with 30H (ASCII 0), the character to compare each digit with.
Leading Zero Loop
Register Pair HL = the digit, Register B = the digits that may still be blanked.
5B36
CP (HL) BE
Compare Register A (30H) against the digit at Register Pair HL. The Z FLAG is set for a leading zero.
5B37
If the NZ FLAG is set (the first significant digit), JUMP to 5B3EH.
5B39
LD (HL),20H 36 20
Store 20H (a space) over the leading zero at Register Pair HL.
5B3B
INC HL 23
INCrement Register Pair HL to the next digit.
5B3C
DECrement Register B (the digits that may still be blanked) and LOOP BACK to 5B36H while it is not 0.
5B3E
INC B 04
INCrement Register B: B = the number of digits from Register Pair HL to 526DH.
5B3F
POP DE D1
Restore Register Pair DE from the stack: DE = the caller's Register Pair HL, saved at 5B2BH.
5B40
RET C9
RETURN with Register Pair HL on the first digit to output and Register B = the number of digits.
5B41
LD BC,5269H 01 69 52
Point Register Pair BC to 5269H, where the first digit goes.
5B44
LD HL,5B69H 21 69 5B
Point Register Pair HL to 5B69H, the table of powers of ten, stored as negative numbers.
5B47
LD A,04H 3E 04
Load Register A with 04H. The next instruction loads the same value again, so this one has no effect.
5B49
LD A,04H 3E 04
Load Register A with 04H, the number of digits found by subtraction (ten thousands, thousands, hundreds, tens).
Digit Loop
Register A (kept in the alternate AF while the digit is counted) = the digits left, Register Pair HL = the table entry, Register Pair DE = the number, Register Pair BC = where the digit goes.
5B4B
EX AF,AF' 08
Exchange Register Pair AF with the alternate AF: the count of digits left is kept aside.
5B4C
PUSH BC C5
Save Register Pair BC (where the digit goes) on the stack.
5B4D
LD C,(HL) 4E
Load Register C with the byte at Register Pair HL, the low byte of the negative power of ten.
5B4E
INC HL 23
INCrement Register Pair HL to the high byte of the table entry.
5B4F
LD B,(HL) 46
Load Register B with the byte at Register Pair HL: Register Pair BC = the negative power of ten (for example D8F0H, -10000).
5B50
INC HL 23
INCrement Register Pair HL to the next table entry.
5B51
EX DE,HL EB
Exchange Register Pairs DE and HL: HL = the number, DE = the table pointer.
5B52
LD A,2FH 3E 2F
Load Register A with 2FH, one below ASCII 0: the digit counter.
Subtract Loop
Adds the negative power of ten until the number goes below 0; Register A counts the passes.
5B54
ADD HL,BC 09
ADD Register Pair BC (the negative power of ten) to Register Pair HL (the number). The CARRY FLAG is set while the result is still 0 or more.
5B55
INC A 3C
INCrement Register A, the digit character. INC does not change the CARRY FLAG.
5B56
If the CARRY FLAG is set, LOOP BACK to 5B54H to subtract again.
5B59
SBC HL,BC ED 42
SUBtract Register Pair BC (the negative power of ten) from Register Pair HL, with the CARRY FLAG clear: this adds the power of ten back, undoing the last addition. HL = the remainder.
5B5B
EX DE,HL EB
Exchange Register Pairs DE and HL: DE = the remainder, HL = the table pointer.
5B5C
POP BC C1
Restore Register Pair BC (where the digit goes) from the stack.
5B5D
LD (BC),A 02
Store Register A (the digit character) at the byte at Register Pair BC.
5B5E
INC BC 03
INCrement Register Pair BC to the next digit position.
5B5F
EX AF,AF' 08
Exchange Register Pair AF with the alternate AF: Register A = the count of digits left.
5B60
DEC A 3D
DECrement Register A, the digits left to find by subtraction.
5B61
If the NZ FLAG is set, LOOP BACK to 5B4BH for the next power of ten.
5B63
LD A,E 7B
Load Register A with Register E, the remainder (0-9): the units digit.
5B64
ADD A,30H C6 30
ADD 30H to Register A: the units digit character.
5B66
LD (BC),A 02
Store Register A (the units digit) at the byte at Register Pair BC (526DH).
5B67
RET C9
RETURN to 5B2FH with all five digits written.
5B68H - Unreferenced Byte and the Powers of Ten
5B68H is a RET that nothing reaches (5B67H has already returned). 5B69H-5B70H is the table 5B41H uses.
5B68
RET C9
RETURN. (Unreferenced code: 5B67H returns first and nothing jumps here.)
5B69-5B6A
DEFW D8F0H F0 D8
-10000 (D8F0H), the first power of ten subtracted by 5B41H.
5B6B-5B6C
DEFW FC18H 18 FC
-1000 (FC18H), the second power of ten subtracted by 5B41H.
5B6D-5B6E
DEFW FF9CH 9C FF
-100 (FF9CH), the third power of ten subtracted by 5B41H.
5B6F-5B70
DEFW FFF6H F6 FF
-10 (FFF6H), the last entry; the units are what is left.
5B71H - Messages
Every message ends with 03H; 0DH inside a message starts a new line. 5984H outputs them character by character through 5A27H.
5B71-5B83
DEFM "FUNCTION COMPLETED", 03H 46 55 4E 43 54 49 4F 4E 20 43 4F 4D 50 4C 45 54 45 44 03
The message output at 5932H-5938H after a check has run to the end, followed by a blank line and the reply menu.
5B84-5BAF
DEFM "********************* FUNCTION TERMINATED", 0DH, 03H 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 20 20 46 55 4E 43 54 49 4F 4E 20 54 45 52 4D 49 4E 41 54 45 44 0D 03
The message 5AC8H points to when a function ends early: after a DOS error (5ABEH), after DIRECTORY SIZE UNKNOWN (5AC5H), or when up-arrow is pressed during the output (5A67H).
5BB0-5C74
DEFM "REPLY", 0DH, "N TO EXIT PROGRAM", 0DH, "Y IF ANOTHER DISKETTE FOR SAME PRINTER SPECS", 0DH, "I FOR PROGRAM RE-INITIALIZATION", 0DH, "W TO WRITE DIRECTORY SECTORS PROTECTED", 0DH, "C TO CLEAN UP (NOT REPAIR) THE DIRECTORY", 0DH, 03H 52 45 50 4C 59 0D 4E 20 20 20 20 54 4F 20 45 58 49 54 20 50 52 4F 47 52 41 4D 0D 59 20 20 20 20 49 46 20 41 4E 4F 54 48 45 52 20 44 49 53 4B 45 54 54 45 20 46 4F 52 20 53 41 4D 45 20 50 52 49 4E 54 45 52 20 53 50 45 43 53 0D 49 20 20 20 20 46 4F 52 20 50 52 4F 47 52 41 4D 20 52 45 2D 49 4E 49 54 49 41 4C 49 5A 41 54 49 4F 4E 0D 57 20 20 20 20 54 4F 20 57 52 49 54 45 20 44 49 52 45 43 54 4F 52 59 20 53 45 43 54 4F 52 53 20 50 52 4F 54 45 43 54 45 44 0D 43 20 20 20 20 54 4F 20 43 4C 45 41 4E 20 55 50 20 28 4E 4F 54 20 52 45 50 41 49 52 29 20 54 48 45 20 44 49 52 45 43 54 4F 52 59 0D 03
The reply menu displayed by 593BH. The replies are tested at 5944H-5958H: N exits to DOS, Y asks for another drive (5297H), I starts again (5281H), W and C go to 58C5H.
5C75-5C88
DEFM "OUTPUT TO PRINTER? ", 03H 4F 55 54 50 55 54 20 54 4F 20 50 52 49 4E 54 45 52 3F 20 03
The first question, displayed by 5284H-5287H.
5C89-5CAF
DEFM "WHICH DRIVE CONTAINS TARGET DISKETTE? ", 03H 57 48 49 43 48 20 44 52 49 56 45 20 43 4F 4E 54 41 49 4E 53 20 54 41 52 47 45 54 20 44 49 53 4B 45 54 54 45 3F 20 03
The drive question, displayed by 5297H-529AH; the reply is a drive number in decimal.
5CB0-5D05
DEFM '***** DISKETTE 1ST SECTOR NOT "BOOT". ASSUMING DIRECTORY', 0DH, "STARTS ON LUMP 17 DECIMAL.", 0DH, 03H 2A 2A 2A 2A 2A 20 44 49 53 4B 45 54 54 45 20 31 53 54 20 53 45 43 54 4F 52 20 4E 4F 54 20 22 42 4F 4F 54 22 2E 20 20 41 53 53 55 4D 49 4E 47 20 44 49 52 45 43 54 4F 52 59 0D 53 54 41 52 54 53 20 4F 4E 20 4C 55 4D 50 20 31 37 20 44 45 43 49 4D 41 4C 2E 0D 03
Output by 52F7H-52FAH when bytes 0 and 1 of the diskette's first sector are not 00H and FEH; lump 17 (11H) is then used as the directory lump.
5D06-5D34
DEFM "***** ATLEAST ONE DIRECTORY SECTOR UNPROTECTED", 03H 2A 2A 2A 2A 2A 20 41 54 4C 45 41 53 54 20 4F 4E 45 20 44 49 52 45 43 54 4F 52 59 20 53 45 43 54 4F 52 20 55 4E 50 52 4F 54 45 43 54 45 44 03
Output by 5815H: once when the first directory sector without the directory mark is read (5801H), and again after the listing (53BAH).
5D35-5D51
DEFM "***** DIRECTORY SIZE UNKNOWN", 03H 2A 2A 2A 2A 2A 20 44 49 52 45 43 54 4F 52 59 20 53 49 5A 45 20 55 4E 4B 4E 4F 57 4E 03
Output by 5AC5H when W or C is asked for and HIT byte 1FH was bad, so the number of directory sectors (526FH) is 0.
5D52-5D69
DEFM ' BAD "GAT" SECTOR BYTE', 03H 20 20 42 41 44 20 22 47 41 54 22 20 53 45 43 54 4F 52 20 42 59 54 45 03
Output by 5431H after the offset of a GAT byte whose bits for granules that do not exist are not all set.
5D6A-5D81
DEFM ' BAD "HIT" SECTOR BYTE', 03H 20 20 42 41 44 20 22 48 49 54 22 20 53 45 43 54 4F 52 20 42 59 54 45 03
Output by 534AH (HIT byte 1FH is not 0, 5, 10, 15 or 20) and by 5547H (a HIT byte that belongs to no entry), after the byte's offset.
5D82-5DB3
DEFM "***** GRANULE LOCKED OUT, BUT ASSIGNED TO FILE(S)", 03H 2A 2A 2A 2A 2A 20 47 52 41 4E 55 4C 45 20 4C 4F 43 4B 45 44 20 4F 55 54 2C 20 42 55 54 20 41 53 53 49 47 4E 45 44 20 54 4F 20 46 49 4C 45 28 53 29 03
Reported by 5568H for a granule that is locked out and allocated but also in a file's extents. The files are listed after it.
5DB4-5DE8
DEFM "***** GRANULE ALLOCATED BUT NOT ASSIGNED TO ANY FILE", 03H 2A 2A 2A 2A 2A 20 47 52 41 4E 55 4C 45 20 41 4C 4C 4F 43 41 54 45 44 20 42 55 54 20 4E 4F 54 20 41 53 53 49 47 4E 45 44 20 54 4F 20 41 4E 59 20 46 49 4C 45 03
Reported by 557DH for a granule the GAT marks allocated that no file's extents include.
5DE9-5E14
DEFM "***** GRANULE FREE, BUT ASSIGNED TO FILE(S)", 03H 2A 2A 2A 2A 2A 20 47 52 41 4E 55 4C 45 20 46 52 45 45 2C 20 42 55 54 20 41 53 53 49 47 4E 45 44 20 54 4F 20 46 49 4C 45 28 53 29 03
Reported by 5593H for a granule the GAT marks free that a file's extents include. The files are listed after it.
5E15-5E4C
DEFM "***** GRANULE ALLOCATED, BUT ASSIGNED TO MULTIPLE FILES", 03H 2A 2A 2A 2A 2A 20 47 52 41 4E 55 4C 45 20 41 4C 4C 4F 43 41 54 45 44 2C 20 42 55 54 20 41 53 53 49 47 4E 45 44 20 54 4F 20 4D 55 4C 54 49 50 4C 45 20 46 49 4C 45 53 03
Reported by 5589H for an allocated granule that more than one extent includes. The files are listed after it.
5E4D-5E6F
DEFM "***** GRANULE LOCKED OUT, BUT FREE", 03H 2A 2A 2A 2A 2A 20 47 52 41 4E 55 4C 45 20 4C 4F 43 4B 45 44 20 4F 55 54 2C 20 42 55 54 20 46 52 45 45 03
Reported by 556DH for a locked-out granule that the GAT marks free.
5E70-5EAA
DEFM "***** GRANULE LOCKED OUT, BUT FREE AND ASSIGNED TO FILE(S)", 03H 2A 2A 2A 2A 2A 20 47 52 41 4E 55 4C 45 20 4C 4F 43 4B 45 44 20 4F 55 54 2C 20 42 55 54 20 46 52 45 45 20 41 4E 44 20 41 53 53 49 47 4E 45 44 20 54 4F 20 46 49 4C 45 28 53 29 03
Reported by 5574H for a locked-out granule that is free in the GAT and in a file's extents. The files are listed after it.
5EAB-5EBD
DEFM "BAD EXTENT ELEMENT", 03H 42 41 44 20 45 58 54 45 4E 54 20 45 4C 45 4D 45 4E 54 03
Reported by 5495H when all five extent elements of an entry are extents, with no FEH link or FFH end.
5EBE-5EDD
DEFM "EXTENT SPACE OVERFLOWS DISKETTE", 03H 45 58 54 45 4E 54 20 53 50 41 43 45 20 4F 56 45 52 46 4C 4F 57 53 20 44 49 53 4B 45 54 54 45 03
Reported by 547AH when an extent includes a granule past the end of the diskette.
5EDE-5F00
DEFM "EXTENT'S STARTING LUMP # TOO LARGE", 03H 45 58 54 45 4E 54 27 53 20 53 54 41 52 54 49 4E 47 20 4C 55 4D 50 20 23 20 54 4F 4F 20 4C 41 52 47 45 03
Returned by 575DH when an extent element's starting lump is not below the number of lumps.
5F01-5F30
DEFM "EXTENT'S STARTING GRAN'S OFFSET IN LUMP TOO BIG", 03H 45 58 54 45 4E 54 27 53 20 53 54 41 52 54 49 4E 47 20 47 52 41 4E 27 53 20 4F 46 46 53 45 54 20 49 4E 20 4C 55 4D 50 20 54 4F 4F 20 42 49 47 03
Returned by 576FH when an element's first granule within the lump is not below the granules per lump.
5F31-5F44
DEFM "BAD EXTENSION INDEX", 03H 42 41 44 20 45 58 54 45 4E 53 49 4F 4E 20 49 4E 44 45 58 03
Reported by 54B0H when an FEH link names a DEC whose FDE sector is past the directory.
5F45-5F4D
DEFM "BAD FXDE", 03H 42 41 44 20 46 58 44 45 03
Reported by 54E6H when an FXDE has a byte other than 0 in bytes +02H to +15H.
5F4E-5F5B
DEFM "INACTIVE FXDE", 03H 49 4E 41 43 54 49 56 45 20 46 58 44 45 03
Reported by 54BEH when an FEH link names an entry that is not in use.
5F5C-5F6E
DEFM "EXTENSION NOT FXDE", 03H 45 58 54 45 4E 53 49 4F 4E 20 4E 4F 54 20 46 58 44 45 03
Reported by 54C5H when an FEH link names an entry in use that is an FPDE.
5F6F-5F89
DEFM "FXDE HAS BAD BACK DEC CODE", 03H 46 58 44 45 20 48 41 53 20 42 41 44 20 42 41 43 4B 20 44 45 43 20 43 4F 44 45 03
Reported by 54CAH (an FXDE's back link is not the entry that links to it) and by 5506H (a back link names a sector past the directory).
5F8A
DEFM "F" 46
The first letter of the message FPDE (or FXDE) HAS BAD CODE IN "HIT" SECTOR, which 5829H points Register Pair HL to.
5F8B
DEFB 50H 50
Self-Modifying Code
The second letter of that message: 50H (P) in the file; 582CH stores 50H (P, from 5460H) or 58H (X, from 54F8H) so the message reads FPDE or FXDE.
5F8C-5FAB
DEFM 'DE HAS BAD CODE IN "HIT" SECTOR', 03H 44 45 20 48 41 53 20 42 41 44 20 43 4F 44 45 20 49 4E 20 22 48 49 54 22 20 53 45 43 54 4F 52 03
The rest of the message. For an FPDE the HIT byte differs from the code of the name; for an FXDE the HIT byte is 0.
5FAC-5FCD
DEFM " FXDE LINKS BACK TO INACTIVE FDE", 03H 20 20 46 58 44 45 20 4C 49 4E 4B 53 20 42 41 43 4B 20 54 4F 20 49 4E 41 43 54 49 56 45 20 46 44 45 03
Reported by 550FH when an FXDE's back link names an entry that is not in use.
5FCE-5FF8
DEFM " FXDE LINKS BACK TO FDE NOT LINKING TO IT", 03H 20 20 46 58 44 45 20 4C 49 4E 4B 53 20 42 41 43 4B 20 54 4F 20 46 44 45 20 4E 4F 54 20 4C 49 4E 4B 49 4E 47 20 54 4F 20 49 54 03
Reported by 5523H when the entry an FXDE links back to has no FEH link to that FXDE.
5FF9-5FFF
DEFM "EOF = ", 03H 45 4F 46 20 3D 20 03
Output by 5693H before a file's end of file in the listing.
6000-6005
DEFM " EXTS", 03H 20 45 58 54 53 03
Output by 56F2H after the number of extent elements in the listing.
6006-600E
DEFM " SECTORS", 03H 20 53 45 43 54 4F 52 53 03
Output by 570AH after the number of sectors in the listing.
600F-6023
DEFM " FREE GRANULES. ", 03H 20 46 52 45 45 20 47 52 41 4E 55 4C 45 53 2E 20 20 20 20 20 03
Output by 5742H after the number of free granules.
6024-6039
DEFM " LOCKED-OUT GRANULES.", 03H 20 4C 4F 43 4B 45 44 2D 4F 55 54 20 47 52 41 4E 55 4C 45 53 2E 03
Output by 574FH after the number of locked-out granules.
603AH - Unused Bytes
The rest of the last load record is zeros. Nothing reads them as data; the stack (from 61BAH down) can reach down into them.
603A-6111
DEFB 00H x 216 00 x 216
216 bytes of 00H that fill the end of the last load record, 603AH-6111H. The file ends at 6111H; DIRCHECK's stack grows down from 61BAH toward them, and 61BAH-6BB9H hold the FDE buffers, the GAT, the HIT and the granule map.