5200H - Program Header and Data Area
This section contains the program header bytes and pre-allocated data storage areas. The first two bytes may serve as a program identifier or signature. The remainder consists of variable storage that will be initialized during program execution, including the critical repair mode flag at 5206H which determines whether the program operates in check-only or repair mode.
5200
ADD A,D 82
Program header byte 1: 82H. This appears to be part of a two-byte identification signature rather than executable code.
5201
LD H,B 60
Program header byte 2: 60H. Combined with previous byte forms the program signature.
5202
NOP 00
Reserved byte (padding).
5203
NOP 00
Reserved byte (padding).
5204
NOP 00
Reserved byte (padding).
5205
NOP 00
Reserved byte (padding).
5206
NOP 00
Repair mode flag storage. Will be set to non-zero value if user enters repair mode; 00H means check-only mode.
5207
RST 38H FF
Data byte initialized to FFH.
520A
NOP 00
Word storage low byte (will store pointer or counter).
520B
NOP 00
Word storage high byte.
520C
RST 38H FF
Word storage low byte (initialized to FFFFH).
520D
RST 38H FF
Word storage high byte.
520E
RST 38H FF
Reserved area filled with FFH.
5260H - Drive Specification Storage
Eight-byte storage area that will receive a copy of the current drive's specification block from ROM address 430AH. This includes drive geometry parameters needed for disk access operations.
[DATA AREA: 8 bytes at 5260H-5267H reserved for drive specification block - will be copied from 430AH during initialization]
5268H - Drive Number Storage
Single-byte storage for the drive number (0-3) that the user specifies to check. This value is validated and stored here after user input.
[DATA AREA: 1 byte at 5268H for drive number]
526EH - Status and Working Variables
Collection of single-byte and multi-byte working variables used throughout the program for various calculations, flags, and temporary storage.
[DATA AREA: Multiple working variables from 526EH-5275H]
5276H - Additional Reserved Area
Additional padding and reserved space before program entry point.
5276
NOP 00
Reserved/padding.
5277
NOP 00
Reserved/padding.
5278
NOP 00
Reserved/padding.
5279
NOP 00
Reserved/padding.
527A
NOP 00
Reserved/padding.
527B
NOP 00
Reserved/padding.
527C
NOP 00
Reserved/padding.
527D
NOP 00
Reserved/padding.
527E
NOP 00
Reserved/padding.
527F
NOP 00
Reserved/padding.
5280
NOP 00
Reserved/padding.
5281H - Program Entry Point and Initialization
This is the main entry point for DIRCHECK (as indicated by "PROGRAM ENTRY = 5281H" in the listing). The initialization sequence sets up the stack, prompts for drive number and repair mode, clears working buffers, initializes variables, loads the drive specification block, and prepares for disk checking operations. Entry: Called by DOS when DIRCHECK is executed. Exit: Branches to disk checking routines or error handlers.
5281
LD SP,61BAH 31 BA 61
[PROGRAM ENTRY POINT] Initialize the stack pointer to 61BAH. This sets up the stack at the top of a 256-byte buffer area, allowing the stack to grow downward from 61B9H.
[PROMPT USER FOR OUTPUT TO PRINTER - Loop until Y or N entered]
5284
LD HL,5C75H 21 75 5C
[LOOP START] Load HL with address 5C75H, which points to "OUTPUT TO PRINTER?".
5287
Call subroutine at 59B6H to display the prompt message pointed to by HL.
528A
Decrement B register and jump to 5284H if not zero. This creates a deliberate delay loop (B register value determines delay duration) before accepting input, possibly to allow user to read the prompt.
528C
SUB 4EH D6 4E
Subtract 4EH ('N') from Register A (which holds the user's answer to OUTPUT TO PRINTER).
528E
LD (5268H),A 32 68 52
Store Register A at 5268H (drive number storage). If user pressed 'N', this stores 00H; otherwise stores the difference.
5291
If the Zero flag is set (user pressed 'N'), jump to 5297H to continue without repair mode.
5293
CP 0BH FE 0B
Compare Register A with 0BH. If user pressed 'Y' (59H), then 59H-4EH=0BH, so this tests for 'Y' response.
5295
If Not Zero (user pressed neither 'N' nor 'Y'), jump back to 5284H to re-prompt. This enforces Y/N response validation.
[GET DRIVE NUMBER - Parse 2-digit drive number from user input]
5297
LD HL,5C89H 21 89 5C
Load HL with address 5C89H, pointing to "WHICH DRIVE CONTAINS TARGET DISKETTE? ".
529A
Call 59B6H to display the drive number prompt.
529D
EX DE,HL EB
Exchange DE and HL. After the CALL returns, HL likely points to the user's input buffer; move this pointer to DE for processing.
529E
XOR A AF
Clear Register A to 00H by XORing with itself. This initializes the accumulator for the numeric parsing loop.
529F
LD L,0AH 2E 0A
Load Register L with 0AH (decimal 10). This is the radix for decimal-to-binary conversion.
52A1
Call subroutine at 5ACEH which are the 16-bit division, binary-to-BCD conversion routine to compute HL = A * L. Initially this gives 0*10=0.
52A4
OR H B4
OR Register A with Register H. This tests if the high byte of HL is non-zero, which would indicate the number is too large (>255).
52A5
If Not Zero (overflow detected), jump back to 5297H to re-prompt for drive number. This prevents accepting invalid drive numbers.
[PARSE DECIMAL DIGITS - Convert ASCII digits to binary, expecting 2-digit drive number]
52A7
LD A,(DE) 1A
Load Register A with the byte pointed to by DE (next character from input buffer).
52A8
SUB 30H D6 30
Subtract 30H (ASCII '0') from Register A to convert ASCII digit to binary value. '0'=30H becomes 0, '1'=31H becomes 1, etc.
52AA
CP 0AH FE 0A
Compare Register A with 0AH (decimal 10). If the value is 10 or greater, it wasn't a valid digit.
52AC
INC DE 13
Increment DE to point to next character in input buffer.
52AD
If No Carry (value ≥ 10, invalid digit), jump to 5297H to re-prompt. The Carry flag is clear when subtraction result is non-negative.
52AF
ADD A,L 85
Add Register L (current accumulated value) to Register A (new digit). This combines the digit with previous result: result = (previous*10) + digit.
52B0
If Carry (result > 255, overflow), jump to 5297H to re-prompt. This prevents accepting numbers too large.
52B2
Decrement B and jump to 529FH if not zero. B register acts as digit counter (likely initialized to 2), allowing exactly 2 digits to be parsed.
52B4
LD (5206H),A 32 06 52
Store the parsed drive number from Register A at 5206H (repair mode flag storage). This stores the final drive number after successful parsing.
[CLEAR LARGE WORK BUFFER - Initialize 1536 bytes (0600H) to zero]
52B7
LD BC,0600H 01 00 06
Load BC register pair with 0600H (1536 decimal). This is the byte count for the buffer clear operation.
52BA
LD HL,65BAH 21 BA 65
Load HL with starting address 65BAH of the large work area to be cleared.
52BD
LD (HL),00H 36 00
[CLEAR LOOP START] Store 00H at address pointed to by HL, clearing one byte.
52BF
INC HL 23
Increment HL to point to next byte.
52C0
DEC BC 0B
Decrement BC byte counter.
52C1
LD A,B 78
Load Register A with Register B (high byte of counter).
52C2
OR C B1
OR Register A with Register C (low byte). This tests if BC=0000H by checking if both bytes are zero.
52C3
If Not Zero (more bytes to clear), jump back to 52BDH to continue loop. Loop completes when all 1536 bytes cleared.
[INITIALIZE WORKING VARIABLES]
52C5
XOR A AF
Clear Register A to 00H.
52C6
LD (526EH),A 32 6E 52
Store 00H at address 526EH (status flag). Initializes status variable to zero.
52C9
LD HL,FFFFH 21 FF FF
Load HL with FFFFH (all bits set, -1 in two's complement).
52CC
LD (520CH),HL 22 0C 52
Store HL (FFFFH) at address 520CH-520DH. Initializes 16-bit variable to FFFFH.
52CF
LD HL,0000H 21 00 00
Load HL with 0000H (zero).
52D2
LD (520AH),HL 22 0A 52
Store HL (0000H) at address 520AH-520BH. Initializes another 16-bit variable to zero.
[LOAD GAT SECTOR - Read Granule Allocation Table from disk]
52D5
LD HL,63BAH 21 BA 63
Load HL with address 63BAH (GAT buffer). This 256-byte buffer will receive the GAT sector.
52D8
Call subroutine at 5820H to read the GAT sector into the buffer at HL. This loads the master allocation table for disk checking.
52DB
If Not Zero flag (read error), jump to 5ABEH (error handler). This aborts if GAT cannot be loaded.
[COPY DRIVE SPECIFICATION BLOCK FROM ROM]
52DE
PUSH HL E5
Save HL (GAT buffer pointer) on stack for later use.
52DF
LD HL,430AH 21 0A 43
Load HL with ROM address 430AH, which contains the current drive's specification block (drive geometry and parameters).
52E2
LD DE,5260H 11 60 52
Load DE with destination address 5260H (drive specification storage area in this program).
52E5
LD BC,0008H 01 08 00
Load BC with byte count 0008H (8 bytes). The drive specification block is 8 bytes.
52E8
LDIR ED B0
Block copy 8 bytes from (HL) to (DE), incrementing both pointers. Copies drive specification from ROM at 430AH to RAM at 5260H. After LDIR, BC=0, HL=4312H, DE=5268H.
52EA
POP HL E1
Restore HL from stack (GAT buffer pointer at 63BAH).
[CHECK FIRST BYTE OF GAT - Determine disk format]
52EB
LD A,(HL) 7E
Load Register A with first byte of GAT at address 63BAH. This byte indicates disk format/compatibility.
52EC
OR A B7
OR Register A with itself to test if it's zero and set flags. If first byte is 00H, indicates special condition.
52ED
INC HL 23
Increment HL to point to second byte of GAT (63BBH).
52EE
If Not Zero (first byte non-zero), jump to 52F7H. This handles standard NEWDOS/80 format.
[SPECIAL CASE - First byte is 00H, check second byte]
52F0
LD A,(HL) 7E
Load Register A with second byte of GAT (at 63BBH).
52F1
CP FEH FE FE
Compare Register A with FEH. The sequence 00H,FEH indicates TRSDOS 2.3 compatibility format.
52F3
INC HL 23
Increment HL to point to third byte (63BCH).
52F4
LD A,(HL) 7E
Load Register A with third byte of GAT.
52F5
If Zero flag set (second byte was FEH), jump to 52FFH. This handles TRSDOS 2.3 compatible disks.
[NON-COMPATIBLE DISK - Display error message and set format code]
52F7
Load HL with address 5CB0H to point to "***** DISKETTE 1ST SECTOR NOT 'BOOT'. ASSUMING DIRECTORY".
52FA
Call subroutine at 5977H to display error message. Informs user the disk format isn't standard NEWDOS/80.
52FD
LD A,11H 3E 11
Load Register A with 11H. This value will be used as the track format/compatibility code.
[CONTINUE PROCESSING - Calculate buffer area and initialize sector pointers]
52FF
LD (5260H),A 32 60 52
Store Register A at 5260H (first byte of drive specification storage). This sets the format compatibility code.
5302
LD L,A 6F
Load Register L with Register A (format code 11H). Will use this for calculation.
5303
LD A,(5265H) 3A 65 52
Load Register A with byte at 5265H (offset +5 in drive specification block, likely granules per track).
5306
LD H,A 67
Load Register H with Register A. Now HL contains format code in L and granules-per-track in H.
5307
RLCA 07
Rotate Register A left through Carry. Multiplies A by 2 (if A=5, becomes 10).
5308
RLCA 07
Rotate Register A left again. Now A = original * 4.
5309
ADD A,H 84
Add Register H (original granules-per-track) to Register A. Result = (granules*4) + granules = granules*5.
530A
Call multiply routine at 5ACEH. Computes HL = A * L = (granules*5) * format_code. This calculates buffer size needed.
530D
LD (5274H),HL 22 74 52
Store HL at 5274H-5275H (calculated buffer pointer). Saves computed address for later use.
5310
LD (520AH),HL 22 0A 52
Store HL at 520AH-520BH. Initializes another pointer variable with same value.
[INITIALIZE DIRECTORY BUFFERS - Load first two directory sectors]
5313
LD HL,62BAH 21 BA 62
Load HL with address 62BAH (first directory buffer, 256 bytes).
5316
LD B,02H 06 02
Load B register with 02H (loop counter for 2 iterations). Will load two consecutive directory sectors.
5318
INC H 24
[DIRECTORY LOAD LOOP] Increment H register (high byte of HL). Advances buffer pointer by 256 bytes: 62BAH→63BAH→64BAH.
5319
Call subroutine at 5801H to read directory sector into buffer pointed to by HL. Loads directory data for processing.
531C
Decrement B and jump to 5318H if not zero. Loops to load second directory sector.
[LOAD ADDITIONAL WORKING BUFFERS]
531E
LD HL,60BAH 21 BA 60
Load HL with address 60BAH (another working buffer area).
5321
LD B,02H 06 02
Load B with 02H for 2 iterations.
5323
INC H 24
[BUFFER LOAD LOOP] Increment H to next 256-byte page: 60BAH→61BAH→62BAH.
5324
Call 5801H to load another sector into this buffer.
5327
Loop back to 5323H for second buffer load.
[INITIALIZE TRACK AND SECTOR VARIABLES]
5329
LD A,00H 3E 00
Load Register A with 00H (track 0).
532B
LD (5272H),A 32 72 52
Store 00H at 5272H (current track variable). Initialize to track 0.
532E
LD A,01H 3E 01
Load Register A with 01H (sector 1).
5330
LD (5273H),A 32 73 52
Store 01H at 5273H (current sector variable). Initialize to sector 1.
[CALCULATE SECTORS PER TRACK - From drive specification]
5333
LD A,(64D9H) 3A D9 64
Load Register A with byte at 64D9H. This address may contain sectors-per-track from disk parameters.
5336
LD L,A 6F
Load Register L with Register A (sectors per track value).
5337
LD H,00H 26 00
Load Register H with 00H. Now HL contains sectors-per-track as 16-bit value.
5339
Call subroutine at 5AEEH, possibly a validation or calculation routine.
533C
If Not Zero flag, jump to 5345H. This may handle special case or error condition.
533E
INC L 2C
Increment Register L (sectors-per-track value).
533F
INC L 2C
Increment Register L again. Adds 2 to sectors-per-track.
5340
LD A,L 7D
Load Register A with Register L (adjusted value).
5341
CP 07H FE 07
Compare Register A with 07H. Tests if adjusted value is less than 7.
5343
If Carry (value < 7), jump to 534EH to continue. This validates the sectors-per-track is in acceptable range.
[ERROR CASE - Invalid sectors-per-track value]
5345
LD A,1FH 3E 1F
Load Register A with 1FH (error code for invalid disk parameter).
5347
Load HL with address 5D6AH (error message pointer for disk parameter error).
534A
Call error handler at 583FH to display error and possibly abort.
534D
XOR A AF
Clear Register A to 00H after error handling.
[COMPUTE GRANULE PARAMETER - Calculate granules*5]
534E
LD L,05H 2E 05
Load Register L with 05H (multiplier 5).
5350
Call multiply routine at 5ACEH. Computes HL = A * L. If A contains granules-per-track, result is granules*5.
5353
LD A,L 7D
Load Register A with Register L (low byte of result).
5354
LD (526FH),A 32 6F 52
Store Register A at 526FH (save granules*5 value for later calculations).
[CALCULATE TOTAL SECTORS - Multiply tracks × sectors-per-track]
5357
LD A,(5263H) 3A 63 52
Load Register A with byte at 5263H (offset +3 in drive spec, likely total tracks).
535A
LD L,A 6F
Load Register L with Register A (track count).
535B
LD A,(5264H) 3A 64 52
Load Register A with byte at 5264H (offset +4, likely sectors per track).
535E
Call multiply routine. Computes HL = A * L = sectors-per-track * tracks = total sectors on disk.
5361
Call subroutine at 5AEEH for additional processing or validation of sector count.
5364
LD (5270H),HL 22 70 52
Store HL (total sector count) at 5270H-5271H for later reference.
5367H - Drive Type Detection and Parameter Setup
This section analyzes the drive specification to determine if it's a single or double-density drive, then configures sector size parameters and display formatting accordingly. The code checks byte offset +1 in the drive specification block and adjusts parameters based on density type. Entry: Drive specification block has been loaded at 5260H. Exit: Display parameters configured at 53E5H and 53E1H.
5367
LD A,(5261H) 3A 61 52
Load Register A with byte at 5261H (offset +1 in drive specification block, likely density indicator: single-density < 61H, double-density ≥ 61H).
536A
CP 61H FE 61
Compare Register A with 61H (ASCII 'a'). This value distinguishes between single-density and double-density drives.
536C
If No Carry (A ≥ 61H, double-density drive), jump to 5378H to set double-density parameters.
[SINGLE-DENSITY CONFIGURATION]
536E
LD A,(641AH) 3A 1A 64
Load Register A with byte at 641AH (additional parameter check, possibly format verification byte).
5371
INC A 3C
Increment Register A. Tests if the value was FFH (becomes 00H after increment).
5372
LD A,3EH 3E 3E
Load Register A with 3EH (62 decimal). This is the sector size parameter for single-density (likely 62 bytes displayable per sector line).
5374
LD B,60H 06 60
Load Register B with 60H (96 decimal). Secondary parameter for single-density formatting.
5376
If Not Zero (value at 641AH was not FFH), jump to 537CH to store parameters. This validates the format byte.
[DOUBLE-DENSITY CONFIGURATION]
5378
LD A,18H 3E 18
Load Register A with 18H (24 decimal). Sector size parameter for double-density (24 bytes per display line, accommodating 256-byte sectors).
537A
LD B,C0H 06 C0
Load Register B with C0H (192 decimal). Secondary parameter for double-density formatting.
[STORE DENSITY PARAMETERS]
537C
LD (53E5H),A 32 E5 53
Store Register A at 53E5H. This self-modifies code at that address to set sector size for display operations (later used in loop at 53E5H).
537F
LD A,B 78
Load Register A with Register B (contains 60H for single-density or C0H for double-density).
5380
LD (53E1H),A 32 E1 53
Store Register A at 53E1H. Self-modifies code to set the secondary density parameter.
[CHECK IF DRIVE IS ALREADY SELECTED]
5383
LD A,(5268H) 3A 68 52
Load Register A with byte at 5268H (the drive number entered by user: 0-3).
5386
OR A B7
OR Register A with itself to test if it's zero and set flags.
5387
If Not Zero (drive number is not 0), call subroutine at 59DBH. This likely selects/activates the specified drive.
[BEGIN DISPLAY OUTPUT - Show checking progress]
538A
LD B,02H 06 02
Load Register B with 02H to set up to display TWO carriage returns.
538C
Call display subroutine at 597CH to output B number of CARRIAGE RETURNS.
538F
LD B,08H 06 08
Load Register B with 08H (8 bytes to display).
5391
LD HL,648AH 21 8A 64
Load HL with address 648AH (points to text or data to display, possibly drive name or disk label).
5394
Call subroutine at 599BH to display B bytes from address HL.
5397
LD B,04H 06 04
Load Register B with 04H (4 spaces or formatting bytes).
5399
Call subroutine at 59AEH to output 4 spaces
539C
LD B,08H 06 08
Load Register B with 08H for next display operation.
539E
Call 599BH again to display additional 8 bytes.
53A1
Call subroutine at 597AH, possibly outputs carriage return/line feed.
[CALL MAIN DISK CHECKING ROUTINES]
53A4
Call subroutine at 53C0H. This begins GAT analysis - comparing actual granule usage against GAT entries.
53A7
Call subroutine at 543AH. This checks file directory entries and extent chains for consistency.
53AA
Call subroutine at 5535H. Additional directory validation routine.
53AD
Call subroutine at 554EH. This analyzes granule allocation status and reports errors.
53B0
Call subroutine at 5625H. Additional disk structure verification.
53B3
Call subroutine at 571BH. Final validation or summary routine.
[CHECK IF ERRORS FOUND - Write GAT back if repairs made]
53B6
LD A,(526EH) 3A 6E 52
Load Register A with byte at 526EH (error flag/status variable). Non-zero indicates errors were found and repaired.
53B9
OR A B7
OR Register A with itself to test if any errors occurred and set flags.
53BA
If Not Zero (errors found and repaired), call 5815H to write the corrected GAT back to disk. This saves repairs.
53BD
Jump to 5932H (program completion routine to display statistics and exit).
53C0H - GAT Cross-Reference Check
This routine performs the critical GAT (Granule Allocation Table) cross-reference operation. It compares the GAT entries against actual file allocations stored in the working buffer at 65BAH. The routine uses index registers IX (pointing to GAT at 63BAH) and IY (pointing to allocation tracking buffer at 65BAH) to simultaneously scan both tables, checking each granule's status bit-by-bit. For each granule, it verifies that the GAT allocation status matches the actual usage determined from file extent chains. Entry: GAT loaded at 63BAH, file allocation tracking at 65BAH. Exit: Errors flagged in working buffer.
53C0
LD IX,63BAH DD 21 BA 63
Load index register IX with address 63BAH (start of GAT buffer). IX will scan through GAT entries.
53C4
LD IY,65BAH FD 21 BA 65
Load index register IY with address 65BAH (start of allocation tracking buffer). IY points to the buffer that tracks which granules are actually used by files.
53C8
LD L,00H 2E 00
Load Register L with 00H. L will serve as granule number counter (0-255).
53CA
LD DE,(5270H) ED 5B 70 52
Load DE register pair with 16-bit value at 5270H-5271H (total sector count on disk, calculated earlier).
53CE
LD A,(5265H) 3A 65 52
Load Register A with byte at 5265H (offset +5 in drive specification, contains granules-per-track).
53D1
LD H,A 67
Load Register H with Register A. H now contains granules-per-track value.
[CALCULATE MAXIMUM GRANULE NUMBER - Limit to available disk space]
53D2
LD A,D 7A
Load Register A with Register D (high byte of sector count).
53D3
OR A B7
OR Register A with itself to test if high byte is non-zero (more than 255 sectors).
53D4
If Not Zero (more than 255 sectors), jump to 53DBH. Use full granule count from H.
53D6
LD A,E 7B
Load Register A with Register E (low byte of sector count, total sectors < 256).
53D7
CP H BC
Compare Register A (actual sectors) with Register H (granules-per-track). Check if actual is less than expected.
53D8
If No Carry (actual ≥ expected), jump to 53DBH to use standard granule count.
53DA
LD H,E 63
Load Register H with Register E. For small disks, limit maximum granule count to actual sector count.
[INITIALIZE BIT SCANNING LOOP - Check 8 granules per byte]
53DB
LD B,08H 06 08
Load Register B with 08H (8 bits per byte counter). Will check 8 granules per GAT byte.
53DD
LD C,01H 0E 01
Load Register C with 01H (bit mask: 00000001b). Will be rotated left to test each bit position.
53DF
LD A,L 7D
Load Register A with Register L (current granule number).
53E0
CP 00H FE 00
Compare Register A with 00H. This checks if we've processed all granules (wraps to 0 after 255).
53E2
RET NC D0
Return if No Carry (A ≥ 0, but since we're comparing with 0, this returns when A wraps back to 0 after processing all 256 possible granules). Exit point when all granules checked.
53E3
XOR A AF
Clear Register A to 00H. Will be used to accumulate error flags.
53E4
PUSH AF F5
Push AF (error flag accumulator) onto stack for safekeeping during bit processing.
53E5
Jump to 53FEH to begin bit checking loop. Note: First byte (18H) is self-modified at 537CH based on disk density.
[CHECK GAT HIGH OFFSET - Locked-out granule detection]
53E7
LD A,(IX+60H) DD 7E 60
Load Register A with byte at (IX+60H). This is the GAT high offset (offset 96 bytes into GAT, where locked-out bits are stored). Locked-out granules have corresponding bit set here.
53EA
INC H 24
Increment Register H (test if more granules to check).
53EB
DEC H 25
Decrement Register H back to original value. This INC/DEC sequence tests if H=0 without changing it, setting flags.
53EC
If Not Zero (more granules remain), jump to 53F7H to check allocation bit.
[GRANULE IS LOCKED-OUT - Check for error condition]
53EE
AND C A1
AND Register A with Register C (bit mask). Tests if this granule's locked-out bit is set in GAT high offset.
53EF
If Not Zero (granule IS locked-out), jump to 53FEH to skip to next bit. Locked-out granules should not be allocated.
53F1
EX (SP),HL E3
Exchange HL with value on top of stack. This swaps error flag (on stack) with HL (granule counter/limit).
53F2
SET 1,H CB CC
Set bit 1 of Register H. Records error type: bit 1 = locked-out granule is marked free (should be allocated or properly marked).
53F4
EX (SP),HL E3
Exchange back, restoring HL and putting updated error flag on stack.
53F5
Jump to 53FEH to continue to allocation bit check.
[CHECK ALLOCATION BIT IN GAT HIGH OFFSET]
53F7
AND C A1
AND Register A with Register C (bit mask). Tests if this granule is marked as locked-out in GAT.
53F8
If Zero (granule not locked-out), jump to 53FEH to check main GAT allocation.
53FA
SET 7,(IY+00H) FD CB 00 FE
Set bit 7 of byte at (IY+00H) in allocation tracking buffer. Marks this granule as locked-out in our tracking table.
[CHECK MAIN GAT ALLOCATION BIT]
53FE
LD A,(IX+00H) DD 7E 00
Load Register A with byte at (IX+00H) (current GAT byte). This contains allocation bits for 8 granules.
5401
INC H 24
Increment Register H.
5402
DEC H 25
Decrement Register H. Again tests if H=0 (no more granules to check).
5403
If Not Zero (more granules exist), jump to 540EH to check if allocated.
[GAT SHOWS FREE - Check if actually in use]
5405
AND C A1
AND Register A with Register C (bit mask). Tests if GAT shows this granule as free (bit=0) or allocated (bit=1).
5406
If Not Zero (GAT shows allocated), jump to 5419H to advance to next bit. GAT is consistent.
5408
EX (SP),HL E3
Exchange HL with stack (get error flag).
5409
SET 0,H CB C4
Set bit 0 of Register H. Records error: bit 0 = GAT shows free but granule is actually allocated to file(s).
540B
EX (SP),HL E3
Restore HL from stack.
540C
Jump to 5419H to continue.
[GAT SHOWS ALLOCATED - Check if actually free]
540E
AND C A1
AND Register A with Register C. Tests allocation bit in GAT.
540F
If Zero (GAT shows free), jump to 5415H to advance counters. No conflict detected.
5411
SET 6,(IY+00H) FD CB 00 F6
Set bit 6 of byte at (IY+00H). Marks this granule as allocated in GAT in our tracking buffer.
[ADVANCE TO NEXT GRANULE]
5415
DEC DE 1B
Decrement DE (sectors remaining counter).
5416
DEC H 25
Decrement H (granules remaining counter).
5417
INC IY FD 23
Increment IY to point to next byte in allocation tracking buffer (next granule).
[ADVANCE BIT MASK AND LOOP]
5419
RLC C CB 01
Rotate Register C left through carry. Advances bit mask to next position: 01H→02H→04H→08H→10H→20H→40H→80H.
541B
Decrement B (bit counter) and jump to 53E5H if not zero. Loops to check all 8 bits in current GAT byte.
[PROCESS ERROR FLAGS FOR THIS GAT BYTE]
541D
LD A,L 7D
Load Register A with Register L (current granule base number for this byte).
541E
POP BC C1
Pop BC from stack (B contains error flags: bit 0=free but allocated, bit 1=locked-out but free).
541F
BIT 0,B CB 40
Test bit 0 of Register B (GAT shows free but actually allocated error).
5421
If Not Zero (error type 0 detected), call 5431H to report "GAT shows free but granule assigned to file(s)" error.
5424
LD A,L 7D
Reload Register A with Register L (granule base number).
5425
ADD 60H C6 60
Add 60H (96 decimal) to Register A. This creates the granule number for the high offset range (locked-out bit errors).
5427
BIT 1,B CB 48
Test bit 1 of Register B (locked-out but free error).
5429
If Not Zero (error type 1 detected), call 5431H to report "locked-out granule marked as free" error.
542C
INC IX DD 23
Increment IX to point to next GAT byte (next 8 granules).
542E
INC L 2C
Increment L (granule counter, now points to next group of 8 granules).
542F
Jump back to 53CEH to continue GAT checking loop with next byte.
5431H - GAT Error Reporter
Simple error reporting subroutine that displays a GAT allocation error message. The granule number in Register A and error message address in HL are used to format and display the error. Entry: A=granule number, HL preserved. Exit: Error message displayed, registers restored.
5431
PUSH HL E5
Save HL register pair on stack (preserves caller's data pointer).
5432
Load HL with address 5D52H (points to GAT error message template).
5435
Call error display routine at 583FH. Displays error message with granule number from Register A.
5438
POP HL E1
Restore HL from stack.
5439
RET C9
Return to caller.
543AH - Directory Entry Validation Main Loop
This is the main directory entry validation routine that scans through all directory entries in the Hash Index Table (HIT), checking file primary directory entries (FPDEs) and file extension directory entries (FXDEs) for consistency. The routine validates extent chains, checks directory entry linkages, verifies that active entries have valid data, and ensures extensions properly link back to their primary entries. Entry: Directory sectors loaded, IY points to allocation tracking buffer. Exit: All directory entries validated, errors reported.
543A
XOR A AF
Clear Register A to 00H.
543B
LD (5279H),A 32 79 52
Store 00H at 5279H (directory entry counter or status flag). Initialize to zero before scanning directory.
543E
LD (527AH),A 32 7A 52
Store 00H at 527AH (secondary counter or index). Initialize to zero.
5441
Call subroutine at 586AH. This likely loads next directory entry into IY or advances to next entry.
5444
RET NZ C0
Return if Not Zero flag (no more directory entries to process). Exit point when all entries checked.
[CHECK DIRECTORY ENTRY TYPE AND STATUS]
5445
LD A,(IY+00H) FD 7E 00
Load Register A with byte at (IY+00H) (directory entry flags/type byte). Bits indicate entry type: bit 7=locked-out, bit 6=allocated, bit 5=assigned, bit 4=active.
5448
BIT 4,A CB 67
Test bit 4 of Register A (active flag). Bit 4=1 means entry is active (contains file data).
544A
If Zero (entry inactive/deleted), jump to 54DBH to advance to next entry. Skip validation of deleted entries.
544D
BIT 7,A CB 7F
Test bit 7 of Register A (extension flag). Bit 7=1 indicates this is an FXDE (file extension directory entry).
544F
If Not Zero (this is an FXDE), jump to 54E1H to handle extension entry validation separately.
[PROCESS FILE PRIMARY DIRECTORY ENTRY (FPDE)]
5452
Call subroutine at 5786H to calculate the directory entry checksum.
5455
Call subroutine at 579EH to validate the entry against a stored checksum.
5458
LD (HL),00H 36 00
Store 00H at address pointed to by HL. Clears a flag or marker at this location.
545A
If Zero flag set (extent processing completed normally), jump to 5465H to process extent elements.
545C
LD A,(5279H) 3A 79 52
Load Register A with byte at 5279H (directory entry counter).
545F
DEC A 3D
Decrement Register A. Tests if this is the first entry (becomes FFH if was 00H).
5460
LD A,50H 3E 50
Load Register A with 50H (error code 50H for extent error).
5462
If Not Zero (not first entry), call 5829H to report extent error.
[VALIDATE EXTENT CHAIN - Check 5 extent elements in directory entry]
5465
LD B,05H 06 05
Load Register B with 05H (5 iterations). Each FPDE contains up to 5 extent elements (2 bytes each).
5467
LD A,(IY+16H) FD 7E 16
Load Register A with byte at (IY+16H) (offset +22 decimal, first extent element high byte). This starts the extent chain.
546A
CP FEH FE FE
Compare Register A with FEH. Value FEH or FFH indicates empty/terminator extent element.
546C
If No Carry (A ≥ FEH, empty extent), jump to 549FH to check if this is an extension index.
546E
Call subroutine at 5758H. Decodes extent element into starting granule (DE) and count (C).
5471
If Zero (extent decode successful), jump to 549AH to report extent error and continue.
[VALIDATE GRANULES IN EXTENT - Check each granule is within disk bounds]
5473
LD HL,(5270H) 2A 70 52
Load HL with 16-bit value at 5270H-5271H (total sectors on disk).
5476
DEC HL 2B
Decrement HL (maximum valid sector number = total-1).
5477
OR A B7
Clear Carry flag by ORing A with itself (prepare for SBC).
5478
SBC HL,DE ED 52
Subtract DE from HL with borrow (HL = max_sector - starting_granule). If result negative, granule is beyond disk end.
547A
Load HL with address 5EBEH (error message: "EXTENT SPACE OVERFLOWS DISKETTE").
547D
If Carry (starting granule > max sector, overflow error), jump to 549AH to report error.
[MARK GRANULES AS ALLOCATED IN TRACKING BUFFER]
547F
LD HL,65BAH 21 BA 65
Load HL with address 65BAH (allocation tracking buffer base).
5482
ADD HL,DE 19
Add DE (granule number) to HL. Now HL points to this granule's byte in tracking buffer.
5483
BIT 5,(HL) CB 6E
Test bit 5 of byte at (HL) in tracking buffer. Bit 5 indicates if this granule is already assigned to a file.
5485
If Zero (granule not yet assigned), jump to 5489H to mark it as assigned.
5487
SET 4,(HL) CB E6
Set bit 4 of (HL). Marks granule as cross-linked - assigned to multiple files. This is a serious error condition.
5489
SET 5,(HL) CB EE
Set bit 5 of (HL). Marks granule as assigned to file in tracking buffer.
548B
INC DE 13
Increment DE (advance to next granule in extent).
548C
DEC C 0D
Decrement C (granule count in this extent).
548D
If Not Zero (more granules in extent), loop back to 5473H to validate and mark next granule.
[ADVANCE TO NEXT EXTENT ELEMENT]
548F
INC IY FD 23
Increment IY by 1 byte.
5491
INC IY FD 23
Increment IY again. Total +2 bytes advances to next extent element (each extent is 2 bytes).
5493
Decrement B (extent counter) and jump to 5467H if not zero. Loop to process all 5 extent elements.
5495
Load HL with address 5EABH (error message: "BAD EXTENT ELEMENT").
5498
Jump to 54D8H to report error if extent validation failed.
[HANDLE EXTENT ERROR REPORTING]
549A
Call error reporting routine at 582EH. Displays extent error message.
549D
Jump back to 548FH to continue with next extent element after reporting error.
[CHECK FOR EXTENSION INDEX - Last extent element may point to FXDE]
549F
If Not Zero (extent byte is FFH, true terminator), jump to 54DBH to finish this entry. No extension exists.
54A1
LD A,(527AH) 3A 7A 52
Load Register A with byte at 527AH (previous extension index value).
54A4
LD (527BH),A 32 7B 52
Store Register A at 527BH (save previous extension index for backward link validation).
54A7
LD A,(IY+17H) FD 7E 17
Load Register A with byte at (IY+17H) (offset +23, extension index byte following the FEH marker).
54AA
LD (527AH),A 32 7A 52
Store Register A at 527AH (current extension index, used to locate the FXDE).
54AD
Call subroutine at 5893H. Loads the FXDE directory entry specified by the extension index in A.
54B0
Load HL with address 5F31H (error message: "BAD EXTENSION INDEX").
54B3
If Not Zero (extension index invalid or FXDE not found), jump to 54D8H to report error.
[VALIDATE EXTENSION ENTRY TYPE]
54B5
LD A,(IY+00H) FD 7E 00
Load Register A with byte at (IY+00H) (FXDE flags/type byte).
54B8
AND 90H E6 90
AND Register A with 90H (mask bits 7 and 4: extension flag and active flag). Result should be 90H for valid active FXDE.
54BA
CP 90H FE 90
Compare Register A with 90H. Tests if this is an active extension entry.
54BC
If Zero (valid active FXDE), jump to 54CAH to validate backward linkage.
54BE
Load HL with address 5F4EH (error message: "INACTIVE FXDE").
54C1
BIT 4,A CB 67
Test bit 4 of Register A (active flag).
54C3
If Zero (FXDE is inactive), jump to 54D8H to report "INACTIVE FXDE" error.
54C5
Load HL with address 5F5CH (error message: "EXTENSION NOT FXDE").
54C8
Jump to 54D8H to report "EXTENSION NOT FXDE" error (bit 7 not set, not an extension type).
[VALIDATE BACKWARD LINKAGE - FXDE should link back to this FPDE]
54CA
Load HL with address 5F6FH (error message: "FXDE HAS BAD BACK DEC CODE").
54CD
LD A,(527BH) 3A 7B 52
Load Register A with byte at 527BH (previous extension index or primary entry index).
54D0
CP (IY+01H) FD BE 01
Compare Register A with byte at (IY+01H) (FXDE's backward DEC code at offset +1). This should match the index of the entry that linked to this FXDE.
54D3
If Not Zero (backward link doesn't match), jump to 54D8H to report bad back-link error.
54D5
If backward link valid, jump to 5465H to process the 5 extent elements in this FXDE (extensions contain additional extents).
[ERROR HANDLER - Report directory structure error]
54D8
Call error reporting routine at 582EH. Displays the error message pointed to by HL.
[ADVANCE TO NEXT DIRECTORY ENTRY]
54DB
Call subroutine at 58BDH. Advances IY to next directory entry in HIT.
54DE
Jump back to 543BH to process next directory entry. [MAIN LOOP CONTINUES]
54E1H - File Extension (FXDE) Validation
This routine validates File eXtension Directory Entries (FXDEs). It checks that the FXDE is truly inactive (all extent elements are zero) if it appears to be unused, validates the backward linkage to the primary entry, and processes the extent chain if active. FXDEs contain additional extent elements when a file's allocation exceeds the 5 extents available in the primary directory entry. Entry: IY points to FXDE, (IY+00H) has bit 7 set. Exit: FXDE validated or error reported.
54E1
PUSH IY FD E5
Push IY onto stack (save FXDE pointer for later restoration).
54E3
POP DE D1
Pop into DE (copy IY value to DE for use as data pointer).
54E4
LD B,14H 06 14
Load Register B with 14H (20 decimal). Will check 20 bytes of extent data (10 extent elements × 2 bytes each).
54E6
Load HL with address 5F45H (error message: "BAD FXDE").
[CHECK IF ALL EXTENT BYTES ARE ZERO - Verify truly inactive FXDE]
54E9
INC DE 13
Increment DE (skip first byte of FXDE).
54EA
INC DE 13
Increment DE again (skip second byte, now pointing to first extent element at offset +2).
54EB
LD A,(DE) 1A
Load Register A with byte pointed to by DE (extent element byte).
54EC
OR A B7
OR Register A with itself to test if zero.
54ED
If Not Zero (extent byte is non-zero but FXDE claims inactive), jump to 54D8H to report "BAD FXDE" error.
54EF
Decrement B and loop back to 54EAH to check next byte. Loops through all 20 extent bytes.
[VALIDATE ACTIVE FXDE - Check that extents exist and are properly formatted]
54F1
Call subroutine at 579EH. Loads or processes extent chain for this FXDE.
54F4
LD A,(HL) 7E
Load Register A with byte pointed to by HL (extent validation result or flag).
54F5
OR A B7
OR Register A with itself to test status.
54F6
LD (HL),00H 36 00
Store 00H at (HL) to clear the flag or marker.
54F8
LD A,58H 3E 58
Load Register A with 58H (error code for FXDE extent error).
54FA
If Zero (extent validation failed), call 5829H to report error with code 58H.
[VALIDATE BACKWARD LINKAGE TO PRIMARY ENTRY]
54FD
LD A,(IY+01H) FD 7E 01
Load Register A with byte at (IY+01H) (FXDE's backward DEC code, points to primary entry or previous FXDE).
5500
LD (527BH),A 32 7B 52
Store Register A at 527BH (save for comparison).
5503
Call subroutine at 5893H. Loads the directory entry that this FXDE claims to link back to.
5506
Load HL with address 5F6FH (error message: "FXDE HAS BAD BACK DEC CODE").
5509
If Not Zero (referenced entry not found), jump to 54D8H to report bad back-link error.
550B
BIT 4,(IY+00H) FD CB 00 66
Test bit 4 of byte at (IY+00H) (active flag of the entry we linked back to).
550F
Load HL with address 5FACH (error message: "FXDE LINKS BACK TO INACTIVE FDE").
5512
If Zero (linked entry is inactive), jump to 54D8H to report error. Active FXDE shouldn't link to inactive entry.
[VERIFY FORWARD LINKAGE - Check that parent entry links to this FXDE]
5514
LD B,05H 06 05
Load Register B with 05H (check 5 extent elements for extension index).
5516
LD A,(IY+16H) FD 7E 16
Load Register A with byte at (IY+16H) (first extent element in parent entry).
5519
CP FEH FE FE
Compare Register A with FEH (extension index marker).
551B
If No Carry (found FEH marker), jump to 5528H to validate extension index.
551D
INC IY FD 23
Increment IY to next extent element.
551F
INC IY FD 23
Increment IY again (+2 bytes per extent).
5521
Decrement B and loop back to 5516H to check next extent element.
5523
Load HL with address 5FCEH (error message: "FXDE LINKS BACK TO FDE NOT LINKING TO IT").
5526
Jump to 54D8H to report bidirectional link error (parent doesn't link forward to this FXDE).
[VALIDATE EXTENSION INDEX MATCHES]
5528
If Not Zero (byte was FFH not FEH), jump to 5523H. No extension index found in parent.
552B
LD A,(527AH) 3A 7A 52
Load Register A with byte at 527AH (current FXDE's index from earlier scan).
552E
CP (IY+17H) FD BE 17
Compare Register A with byte at (IY+17H) (extension index value in parent entry, follows FEH marker).
5531
If Not Zero (extension index doesn't match), jump to 5523H to report link error.
5533
If all validations passed, jump to 54DBH to advance to next directory entry.
5535H - Check for Files Beyond Allowed Count
This routine scans the directory buffer at 64BAH to verify that the number of files on the disk doesn't exceed the limit of 31 files (1FH). NEWDOS/80 has a maximum directory entry limit, and this routine ensures that limit is not violated. Entry: Directory data loaded at 64BAH. Exit: Error reported if more than 31 files found.
5535
LD DE,64BAH 11 BA 64
Load DE with address 64BAH (start of directory buffer containing file entry status bytes).
5538
LD B,00H 06 00
Load Register B with 00H. B will count the number of active file entries found.
[SCAN DIRECTORY ENTRIES - Count active files]
553A
LD A,(DE) 1A
[SCAN LOOP START] Load Register A with byte at address pointed to by DE (directory entry status byte).
553B
OR A B7
OR Register A with itself to test if zero (inactive entry).
553C
INC DE 13
Increment DE to point to next directory entry status byte.
553D
If Zero (entry is inactive/empty), jump to 554AH to increment counter and continue scan without error.
553F
LD A,B 78
Load Register A with Register B (current file count).
5540
CP 1FH FE 1F
Compare Register A with 1FH (31 decimal, maximum allowed files in NEWDOS/80).
5542
If Zero (already at 31 files), jump to 554AH to continue without incrementing. Prevents overflow past limit check.
5544
Load HL with address 5D6AH (error message for too many files or invalid directory condition).
5547
Call error handler at 583FH to report the directory overflow error.
554A
INC B 04
Increment Register B (file counter). Counts both active and the position past 31st file.
554B
If Not Zero (B hasn't wrapped to 00H, more entries to check), loop back to 553AH. Scans all 256 possible directory slots.
554D
RET C9
Return to caller after completing directory entry count scan.
554EH - Granule Allocation Error Analysis
This is the main granule allocation error analysis routine. It scans through the allocation tracking buffer at 65BAH checking each granule's status bits to identify and report various allocation errors. The routine uses bit flags to determine error types: bit 7=locked-out, bit 6=allocated in GAT, bit 5=assigned to file, bit 4=cross-linked. By examining combinations of these bits, it can detect conditions like granules allocated but unassigned, granules free but assigned, locked-out granules improperly marked, and cross-linked files. Entry: Allocation tracking buffer populated at 65BAH. Exit: All allocation errors reported, statistics displayed.
554E
LD HL,65BAH 21 BA 65
Load HL with address 65BAH (start of allocation tracking buffer). Each byte represents one granule's status.
5551
LD DE,0000H 11 00 00
Load DE with 0000H. DE will serve as the granule number counter (0-65535).
5554
LD (527DH),DE ED 53 7D 52
Store DE at 527DH-527EH (save granule counter, also used for statistics accumulation).
5558
LD (527FH),HL 22 7F 52
Store HL at 527FH-5280H (save current buffer pointer for later retrieval).
[CHECK GRANULE STATUS BITS - Analyze bit pattern to determine error type]
555B
BIT 7,(HL) CB 7E
Test bit 7 of byte at (HL) in tracking buffer. Bit 7 = granule is locked-out (bad sector or reserved).
555D
If Zero (not locked-out), jump to 5579H to check for normal allocation errors.
[GRANULE IS LOCKED-OUT - Check for inconsistent status]
555F
BIT 6,(HL) CB 76
Test bit 6 of (HL). Bit 6 = granule marked as allocated in GAT.
5561
If Zero (locked-out but NOT allocated in GAT), jump to 556DH to handle different error case.
5563
BIT 5,(HL) CB 6E
Test bit 5 of (HL). Bit 5 = granule assigned to file's extent chain.
5565
If Zero (locked-out, allocated, but NOT assigned to file), jump to 5611H to advance to next granule. This combination might be valid or transitional.
5568
LD DE,5D82H 11 82 5D
Load DE with address 5D82H to point to "***** GRANULE LOCKED OUT, BUT ASSIGNED TO FILE(S)".
556B
Jump to 5596H to report this critical error (locked-out granule that is both allocated and assigned).
[LOCKED-OUT BUT NOT ALLOCATED IN GAT]
556D
LD DE,5E4DH 11 4D 5E
Load DE with address 5E4DH (error message: "***** GRANULE LOCKED OUT, BUT FREE").
5570
BIT 5,(HL) CB 6E
Test bit 5 of (HL) (assigned to file flag).
5572
If Zero (locked-out, free in GAT, NOT assigned), jump to 5596H to report "LOCKED OUT BUT FREE" error.
5574
LD DE,5E70H 11 70 5E
Load DE with address 5E70H (error message: "***** GRANULE LOCKED OUT, BUT FREE AND ASSIGNED TO FILE(S)").
5577
Jump to 5596H to report this triple-error condition (locked-out, marked free, but assigned).
[GRANULE NOT LOCKED-OUT - Check normal allocation status]
5579
BIT 6,(HL) CB 76
Test bit 6 of (HL) (allocated in GAT flag).
557B
If Zero (NOT allocated in GAT), jump to 558EH to check if improperly assigned.
[GRANULE ALLOCATED IN GAT - Check if assigned to files]
557D
LD DE,5DB4H 11 B4 5D
Load DE with address 5DB4H (error message: "***** GRANULE ALLOCATED BUT NOT ASSIGNED TO ANY FILE").
5580
BIT 5,(HL) CB 6E
Test bit 5 of (HL) (assigned to file flag).
5582
If Zero (allocated in GAT but NOT assigned to any file), jump to 5596H to report lost cluster error.
5584
BIT 4,(HL) CB 66
Test bit 4 of (HL). Bit 4 = granule assigned to multiple files (cross-linked).
5586
If Zero (allocated, assigned, NOT cross-linked), jump to 5611H to advance. This is the correct state - no error.
5589
LD DE,5E15H 11 15 5E
Load DE with address 5E15H (error message: "***** GRANULE ALLOCATED, BUT ASSIGNED TO MULTIPLE FILES").
558C
Jump to 5596H to report cross-linking error (serious corruption).
[GRANULE FREE IN GAT - Should not be assigned to files]
558E
BIT 5,(HL) CB 6E
Test bit 5 of (HL) (assigned to file flag).
5590
If Zero (free in GAT and NOT assigned), jump to 5611H. This is correct state - no error.
5593
LD DE,5DE9H 11 E9 5D
Load DE with address 5DE9H (error message: "***** GRANULE FREE, BUT ASSIGNED TO FILE(S)").
[REPORT ALLOCATION ERROR - Display error message and granule number]
5596
LD HL,(527DH) 2A 7D 52
Load HL with 16-bit value at 527DH-527EH (current granule number being checked).
5599
Call subroutine at 584DH to display error message (DE=message address) with granule number (HL).
559C
LD HL,(527FH) 2A 7F 52
Load HL with 16-bit value at 527FH-5280H (restore buffer pointer to current granule).
559F
BIT 5,(HL) CB 6E
Test bit 5 of (HL) (assigned to file flag).
55A1
If Zero (granule NOT assigned to file), jump to 560EH to advance to next granule without file detail scan.
[SCAN FOR FILES USING THIS GRANULE - Find which file(s) reference this granule]
55A4
XOR A AF
Clear Register A to 00H.
55A5
LD (5279H),A 32 79 52
Store 00H at 5279H (initialize directory entry counter).
55A8
LD (527AH),A 32 7A 52
Store 00H at 527AH (initialize extension index).
55AB
Call subroutine at 586AH to load next directory entry into IY.
55AE
If Not Zero (no more directory entries), jump to 560EH to finish this granule and move to next.
55B1
LD A,(IY+00H) FD 7E 00
Load Register A with byte at (IY+00H) (directory entry flags/type byte).
55B4
AND 90H E6 90
AND Register A with 90H (mask bits 7 and 4: extension flag and active flag).
55B6
CP 10H FE 10
Compare Register A with 10H (active primary entry: bit 4=1, bit 7=0).
55B8
If Not Zero (not an active primary entry, either inactive or extension), jump to 5608H to advance to next entry.
[CHECK FILE'S EXTENT CHAIN FOR THIS GRANULE - Scan all 5 extent elements]
55BB
LD B,05H 06 05
Load Register B with 05H (5 extent elements to check per directory entry).
55BD
LD A,(IY+16H) FD 7E 16
[EXTENT LOOP] Load Register A with byte at (IY+16H) (extent element high byte, starts at offset +22).
55C0
CP FEH FE FE
Compare Register A with FEH (extension index marker or terminator).
55C2
If No Carry (A ≥ FEH, empty extent or extension index), jump to 55F8H to handle extension.
55C4
Call subroutine at 5758H to decode extent element into starting granule (DE) and count (C).
55C7
If Zero (extent decode failed), jump to 55D4H to skip to next extent element.
[CHECK IF PROBLEM GRANULE IS IN THIS EXTENT RANGE]
55C9
LD HL,(527DH) 2A 7D 52
Load HL with 16-bit value at 527DH-527EH (the problem granule number we're searching for).
55CC
RST 18H DF
Call RST 18H vector (ROM routine for 16-bit compare: CP HL,DE). Compares problem granule against extent start.
55CD
If Zero (exact match, problem granule is first in extent), call 55DCH to display file information.
55D0
INC DE 13
Increment DE (check next granule in extent).
55D1
DEC C 0D
Decrement C (granules remaining in extent).
55D2
If Not Zero (more granules in extent), loop back to 55CCH to check next granule number.
[ADVANCE TO NEXT EXTENT ELEMENT]
55D4
INC IY FD 23
Increment IY by 1 byte.
55D6
INC IY FD 23
Increment IY again (total +2, advance to next extent element).
55D8
Decrement B (extent counter) and jump to 55BDH if not zero. Loop through all 5 extents.
55DA
Jump to 5608H to advance to next directory entry.
55DCH - Display File Using Problem Granule
This subroutine displays the filename and extent information for a file that uses the problem granule. It's called when the granule allocation scanner finds a file referencing a granule that has allocation errors. The routine displays the entry number, filename with extension, and EOF marker. Entry: IY points to directory entry, (5279H) contains entry number. Exit: File information displayed.
55DC
Call subroutine at 5A90H which creates dynamic jumps for I/O routing.
55DF
LD B,0AH 06 0A
Load Register B with 0AH (10 spaces for formatting/alignment).
55E1
Call subroutine at 59A3H to output B spaces for indentation.
55E4
LD A,(5279H) 3A 79 52
Load Register A with byte at 5279H (directory entry number, 0-31).
55E7
Call subroutine at 5B01H to convert entry number in A to ASCII and display it.
55EA
LD B,03H 06 03
Load Register B with 03H (3 spaces).
55EC
Call subroutine at 59AEH to output 3 spaces.
55EF
Call subroutine at 57AEH to display the filename (8 characters) and extension (3 characters) from directory entry.
55F2
Call subroutine at 597AH to output carriage return/line feed.
55F5
Jump to 5AADH to restore all register pairs and then RETurn.
[HANDLE EXTENSION INDEX - Follow extension chain to check more extents]
55F8
If Not Zero (extent byte was FFH, true terminator with no extension), jump to 5608H to advance to next entry.
55FA
LD A,(IY+17H) FD 7E 17
Load Register A with byte at (IY+17H) (extension index following FEH marker).
55FD
LD (527AH),A 32 7A 52
Store Register A at 527AH (save extension index for FXDE lookup).
5600
Call subroutine at 5893H to load the FXDE (extension directory entry) specified by index in A.
5603
If Not Zero (extension not found or invalid), jump to 5608H to skip to next entry.
5606
Jump back to 55BBH to check the 5 extent elements in this FXDE for the problem granule.
[ADVANCE TO NEXT DIRECTORY ENTRY]
5608
Call subroutine at 58BDH to advance IY to next directory entry.
560B
Jump back to 55A5H to continue scanning directory entries for this problem granule.
[OUTPUT SEPARATOR LINE AND ADVANCE TO NEXT GRANULE]
560E
Call subroutine at 597AH to output carriage return/line feed (blank line after granule error details).
5611H - Advance to Next Granule in Scan
This routine advances the granule counter and buffer pointer to the next granule in the allocation tracking scan. It also checks if we've scanned beyond the valid disk space and returns when complete. Entry: HL points to current granule in buffer, DE contains granule number. Exit: Pointers advanced, returns if scan complete.
5611
LD DE,(527DH) ED 5B 7D 52
Load DE with 16-bit value at 527DH-527EH (current granule counter).
5615
LD HL,(5270H) 2A 70 52
Load HL with 16-bit value at 5270H-5271H (total sectors on disk, calculated during initialization).
5618
INC DE 13
Increment DE (advance granule counter to next granule number).
5619
DEC HL 2B
Decrement HL (maximum valid sector/granule number).
561A
OR A B7
Clear Carry flag (prepare for SBC).
561B
SBC HL,DE ED 52
Subtract DE from HL with borrow (HL = max_sector - current_granule). If negative, we've scanned beyond disk end.
561D
LD HL,(527FH) 2A 7F 52
Load HL with 16-bit value at 527FH-5280H (current buffer pointer).
5620
INC HL 23
Increment HL (advance buffer pointer to next granule's status byte).
5621
If No Carry (more granules to check, within disk bounds), jump back to 5554H to continue granule allocation scan.
5624
RET C9
Return to caller. All granules have been scanned and reported.
5625H - Display File Directory Listing
This routine generates a formatted directory listing showing all active files on the disk. For each file, it displays the entry number, filename with extension, protection flags (System/Invisible), EOF position, extent count, and sector count. The display is formatted with proper spacing and uses symbols to indicate special file attributes. Entry: Directory data loaded. Exit: Complete file listing displayed.
5625
Call subroutine at 597AH to output carriage return/line feed (blank line before directory listing).
5628
LD A,FFH 3E FF
Load Register A with FFH (255, marker value).
562A
LD (527BH),A 32 7B 52
Store FFH at 527BH (initialize backward link variable to invalid value).
562D
XOR A AF
Clear Register A to 00H.
562E
LD (5279H),A 32 79 52
Store 00H at 5279H (initialize directory entry counter).
5631
LD (527AH),A 32 7A 52
Store 00H at 527AH (initialize extension index).
[DIRECTORY LISTING MAIN LOOP - Scan all entries]
5634
Call subroutine at 586AH to load next directory entry into IY.
5637
If Not Zero (no more entries), jump to 597AH to output final CR/LF and return. Exit point when listing complete.
563A
LD A,(IY+00H) FD 7E 00
Load Register A with byte at (IY+00H) (directory entry flags/type byte).
563D
AND 90H E6 90
AND Register A with 90H (mask for extension and active flags).
563F
CP 10H FE 10
Compare Register A with 10H (active primary file entry).
5641
If Not Zero (not active primary entry), jump to 5715H to skip to next entry.
[DISPLAY ENTRY NUMBER AND FILENAME]
5644
Call subroutine at 57B1H to display the filename (8 chars) and extension (3 chars).
5647
LD B,0EH 06 0E
Load Register B with 0EH (14 spaces for column alignment).
5649
Call subroutine at 59A3H to output 14 spaces.
[DISPLAY FILE ATTRIBUTES - System and Invisible flags]
564C
LD A,53H 3E 53
Load Register A with 53H (ASCII 'S' for System file flag).
564E
BIT 6,(IY+00H) FD CB 00 76
Test bit 6 of byte at (IY+00H) (System file flag).
5652
If Not Zero (file is System file), call 5A27H to output 'S' character.
5655
LD A,49H 3E 49
Load Register A with 49H (ASCII 'I' for Invisible file flag).
5657
BIT 3,(IY+00H) FD CB 00 5E
Test bit 3 of byte at (IY+00H) (Invisible file flag).
565B
If Not Zero (file is Invisible), call 5A27H to output 'I' character.
[DISPLAY EOF RECORD NUMBER - Shows file size]
565E
LD DE,4296H 11 96 42
Load DE with value 4296H (ROM routine address or comparison value for EOF calculation).
5661
LD L,(IY+10H) FD 6E 10
Load Register L with byte at (IY+10H) (EOF record number low byte at offset +16).
5664
LD H,(IY+11H) FD 66 11
Load Register H with byte at (IY+11H) (EOF record number high byte at offset +17).
5667
RST 18H DF
Call RST 18H (ROM compare routine: CP HL,DE). Compares EOF record with threshold value.
5668
If Zero (EOF record equals threshold), jump to 568EH to skip EOF adjustment.
566A
LD L,(IY+12H) FD 6E 12
Load Register L with byte at (IY+12H) (EOF byte offset low at offset +18).
566D
LD H,(IY+13H) FD 66 13
Load Register H with byte at (IY+13H) (EOF byte offset high at offset +19).
5670
RST 18H DF
Call RST 18H (compare HL,DE). Checks EOF byte offset.
5671
If Not Zero (EOF byte offset differs from threshold), jump to 567AH to display protection level.
5673
LD A,(IY+00H) FD 7E 00
Load Register A with byte at (IY+00H) (entry flags).
5676
AND 07HAND 00000111 E6 07
AND Register A with 07H (mask lower 3 bits: protection level 0-7).
5678
If Zero (protection level 0, no protection), jump to 568EH to skip protection display.
[DISPLAY PROTECTION LEVEL - P=n format]
567A
LD A,50H 3E 50
Load Register A with 50H (ASCII 'P' for Protection indicator).
567C
Call 5A27H to output 'P' character.
567F
LD A,3DH 3E 3D
Load Register A with 3DH (ASCII '=' equals sign).
5681
Call 5A27H to output '=' character.
5684
LD A,(IY+00H) FD 7E 00
Load Register A with byte at (IY+00H) (entry flags).
5687
AND 07HAND 00000111 E6 07
AND Register A with 07H (extract protection level 0-7).
5689
ADD 30H C6 30
Add 30H to Register A (convert binary digit to ASCII: 0→'0', 1→'1', etc).
568B
Call 5A27H to output protection level digit.
[DISPLAY EOF POSITION - Format: "EOF = nnnn/nn"]
568E
LD B,15H 06 15
Load Register B with 15H (21 spaces for column alignment).
5690
Call subroutine at 59A3H to output 21 spaces.
5693
Load HL with address 5FF9H (message string: "EOF = ").
5696
Call subroutine at 5984H to display the "EOF = " label.
5699
LD E,(IY+14H) FD 5E 14
Load Register E with byte at (IY+14H) (ERN - End Record Number low byte at offset +20).
569C
LD D,(IY+15H) FD 56 15
Load Register D with byte at (IY+15H) (ERN high byte at offset +21).
569F
LD A,(IY+03H) FD 7E 03
Load Register A with byte at (IY+03H) (EBN - End Byte Number at offset +3, 0-255).
56A2
OR A B7
OR Register A with itself to test if zero (record fully used).
56A3
If Zero (EBN=0, record is full), jump to 56A6H without adjustment.
56A5
DEC DE 1B
Decrement DE (adjust record number if partial record). EOF record = ERN - 1 when EBN > 0.
56A6
Call subroutine at 5B2BH to convert DE (record number) to ASCII decimal and format for display.
56A9
Call subroutine at 599BH to display the formatted record number.
56AC
LD A,2FH 3E 2F
Load Register A with 2FH (ASCII '/' slash separator).
56AE
Call 5A27H to output '/' character between record and byte numbers.
56B1
LD E,(IY+03H) FD 5E 03
Load Register E with byte at (IY+03H) (EBN - End Byte Number).
56B4
Call subroutine at 5B29H to convert E (byte number) to ASCII decimal.
56B7
Call 599BH to display the byte number.
[COUNT EXTENTS AND SECTORS - Calculate file statistics]
56BA
LD B,26H 06 26
Load Register B with 26H (38 spaces for column positioning before extent/sector counts).
56BC
Call subroutine at 59A3H to output 38 spaces.
56BF
LD DE,0000H 11 00 00
Load DE with 0000H. DE will accumulate total sector count for this file.
56C2
LD C,E 4B
Load Register C with Register E (00H). C will count number of extents.
56C3
LD B,05H 06 05
Load Register B with 05H (5 extent elements to process per directory entry).
[EXTENT COUNTING LOOP]
56C5
LD A,(IY+16H) FD 7E 16
[EXTENT LOOP START] Load Register A with byte at (IY+16H) (extent element high byte, starting at offset +22).
56C8
CP FEH FE FE
Compare Register A with FEH (extension marker or empty extent indicator).
56CA
If No Carry (A ≥ FEH, empty or extension), jump to 56E0H to handle extension case.
56CC
INC C 0C
Increment C (count this extent).
56CD
LD A,(IY+17H) FD 7E 17
Load Register A with byte at (IY+17H) (extent element low byte contains sector count in bits 0-4).
56D0
AND 1FHAND 00011111 E6 1F
AND Register A with 1FH (mask lower 5 bits to extract sector count: 0-31 sectors per extent).
56D2
INC A 3C
Increment Register A (actual sector count = masked value + 1, range 1-32).
56D3
ADD A,E 83
Add Register A to Register E (accumulate sector count in DE).
56D4
LD E,A 5F
Load Register E with Register A (store updated low byte).
56D5
If No Carry (sum < 256), jump to 56D8H to skip high byte increment.
56D7
INC D 14
Increment Register D (propagate carry to high byte of sector count).
56D8
INC IY FD 23
Increment IY by 1 byte.
56DA
INC IY FD 23
Increment IY again (advance +2 to next extent element).
56DC
Decrement B (extent counter) and loop to 56C5H if not zero. Process all 5 extent elements.
56DE
Jump to 56EAH to display extent and sector counts.
[HANDLE EXTENSION ENTRY - Follow chain to count additional extents]
56E0
If Not Zero (extent byte was FFH, terminator with no extension), jump to 56EAH to finish counting.
56E2
LD A,(IY+17H) FD 7E 17
Load Register A with byte at (IY+17H) (extension index following FEH marker).
56E5
Call subroutine at 5893H to load FXDE entry specified by extension index in A.
56E8
If Zero (extension found and loaded), jump back to 56C3H to count extents in this FXDE.
[DISPLAY EXTENT AND SECTOR COUNTS]
56EA
PUSH DE D5
Push DE (total sector count) onto stack for later use.
56EB
LD E,C 59
Load Register E with Register C (extent count).
56EC
Call subroutine at 5B29H to convert extent count to ASCII.
56EF
Call subroutine at 599BH to display extent count.
56F2
LD HL,6000H 21 00 60
Load HL with address 6000H (message string: "EXTS").
56F5
Call subroutine at 5984H to display " EXTS" label.
56F8
LD B,2FH 06 2F
Load Register B with 2FH (47 spaces for column alignment).
56FA
Call subroutine at 59A3H to output 47 spaces.
56FD
POP HL E1
Pop HL from stack (retrieve total sector count).
56FE
LD A,05H 3E 05
Load Register A with 05H (field width for sector count display).
5700
Call subroutine at 5AD0H to convert HL to ASCII decimal with specified field width.
5703
EX DE,HL EB
Exchange DE and HL (move formatted string pointer to DE for display).
5704
Call subroutine at 5B2BH to finalize sector count formatting.
5707
Call subroutine at 599BH to display sector count.
570A
LD HL,6006H 21 06 60
Load HL with address 6006H (message string: " SECTORS").
570D
Call subroutine at 5977H to display " SECTORS" label and carriage return/line feed.
[MARK ENTRY AS PROCESSED]
5710
LD HL,(527FH) 2A 7F 52
Load HL with 16-bit value at 527FH-5280H (pointer to current entry's status in tracking buffer).
5713
SET 0,(HL) CB C6
Set bit 0 of byte at (HL). Marks this entry as having been displayed in directory listing.
[ADVANCE TO NEXT DIRECTORY ENTRY]
5715
Call subroutine at 58BDH to advance to next directory entry.
5718
Jump back to 562EH to continue directory listing loop. [MAIN LISTING LOOP]
571BH - Display Final Disk Statistics Summary
This routine generates the final summary statistics showing total free granules and locked-out granules on the disk. It scans through the entire allocation tracking buffer, counting granules in each state by examining status bits. Uses the alternate register set (EXX) to maintain a separate counter for locked-out granules while the primary registers track free granules. The results are displayed with descriptive labels. Entry: Allocation tracking buffer at 65BAH contains final status. Exit: Statistics displayed, routine returns.
571B
LD DE,0000H 11 00 00
Load DE with 0000H. DE will count free granules (neither locked-out nor allocated).
571E
PUSH DE D5
Push DE (0000H) onto stack. This will initialize the alternate DE' register.
571F
EXX D9
Exchange to alternate register set (BC', DE', HL'). Now using shadow registers.
5720
LD BC,(5270H) ED 4B 70 52
Load BC' with 16-bit value at 5270H-5271H (total sectors on disk). BC' will be the loop counter.
5724
LD HL,65BAH 21 BA 65
Load HL' with address 65BAH (allocation tracking buffer start).
5727
POP DE D1
Pop from stack into DE' (initializes locked-out counter to 0000H).
[SCAN ALL GRANULES - Count free and locked-out]
5728
BIT 7,(HL) CB 7E
[STATISTICS LOOP START] Test bit 7 of byte at (HL') in tracking buffer. Bit 7 = locked-out granule.
572A
If Not Zero (granule is locked-out), jump to 5733H to increment locked-out counter.
572C
BIT 6,(HL) CB 76
Test bit 6 of (HL'). Bit 6 = granule allocated in GAT.
572E
If Not Zero (granule is allocated), jump to 5736H to advance without counting as free.
5730
INC DE 13
Increment DE (free granule counter in primary register set).
5731
Jump to 5736H to advance to next granule.
[INCREMENT LOCKED-OUT COUNTER]
5733
EXX D9
Switch to primary register set.
5734
INC DE 13
Increment DE (locked-out granule counter in primary set).
5735
EXX D9
Switch back to alternate register set to continue scan.
[ADVANCE TO NEXT GRANULE]
5736
INC HL 23
Increment HL' (advance buffer pointer to next granule status byte).
5737
DEC BC 0B
Decrement BC' (granule counter).
5738
LD A,B 78
Load Register A with Register B' (high byte of counter).
5739
OR C B1
OR Register A with Register C' (low byte). Tests if BC'=0000H.
573A
If Not Zero (more granules to check), loop back to 5728H to continue scanning.
[DISPLAY FREE GRANULES COUNT]
573C
Call subroutine at 5B2BH to convert DE (free granule count) to ASCII decimal string.
573F
Call subroutine at 599BH to display the free granule count.
5742
LD HL,600FH 21 0F 60
Load HL with address 600FH (message string: " FREE GRANULES.").
5745
Call subroutine at 5984H to display the label.
[DISPLAY LOCKED-OUT GRANULES COUNT]
5748
EXX D9
Switch to alternate register set to access locked-out counter in DE'.
5749
Call subroutine at 5B2BH to convert DE' (locked-out count) to ASCII.
574C
Call subroutine at 599BH to display the locked-out granule count.
574F
LD HL,6024H 21 24 60
Load HL with address 6024H (message string: " LOCKED-OUT GRANULES.").
5752
Call subroutine at 5977H to display label and carriage return/line feed.
5755
Jump to 597AH to output final CR/LF and return to caller.
5758H - Decode Extent Element to Granule Range
This critical subroutine decodes a 2-byte extent element into its component parts: starting granule number (returned in DE) and granule count (returned in C). NEWDOS/80 extent elements encode the starting lump number and offset within lump in the high byte, and the granule count in the low 5 bits of the low byte. The routine validates that the starting position is within valid disk bounds and performs the arithmetic to calculate the absolute starting granule. Entry: A=extent high byte, (IY+17H)=extent low byte. Exit: Z flag=error, NZ=success with DE=start granule, C=count.
5758
LD HL,5261H 21 61 52
Load HL with address 5261H (offset +1 in drive specification, likely tracks per side or density indicator).
575B
CP (HL) BE
Compare Register A (extent high byte) with byte at (HL). Validates extent high byte against drive parameter.
575C
LD E,A 5F
Load Register E with Register A (save extent high byte for processing).
575D
Load HL with address 5EDEH (error message: "EXTENT'S STARTING LUMP # TOO LARGE").
5760
If No Carry (extent high byte ≥ drive parameter, invalid), jump to 5784H to return error (Z flag set).
[DECODE LUMP NUMBER AND OFFSET]
5762
LD A,(5265H) 3A 65 52
Load Register A with byte at 5265H (offset +5 in drive spec, granules-per-track).
5765
LD C,A 4F
Load Register C with Register A (save granules-per-track for calculation).
5766
LD D,(IY+17H) FD 56 17
Load Register D with byte at (IY+17H) (extent element low byte).
5769
LD A,D 7A
Load Register A with Register D (copy low byte for bit manipulation).
576A
AND 0E0HAND 11100000 E6 E0
AND Register A with E0H (11100000b, mask upper 3 bits). These bits encode the lump number (0-7).
576C
RLCA 07
Rotate Register A left. Shifts lump bits right by rotating left 3 times total.
576D
RLCA 07
Rotate Register A left again.
576E
RLCA 07
Rotate Register A left third time. Now A contains lump number (0-7) in lower 3 bits.
576F
Load HL with address 5F01H (error message: "EXTENT'S STARTING GRAN'S OFFSET IN LUMP TOO BIG").
5772
CP C B9
Compare Register A (lump number) with Register C (granules-per-track). Validates lump number.
5773
If No Carry (lump number ≥ granules-per-track, invalid), jump to 5784H to return error.
[CALCULATE STARTING GRANULE NUMBER - (lump * granules_per_track) + offset]
5775
LD L,A 6F
Load Register L with Register A (lump number).
5776
LD H,00H 26 00
Load Register H with 00H. Now HL contains lump number as 16-bit value.
5778
LD A,D 7A
Load Register A with Register D (extent low byte again).
5779
LD D,H 54
Load Register D with Register H (00H). Now DE contains offset in E.
577A
ADD HL,DE 19
[MULTIPLY LOOP] Add DE to HL. Performs multiplication: HL = lump × granules_per_track by repeated addition.
577B
DEC C 0D
Decrement C (loop counter, initially granules-per-track).
577C
If Not Zero (more iterations needed), loop back to 577AH. After loop, HL = lump × granules_per_track.
577E
EX DE,HL EB
Exchange DE and HL. Now DE contains the base granule number for this lump.
577F
AND 1FHAND 00011111 E6 1F
AND Register A with 1FH (00011111b, mask lower 5 bits). Extracts granule count from extent low byte (0-31 sectors).
5781
LD C,A 4F
Load Register C with Register A (granule count extracted from extent).
5782
INC C 0C
Increment C. Actual count = encoded value + 1 (range 1-32 granules per extent).
5783
RET C9
Return with NZ flag set (success). DE = starting granule number, C = granule count.
[ERROR RETURN - Invalid extent element]
5784
XOR A AF
Clear Register A to 00H. Sets Z flag to indicate error condition.
5785
RET C9
Return with Z flag set (error). HL contains error message address.
5786H - Calculate Directory Entry Checksum
This subroutine calculates a checksum for a directory entry by XORing and rotating bytes from the entry. The checksum is computed over 11 bytes starting at offset +5 in the directory entry (the filename and extension area). The result is used to detect directory corruption or verify entry integrity. Entry: IY points to directory entry. Exit: Checksum stored at 527CH.
5786
PUSH IY FD E5
Push IY onto stack (save directory entry pointer).
5788
PUSH BC C5
Push BC onto stack (preserve caller's BC register).
5789
LD B,0BH 06 0B
Load Register B with 0BH (11 decimal, number of bytes to checksum: 8-char filename + 3-char extension).
578B
XOR A AF
Clear Register A to 00H. A will accumulate the checksum value.
[CHECKSUM CALCULATION LOOP]
578C
XOR (IY+05H) FD AE 05
[CHECKSUM LOOP START] XOR Register A with byte at (IY+05H) (directory entry byte, starting at filename offset +5). Accumulates XOR of all bytes.
578F
RLCA 07
Rotate Register A left through carry. Mixes bits to create better checksum distribution.
5790
INC IY FD 23
Increment IY (advance to next byte in directory entry).
5792
Decrement B and jump to 578CH if not zero. Loops through all 11 bytes (filename + extension).
5794
If Not Zero (checksum is non-zero), jump to 5797H to store it.
5796
INC A 3C
Increment Register A. Prevents zero checksum (changes 00H to 01H), ensuring all entries have non-zero checksums.
5797
LD (527CH),A 32 7C 52
Store Register A at 527CH (save calculated checksum for later validation).
579A
POP BC C1
Restore BC from stack.
579B
POP IY FD E1
Restore IY from stack (directory entry pointer).
579D
RET C9
Return to caller.
579EH - Validate Entry Against Stored Checksum
This routine retrieves a previously stored checksum from the directory tracking buffer and compares it against the current directory entry. Used to verify that an entry matches what was expected or to detect if entries have been modified. Entry: (527AH) contains entry index, (527CH) contains calculated checksum. Exit: Z flag set if match, NZ if mismatch.
579E
LD A,(527AH) 3A 7A 52
Load Register A with byte at 527AH (directory entry index or extension index).
57A1
LD HL,64BAH 21 BA 64
Load HL with address 64BAH (directory tracking buffer containing stored checksums).
57A4
ADD A,L 85
Add Register A (entry index) to Register L. Calculates offset into tracking buffer.
57A5
LD L,A 6F
Load Register L with Register A (updated low byte of address).
57A6
If No Carry (no overflow from low byte), jump to 57A9H to skip high byte increment.
57A8
INC H 24
Increment Register H (propagate carry to high byte). Now HL points to stored checksum for this entry.
57A9
LD A,(527CH) 3A 7C 52
Load Register A with byte at 527CH (calculated checksum from 5786H).
57AC
CP (HL) BE
Compare Register A with byte at (HL) (stored checksum). Sets Z flag if equal, NZ if different.
57AD
RET C9
Return with flags set to indicate match (Z) or mismatch (NZ).
57AEH - Display Entry Number and Filename
Helper routine that first calls the entry number display, then falls through to display the filename and extension from the directory entry pointed to by IY. Entry: IY points to directory entry. Exit: Entry number and filename displayed.
57AE
Call subroutine at 5867H to display the directory entry number from (5279H).
57B1H - Display Filename and Extension
This routine formats and displays a file's name and extension from a directory entry. It outputs the 8-character filename, suppressing trailing spaces, optionally adds a slash separator if an extension exists, then outputs the 3-character extension. The routine handles padding and formatting to produce clean filename display like "FILENAME/EXT" or just "FILENAME" if no extension. Entry: IY points to directory entry at offset +5 (filename start). Exit: Filename and extension displayed.
57B1
PUSH IY FD E5
Push IY onto stack (save directory entry pointer).
57B3
PUSH BC C5
Push BC onto stack (preserve caller's registers).
[DISPLAY 8-CHARACTER FILENAME - Skip trailing spaces]
57B4
LD B,08H 06 08
Load Register B with 08H (8 characters in filename).
57B6
LD A,(IY+05H) FD 7E 05
[FILENAME LOOP START] Load Register A with byte at (IY+05H) (filename character at offset +5).
57B9
CP 20H FE 20
Compare Register A with 20H (ASCII space character).
57BB
If Not Zero (character is not space), call 5A27H to output the character.
57BE
INC IY FD 23
Increment IY (advance to next filename character).
57C0
Decrement B and loop to 57B6H if not zero. Processes all 8 filename characters.
[CHECK IF EXTENSION EXISTS - Add slash separator if needed]
57C2
LD A,(IY+05H) FD 7E 05
Load Register A with byte at (IY+05H) (first character of 3-char extension at offset +13).
57C5
CP 20H FE 20
Compare Register A with 20H (space). Empty extension starts with space.
57C7
If Zero (extension is empty, starts with space), jump to 57CEH to skip extension display.
57C9
LD A,2FH 3E 2F
Load Register A with 2FH (ASCII '/' slash separator between filename and extension).
57CB
Call 5A27H to output '/' character.
[DISPLAY 3-CHARACTER EXTENSION]
57CE
LD B,03H 06 03
Load Register B with 03H (3 characters in extension).
57D0
LD A,(IY+05H) FD 7E 05
[EXTENSION LOOP START] Load Register A with byte at (IY+05H) (extension character).
57D3
CP 20H FE 20
Compare Register A with 20H (space).
57D5
If Not Zero (not space), call 5A27H to output extension character.
57D8
INC IY FD 23
Increment IY (advance to next extension character).
57DA
Decrement B and loop to 57D0H if not zero. Processes all 3 extension characters.
57DC
POP BC C1
Restore BC from stack.
57DD
POP IY FD E1
Restore IY from stack (directory entry pointer).
57DF
RET C9
Return to caller.
57E0H - Load Directory Sector Into Buffer
This routine loads a specific directory sector into the buffer pointed to by HL. It calculates the appropriate track and sector number from the entry index in Register A, checks if the sector is already loaded in the current track buffer, and reads it from disk if necessary. The routine handles the mapping from entry index to physical disk location. Entry: A=entry index (0-31), HL=destination buffer. Exit: Z flag set if success, NZ if error, IY points to entry in buffer.
57E0
PUSH DE D5
Push DE onto stack (preserve caller's registers).
57E1
PUSH BC C5
Push BC onto stack.
57E2
AND 1FHAND 00011111 E6 1F
AND Register A with 1FH (mask lower 5 bits, ensures entry index is 0-31).
57E4
LD E,A 5F
Load Register E with Register A (save masked entry index).
57E5
LD D,00H 16 00
Load Register D with 00H. Now DE contains entry index as 16-bit value.
57E7
LD A,(64D9H) 3A D9 64
Load Register A with byte at 64D9H (sectors-per-track parameter from disk specification).
57EA
ADD 07H C6 07
Add 07H to Register A. This adjusts for directory placement (directory starts at sector 7 or similar offset).
57EC
CP E BB
Compare Register A with Register E (check if entry index exceeds adjusted sector count).
57ED
If Carry (entry index too large), jump to 57FEH to return with success flag (skip load).
[CALCULATE BUFFER ADDRESS AND READ SECTOR]
57EF
INC DE 13
Increment DE twice to account for directory structure.
57F0
INC DE 13
Second increment.
57F1
PUSH HL E5
Push HL (destination buffer pointer) onto stack.
57F2
LD HL,(5274H) 2A 74 52
Load HL with 16-bit value at 5274H-5275H (base sector buffer address calculated during init).
57F5
ADD HL,DE 19
Add DE to HL (calculate exact buffer position for this sector).
57F6
LD (520AH),HL 22 0A 52
Store HL at 520AH-520BH (update current sector buffer pointer).
57F9
POP HL E1
Restore HL from stack (destination buffer).
57FA
Call subroutine at 5801H to read the directory sector from disk into buffer.
57FD
XOR A AF
Clear Register A to 00H (sets Z flag for success).
57FE
POP BC C1
Restore BC from stack.
57FF
POP DE D1
Restore DE from stack.
5800
RET C9
Return to caller with Z flag indicating success/failure.
5801H - Read Sector and Check for Write-Back
This routine reads a sector from disk via the DOS sector I/O routine. After reading, it checks if the read was successful and whether any modifications were made to the data (if in repair mode). If errors need to be written back, it marks the sector for write-back by setting a flag. Entry: HL=buffer address, sector parameters set. Exit: Z flag set if success, error code in A if failure.
5801
Call subroutine at 5820H to read sector from disk into buffer at HL.
5804
If Zero (read successful), jump to 580CH to check if write-back needed.
5806
CP 06H FE 06
Compare Register A with 06H (specific error code, possibly "sector not found").
5808
If Not Zero (different error, not code 06H), jump to 5ABEH (fatal error handler).
580B
RET C9
Return with error code 06H (non-fatal error, possibly acceptable condition).
[CHECK IF SECTOR NEEDS TO BE WRITTEN BACK]
580C
LD A,(526EH) 3A 6E 52
Load Register A with byte at 526EH (error/repair flag). Non-zero indicates errors were found and repaired.
580F
OR A B7
OR Register A with itself to test if zero.
5810
RET NZ C0
Return if Not Zero (repairs already flagged, no need to flag again).
5811
INC A 3C
Increment Register A (set flag to 01H).
5812
LD (526EH),A 32 6E 52
Store 01H at 526EH. Marks that repairs have been made and sectors need to be written back.
5815H - Display "Writing Corrections" Message
Simple routine that displays a message to inform the user that corrected data is being written back to disk. This is called when the program is in repair mode and has found and fixed errors. Entry: Called when write-back is about to occur. Exit: Message displayed.
5815
PUSH HL E5
Push HL onto stack (preserve registers).
5816
PUSH BC C5
Push BC onto stack.
5817
Load HL with address 5D06H to point to "***** AT LEAST ONE DIRECTORY SECTOR UNPROTECTED".
581A
Call subroutine at 5977H to display message with CR/LF.
581D
POP BC C1
Restore BC from stack.
581E
POP HL E1
Restore HL from stack.
581F
RET C9
Return to caller.
5820H - Disk Sector Read via DOS
This is a thin wrapper around the DOS disk I/O routine. It sets up the sector read parameters by storing the buffer address and command block address, then jumps to the ROM DOS sector read routine at 4436H. The DOS uses a command block at 5200H containing drive parameters. Entry: HL=buffer address for sector data. Exit: Z flag set if success, error code in A if failure.
5820
LD (5203H),HL 22 03 52
Store HL at 5203H-5204H (buffer address field in DOS command block). DOS will read sector data into this buffer.
5823
LD DE,5200H 11 00 52
Load DE with address 5200H (DOS command block containing drive number, track, sector, etc.).
5826
Jump to ROM routine at 4436H (DOS disk sector read routine). Does not return here; routine returns directly to 5801H's caller.
5829H - Display File Error with Entry Number
This routine displays an error message associated with a specific file entry. It stores an error code, displays the filename and entry number, then shows the error message. Used when errors are detected during file validation that need to be associated with a specific directory entry. Entry: A=error code, IY points to directory entry, HL=error message. Exit: Error details displayed.
5829
Load HL with address 5F8BH (storage location for error code, likely part of error message template).
582C
LD (HL),A 77
Store Register A (error code) at address 5F8BH. Saves error code for display or processing.
582D
DEC HL 2B
Decrement HL to point to 5F8AH to the message "FPDE HAS BAD CODE IN 'HIT' SECTOR".
582E
PUSH BC C5
Push BC onto stack (preserve registers).
582F
PUSH IY FD E5
Push IY onto stack (save directory entry pointer).
5831
Call subroutine at 57AEH to display entry number and filename from directory entry.
5834
LD B,03H 06 03
Load Register B with 03H (3 spaces for formatting).
5836
Call subroutine at 59AEH to output 3 spaces.
5839
POP IY FD E1
Restore IY from stack.
583B
POP BC C1
Restore BC from stack.
583C
LD A,(5279H) 3A 79 52
Load Register A with byte at 5279H (directory entry number).
583FH - Display Error Message with Entry Number
General error message display routine that shows an entry number followed by the error message text. This is the common path for displaying most disk checker errors. Entry: A=entry number (or data value), HL=message address. Exit: Message displayed with entry number.
583F
PUSH BC C5
Push BC onto stack (preserve caller's BC).
5840
Call subroutine at 5B01H to convert entry number in A to ASCII and display it.
5843
LD B,03H 06 03
Load Register B with 03H (3 spaces).
5845
Call subroutine at 59AEH to output 3 spaces for formatting.
5848
Call subroutine at 5977H to display message at HL with CR/LF.
584B
POP BC C1
Restore BC from stack.
584C
RET C9
Return to caller.
584DH - Display Granule Number with Lump/Offset Format
This routine converts a granule number into lump and offset format for display. NEWDOS/80 uses lumps (groups of granules) for organization, so granule numbers are often displayed as "lump,offset" (e.g., "5,3" for granule 43 when lumps are 8 granules each). The routine performs division to extract the lump number and offset. Entry: HL=granule number, DE=message address. Exit: Granule displayed in lump,offset format followed by message.
584D
PUSH BC C5
Push BC onto stack (preserve registers).
584E
LD A,(5265H) 3A 65 52
Load Register A with byte at 5265H (offset +5 in drive spec, granules-per-track which equals granules-per-lump).
5851
Call subroutine at 5AF0H. Performs division: HL / A, returns quotient in HL (lump number), remainder in A (offset).
5854
PUSH AF F5
Push AF onto stack (save remainder/offset for later display).
5855
LD A,L 7D
Load Register A with Register L (lump number low byte).
5856
Call 5B01H to convert lump number to ASCII and display it.
5859
LD A,2CH 3E 2C
Load Register A with 2CH (ASCII ',' comma separator).
585B
Call 5A27H to output comma character.
585E
POP AF F1
Restore AF from stack (retrieve offset value).
585F
ADD 30H C6 30
Add 30H to Register A (convert offset 0-7 to ASCII '0'-'7').
5861
Call 5A27H to output offset digit.
5864
EX DE,HL EB
Exchange DE and HL. Moves error message address from DE to HL for display.
5865
Jump to 5843H to display spaces and error message, then return.
5867H - Display Entry Number from Counter
Simple helper routine that loads the current entry number from memory and falls through to display it. Entry: Entry number stored at 5279H. Exit: Entry number displayed.
5867
LD A,(5279H) 3A 79 52
Load Register A with byte at 5279H (current directory entry counter/number).
586AH - Load Next Directory Entry into IY
This critical routine advances through the directory by loading the next entry into the IY index register. It handles the complex mapping of entry numbers to physical disk sectors, managing track and sector buffers. The routine extracts the track number (upper 5 bits) and sector offset (lower 5 bits) from the entry counter, loads the appropriate sector if not already cached, and positions IY to point to the entry within the sector. Entry: (5279H) contains entry number. Exit: IY points to entry, Z flag clear if success, set if no more entries.
586A
PUSH DE D5
Push DE onto stack (preserve caller's registers).
586B
LD D,A 57
Load Register D with Register A (save entry number for bit manipulation).
586C
AND 0E0HAND 11100000 E6 E0
AND Register A with E0H (11100000b, mask upper 3 bits which encode track/page number).
586E
LD E,A 5F
Load Register E with Register A (save masked track bits).
586F
LD A,D 7A
Load Register A with Register D (restore full entry number).
5870
AND 1FHAND 00011111 E6 1F
AND Register A with 1FH (00011111b, mask lower 5 bits which are entry offset within sector, 0-31).
5872
LD D,A 57
Load Register D with Register A. Now D=entry offset (0-31), E=track bits.
5873
LD A,(5272H) 3A 72 52
Load Register A with byte at 5272H (currently loaded track number in buffer at 61BAH).
5876
CP D BA
Compare Register A with Register D (check if needed track is already loaded).
5877
If Zero (track already loaded in buffer), jump to 5888H to set IY pointer and return.
[LOAD NEW TRACK INTO BUFFER AT 61BAH]
5879
PUSH HL E5
Push HL onto stack (preserve caller's HL).
587A
LD A,D 7A
Load Register A with Register D (track/page number to load).
587B
LD HL,61BAH 21 BA 61
Load HL with address 61BAH (primary directory sector buffer).
587E
Call subroutine at 57E0H to load directory sector for entry number A into buffer at HL.
5881
POP HL E1
Restore HL from stack.
5882
If Not Zero (load error), jump to 5891H to return with error indication.
5884
LD A,D 7A
Load Register A with Register D (track number just loaded).
5885
LD (5272H),A 32 72 52
Store Register A at 5272H. Updates current track variable to reflect newly loaded track.
[SET IY TO POINT TO ENTRY IN BUFFER]
5888
LD IY,61BAH FD 21 BA 61
Load IY with base address 61BAH (start of directory sector buffer).
588C
LD D,00H 16 00
Load Register D with 00H. Prepares DE for addition (E already contains entry offset within sector).
588E
ADD IY,DE FD 19
Add DE to IY. Now IY points to the specific directory entry within the buffer.
5890
XOR A AF
Clear Register A to 00H. Sets Z flag to indicate success.
5891
POP DE D1
Restore DE from stack.
5892
RET C9
Return to caller. Z flag indicates success (clear) or no more entries (set).
5893H - Load Extension Entry (FXDE) into IY
Similar to 586AH but specifically for loading File eXtension Directory Entries (FXDEs). FXDEs are stored in a different sector buffer (62BAH) than primary entries. This routine handles the sector mapping for extension entries, checking if the needed sector is already loaded, and positions IY to the extension entry. Entry: A=extension index. Exit: IY points to FXDE, Z flag clear if success.
5893
PUSH DE D5
Push DE onto stack.
5894
LD D,A 57
Load Register D with Register A (save extension index).
5895
AND 0E0HAND 11100000 E6 E0
AND Register A with E0H (mask upper 3 bits for sector/track number).
5897
LD E,A 5F
Load Register E with Register A (save sector bits).
5898
LD A,D 7A
Load Register A with Register D (restore full index).
5899
AND 1FHAND 00011111 E6 1F
AND Register A with 1FH (mask lower 5 bits for entry offset 0-31).
589B
LD D,A 57
Load Register D with Register A. D=offset, E=sector bits.
589C
LD A,(5272H) 3A 72 52
Load Register A with byte at 5272H (track loaded in primary buffer 61BAH).
589F
CP D BA
Compare Register A with Register D (check if extension track matches primary buffer track).
58A0
If Zero (same track as primary buffer), jump to 5888H to use buffer at 61BAH.
[CHECK EXTENSION BUFFER AT 62BAH]
58A2
LD IY,62BAH FD 21 BA 62
Load IY with address 62BAH (extension/secondary directory buffer).
58A6
LD A,(5273H) 3A 73 52
Load Register A with byte at 5273H (track loaded in extension buffer 62BAH).
58A9
CP D BA
Compare Register A with Register D (check if extension track already loaded in secondary buffer).
58AA
If Zero (already loaded), jump to 588CH to calculate IY pointer and return.
[LOAD EXTENSION SECTOR INTO 62BAH BUFFER]
58AC
PUSH HL E5
Push HL onto stack.
58AD
LD A,D 7A
Load Register A with Register D (extension track to load).
58AE
LD HL,62BAH 21 BA 62
Load HL with address 62BAH (extension buffer).
58B1
Call 57E0H to load extension sector into buffer at 62BAH.
58B4
POP HL E1
Restore HL from stack.
58B5
If Not Zero (load error), jump to 5891H to return with error.
58B7
LD A,D 7A
Load Register A with Register D (track just loaded).
58B8
LD (5273H),A 32 73 52
Store Register A at 5273H. Updates extension buffer track variable.
588C
Jump to 588CH (note: this appears to be a relative jump back to earlier code at 588CH for setting IY offset).
58BDH - Advance to Next Directory Entry
Simple increment routine that advances the directory entry counter. It adds 20H (32 decimal) to move to the next "block" of entries, implementing wraparound detection. Used to iterate through all directory entries. Entry: (5279H) contains current entry number. Exit: Entry number incremented, NC flag if wrapped around.
58BD
LD A,(5279H) 3A 79 52
Load Register A with byte at 5279H (current directory entry counter).
58C0
ADD 20H C6 20
Add 20H (32 decimal) to Register A. Advances to next entry or block of entries.
58C2
RET NC D0
Return if No Carry (addition didn't overflow past FFH). Normal advancement case.
58C3
INC A 3C
Increment Register A. Handles wraparound case after overflow.
58C4
RET C9
Return to caller with updated entry counter.
58C5H - Write Corrected Data Back to Disk
This is the disk write-back routine that executes when the user confirms they want to write corrections. It verifies the user has a writable disk, then systematically writes back all sectors that were loaded and potentially modified during checking. The routine uses the allocation tracking buffer to determine which sectors need to be written, marks sectors for write in the DOS command block, and calls the DOS write routine. Entry: A contains user's response code. Exit: All corrected sectors written or error occurred.
58C5
LD (58FBH),A 32 FB 58
Store Register A at 58FBH (self-modifying code location, saves user response or mode flag).
[CHECK IF DISK IS WRITE-PROTECTED]
58C8
LD A,(436DH) 3A 6D 43
Load Register A with byte at 436DH (ROM/DOS location containing drive status or write-protect flag).
58CB
BIT 4,A CB 67
Test bit 4 of Register A (write-protect status bit).
58CD
LD A,37H 3E 37
Load Register A with 37H (error code 37H for write-protected disk).
58CF
If Zero (write-protect bit not set, disk IS write-protected), jump to 5ABEH (error handler) to abort.
[PREPARE FOR SECTOR WRITE LOOP]
58D2
LD A,(526FH) 3A 6F 52
Load Register A with byte at 526FH (granules-per-track × 5, calculated during init).
58D5
OR A B7
OR Register A with itself to test if zero.
58D6
LD B,A 47
Load Register B with Register A (loop counter for number of sectors to potentially write).
58D7
Load HL with address 5D35H (message pointer, possibly "WRITING SECTORS" or error message).
58DA
If Zero (no sectors to write, invalid count), jump to 5AC5H to display message and exit.
58DD
LD HL,61BAH 21 BA 61
Load HL with address 61BAH (sector buffer base address).
58E0
LD (5203H),HL 22 03 52
Store HL at 5203H-5204H (DOS command block buffer address field).
58E3
LD HL,(5274H) 2A 74 52
Load HL with 16-bit value at 5274H-5275H (sector buffer pointer base).
58E6
LD DE,5200H 11 00 52
Load DE with address 5200H (DOS command block for sector I/O).
58E9
LD C,00H 0E 00
Load Register C with 00H. C will count sectors successfully written.
[SECTOR WRITE LOOP - Write each modified sector]
58EB
LD (520AH),HL 22 0A 52
[WRITE LOOP START] Store HL at 520AH-520BH (update sector buffer pointer in command block).
58EE
Call ROM disk I/O routine at 4436H to read current sector into buffer.
58F1
If Zero (read successful), jump to 58F8H to check if sector needs writing.
58F3
CP 06H FE 06
Compare Register A with 06H (specific error code).
58F5
If Not Zero (different error, serious problem), jump to 5ABEH (error handler).
[CHECK IF SECTOR NEEDS TO BE WRITTEN - Compare mode flags]
58F8
LD A,43H 3E 43
Load Register A with 43H (ASCII 'C' or comparison value).
58FA
CP 00H FE 00
Compare Register A with 00H. Note: This instruction is self-modified at 58C5H, comparing with user's mode flag.
58FC
If Not Zero (mode check failed), jump to 591AH to skip to next sector without writing.
58FE
LD A,C 79
Load Register A with Register C (sectors written counter).
58FF
CP 02H FE 02
Compare Register A with 02H. Checks if at least 2 sectors have been written.
5901
If Carry (fewer than 2 sectors written), jump to 591AH to continue without processing.
[CLEAR INACTIVE ENTRIES - Zero out unused directory slots]
5903
EXX D9
Switch to alternate register set (preserve primary registers).
5904
LD HL,(5203H) 2A 03 52
Load HL' with 16-bit value at 5203H-5204H (sector buffer address from DOS command block).
5907
LD B,08H 06 08
Load Register B' with 08H (8 groups of entries to check).
5909
LD DE,0020H 11 20 00
[CLEAR LOOP START] Load DE' with 0020H (32 bytes per directory entry).
590C
BIT 4,(HL) CB 66
Test bit 4 of byte at (HL') (active flag in directory entry).
590E
If Not Zero (entry is active), jump to 5916H to skip clearing and advance to next.
[ZERO OUT INACTIVE ENTRY]
5910
LD (HL),00H 36 00
[ZERO LOOP] Store 00H at address pointed to by HL' (clear one byte of inactive entry).
5912
DEC E 1D
Decrement E' (byte counter within entry).
5913
INC HL 23
Increment HL' (advance to next byte).
5914
If Not Zero (more bytes to clear in this entry), loop to 5910H. Clears all 32 bytes.
5916
ADD HL,DE 19
Add DE' to HL' (skip remaining bytes, advance to next entry).
5917
Decrement B' and loop to 5909H if not zero. Process all 8 entry groups.
5919
EXX D9
Switch back to primary register set.
[WRITE SECTOR TO DISK]
591A
EX DE,HL EB
Exchange DE and HL. Swaps command block address with buffer pointer.
591B
SET 0,(HL) CB C6
Set bit 0 of byte at (HL) in command block. Marks sector for WRITE operation (bit 0=1 means write, 0 means read).
591D
EX DE,HL EB
Exchange back, restoring original register contents.
591E
LD (520AH),HL 22 0A 52
Store HL at 520AH-520BH (update buffer pointer in command block).
5921
Call ROM routine at 443CH (DOS sector WRITE operation). Writes buffer to disk.
5924
EX DE,HL EB
Exchange DE and HL again.
5925
RES 0,(HL) CB 86
Reset bit 0 of byte at (HL). Clears write flag, returning command block to read mode.
5927
EX DE,HL EB
Exchange back to original state.
5928
If Not Zero (write error returned from 443CH), jump to 5ABEH (error handler).
592B
INC C 0C
Increment C (successfully written sector counter).
592C
INC HL 23
Increment HL (advance buffer pointer to next sector).
592D
Decrement B (sector counter) and jump to 58EBH if not zero. Loop through all sectors.
592F
Jump to 52B7H after all sectors written. This likely restarts the checking process or cleans up and exits.
5932H - Program Completion and User Response Handler
Main completion routine that displays completion message and prompts user for next action: N=exit, Y=check another disk, I=reinitialize, W=write corrections, C=clean directory.
5932
Load HL with 5B71H ("FUNCTION COMPLETED" message).
5935
Call 59D1H (handle screen/printer mode switching).
5938
Call 595FH (display message + blank line).
593B
[PROMPT LOOP] Load HL with 5BB0H (menu prompt with options).
593E
Call 59B6H (display prompt, get user input).
5941
LD SP,61BAH 31 BA 61
Reset stack pointer to 61BAH.
5944
CP 4EH FE 4E
Compare A with 4EH ('N' for exit).
5946
JP Z,402DH CA 2D 40
If 'N', jump to ROM DOS warm start at 402DH.
5949
CP 59H FE 59
Compare A with 59H ('Y' for another disk).
594B
JP Z,5297H CA 97 52
If 'Y', jump to 5297H (restart with same settings).
594E
CP 57H FE 57
Compare A with 57H ('W' for write).
5950
JP Z,58C5H CA C5 58
If 'W', jump to 58C5H (write corrections to disk).
5953
CP 43H FE 43
Compare A with 43H ('C' for clean).
5955
JP Z,58C5H CA C5 58
If 'C', jump to 58C5H (clean directory).
5958
CP 49H FE 49
Compare A with 49H ('I' for initialize).
595A
If invalid response, loop back to 593BH.
595C
JP 5281H C3 81 52
If 'I', jump to 5281H (complete reinitialize).
595FH - Display Message and Add Blank Line
595F
Call 5977H (display message with CR/LF).
5962
Jump to 597AH (output additional CR/LF).
5964H - Multi-Line Display with Paging
5964
PUSH HL E5
[LINE LOOP] Push HL (save pointer).
5965
Call 59B6H (display line).
596B
CP 4EH FE 4E
Compare with 'N'.
596D
RET Z C8
Return if 'N' pressed.
596E
CP 59H FE 59
Compare with 'Y'.
5970
If not 'Y', loop back.
5974H - Display Message via Mode Handler
5974
Call 59D1H (mode switching).
5977H - Display ETX-Terminated String with CR/LF
5977
Call 5984H (display string).
597AH - Output CR/LF
597A
LD B,01H 06 01
Load B with 01H (one iteration).
597C
LD A,0DH 3E 0D
[CR LOOP] Load A with 0DH (CR).
597E
Call 5A27H (output character).
5984H - Display ETX-Terminated String
Core string output. Displays characters until ETX (03H) found.
5984
LD A,(HL) 7E
[LOOP] Load character from HL.
5985
CP 03H FE 03
Compare with 03H (ETX).
5987
INC HL 23
Increment HL.
5988
RET Z C8
Return if ETX found.
5989
Call 5A27H (output character).
598EH - Cursor Home Sequence
5991
LD A,1FH 3E 1F
Load A with 1FH (home).
5996H - Output Escape
5996
LD A,1CH 3E 1C
Load A with 1CH (ESC).
599BH - Display B Characters
599B
LD A,(HL) 7E
[LOOP] Load byte from HL.
599C
INC HL 23
Increment HL.
59A0
Loop for B characters.
59A3H - Intelligent Space Output
Outputs spaces with screen width checking.
59A3
LD A,40H 3E 40
Load A with 40H (64, screen width).
59A5
SUB B 90
Subtract requested spaces.
59A6
LD B,A 47
Save adjusted value.
59A7
LD A,(5278H) 3A 78 52
Load current column from 5278H.
59AA
SUB B 90
Calculate available space.
59AB
LD B,A 47
Spaces that fit.
59AC
RET C D8
Return if would exceed line.
59AD
RET Z C8
Return if no spaces needed.
59AEH - Output B Spaces
59AE
LD A,20H 3E 20
Load A with 20H (space).
59B6H - Display Prompt and Get Input
Shows prompt, gets user input, converts to uppercase.
59B6
Display prompt at HL.
59B9
LD HL,5220H 21 20 52
Load HL with 5220H (input buffer).
59BC
LD B,40H 06 40
Max 64 characters.
59BE
PUSH HL E5
Save buffer pointer.
59BF
CALL 0040H CD 40 00
ROM keyboard input routine.
59C2
LD A,(HL) 7E
[CONVERT LOOP] Load character.
59C3
Convert to uppercase.
59C6
CP 0DH FE 0D
Check for CR.
59C8
LD (HL),A 77
Store converted char.
59C9
INC HL 23
Next position.
59CC
POP HL E1
Restore buffer start.
59CD
LD A,(HL) 7E
Get first character.
59CE
CP 0DH FE 0D
Check if empty input.
59D0
RET C9
Return with char in A.
59D1H - Mode Switching Handler
Switches between screen (00H) and printer (05H) output modes.
59D2
LD A,(5A6DH) 3A 6D 5A
Load current mode from 5A6DH.
59D5
CP 05H FE 05
Check if printer mode.
59D7
LD A,05H 3E 05
Prepare printer mode.
59D9
Jump to mode handler.
59DBH - Switch to Screen Mode
59DC
LD A,(5A6DH) 3A 6D 5A
Load current mode.
59DF
CP 00H FE 00
Check if screen mode.
59E1
LD A,00H 3E 00
Prepare screen mode.
59E3
Skip if already in mode.
59E5
PUSH AF F5
Save new mode.
59E6
Output CR/LF before switch.
59E9
POP AF F1
Restore new mode.
59EA
LD (5A6DH),A 32 6D 5A
Store new mode at 5A6DH.
59ED
POP AF F1
Restore caller's AF.
59EFH - Check Line Counter
59EF
LD A,(5277H) 3A 77 52
Load line counter from 5277H.
59F2
CP 3CH FE 3C
Compare with 3CH (60 lines).
59F4
RET C9
Return with Z if at limit.
59F5H - Screen Paging Handler
Resets line counters, outputs form feeds for printer if needed.
59F5
LD A,(5A6DH) 3A 6D 5A
Check output mode.
59F8
CP 05H FE 05
Printer mode?
59FA
Skip form feeds if printer.
59FC
LD A,(5277H) 3A 77 52
Load line counter.
59FF
DEC A 3D
Check if at 1.
5A00
Jump if not at limit.
5A02
LD A,(5276H) 3A 76 52
Load page flag.
5A06
Skip form feeds if zero.
5A08
LD B,06H 06 06
6 form feeds.
5A0A
LD A,0DH 3E 0D
CR character.
5A0C
[FF LOOP] Output character.
5A11
LD A,3CH 3E 3C
Reset to 60 lines.
5A13
LD (5277H),A 32 77 52
Store line counter.
5A16
LD A,40H 3E 40
Reset column to 64.
5A18
LD (5278H),A 32 78 52
Store at 5278H.
5A1CH - Output C Blank Lines
5A1C
[LOOP] Check page limit.
5A1F
RET Z C8
Return if at limit.
5A23
DEC C 0D
Decrement counter.
5A27H - Character Output with Line Tracking
Main character output routine. Tracks cursor position, handles line wrapping, manages CR specially.
5A27
PUSH HL E5
Save registers.
5A29
PUSH AF F5
Save character.
5A2A
LD HL,5278H 21 78 52
Point to column counter.
5A2D
CP 0DH FE 0D
Check if CR.
5A34
DEC (HL) 35
Decrement column counter.
5A35
Exit if not at line end.
5A37
LD A,40H 3E 40
[LINE END] Reset to 64.
5A39
CP (HL) BE
Check current position.
5A3A
LD A,20H 3E 20
Load space.
5A3C
Output space if at 64.
5A3F
LD A,0DH 3E 0D
Load CR.
5A47
LD A,(3840H) 3A 40 38
[KEYBOARD CHECK] ROM keyboard status.
5A4A
AND 04HAND 00000100 E6 04
Test bit 2.
5A4E
LD A,(3840H) 3A 40 38
[WAIT] Check status.
5A51
AND 09H E6 09
Test bits.
5A55
LD A,(3840H) 3A 40 38
Check again.
5A58
AND 08HAND 00001000 E6 08
Test bit 3.
5A5D
POP AF F1
Restore registers.
5A61
LD A,(3840H) 3A 40 38
[BREAK] Wait for release.
5A69H - Low-Level Character Router
5A6EH - Alternate Output Entry
5A6F
CALL 003BH CD 3B 00
ROM screen output.
5A73H - Post-Output Processing
5A73
CP 0DH FE 0D
Check if CR.
5A77
LD A,40H 3E 40
Load 64.
5A79
LD HL,5278H 21 78 52
Column counter address.
5A7C
SUB (HL) 96
Calculate chars on line.
5A7D
LD HL,5278H 21 78 52
Reload address.
5A80
LD A,40H 3E 40
Load 64 again.
5A82
SUB (HL) 96
Recalculate.
5A83
Jump if line was full.
5A85
AND 3FHAND 00111111 E6 3F
Mask to 0-63.
5A89
LD A,0DH 3E 0D
Load CR.
5A8B
CALL 0033H CD 33 00
ROM screen output.
5A90H - Output Vector Setup (Self-Modifying)
Complex self-modifying code that creates dynamic jumps for I/O routing.
5A90
EX (SP),HL E3
Get return address into HL.
5A91
LD (5A9DH),HL 22 9D 5A
Self-modify JP at 5A9CH.
5A94
POP HL E1
Get original HL.
5A95
PUSH HL E5
Restore it.
5A96
PUSH DE D5
Save all registers.
5A98
PUSH IX DD E5
Save IX.
5A9A
PUSH IY FD E5
Save IY.
5A9C
JP 0000H C3 00 00
SELF-MODIFIED by 5A91H to jump to output routine.
5A9F
POP HL E1
[RETURN POINT] Get return address.
5AA0
LD (5AABH),HL 22 AB 5A
Self-modify next JP at 5AAAH.
5AA3
POP IY FD E1
Restore IY.
5AA5
POP IX DD E1
Restore IX.
5AAA
JP 0000H C3 00 00
SELF-MODIFIED by 5AA0H to return to caller.
5AAD
POP IY FD E1
[ALT PATH] Restore IY.
5AAF
POP IX DD E1
Restore IX.
5AB5H - Lowercase to Uppercase
5AB5
CP 61H FE 61
Compare with 'a'.
5AB7
RET C D8
Return if < 'a'.
5AB8
CP 7BH FE 7B
Compare with 'z'+1.
5ABA
RET NC D0
Return if > 'z'.
5ABB
SUB 20H D6 20
Convert to uppercase.
5ABEH - Fatal Error Handler
5ABE
OR 0C0HOR 11000000 F6 C0
Set fatal error bits.
5AC0
CALL 4409H CD 09 44
ROM error display.
5AC5H - Display and Terminate
5AC5
Display message at HL.
5AC8H - Program Termination
5AC8
LD HL,5B84H 21 84 5B
Load termination message address.
5ACB
JP 5935H C3 35 59
Display and return to DOS.
5ACEH - 8-Bit to BCD Entry
5ACE
LD H,00H 26 00
Extend L to 16-bit HL.
5AD0H - 16-Bit to Decimal Conversion
5AD4
LD A,H 7C
Get high digit.
5AD5
LD H,L 65
Shift result.
5AD6
LD L,C 69
Shift result.
5AD9H - Binary to BCD (Multiply Method)
5ADA
EX DE,HL EB
Number to convert in DE.
5ADB
LD C,80H 0E 80
BCD accumulator.
5ADD
LD HL,0000H 21 00 00
Clear result.
5AE0
RRCA 0F
[LOOP] Rotate multiplier.
5AE3
ADD HL,DE 19
Add to accumulator.
5AE4
SRL H CB 3C
Shift right.
5AE6
RR L CB 1D
Rotate through carry.
5AE8
RR C CB 19
Accumulate BCD.
5AED
RET C9
Return with BCD in HL,C.
5AEEH - Fixed Divisor 5 Entry
5AEE
LD A,05H 3E 05
Set divisor to 5.
5AF0H - 16-Bit Division by 8-Bit
Divides HL by A using shift-and-subtract. Returns quotient in HL, remainder in A.
5AF0
LD C,A 4F
Save divisor in C.
5AF1
LD B,10H 06 10
16 bits to process.
5AF3
XOR A AF
Clear remainder accumulator.
5AF4
ADD HL,HL 29
[DIV LOOP] Shift HL left.
5AF5
RLA 17
Rotate bit into A.
5AF6
Subtract if overflow.
5AF8
CP C B9
Compare with divisor.
5AF9
Skip if can't subtract.
5AFB
SUB C 91
Subtract divisor.
5AFC
INC L 2C
Set quotient bit.
5AFF
OR A B7
Set flags on remainder.
5B00
RET C9
Return: HL=quotient, A=remainder.
5B01H - Convert Byte to 2-Digit Hex and Display
Converts byte in A to 2-character hexadecimal ASCII string and displays it. Used for displaying entry numbers, granule numbers, etc.
5B03
LD HL,5269H 21 69 52
Load HL with 5269H (hex string output buffer).
5B06
Call 5B13H to convert byte to hex (stores 2 chars).
5B09
DEC HL 2B
Decrement HL (point to first char).
5B0A
DEC HL 2B
Decrement again.
5B0B
LD B,02H 06 02
Load B with 02H (2 characters to display).
5B0D
Call 599BH to display 2 characters.
5B13H - Convert Byte to Hex ASCII String
Converts byte in A to 2 ASCII hex digits stored at HL and HL+1. Processes high nibble then low nibble.
5B13
PUSH AF F5
Push AF (save full byte).
5B14
RRCA 0F
Rotate right to get high nibble.
5B15
RRCA 0F
Second rotation.
5B16
RRCA 0F
Third rotation.
5B17
RRCA 0F
Fourth rotation. High nibble now in bits 0-3.
5B18
Call 5B1CH to convert nibble to ASCII hex.
5B1B
POP AF F1
Restore original byte for low nibble.
5B1CH - Convert Nibble to Hex ASCII
Converts 4-bit nibble (0-F) to ASCII hex digit ('0'-'9' or 'A'-'F'). Stores result at HL and increments HL.
5B1C
AND 0FHAND 00001111 E6 0F
Mask to lower 4 bits only.
5B1E
CP 0AH FE 0A
Compare with 0AH (check if 0-9 or A-F).
5B20
If < 10, jump to add '0' offset.
5B22
ADD 07H C6 07
Add 07H for A-F range (0AH→11H, 0FH→16H).
5B24
ADD 30H C6 30
Add 30H to convert to ASCII ('0'-'9' or 'A'-'F').
5B26
LD (HL),A 77
Store ASCII hex digit at (HL).
5B27
INC HL 23
Increment HL for next digit position.
5B29H - 8-Bit to Decimal Entry Point
Helper entry point for converting 8-bit value (0-255) to decimal ASCII. Extends to 16-bit then processes.
5B29
LD D,00H 16 00
Load D with 00H. Extends E to 16-bit value in DE.
5B2BH - Convert 16-Bit to Decimal String
Converts 16-bit value in DE to decimal ASCII string with leading space suppression. Result stored at 5269H-526CH (5 digits maximum).
5B2C
Call 5B41H to convert to decimal digits.
5B2F
LD B,04H 06 04
Load B with 04H (4 leading digits to check).
5B31
LD HL,5269H 21 69 52
Load HL with 5269H (decimal string buffer).
5B34
LD A,30H 3E 30
Load A with 30H (ASCII '0').
5B36
CP (HL) BE
[SUPPRESS LOOP] Compare (HL) with '0'.
5B37
If not '0', done with suppression.
5B39
LD (HL),20H 36 20
Store 20H (space) to replace leading '0'.
5B3B
INC HL 23
Increment HL (next digit).
5B3C
Loop for up to 4 leading zeros.
5B3E
INC B 04
Increment B (adjust count).
5B3F
POP DE D1
Pop DE (was pushed as HL).
5B40
RET C9
Return with B=effective string length.
5B41H - Binary to Decimal Conversion Core
Converts 16-bit binary in DE to 5-digit decimal string using repeated division by powers of 10 (10000, 1000, 100, 10). Each division yields one decimal digit. Uses division-by-subtraction algorithm.
5B41
LD BC,5269H 01 69 52
Load BC with 5269H (output buffer pointer).
5B44
LD HL,5B69H 21 69 5B
Load HL with 5B69H (divisor table address).
5B47
LD A,04H 3E 04
Load A with 04H (4 powers of 10 to process).
5B49
LD A,04H 3E 04
Load A with 04H again (loop counter).
5B4B
EX AF,AF' 08
Exchange AF with shadow AF' (save counter).
5B4C
PUSH BC C5
[DIGIT LOOP] Save output buffer pointer.
5B4D
LD C,(HL) 4E
Load C with low byte of divisor.
5B4E
INC HL 23
Increment HL.
5B4F
LD B,(HL) 46
Load B with high byte of divisor. BC now holds divisor.
5B50
INC HL 23
Increment HL (point to next divisor).
5B51
EX DE,HL EB
Exchange DE,HL. Dividend in HL, table pointer in DE.
5B52
LD A,2FH 3E 2F
Load A with 2FH (ASCII '/' which is '0'-1).
5B54
ADD HL,BC 09
[DIV BY SUBTRACTION] Add BC to HL (subtract negative).
5B55
INC A 3C
Increment A (count divisions, '/'→'0'→'1'→...).
5B56
If Carry (no overflow), loop to subtract again.
5B59
SBC HL,BC ED 42
Subtract BC with borrow (back up one, get true remainder).
5B5B
EX DE,HL EB
Exchange back. Remainder in DE, table pointer in HL.
5B5C
POP BC C1
Restore output buffer pointer.
5B5D
LD (BC),A 02
Store ASCII digit at buffer position.
5B5E
INC BC 03
Increment output position.
5B5F
EX AF,AF' 08
Get loop counter from shadow.
5B60
DEC A 3D
Decrement digit counter.
5B61
If more digits, loop to 5B4BH.
5B63
LD A,E 7B
Load A with E (final remainder is 5th digit, 0-9).
5B64
ADD 30H C6 30
Convert binary digit to ASCII.
5B66
LD (BC),A 02
Store 5th digit at buffer.
5B67
RET C9
Return with 5-digit string at 5269H-526DH.
5B68
RET C9
Unreachable redundant RET.
5B69H - Power of 10 Divisor Table
Data table containing 16-bit divisors used by decimal conversion routine. Values stored in little-endian format (low byte, high byte). These are actually negative values (two's complement) used for division-by-addition algorithm.
5B69
DEFB F0H F0
DATA: Low byte of -10000 (D8F0H = 55536).
5B6A
DEFB D8H D8
High byte of -10000. (65536-10000=55536=D8F0H).
5B6B
DEFB 18H 18
DATA: Low byte of -1000 (FC18H = 64536).
5B6C
DEFB FCH FC
High byte of -1000. (65536-1000=64536=FC18H).
5B6D
DEFB 9CH 9C
DATA: Low byte of -100 (FF9CH = 65436).
5B6E
DEFB FFH FF
High byte of -100. (65536-100=65436=FF9CH).
5B6F
DEFB F6H F6
DATA: Low byte of -10 (FFF6H = 65526).
5B70
DEFB FFH FF
High byte of -10. (65536-10=65526=FFF6H).
Message String Data (5B71H-6039H)
All message strings in DIRCHECK are terminated with ETX (03H). Carriage returns (0DH) are embedded where multi-line messages need line breaks. This comprehensive list documents every user-visible message in the program.
[PROGRAM STATUS MESSAGES]
5B71-5B83
DEFM "FUNCTION COMPLETED" + 03H
Displayed when disk check completes successfully.
5B84-5BAF
DEFM "********************* FUNCTION TERMINATED" + 0DH + 03H
Displayed when program terminates (error or user exit).
[USER PROMPT MESSAGES]
5BB0-5BB5
DEFM "REPLY" + 0DH
Prompt header for user response menu.
5BB6-5BCA
DEFM "N TO EXIT PROGRAM" + 0DH
Menu option: exit to DOS.
5BCB-5BFA
DEFM "Y IF ANOTHER DISKETTE FOR SAME PRINTER SPECS" + 0DH
Menu option: check another disk with same settings.
5BFB-5C1D
DEFM "I FOR PROGRAM RE-INITIALIZATION" + 0DH
Menu option: restart from beginning including printer prompt.
5C1E-5C47
DEFM "W TO WRITE DIRECTOR SECTORS PROTECTED" + 0DH
Menu option: write corrections back to disk (protect directory).
5C48-5C74
DEFM "C TO CLEAN (NOT REPAIR) THE DIRECTORY" + 0DH + 03H
Menu option: clean directory without repairing GAT errors.
5C75-5C88
DEFM "OUTPUT TO PRINTER? " + 03H
Initial program prompt asking if output should go to printer.
5C89-5CAF
DEFM "WHICH DRIVE CONTAINS TARGET DISKETTE? " + 03H
Drive selection prompt (0-3).
[WARNING MESSAGES - Disk Configuration Issues]
5CB0-5CE9
DEFM "***** DISKETTE 1ST SECTOR NOT 'BOOT'. ASSUMING DIRECTORY" + 0DH
Warning when boot sector signature not found.
5CEA-5D05
DEFM "STARTS ON LUMP 17 DECIMAL." + 0DH + 03H
Continuation: assumes standard directory location.
5D06-5D34
DEFM "***** AT LEAST ONE DIRECTORY SECTOR UNPROTECTED" + 03H
Warning: directory not write-protected (could be corrupted by writes).
5D35-5D51
DEFM "***** DIRECTORY SIZE UNKNOWN" + 03H
Error: cannot determine directory size from disk parameters.
[GAT ERROR MESSAGES]
5D52-5D69
DEFM " BAD 'GAT' SECTOR BYTE" + 03H
Error in Granule Allocation Table sector.
5D6A-5D81
DEFM " BAD 'HIT' SECTOR BYTE" + 03H
Error in Hash Index Table sector.
[GRANULE ALLOCATION ERROR MESSAGES]
5D82-5DB3
DEFM "***** GRANULE LOCKED OUT, BUT ASSIGNED TO FILE(S)" + 03H
Critical: locked-out granule referenced by file (data loss risk).
5DB4-5DE8
DEFM "***** GRANULE ALLOCATED BUT NOT ASSIGNED TO ANY FILE" + 03H
Lost cluster: granule marked used but no file references it (wasted space).
5DE9-5E14
DEFM "***** GRANULE FREE, BUT ASSIGNED TO FILE(S)" + 03H
GAT inconsistency: file claims granule but GAT shows free (data loss risk).
5E15-5E4C
DEFM "***** GRANULE ALLOCATED, BUT ASSIGNED TO MULTIPLE FILES" + 03H
Cross-linking: multiple files claim same granule (severe corruption).
5E4D-5E6F
DEFM "***** GRANULE LOCKED OUT, BUT FREE" + 03H
GAT inconsistency: locked-out granule marked as free.
5E70-5EAA
DEFM "***** GRANULE LOCKED OUT, BUT FREE AND ASSIGNED TO FILE(S)" + 03H
Triple error: locked-out, free in GAT, yet assigned to file(s).
[EXTENT ERROR MESSAGES]
5EAB-5EBD
DEFM "BAD EXTENT ELEMENT" + 03H
Invalid extent element found in directory entry.
5EBE-5EDD
DEFM "EXTENT SPACE OVERFLOWS DISKETTE" + 03H
Extent references granules beyond disk capacity.
5EDE-5F00
DEFM "EXTENT'S STARTING LUMP # TOO LARGE" + 03H
Lump number in extent exceeds disk geometry.
5F01-5F30
DEFM "EXTENT'S STARTING GRAN'S OFFSET IN LUMP TOO BIG" + 03H
Granule offset within lump exceeds granules-per-track.
[FILE EXTENSION (FXDE) ERROR MESSAGES]
5F31-5F44
DEFM "BAD EXTENSION INDEX" + 03H
Extension index points to invalid directory entry.
5F45-5F4D
DEFM "BAD FXDE" + 03H
File extension entry corrupted or invalid.
5F4E-5F5B
DEFM "INACTIVE FXDE" + 03H
Extension entry referenced but marked inactive.
5F5C-5F6E
DEFM "EXTENSION NOT FXDE" + 03H
Extension index points to non-extension entry.
5F6F-5F89
DEFM "FXDE HAS BAD BACK DEC CODE" + 03H
Extension's backward link (DEC) doesn't match expected parent.
5F8A-5FAB
DEFM "FPDE HAS BAD CODE IN 'HIT' SECTOR" + 03H
File Primary Directory Entry has corruption in hash index reference.
5FAC-5FCD
DEFM "FXDE LINKS BACK TO INACTIVE FDE" + 03H
Extension links to parent that is marked inactive.
5FCE-5FF8
DEFM " FXDE LINKS BACK TO FDE NOT LINKING TO IT" + 03H
Broken bidirectional link: extension points to parent, but parent doesn't point back.
[DIRECTORY LISTING LABELS]
5FF9-5FFF
DEFM "EOF = " + 03H
Label for End-Of-File display in directory listing.
6000-6005
DEFM "EXTS" + 03H
Label for extent count in directory listing.
6006-600E
DEFM " SECTORS" + 03H
Label for sector count in directory listing.
600F-6023
DEFM " FREE GRANULES. " + 03H
Label for free granule count in statistics.
6024-6039
DEFM " LOCKED-OUT GRANULES." + 03H
Label for locked-out granule count in statistics.
[PADDING TO END OF PROGRAM]
603A-6060
NOP (multiple)
Padding bytes (00H/NOP) fill remainder of program space to end at 6060H.