TRS-80 DOS - NEWDOS/80 v2.0 for the Model III - SYS8/SYS Disassembled

Page Customization

Introduction / Summary

SYS8/SYS implements the DIR DOS command for NEWDOS/80 v2.0 on the TRS-80 Model III. The DIR command displays directory information for files on a diskette, with extensive filtering and display options. SYS8 is loaded from disk into memory at 4D00H by SYS1 (the command dispatcher) when the user enters the DIR command. The module spans from 4D00H to 51E7H (1,256 bytes).

Two Entry Paths: SYS8 handles two related commands. When Register A contains 2AH (ASCII *), the standard DIR command is invoked via 4D50H. When Register A contains 4AH (ASCII J), the "jump to directory" variant is invoked, which enters at 4D0DH and shares the DIR infrastructure.

Command Line Syntax: DIR [d:][$][n][,options] where d: is an optional drive number with colon prefix, $ enables diskette swap mode, n is an optional directory entry number (0–99), and options are single-letter filters: A (show all file attributes), S (include System files), I (include Invisible files), U (show only Updated files), P (prefix invokes Printer mode), and /ext (filter by file extension).

Display Modes: Without the A option, DIR shows a compact listing with filename, extension, and file attribute flags. With the A option, each file gets an additional detail line showing EOF offset, logical record length, record count, granule count, extent count, and attribute flags. Disk summary statistics (free tracks, free FDEs, free granules) are displayed at the end.

Printer Output: When the P option is specified (via the command prefix), SYS8 uses self-modifying code to redirect all character output from the ROM screen display routine at 0033H to the ROM printer routine at 003BH, and changes the string display vector at 508FH from JP 4467H (screen) to JP 446AH (printer). This allows the entire directory listing to be sent to the printer without modifying the core display routines.

Diskette Swap Mode: When the $ prefix is used, SYS8 modifies the instruction at 4D47H from LD HL (opcode 21H) to CALL (opcode CDH), enabling prompts to mount the source/target diskette on each directory sector read. This allows directory operations on a different diskette than the system diskette, sharing a single drive.

SYS8/SYS – Variables and Self-Modifying Code

AddressBytesPurpose
4280H16+PDRIVE Parameter Block
(pointed to by IY). Contains disk geometry: 4280H=parameter word, 4283H=max track, 4284H=sectors/track, 4285H=sectors/granule, 4289H=disk config flags.
42C0H1Default Drive Number
Read at 4D50H to initialize the drive number in Register C.
4D33H1Directory Sector Counter
[SELF-MODIFYING CODE]. The operand byte inside "LD A,00H" at 4D32H. Written by the routine at 4D34H to track which directory sector is being processed. Reset to 00H at 4D32H, then incremented by 48D4H on each call.
4D47H1Instruction Opcode
[SELF-MODIFYING CODE]. Normally contains 21H (LD HL opcode). Changed to CDH (CALL opcode) at 4DE7H when diskette swap mode ($) is active. When CDH, the instruction at 4D47H becomes CALL 4F96H, which prompts the user to mount the target diskette before each directory sector read.
4E0EH–4E10H3Extension Filter Buffer
Stores the three-character file extension entered after the / option. Used by the extension matching routine at 4F5CH–4F71H to filter directory entries.
4F35H1Granule Count Limit
[SELF-MODIFYING CODE]. The operand byte inside "CP 00H" at 4F34H. Written at 5035H with the total number of granules to scan (max track number + 8). Controls when the directory scan loop terminates.
50A8H1Character Output Vector Low Byte
[SELF-MODIFYING CODE]. The low byte of the target address inside "CALL 0033H" at 50A7H. Normally 33H (ROM screen display). Changed to 3BH at 506FH when printer output is selected, redirecting CALL 0033H to CALL 003BH (ROM printer routine).
5090H1String Display Vector Low Byte
[SELF-MODIFYING CODE]. The low byte of the target address inside "JP 4467H" at 508FH. Normally 67H (SYS0 screen string display). Changed to 6AH at 5064H when printer output is selected, redirecting JP 4467H to JP 446AH (SYS0 printer string display).
5109H–5117H15Decimal Conversion Divisor Table
Five 3-byte entries (little-endian) used by the number-to-ASCII routine at 50BFH/50C7H: +100,000 / −10,000 / −1,000 / −100 / −10. The units digit is computed by adding 30H to the remainder.
5118H–513CH37Text: Mount Prompt
"MOUNT " + 03H + " DISKETTE ON DRIVE 0 (ENTER)" + 0DH. Used at 4F96H–4FA7H to prompt for diskette swap.
513DH–5143H7Text: "SYSTEM" + 03H
Displayed as the diskette label when mounting the system diskette.
5144H–514AH7Text: "TARGET" + 03H
Displayed as the diskette label when mounting the target diskette in swap mode.
514BH–514DH3Screen Control: Clear Screen
Bytes 1CH + 1FH + 03H. Sent to the display routine to clear the screen and home the cursor before printing the directory listing header.
514EH–518BH62Disk Summary Template
"DRIVE 000 XXXXXXXXXX MM/DD/YY 000 TRKS 000 FDES 0000 GRANS" + 0DH. Template line filled in with actual disk statistics by the summary display routine at 4FDBH.
518CH–51BBH48File Detail Template (Line 2)
" 000000000 000 000000 0000 000 SIUEC....AUL" + 03H. Template filled in with file-level detail when the A option is active.
51BCH–51E6H43File Detail Header
"EOF LRL RECS GRANS EXTS SIUEC....UAL" + 0DH. Column header line displayed before detailed file listings when the A option is active.
51E7H1Terminator
00H byte marking the end of SYS8 data.

SYS8/SYS – Major Routines

AddressDescription
4D00HSYS8 Entry Point
Entry dispatcher. Checks command code in Register A: 2AH (*) routes to DIR at 4D50H, 4AH (J) routes to the jump-to-directory variant at 4D0DH.
4D0DHJ Command Handler
Handles the "J" (jump to directory entry) command variant. Parses optional parameters, reads directory sector, and processes display with column-count management.
4D32HDirectory Sector Init
Self-modifying code: loads directory sector counter (4D33H) and calls 48D4H to read the next directory sector. Returns Z if sector read succeeded.
4D43HError Exit / Cleanup
Common exit point. Pushes error code, loads cleanup address, restores error code, and either returns (if zero) or jumps to 4409H error handler.
4D50HDIR Main Parameter Parser
Parses command line: drive number prefix, $ swap mode, directory entry number (0–99), and option letters A/S/I/U/P and /ext extension filter.
4DD5HDIR Execute (Enter Key)
Called when Enter (0DH) is found after all options are parsed. Clears screen (if not printer), sets up swap mode, then dispatches to the directory scan loop.
4E11HFormat Directory Entry
Formats a single directory entry for display. Extracts filename, extension, date, attributes (S/I/U/E/C flags), and file statistics into the display template buffers.
4E86HFull Attribute Display
When the A option is active, displays the extended detail line: EOF position, LRL, record count, granule count, extent count, and file permission flags.
4F28HAdvance to Next Entry
Advances HL to the next directory entry (adds 20H) and checks for end of sector. Loads next sector when needed.
4F3BHDirectory Entry Filter
Tests each directory entry against the active filters: checks entry status byte (bits 4 and 7), System flag, Invisible flag, extension match, and Updated flag.
4F96HMount Diskette Prompt
Displays "MOUNT [label] DISKETTE ON DRIVE n (ENTER)" and waits for the Enter key. Used for diskette swap mode.
4FAFHEnd of Directory Handler
Called when all directory sectors have been scanned. Outputs final spacing and returns to the caller.
4FB8HSpace/Blank Line Handler
Outputs spacing for printer mode (extra blank lines between sections).
4FC7HColumn Header Display
Displays the "EOF LRL RECS GRANS EXTS SIUEC....UAL" header line when A option is active and the detail listing begins.
4FDBHDisk Statistics Display
Reads the directory and granule allocation table, counts free granules, free directory entries, and free tracks, then formats and displays the disk summary line.
5058HCheck for P (Printer) Option
Checks if the current command-line character is P (50H). If so, modifies the output vectors at 50A8H and 5090H to redirect all output to the printer.
506BHPause for Screen Full
When outputting to screen (50A8H=33H), displays "?" prompt and waits for Enter or Break key. Skipped when output is to printer (50A8H=3BH).
5086HOutput Space + CR
Outputs a space character (20H) followed by a carriage return (0DH).
508FHString Display Vector
JP 4467H (or JP 446AH for printer). Displays the 03H-terminated string at HL. Target address is self-modified for printer mode.
5092HOutput B Spaces
Outputs B space characters (20H) using repeated calls to 50A5H.
509AHDisplay B Characters
Displays B characters from the buffer at HL, decrementing C for each non-space character encountered.
50A4HDecrement and Print
Decrements C (column counter) and falls through to 50A5H to print the character.
50A5HCharacter Output
Saves DE and AF, calls ROM 0033H (or 003BH for printer) to output the character in Register A, then restores AF and DE.
50ADH24-bit Division
Performs 24-bit division: AHL ÷ C. Uses repeated shift-and-subtract. Called by the decimal conversion routines to extract individual digits.
50BFHFormat Number (6 digits)
Converts the 24-bit value in A:HL to a 6-digit ASCII decimal string using the divisor table at 5112H, storing digits into the template buffer at (DE).
50C4HFormat Number (4 digits)
Alternate entry for 4-digit formatting using the divisor table at 510FH.
50C7HFormat Number (Core)
Core number formatting loop. Reads 3-byte divisor entries, performs repeated subtraction to extract each decimal digit, and stores ASCII characters into the output buffer.

Disassembly

4D00H – SYS8 Entry Point and Command Dispatch

SYS8 is entered at 4D00H by SYS1 with the command code in Register A and the command-line pointer in Register HL. Register A contains 2AH (ASCII *) for the standard DIR command, or 4AH (ASCII J) for the jump-to-directory command. IY is loaded with 4280H (the PDRIVE parameter block base address) and remains set throughout SYS8 execution.

4D00
LD IY,4280H FD 21 80 42
Point Index Register IY to 4280H, the PDRIVE parameter block base address. IY remains set to this value for the entire duration of SYS8 execution. All (IY+offset) references throughout SYS8 address fields within the PDRIVE parameter block: IY+01H (4281H) = track-related parameter, IY+05H (4285H) = sectors per granule, IY+09H (4289H) = disk configuration flags.
4D04
CP 2AH FE 2A
Compare Register A (command code from SYS1) against 2AH (ASCII *). If Register A equals 2AH, the Z FLAG is set, indicating the standard DIR command was entered.
4D06
If the Z FLAG is set (command code is 2AH = DIR), JUMP to 4D50H to begin parsing the DIR command line parameters.
4D08
CP 4AH FE 4A
Compare Register A against 4AH (ASCII J). If Register A equals 4AH, the Z FLAG is set, indicating the J (jump to directory entry) command was entered.
4D0A
LD A,2AH 3E 2A
Load Register A with 2AH (NEWDOS/80 error code for "general error"). This error code will be used if neither command code matched.
4D0C
RET NZ C0
If the NZ FLAG is set (command code was neither 2AH nor 4AH), RETURN to the caller with error code 2AH in Register A. This is an invalid SYS8 invocation.

If execution reaches here, the J command (4AH) was specified. The J command parses optional parameters and then enters the directory scan loop.

4D0DH – J Command: Parse Options and Begin Scan

The J command handler. Parses the command line for the P (printer) prefix, then enters the directory entry scan with column-count management. Calls 5058H to check for the P option, then reads directory sectors and displays matching entries.

4D0D
GOSUB to 5058H to check whether the current command-line character is P (50H, printer mode). If it is, the output vectors at 50A8H and 5090H are modified to redirect output to the printer, bit 3 of Register B is set, and Register A returns with the next character. If not, Register A returns with the current character unchanged.
4D10
CP 0DH FE 0D
Compare Register A against 0DH (ASCII carriage return / Enter). If Register A equals 0DH, the Z FLAG is set, meaning the command line has ended with no further parameters.
4D12
If the NZ FLAG is set (command line continues with more characters), JUMP to 4D3DH to report a parse error (error code 34H).

The command line ended immediately after the optional P prefix. Begin the J command directory scan with C=0 (start at first directory entry) and D=0DH (13 entries per screen page).

4D14
LD C,00H 0E 00
Load Register C with 00H to initialize the column counter to zero (start of display line).
4D16
GOSUB to 5086H to output a space character (20H) followed by a carriage return (0DH), starting the display on a fresh line.
4D19
LD B,0DH 06 0D
Load Register B with 0DH (13 decimal). This sets the entries-per-page counter: 13 directory entries will be displayed before pausing for a screen-full prompt.

[MAIN DISPLAY LOOP START] – Each iteration reads one directory entry, displays it, and manages the column and page counters.

4D1B
GOSUB to 4FDBH to read the next directory entry and display the disk summary statistics. Returns Z flag set if the entry is valid, NZ if end of directory.
4D1E
If the Z FLAG is set (valid directory entry returned), JUMP to 4D2AH to increment the column counter and continue.
4D20
CP 20H FE 20
Compare Register A against 20H (space character, indicating a "blank line" separator return). If Register A equals 20H, the Z FLAG is set.
4D22
If the Z FLAG is set (separator return), JUMP to 4FB8H to handle spacing for printer mode output.
4D25
CP 08H FE 08
Compare Register A against 08H (backspace, used as a "continue next page" signal). If Register A equals 08H, the Z FLAG is set.
4D27
If the NZ FLAG is set (return code is neither valid entry, separator, nor continue signal), JUMP to 4D43H to exit with the error code in Register A.
4D29
INC B 04
INCrement Register B (entries-per-page counter) by 1. The 08H return code means "continue with next page," so adding 1 to B compensates for the DEC B at the DJNZ, keeping the page count on track.
4D2A
INC C 0C
INCrement Register C (column counter / entries-displayed counter) by 1.
4D2B
DECrement Register B (entries-per-page counter) and loop back to 4D1BH if not zero. Continues displaying entries until B reaches zero (13 entries per page).

[PAGE FULL] – B has reached zero, meaning a full page of entries has been displayed. Call the screen-full pause routine before continuing.

4D2D
GOSUB to 506BH to pause for a screen-full. If output is to the screen (50A8H = 33H), displays a "?" prompt and waits for the Enter key or Break key. If output is to the printer (50A8H = 3BH), returns immediately without pausing.
4D30
JUMP back to 4D19H to reset B to 13 and begin displaying the next page of entries. [LOOP END – returns to MAIN DISPLAY LOOP]

4D32H – Directory Sector Counter and Read

This two-instruction sequence manages the directory sector counter via self-modifying code. The immediate operand at 4D33H is written by 48D4H to track the current directory sector number. The LD A instruction loads the counter, and the CALL reads the next directory sector into the buffer.

4D32
LD A,00H 3E 00
Load Register A with the directory sector counter. The immediate value 00H at address 4D33H is [SELF-MODIFYING CODE]: it is overwritten by the routine at 48D4H each time a new directory sector is read. The value starts at 00H and increments with each directory sector processed.
4D34
LD (4D33H),A 32 33 4D
Store Register A back into the self-modifying operand at 4D33H. [SELF-MODIFYING CODE] This writes the updated directory sector counter so the next LD A,00H at 4D32H will load the current value instead of zero.

Wait — the instruction at 4D34H stores A into 4D33H, but 4D34H is LD (4D33H),A which is 32 33 4D. That means the CALL at 4D37H is the one that actually reads the sector.

4D37
GOSUB to SYS0 routine at 48D4H to read the next directory sector into the sector buffer. Uses the directory sector counter at 4D33H to determine which sector to read. Returns with Z flag set if the read was successful, NZ if an error occurred or end of directory reached.
4D3A
RET Z C8
If the Z FLAG is set (directory sector read succeeded), RETURN to the caller with success.
4D3B
JUMP to 4D43H to handle the error. Register A contains the error code from the failed sector read.

4D3DH – Parse Error Exit

Reached when the command line contains unexpected characters after the J command. Loads error code 34H (parse error) and falls through to the error exit at 4D43H.

4D3D
LD A,34H 3E 34
Load Register A with 34H (NEWDOS/80 error code for "Parse Error"). The J command line contained unexpected characters after the optional P prefix.
4D3F
JUMP to 4D43H to exit with the parse error code.

4D41H – Alternate Error Exit (Error 2FH)

Loads error code 2FH and falls through to the common error exit.

4D41
LD A,2FH 3E 2F
Load Register A with 2FH (NEWDOS/80 error code). This error path is reached from the drive number parser when the entry number exceeds the valid range.

4D43H – Common Error / Cleanup Exit

Common exit point for SYS8. Saves the error code, loads the appropriate cleanup routine address into HL, restores the error code, and either returns with success (if error code is zero) or jumps to the SYS0 error handler at 4409H.

4D43
PUSH AF F5
Save Register A (error code) and flags onto the stack.
4D44
LD HL,513DH 21 3D 51
Point Register Pair HL to 513DH, the address of the "SYSTEM" text string. This is the "mount system diskette" prompt label, used if diskette swap mode is active.
4D47
LD HL,4F96H 21 96 4F
Point Register Pair HL to 4F96H, the mount diskette prompt routine. [SELF-MODIFYING CODE] The opcode at 4D47H is normally 21H (LD HL). When diskette swap mode ($) is active, the byte at 4D47H is changed to CDH (CALL) at 4DE7H, transforming this instruction into CALL 4F96H, which prompts the user to mount the system diskette before returning. When swap mode is NOT active, this is simply LD HL,4F96H which loads an address into HL but has no side effect — the value is immediately overwritten by the POP AF below.
4D4A
POP AF F1
Restore Register A (error code) and flags from the stack.
4D4B
OR A B7
OR Register A with itself to set flags based on the error code. If A is 00H (no error), the Z FLAG is set.
4D4C
RET Z C8
If the Z FLAG is set (error code is zero = no error), RETURN to the caller with success.
4D4D
JUMP to the SYS0 error handler at 4409H. Register A contains the non-zero error code. The error handler displays the corresponding error message and returns to NEWDOS/80 READY.

4D50H – DIR Main Parameter Parser: Drive Number and Options

This is the main entry point for the DIR command (entered when command code = 2AH). It parses the command line to extract: an optional drive number with colon prefix, an optional $ diskette swap prefix, a directory entry number (0–99), and option letters. Register B accumulates the option flags (bit 0=A, bit 1=S, bit 2=I, bit 3=P, bit 4=/ext, bit 5=U, bit 6=$). Register C holds the drive number. HL points to the current position in the command line buffer.

4D50
LD A,(42C0H) 3A C0 42
Load Register A with the default drive number from the DOS parameter area at 42C0H. This is the system default drive (set at boot or by a previous PDRIVE command), used when no drive number is specified on the command line.
4D53
LD C,A 4F
Copy the default drive number from Register A to Register C. Register C holds the active drive number throughout the DIR parameter parsing.
4D54
LD B,00H 06 00
Load Register B with 00H to initialize the option flags register. Each bit in B will be set as options are parsed: bit 0=A (show all attributes), bit 1=S (system files), bit 2=I (invisible files), bit 3=P (printer), bit 4=/ext (extension filter), bit 5=U (updated files), bit 6=$ (swap mode).

Begin parsing the command line. First check for an optional drive number prefix (digit followed by colon).

4D56
LD A,(HL) 7E
Load Register A with the current character from the command line at position HL.
4D57
CP 3AH FE 3A
Compare Register A against 3AH (ASCII :). If Register A equals 3AH, the Z FLAG is set, indicating a colon (drive number separator) is present at the current position.
4D59
If the NZ FLAG is set (no colon found at this position), JUMP to 4D5CH to skip the colon and continue parsing.
4D5B
INC HL 23
INCrement HL by 1 to advance past the colon character in the command line.

Check for the $ (diskette swap mode) prefix character.

4D5C
LD A,(HL) 7E
Load Register A with the current character from the command line at position HL.
4D5D
CP 24H FE 24
Compare Register A against 24H (ASCII $). If Register A equals 24H, the Z FLAG is set, indicating diskette swap mode is requested.
4D5F
If the NZ FLAG is set (no $ found), JUMP to 4D64H to skip swap mode setup and continue parsing.
4D61
SET 6,B CB F0
SET bit 6 of Register B to mark diskette swap mode ($) as active in the option flags.
4D63
INC HL 23
INCrement HL by 1 to advance past the $ character in the command line.

Now parse the directory entry number (one or two decimal digits, 0–99). The entry number is converted from ASCII to binary in Register C.

4D64
LD A,(HL) 7E
Load Register A with the current character from the command line at position HL.
4D65
SUB 30H D6 30
SUBtract 30H (ASCII 0) from Register A, converting an ASCII digit character to its binary value (0–9). If the character was not a digit, the result will be negative or ≥ 10.
4D67
CP 0AH FE 0A
Compare Register A against 0AH (10 decimal). If Register A < 0AH, the CARRY FLAG is set, confirming the character was a valid decimal digit (0–9). If Register A ≥ 0AH, the NO CARRY FLAG is set (not a digit).
4D69
If the NO CARRY FLAG is set (character is not a digit), JUMP to 4D89H to skip the number and continue parsing option letters.
4D6B
LD C,A 4F
Copy the first digit value (0–9) from Register A into Register C. C now holds the drive/entry number so far (tens digit or single digit).
4D6C
INC HL 23
INCrement HL by 1 to advance to the next command-line character.
4D6D
LD A,(HL) 7E
Load Register A with the next character from the command line at position HL.
4D6E
SUB 30H D6 30
SUBtract 30H (ASCII 0) from Register A to convert the second character to binary.
4D70
CP 0AH FE 0A
Compare Register A against 0AH. If the CARRY FLAG is set (A < 10), this is a valid second digit.
4D72
If the NO CARRY FLAG is set (not a digit), JUMP to 4D85H. Only one digit was found, so C already holds the correct single-digit entry number.

Two digits found. Multiply the first digit (in C) by 10 and add the second digit (in A). Uses a repeated-addition loop: C × 10 = C + C×9 (add C to itself 9 times).

4D74
LD E,A 5F
Save the second digit (units value, 0–9) from Register A into Register E.
4D75
LD A,C 79
Load Register A with the first digit (tens value) from Register C.
4D76
LD D,09H 16 09
Load Register D with 09H (9 decimal). This sets the loop counter for multiplying the first digit by 10 through repeated addition: A = A + C × 9 times, effectively computing C × 10.

[MULTIPLY LOOP START] – Computes A = first_digit × 10 by adding C to A nine times. A starts equal to C, so after 9 additions A = C × 10.

4D78
ADD A,C 81
ADD Register C (first digit value) to Register A. Each iteration adds C once, accumulating C × (D+1).
4D79
If the CARRY FLAG is set (result exceeded 255), JUMP to 4D81H to report an overflow error (entry number > 99 is invalid).
4D7B
DEC D 15
DECrement Register D (loop counter) by 1.
4D7C
If the NZ FLAG is set (loop counter not zero), JUMP back to 4D78H to continue the multiplication loop. [MULTIPLY LOOP END]
4D7E
ADD A,E 83
ADD Register E (second digit / units value) to Register A, completing the two-digit entry number: A = (first_digit × 10) + second_digit.
4D7F
If the NO CARRY FLAG is set (result fits in 8 bits, entry number is valid 0–99), JUMP back to 4D6BH to store the result in C and continue parsing the next character.

If we reach here, the entry number overflowed (exceeded 255). Report error 20H (space character = invalid number).

4D81
LD A,20H 3E 20
Load Register A with 20H. This serves as an error/overflow signal code.
4D83
JUMP to 4D43H to exit. Since 20H is non-zero, the exit routine will jump to the SYS0 error handler.

4D85H – Continue Parsing After Number

After parsing the drive/entry number, this point advances through the remaining command-line characters, checking for option letters (A, S, I, U) and the /ext extension filter. Register B accumulates option flags, Register C holds the drive/entry number, and HL points to the current command-line position.

4D85
GOSUB to SYS0 routine at 4C7AH to advance to the next non-space character on the command line. HL is advanced past any whitespace. Returns with the CARRY FLAG set if end of line is reached, or the next non-space character in Register A.
4D88
RET C D8
If the CARRY FLAG is set (end of command line reached), RETURN to the caller. All parameters have been successfully parsed.

4D89H – Option Letter Parser

Checks the current command-line character for the P (printer) option prefix, then checks for Enter (0DH = execute), followed by the individual option letters A, S, I, U, and the /ext extension filter. Each option sets a corresponding bit in Register B.

4D89
GOSUB to 5058H to check for the P (printer) option. If the current character is P (50H), the output vectors are modified for printer mode, bit 3 of B is set, and A returns with the next character. If not P, A returns unchanged.
4D8C
If the Z FLAG is set (returned from the P check with Z, meaning the character was P and has been consumed), JUMP back to 4D85H to skip spaces and continue parsing the next option.
4D8E
CP 0DH FE 0D
Compare Register A against 0DH (ASCII carriage return / Enter). If Register A equals 0DH, the Z FLAG is set, indicating the end of the command line.
4D90
If the Z FLAG is set (Enter found, command line complete), JUMP to 4DD5H to begin executing the DIR command with all parsed options.

Check for option letter A (show All file attributes).

4D92
CP 41H FE 41
Compare Register A against 41H (ASCII A). If Register A equals 41H, the Z FLAG is set.
4D94
If the NZ FLAG is set (not letter A), JUMP to 4D9AH to check the next option letter.
4D96
SET 0,B CB C0
SET bit 0 of Register B to mark A (show All attributes) as active. When this bit is set, each file entry will display an additional detail line with EOF, LRL, RECS, GRANS, EXTS, and attribute flags.
4D98
JUMP back to 4D85H to skip spaces and continue parsing the next option.

Check for option letter S (include System files).

4D9A
CP 53H FE 53
Compare Register A against 53H (ASCII S). If Register A equals 53H, the Z FLAG is set.
4D9C
If the NZ FLAG is set (not letter S), JUMP to 4DA2H to check the next option letter.
4D9E
SET 1,B CB C8
SET bit 1 of Register B to mark S (include System files) as active. System files have bit 6 set in their directory entry status byte.
4DA0
JUMP back to 4D85H to continue parsing.

Check for option letter I (include Invisible files).

4DA2
CP 49H FE 49
Compare Register A against 49H (ASCII I). If Register A equals 49H, the Z FLAG is set.
4DA4
If the NZ FLAG is set (not letter I), JUMP to 4DAAH to check the next option letter.
4DA6
SET 2,B CB D0
SET bit 2 of Register B to mark I (include Invisible files) as active. Invisible files have bit 3 set in their directory entry status byte.
4DA8
JUMP back to 4D85H to continue parsing.

Check for option letter U (show only Updated files).

4DAA
CP 55H FE 55
Compare Register A against 55H (ASCII U). If Register A equals 55H, the Z FLAG is set.
4DAC
If the NZ FLAG is set (not letter U), JUMP to 4DB2H to check for the /ext filter.
4DAE
SET 5,B CB E8
SET bit 5 of Register B to mark U (show only Updated files) as active. Updated files have bit 5 set in byte 01H of their directory entry.
4DB0
JUMP back to 4D85H to continue parsing.

Check for the / (extension filter) option.

4DB2
CP 2FH FE 2F
Compare Register A against 2FH (ASCII /). If Register A equals 2FH, the Z FLAG is set, indicating a file extension filter follows.
4DB4
If the NZ FLAG is set (character is not / and not any recognized option), JUMP to 4D3DH to report a parse error (34H). The character is invalid in this context.
4DB7
SET 4,B CB E0
SET bit 4 of Register B to mark /ext (extension filter) as active.
4DB9
PUSH BC C5
Save Register Pair BC (B=option flags, C=drive/entry number) onto the stack. The extension copy loop below uses B as a counter.
4DBA
LD B,03H 06 03
Load Register B with 03H (3 decimal). The extension is exactly 3 characters long.
4DBC
LD DE,4E0EH 11 0E 4E
Point Register Pair DE to 4E0EH, the extension filter buffer. The three extension characters from the command line will be copied here.

[EXTENSION COPY LOOP START] – Copies up to 3 characters from the command line (after the /) into the extension filter buffer at 4E0EH.

4DBF
LD A,(HL) 7E
Load Register A with the current character from the command line at position HL.
4DC0
SUB 30H D6 30
SUBtract 30H from Register A. This shifts ASCII digits ('0'–'9') to 0–9 and letters ('A'–'Z') to 11H–2AH. If the result is < 0AH, the character is a digit; if 11H–2AH, it is a letter.
4DC2
CP 0AH FE 0A
Compare Register A against 0AH. If A < 0AH (CARRY set), the character is a digit (valid extension character).
4DC4
If the CARRY FLAG is set (character is a digit 0–9), JUMP to 4DCCH to store it in the extension buffer.
4DC6
SUB 11H D6 11
SUBtract 11H from Register A. After the previous SUB 30H, letters 'A'–'Z' are at 11H–2AH. Subtracting 11H shifts them to 00H–19H. If the result is < 1AH (26 decimal), the character is a letter.
4DC8
CP 1AH FE 1A
Compare Register A against 1AH (26 decimal). If A < 1AH (CARRY set), the character is a valid letter (A–Z). If A ≥ 1AH (NO CARRY), it is not a valid alphanumeric character.
4DCA
If the NO CARRY FLAG is set (character is not a digit or letter), JUMP to 4DD2H to end the extension copy. The extension may be shorter than 3 characters.
4DCC
LD A,(HL) 7E
Reload Register A with the original character from the command line (the SUB operations destroyed the original value, so we re-read it).
4DCD
LD (DE),A 12
Store the extension character from Register A into the extension filter buffer at the position pointed to by DE (4E0EH, 4E0FH, or 4E10H).
4DCE
INC DE 13
INCrement DE by 1 to advance to the next position in the extension filter buffer.
4DCF
INC HL 23
INCrement HL by 1 to advance to the next character on the command line.
4DD0
DECrement B (character counter, started at 3) and loop back to 4DBFH if not zero. Continues copying until 3 characters have been stored or a non-alphanumeric character is encountered. [EXTENSION COPY LOOP END]
4DD2
POP BC C1
Restore Register Pair BC (B=option flags with bit 4 now set, C=drive/entry number) from the stack.
4DD3
JUMP back to 4D85H to skip spaces and continue parsing any remaining options after the extension filter.

4DD5H – DIR Execute: Begin Directory Scan

Reached when Enter (0DH) is found at the end of the command line. All options have been parsed and stored in Register B. This routine clears the screen (if not in printer mode), sets up diskette swap mode if the $ flag is active, reads the first directory sector, and dispatches to the main directory entry scan loop. Register B holds the option flags, Register C holds the drive number.

4DD5
BIT 3,B CB 58
Test bit 3 of Register B (the P = Printer option flag). If bit 3 is clear (0), the Z FLAG is set (output is to screen, not printer).
4DD7
LD HL,514BH 21 4B 51
Point Register Pair HL to 514BH, the clear screen control sequence (bytes 1CH + 1FH + 03H). When sent to the display routine, 1CH clears the screen and 1FH homes the cursor.
4DDA
If the Z FLAG is set (printer mode is NOT active, meaning output is to the screen), GOSUB to 508FH to display the clear screen sequence. This clears the screen before showing the directory listing. If output is to the printer, the screen is not cleared.

Check if diskette swap mode ($) is active. If so, modify the instruction at 4D47H to enable the mount prompt on every sector read.

4DDD
BIT 6,B CB 70
Test bit 6 of Register B (the $ = diskette swap mode flag). If bit 6 is set (1), the NZ FLAG is set (swap mode is active).
4DDF
If the Z FLAG is set (swap mode is NOT active), JUMP to 4DF6H to skip the swap mode setup and proceed directly to reading the directory.

Diskette swap mode is active. Modify the drive number in the mount prompt and enable the CALL instruction at 4D47H.

4DE1
LD A,C 79
Load Register A with the drive number from Register C.
4DE2
OR A B7
OR Register A with itself to set flags. If the drive number is 0, the Z FLAG is set.
4DE3
If the NZ FLAG is set (drive number is not 0), JUMP to 4DEAH to skip the opcode modification (only drive 0 needs the CALL modification since it is the system drive).
4DE5
LD A,CDH 3E CD
Load Register A with CDH, the Z80 opcode for CALL.
4DE7
LD (4D47H),A 32 47 4D
Store CDH (CALL opcode) at address 4D47H. [SELF-MODIFYING CODE] This changes the instruction at 4D47H from LD HL,4F96H (opcode 21H) to CALL 4F96H (opcode CDH). Now every time the cleanup exit at 4D43H is reached, it will call the mount prompt routine at 4F96H to prompt the user to insert the system diskette before returning.
4DEA
LD A,C 79
Load Register A with the drive number from Register C again.
4DEB
ADD 30H C6 30
ADD 30H (ASCII 0) to Register A, converting the binary drive number to its ASCII digit representation.
4DED
LD (5132H),A 32 32 51
Store the ASCII drive digit at 5132H, which is the drive number position within the mount prompt text at 511FH ("DISKETTE ON DRIVE 0"). This updates the displayed drive number in the swap prompt.
4DF0
LD HL,5144H 21 44 51
Point Register Pair HL to 5144H, the "TARGET" text string (5144H = "TARGET" + 03H). This label will be displayed in the mount prompt as "MOUNT TARGET DISKETTE ON DRIVE n".
4DF3
GOSUB to 4F96H to display the mount prompt: "MOUNT TARGET DISKETTE ON DRIVE n (ENTER)" and wait for the user to press Enter.

4DF6H – Read First Directory Sector and Begin Scan

Reads the first directory sector from disk and begins the main directory entry scan loop. At this point Register B holds the option flags, Register C holds the drive number. The directory read routine at 4FDBH is called to read the disk summary and format the first display line.

4DF6
GOSUB to 4FDBH to read the directory and display the disk summary line (drive number, disk name, date, tracks, FDEs, granules). Returns with Z flag set if a valid directory entry is available for display, NZ if end of directory or error. HL points to the first directory entry in the sector buffer on return.
4DF9
If the NZ FLAG is set (directory read failed or returned an error code), JUMP to 4D43H to exit with the error code in Register A.
4DFC
XOR A AF
Clear Register A to 00H and clear all flags. This resets the directory sector counter before the main scan begins.
4DFD
GOSUB to 4D34H to store the reset sector counter (00H) at 4D33H and call 48D4H to read the first directory sector into the buffer. Returns Z if the sector was read successfully.
4E00
GOSUB to 5086H to output a space + carriage return, placing a blank line before the file listing begins.
4E03
LD D,0DH 16 0D
Load Register D with 0DH (13 decimal). This sets the entries-per-page counter for the main display loop: 13 entries are displayed before a screen-full pause.
4E05
GOSUB to 4FC7H to display the column header line ("EOF LRL RECS GRANS EXTS SIUEC....UAL") if the A option (bit 0 of B) is active. If A is not active, this routine returns immediately.
4E08
PUSH DE D5
Save Register Pair DE (D=entries-per-page counter) onto the stack.
4E09
LD C,05H 0E 05
Load Register C with 05H (5 decimal). This sets the entries-per-line counter: 5 compact directory entries are displayed per line (when not using the A detail mode).
4E0B
JUMP to 4F3BH to enter the main directory entry filter and display loop. This is the core of the DIR command that scans each entry, applies filters, and displays matching files.

4E0EH – Extension Filter Buffer (3 Bytes Data Area)

Three bytes of storage for the extension filter characters. Initially contains spaces (20H, 20H, 20H). Written by the extension parser at 4DBFH–4DD0H when the /ext option is used. Read by the extension match routine at 4F5CH–4F6FH during directory scanning. This area is only accessed via indirect addressing, never by sequential execution.

4E0E
DEFB 20H 20H 20H 20 20 20
Extension filter buffer. These bytes store the first characters of the file extension filter entered after the / option.

4E11H – Format Single Directory Entry for Display

This routine formats one directory entry for display. It extracts the access level, attribute flags (System, Invisible, Updated, Extended, Control) from the directory entry status bytes, and writes them into a display buffer at 51AFH. It then displays the filename (8 chars), extension (3 chars with / separator), and date from the directory entry. DE points to the directory entry on entry. Register B holds option flags, Register C holds entries-per-line counter.

4E11
PUSH DE D5
Save Register Pair DE (D = entries-per-page counter (lines remaining before screen-full pause); E is unused) onto the stack.
4E12
PUSH BC C5
Save Register Pair BC (B=option flags, C=entries-per-line counter) onto the stack.
4E13
PUSH HL E5
Save Register Pair HL (pointer to current directory entry position in the sector buffer) onto the stack.
4E14
EX DE,HL EB
Exchange DE and HL. Now DE points to the directory entry (was in HL from the caller), and HL is free for use.
4E15
Point Register Pair HL to 51AFH, the attribute flag display buffer. This is an 11-byte working area where the flags "SIUEC....nL" will be assembled (S=System, I=Invisible, U=Updated, E=Extended, C=Control, dots=unused, n=access level, L=last position).
4E18
LD B,0BH 06 0B
Load Register B with 0BH (11 decimal). The attribute display area is 11 characters wide.

[INIT LOOP START] – Fill the 11-byte attribute display buffer with dots (2EH) as default placeholders. Each position's address is pushed onto the stack for later use when inserting flag letters.

4E1B
PUSH HL E5
Save HL (address of current buffer position) onto the stack. These pushed addresses are used later to locate each flag position without recalculating offsets.
4E1C
LD (HL),2EH 36 2E
Store 2EH (ASCII .) at the current buffer position. Dots serve as default placeholder characters for unused flag positions.
4E1E
INC HL 23
INCrement HL by 1 to advance to the next position in the display buffer.
4E1F
DECrement B and loop back to 4E1BH if not zero. Fills all 11 positions with dots and pushes each position's address. [INIT LOOP END] After the loop: HL points to 51BAH, and 11 addresses (51AFH through 51B9H) are on the stack in reverse order (51B9H on top).

Extract the access level (bits 0–2) from byte 0 of the directory entry and store its ASCII digit at position 51BAH (the last character of the attribute buffer).

4E20
LD A,(DE) 1A
Load Register A with byte 0 (status byte) of the directory entry pointed to by DE. Bit 7=Primary/Extended, bit 6=System, bit 5=Limited Backup, bit 4=Assigned, bit 3=Invisible, bits 2–0=Access Level.
4E21
AND 07H E6 07
AND Register A with 07H to mask out all but the lower 3 bits (Access Level, 0–7).
4E23
ADD 30H C6 30
ADD 30H (ASCII 0) to Register A, converting the access level (0–7) to its ASCII digit representation (07).
4E25
LD (HL),A 77
Store the ASCII access level digit at 51BAH, the position past the end of the 11-byte flag area. This is the access level display character.

Now pop the saved buffer addresses from the stack and test individual flag bits from the directory entry. Each POP retrieves the next flag position (in reverse order: 51B9H, 51B8H, etc.). When a flag bit is set, the corresponding letter replaces the dot at that position.

4E26
POP HL E1
Restore HL from the stack. POP retrieves 51B9H (the 11th position, last one pushed). This is the position for the System (S) flag character.
4E27
LD A,(DE) 1A
Reload Register A with byte 0 (status byte) of the directory entry at DE.
4E28
BIT 6,A CB 77
Test bit 6 of the status byte (the System file flag). If bit 6 is set, this file is marked as a System file.
4E2A
If the Z FLAG is set (bit 6 is clear, file is NOT a System file), JUMP to 4E2EH to skip the S flag.
4E2C
LD (HL),53H 36 53
Store 53H (ASCII S) at position 51B9H, replacing the dot with the System flag indicator.
4E2E
INC HL 23
INCrement HL by 1. HL advances from 51B9H to 51BAH. Note: this INC is part of the sequential flag placement; the flags are being placed at positions 51B9H, 51BAH onward. The POP/INC pattern alternates between stack-loaded positions and linear advancement.
4E2F
BIT 3,A CB 5F
Test bit 3 of the status byte (the Invisible file flag). If bit 3 is set, this file is marked as Invisible.
4E31
If the Z FLAG is set (bit 3 is clear, file is NOT Invisible), JUMP to 4E35H to skip the I flag.
4E33
LD (HL),49H 36 49
Store 49H (ASCII I) at the current display buffer position, replacing the dot with the Invisible flag indicator.
4E35
INC HL 23
INCrement HL by 1 to advance to the next flag position in the display buffer.
4E36
INC DE 13
INCrement DE by 1 to advance to byte 1 of the directory entry. Byte 1 contains additional flags: bit 5=Updated, bit 7=EOF status, bit 6=access Control.
4E37
LD A,(DE) 1A
Load Register A with byte 1 of the directory entry (additional flags byte).
4E38
BIT 5,A CB 6F
Test bit 5 of byte 1 (the Updated flag). If bit 5 is set, the file has been modified since last backup.
4E3A
If the Z FLAG is set (bit 5 is clear, file is NOT Updated), JUMP to 4E3EH to skip the U flag.
4E3C
LD (HL),55H 36 55
Store 55H (ASCII U) at the current display buffer position, replacing the dot with the Updated flag indicator.
4E3E
INC HL 23
INCrement HL by 1 to advance to the next flag position.
4E3F
BIT 7,A CB 7F
Test bit 7 of byte 1. If bit 7 is set, this indicates an Extended directory entry (the file has additional extent entries beyond the primary FPDE).
4E41
If the Z FLAG is set (bit 7 clear, NOT an extended entry), JUMP to 4E45H to skip the E flag.
4E43
LD (HL),45H 36 45
Store 45H (ASCII E) at the current display buffer position, replacing the dot with the Extended flag indicator.
4E45
INC HL 23
INCrement HL by 1 to advance to the next flag position.
4E46
BIT 6,A CB 77
Test bit 6 of byte 1. If bit 6 is set, this indicates the file has access Control (password protection).
4E48
If the Z FLAG is set (bit 6 clear, no access control), JUMP to 4E4CH to skip the C flag.
4E4A
LD (HL),43H 36 43
Store 43H (ASCII C) at the current display buffer position, replacing the dot with the access Control flag indicator.

All 5 flag positions (S, I, U, E, C) have been filled. Now advance DE to the filename field (offset 05H from directory entry start) and display the 8-character filename followed by the 3-character extension.

4E4C
LD HL,0004H 21 04 00
Load Register Pair HL with 0004H. This offset will be added to DE to reach the filename field.
4E4F
ADD HL,DE 19
ADD DE to HL. Since DE was advanced to byte 1 (at 4E36H), adding 4 makes HL point to byte 5 of the directory entry — the start of the 8-byte filename field (bytes 05H–0CH).
4E50
LD C,0FH 0E 0F
Load Register C with 0FH (15 decimal). This is the column counter for the display line, tracking remaining characters in the filename/extension display area.
4E52
LD B,08H 06 08
Load Register B with 08H (8 decimal). Display 8 characters from the filename field.
4E54
GOSUB to 509AH to display 8 characters from the buffer at HL (the filename field). For each non-space character displayed, Register C is decremented. HL is advanced past the 8 characters.

After the filename, check if the next byte (first byte of the extension at offset 0DH) is a space. If not a space, display a "/" separator before the extension.

4E57
LD A,(HL) 7E
Load Register A with the first byte of the extension field (directory entry offset 0DH). HL now points here after displaying the 8-char filename.
4E58
CP 20H FE 20
Compare Register A against 20H (ASCII space). If the first extension byte is a space, there is no extension to display.
4E5A
LD A,2FH 3E 2F
Load Register A with 2FH (ASCII /), the extension separator character.
4E5C
If the NZ FLAG is set (extension is present, first byte is not a space), GOSUB to 50A4H to decrement C and display the / separator character.
4E5F
LD B,03H 06 03
Load Register B with 03H (3 decimal). The extension is 3 characters long.
4E61
GOSUB to 509AH to display 3 characters from the extension field at HL. C is decremented for each non-space character. HL advances past the extension.

After displaying the filename and extension, output C remaining spaces (to pad the display to 15 characters), then display the date and other file information.

4E64
LD B,C 41
Copy Register C (remaining column count) to Register B. B is now the number of padding spaces to output after the filename/extension.
4E65
GOSUB to 5092H to output B spaces (padding to align the display columns).

Now read the number of sectors (2 bytes at directory entry offset 14H–15H) and the date (2 bytes at offset 16H–17H). HL currently points past the extension (at offset 10H).

4E68
LD E,(HL) 5E
Load Register E with the byte at HL (directory entry offset 10H = update password hash low byte).
4E69
INC HL 23
INCrement HL to offset 11H.
4E6A
LD D,(HL) 56
Load Register D with the byte at HL (directory entry offset 11H = update password hash high byte). DE now contains the update password hash (16-bit value).
4E6B
PUSH DE D5
Save the update password hash (DE) onto the stack for later comparison.
4E6C
INC HL 23
INCrement HL to offset 12H.
4E6D
LD E,(HL) 5E
Load Register E with the byte at HL (directory entry offset 12H = access password hash low byte).
4E6E
INC HL 23
INCrement HL to offset 13H.
4E6F
LD D,(HL) 56
Load Register D with the byte at HL (directory entry offset 13H = access password hash high byte). DE now contains the access password hash.
4E70
LD HL,4296H 21 96 42
Load Register Pair HL with 4296H. This is the address of the "no password" hash value stored in the DOS work area. The standard "no password" code is EF5CH.
4E73
RST 18H DF
Execute RST 18H to compare HL with DE (16-bit comparison). Compares the "no password" hash at 4296H against the access password hash in DE. If they match (Z flag set), the file has no access password.
4E74
If the Z FLAG is set (access password matches "no password"), JUMP to 4E7BH to skip marking the file as password-protected.
4E76
LD A,41H 3E 41
Load Register A with 41H (ASCII A), indicating the file has an Access password.
4E78
LD (51B9H),A 32 B9 51
Store A at address 51B9H in the attribute display buffer, replacing the dot with the Access password indicator.
4E7B
POP DE D1
Restore the update password hash from the stack into DE.
4E7C
RST 18H DF
Execute RST 18H to compare HL (still pointing to 4296H, the "no password" value) with DE (update password hash). If they match, the file has no update password.
4E7D
If the Z FLAG is set (update password matches "no password"), JUMP to 4E84H to skip the update password indicator.
4E7F
LD A,55H 3E 55
Load Register A with 55H (ASCII U), indicating the file has an Update password.
4E81
LD (51B8H),A 32 B8 51
Store U at address 51B8H in the attribute display buffer, replacing the dot with the Update password indicator.
4E84
POP HL E1
Restore Register Pair HL (pointer to current directory entry in the sector buffer) from the stack.
4E85
POP BC C1
Restore Register Pair BC (B=option flags, C=entries-per-line counter) from the stack.

4E86H – Full Attribute Display (A Option Handler)

When bit 0 of Register B (the A option) is set, this section displays the full detail line for the current file: EOF position, Logical Record Length, record count, granule count, extent count, and the attribute flags buffer. If bit 0 is clear, execution jumps directly to 4F28H to advance to the next directory entry.

4E86
BIT 0,B CB 40
Test bit 0 of Register B (the A = show All attributes option flag). If bit 0 is clear, the Z FLAG is set (A option not active).
4E88
If the Z FLAG is set (A option not active), JUMP to 4F28H to skip the detail display and advance directly to the next directory entry.

The A option is active. Prepare to display the full detail line. Set C=01 as a column counter, save BC and HL, then advance HL to the relevant fields in the directory entry.

4E8B
LD C,01H 0E 01
Load Register C with 01H. This initializes a counter/flag used during the detail display.
4E8D
PUSH BC C5
Save Register Pair BC (B=option flags, C=01H) onto the stack.
4E8E
PUSH HL E5
Save Register Pair HL (pointer to current directory entry base) onto the stack.
4E8F
INC HL 23
INCrement HL to advance to offset 01H of the directory entry.
4E90
INC HL 23
INCrement HL to offset 02H.
4E91
INC HL 23
INCrement HL to offset 03H — the EOF relative byte position within the last sector of the file.
4E92
LD E,(HL) 5E
Load Register E with the EOF byte offset (byte 03H of directory entry). This is the relative byte position within the last sector where the file ends.
4E93
LD D,00H 16 00
Load Register D with 00H. DE now contains the 16-bit EOF byte offset (0–255).
4E95
INC HL 23
INCrement HL to offset 04H — the Logical Record Length (LRL) byte.
4E96
LD B,D 42
Load Register B with 00H (from D). Clear B for use as the high byte of BC.
4E97
LD C,(HL) 4E
Load Register C with the Logical Record Length from byte 04H. BC now holds the LRL as a 16-bit value (00:LRL).

Now compute the number of records: total_bytes ÷ LRL. First, get the total sector count from the directory entry. Offset 14H–15H contains the sector count.

4E98
SET 4,L CB E5
SET bit 4 of Register L. Since HL was pointing to offset 04H within the directory entry, setting bit 4 of L advances to offset 14H — the sector count low byte. This is a shortcut that works because directory entries are aligned to 16-byte boundaries within the sector buffer.
4E9A
LD A,(HL) 7E
Load Register A with the sector count low byte from directory entry offset 14H.
4E9B
INC HL 23
INCrement HL to offset 15H — the sector count high byte.
4E9C
PUSH HL E5
Save HL (pointing to directory entry offset 15H) onto the stack.
4E9D
LD H,(HL) 66
Load Register H with the sector count high byte from offset 15H.
4E9E
LD L,A 6F
Load Register L with the sector count low byte (saved in A). HL now contains the total sector count for this file.

Now compute the EOF position within the file. If EOF byte offset (E) is nonzero, decrement the sector count by 1 (the last sector is only partially filled).

4E9F
LD A,E 7B
Load Register A with the EOF byte offset from Register E.
4EA0
OR A B7
OR Register A with itself to test if the EOF offset is zero. If zero, the Z FLAG is set (the last sector is completely filled, no partial sector).
4EA1
If the Z FLAG is set (EOF offset is zero, meaning the file ends at a sector boundary), JUMP to 4EA4H to skip the decrement.
4EA3
DEC HL 2B
DECrement HL (sector count) by 1. When the EOF byte offset is non-zero, the last sector is only partially filled, so the record calculation needs sectors-1 full sectors plus the partial last sector.
4EA4
INC C 0C
INCrement Register C by 1. C was loaded with the LRL at 4E97H. This INC/DEC pair tests whether C is zero (LRL=0 means LRL=256).
4EA5
DEC C 0D
DECrement Register C by 1, restoring it to its original LRL value. The purpose of INC/DEC is to set the Z FLAG if C was zero (LRL = 256 is encoded as 00H).
4EA6
If the NZ FLAG is set (LRL is not 256, i.e., C is not zero), JUMP to 4EAAH to proceed with the division.
4EA8
LD B,01H 06 01
Load Register B with 01H. When LRL=256 (encoded as 0), each sector holds exactly 1 record. Set B=1 to force record_count = sector_count (the division will be by 1 instead of 256).

Prepare registers for the 24-bit division to compute record count. A:HL contains the dividend (total file size in bytes), C contains the divisor (LRL). The division routine at 50ADH computes AHL ÷ C.

4EAA
PUSH DE D5
Save DE (E=EOF byte offset, D=00H) onto the stack.
4EAB
PUSH HL E5
Save HL (sector count) onto the stack.
4EAC
PUSH BC C5
Save BC (B=high byte or 01H, C=LRL) onto the stack.
4EAD
If the NZ FLAG is still set from the C test at 4EA6H (LRL ≠ 256), JUMP to 4EB2H to call the division routine.

LRL = 256 case: 1 record per sector, so record count = sector count. Set up registers so the division is trivial.

4EAF
LD E,L 5D
Copy L (sector count low byte) to E.
4EB0
LD L,H 6C
Copy H (sector count high byte) to L.
4EB1
LD H,D 62
Copy D (00H) to H. Now HL:E = 00:sector_high:sector_low, effectively shifting the sector count so E=remainder and HL=quotient for the LRL=256 case.
4EB2
If the NZ FLAG is set (LRL ≠ 256), GOSUB to 50ADH to perform the 24-bit division: AHL ÷ C. The quotient is returned in AHL and the remainder influences E. This computes the number of records = total_bytes ÷ LRL.

After the division: A:HL contains the record count (quotient), E contains the remainder. Check if the remainder is non-zero, which means there is a partial record at the end.

4EB5
OR A B7
OR Register A with itself. A holds the high byte of the division result. Sets the Z FLAG if A is zero.
4EB6
If the Z FLAG is set (high byte of record count is zero), JUMP to 4EBCH.
4EB8
INC E 1C
INCrement E (remainder counter). If there was a non-zero remainder from the division, this accounts for the partial record.
4EB9
If the NZ FLAG is set (INC E did not wrap to zero), JUMP to 4EBCH.
4EBB
INC HL 23
INCrement HL (record count) by 1. If E wrapped from FFH to 00H, carry the increment into HL.

Now format and display the computed values. A=high byte, B=record count high, C=LRL, E=remainder. Store the values into the display template buffers and call the number formatting routines.

4EBC
LD A,H 7C
Load Register A with H (high byte of record count).
4EBD
LD B,L 45
Load Register B with L (low byte of record count).
4EBE
LD C,E 4B
Load Register C with E (EOF byte count / remainder).
4EBF
LD HL,519BH 21 9B 51
Point Register Pair HL to 519BH, the record count position in the detail display template at 518CH.
4EC2
LD DE,5109H 11 09 51
Point Register Pair DE to 5109H, the 6-digit decimal conversion divisor table (starting with the 100,000 divisor).
4EC5
GOSUB to 50C8H to format the record count as a decimal number string. Converts the 24-bit value in A:B:C into ASCII digits and stores them in the template buffer at 519BH.
4EC8
POP BC C1
Restore BC from the stack (B=high byte or 01H, C=LRL).
4EC9
LD HL,5197H 21 97 51
Point Register Pair HL to 5197H, the LRL display position in the detail template.
4ECC
GOSUB to 50BFH to format the LRL (in BC) as a decimal number and store it at 5197H.
4ECF
POP BC C1
Restore BC from the stack (sector count or related values).
4ED0
LD HL,518CH 21 8C 51
Point Register Pair HL to 518CH, the start of the detail display template line 2.
4ED3
LD DE,510CH 11 0C 51
Point Register Pair DE to 510CH, the 4-digit decimal conversion divisor table (starting with the −10,000 divisor).
4ED6
GOSUB to 50C7H to format the value in A:HL as a decimal number using the 4-digit table and store it at 518CH (the EOF position).
4ED9
LD (HL),30H 36 30
Store 30H (ASCII 0) at the current HL position. This places a trailing zero in the display template.
4EDB
POP BC C1
Restore BC from the stack.
4EDC
PUSH HL E5
Save HL (current position in the display template) onto the stack.
4EDD
GOSUB to 50BFH to format another number value into the template (granule count).
4EE0
POP HL E1
Restore HL from the stack.
4EE1
LD (HL),2FH 36 2F
Store 2FH (ASCII /) at the current position, placing a "/" separator in the display template between fields.
4EE3
POP HL E1
Restore HL (pointer to directory entry offset 15H, saved at 4E9CH) from the stack.
4EE4
INC HL 23
INCrement HL to offset 16H — the start of the file extents area in the directory entry.

[EXTENT SCAN LOOP START] – Walk through the file's extent entries (2 bytes each: track number + encoded granules) to count the total number of granules and extents.

4EE5
LD BC,0000H 01 00 00
Load Register Pair BC with 0000H. Initialize the granule count accumulator (BC) to zero.
4EE8
LD D,B 50
Load Register D with B (00H). Initialize the extent count (D) to zero.
4EE9
LD E,C 59
Load Register E with C (00H). Initialize E to zero (used as an additional counter).
4EEA
LD A,(HL) 7E
[EXTENT LOOP] Load Register A with the track number of the current extent entry at HL.
4EEB
CP FEH FE FE
Compare Register A against FEH. In the extent table: FEH indicates a link to an extended directory entry (continuation FPDE), and FFH indicates the end of extents.
4EED
INC HL 23
INCrement HL to point to the encoded granules byte of the current extent.
4EEE
If the NO CARRY FLAG is set (A ≥ FEH, meaning this is a link entry or end-of-extents marker), JUMP to 4F04H to handle the special cases.

Normal extent entry (track number < FEH). Count the granules in this extent.

4EF0
INC DE 13
INCrement DE (extent counter) by 1. This counts each valid extent entry.
4EF1
LD A,(HL) 7E
Load Register A with the encoded granules byte. The low 5 bits (bits 0–4) encode the number of granules in this extent minus 1.
4EF2
AND 1FH E6 1F
AND Register A with 1FH to mask out the upper 3 bits, extracting the granule count minus 1 (0–31 representing 1–32 granules).
4EF4
INC HL 23
INCrement HL to advance past the encoded granules byte, pointing to the next extent entry.
4EF5
INC A 3C
INCrement A by 1 to convert the "granules minus 1" value to the actual granule count (1–32).
4EF6
ADD A,C 81
ADD Register C (low byte of granule accumulator) to Register A.
4EF7
LD C,A 4F
Store the sum back in Register C. BC accumulates the total granule count across all extents.
4EF8
If the NO CARRY FLAG is set (no 8-bit overflow), JUMP to 4EFBH to skip the carry propagation.
4EFA
INC B 04
INCrement B (high byte of granule accumulator) to propagate the carry from the ADD A,C above.
4EFB
BIT 4,L CB 65
Test bit 4 of Register L. This checks whether HL has advanced past the extent area into the next directory entry. If bit 4 changes state, we have crossed a 16-byte boundary, indicating we are still within the current entry's extent list.
4EFD
If the NZ FLAG is set (still within the extent area), JUMP back to 4EEAH to process the next extent entry. [EXTENT LOOP CONTINUE]

Reached when all 13 extent entries in the primary FPDE have been scanned (HL has advanced past the extent area). If there are more extents than can fit in 13 entries, report an error.

4EFF
LD A,2CH 3E 2C
Load Register A with 2CH (error code for "directory full" or extent overflow).
4F01
JUMP to 4D43H to exit with error code 2CH.

4F04H – Handle Extended Directory / End of Extents

Handles the special extent values: FEH (link to extended directory entry) and FFH (end of extents). If FEH, follows the link to the continuation entry and resumes scanning. If FFH, the extent scan is complete; format and display the accumulated statistics.

4F04
If the NZ FLAG is set (the track byte was FFH, not FEH), JUMP to 4F0FH to handle the end-of-extents case. Note: at 4EEBH, CP FEH was performed. If A=FEH, Z is set; if A=FFH, Z is clear.

Track byte was FEH: this is a link to an extended directory entry. The next byte contains the sector offset to the continuation FPDE. Read that sector and resume extent scanning.

4F06
LD A,(HL) 7E
Load Register A with the link byte following the FEH marker. This byte encodes the location of the continuation directory entry.
4F07
GOSUB to 4D37H (which calls 48D4H) to read the directory sector containing the continuation FPDE.
4F0A
ADD 16H C6 16
ADD 16H (22 decimal) to Register A. This adds the offset to the start of the extent area within the continuation directory entry (offset 16H is where extents begin).
4F0C
LD L,A 6F
Load Register L with the computed offset. HL now points to the first extent entry in the continuation FPDE.
4F0D
JUMP back to 4EEAH to continue the extent scan in the continuation entry. [EXTENT LOOP CONTINUE with linked entry]

End-of-extents reached (FFH marker). Format the accumulated statistics (extent count in DE, granule count in BC) into the display template and output the detail line.

4F0F
GOSUB to 4D32H to re-read the original directory sector (the self-modifying counter at 4D33H still holds the current sector number). This restores the sector buffer after following any extent links.
4F12
PUSH DE D5
Save DE (extent count) onto the stack.
4F13
LD HL,51A3H 21 A3 51
Point Register Pair HL to 51A3H, the granule count position in the detail display template.
4F16
GOSUB to 50C4H to format the granule count (in BC) as a 4-digit decimal number and store it at 51A3H.
4F19
POP BC C1
Restore BC from the stack (was DE = extent count, now in BC for formatting).
4F1A
LD HL,51A9H 21 A9 51
Point Register Pair HL to 51A9H, the extent count position in the detail display template.
4F1D
GOSUB to 50BFH to format the extent count (in BC) as a decimal number and store it at 51A9H.
4F20
LD HL,518CH 21 8C 51
Point Register Pair HL to 518CH, the start of the complete detail display template line 2.
4F23
GOSUB to 508FH to display the complete detail template line (all statistics: EOF, LRL, RECS, GRANS, EXTS, and attribute flags).
4F26
POP HL E1
Restore HL (pointer to directory entry in sector buffer) from the stack (saved at 4E8EH).
4F27
POP BC C1
Restore BC (B=option flags, C=entries-per-line counter) from the stack (saved at 4E8DH).

4F28H – Advance to Next Directory Entry

Advances HL to the next directory entry within the current sector (each entry is 32 bytes = 20H). When all entries in the current sector have been processed (HL wraps past the sector boundary), reads the next directory sector. Checks the self-modifying sector counter at 4D33H to determine if all directory sectors have been scanned.

4F28
LD A,L 7D
Load Register A with the low byte of HL (current position within the sector buffer).
4F29
ADD 20H C6 20
ADD 20H (32 decimal) to Register A, advancing to the next directory entry. Each directory entry is 32 bytes (20H) long.
4F2B
LD L,A 6F
Store the updated low byte back into L. HL now points to the next directory entry.
4F2C
If the NO CARRY FLAG is set (the ADD did not overflow past FFH, meaning we are still within the current sector), JUMP to 4F3BH to filter and display the next entry.

The ADD overflowed, meaning HL has advanced past the end of the current sector. Need to read the next directory sector.

4F2E
LD A,(4D33H) 3A 33 4D
Load Register A with the directory sector counter from the self-modifying location at 4D33H.
4F31
AND 1FH E6 1F
AND Register A with 1FH to mask out the upper bits, keeping only the 5-bit sector index (0–31).
4F33
INC A 3C
INCrement A by 1 to get the next sector number.
4F34
CP 00H FE 00
Compare Register A against 00H. The byte at 4F35H is [SELF-MODIFYING CODE]: it is written at 5035H with the total number of directory sectors to scan. If A equals this limit, all sectors have been processed.
4F36
If the Z FLAG is set (all directory sectors have been scanned), JUMP to 4FAFH to handle the end-of-directory cleanup and return.
4F38
GOSUB to 4D34H to store the updated sector counter and read the next directory sector into the buffer.

4F3BH – Directory Entry Filter Loop

The main directory entry filter. Tests each directory entry against the active filters in Register B. Checks the entry status byte (bits 4 and 7 must show an active, primary entry), then checks the System, Invisible, extension, and Updated filters. Entries that pass all filters are sent to the format and display routine at 4E12H. Entries that fail are skipped by jumping back to 4F28H.

4F3B
LD A,(HL) 7E
Load Register A with byte 0 (status byte) of the current directory entry at HL.
4F3C
AND 90H E6 90
AND Register A with 90H (binary 10010000) to isolate bits 7 and 4. Bit 7: 0=Primary entry, 1=Extended entry. Bit 4: 1=Entry is active (assigned). A valid, displayable entry must have bit 7=0 and bit 4=1, yielding 10H.
4F3E
CP 10H FE 10
Compare Register A against 10H. If A equals 10H, this is a valid active primary directory entry (bit 4 set, bit 7 clear).
4F40
If the NZ FLAG is set (entry is not a valid active primary entry), JUMP to 4F28H to skip this entry and advance to the next one.

The entry is a valid active primary FPDE. Now check if the System/Invisible filter options require special handling.

4F42
LD A,B 78
Load Register A with Register B (the option flags). Bits 4–5 contain the /ext and U filter flags.
4F43
AND 30H E6 30
AND Register A with 30H (binary 00110000) to isolate bits 4 and 5 (the /ext and U option flags). If either is set, the result is non-zero.
4F45
If the NZ FLAG is set (either /ext or U filter is active), JUMP to 4F58H to skip the System/Invisible checks (those filters are checked separately when extension or update filtering is in use).

Neither /ext nor U filter is active. Check the System and Invisible flags on the entry. If the file is System and the S option is not set, skip it. If the file is Invisible and the I option is not set, skip it.

4F47
BIT 6,(HL) CB 76
Test bit 6 of byte 0 at (HL) — the System file flag. If bit 6 is set, this is a System file.
4F49
If the Z FLAG is set (bit 6 clear, file is NOT a System file), JUMP to 4F4FH to check the Invisible flag instead.
4F4B
BIT 1,B CB 48
Test bit 1 of Register B (the S = include System files option). If bit 1 is clear, System files should be hidden.
4F4D
JUMP to 4F55H to evaluate the bit test result: if Z is set (S option not active), the file will be skipped.
4F4F
BIT 3,(HL) CB 5E
Test bit 3 of byte 0 at (HL) — the Invisible file flag. If bit 3 is set, this is an Invisible file.
4F51
If the Z FLAG is set (bit 3 clear, file is NOT Invisible), JUMP to 4F58H to proceed with displaying the entry (it passed all filters).
4F53
BIT 2,B CB 50
Test bit 2 of Register B (the I = include Invisible files option). If bit 2 is clear, Invisible files should be hidden.
4F55
If the Z FLAG is set (the relevant include option is NOT active), JUMP to 4F28H to skip this entry. The file is System or Invisible and the user did not request to see it.

4F58H – Extension and Updated File Filters

Checks the /ext (extension filter) and U (Updated files) options. If /ext is active, compares the file's 3-character extension against the filter buffer at 4E0EH. If U is active, checks the Updated flag (bit 5 of byte 1). Entries that pass are formatted and displayed.

4F58
BIT 4,B CB 60
Test bit 4 of Register B (the /ext = extension filter option). If bit 4 is set, extension filtering is active.
4F5A
If the Z FLAG is set (extension filter is NOT active), JUMP to 4F73H to check the Updated filter instead.

Extension filter is active. Compare the file's extension (3 bytes at directory entry offset 0DH) against the filter buffer at 4E0EH.

4F5C
PUSH HL E5
Save HL (pointer to directory entry base) onto the stack.
4F5D
PUSH BC C5
Save BC (B=option flags, C=entries-per-line counter) onto the stack.
4F5E
LD DE,000DH 11 0D 00
Load Register Pair DE with 000DH (13 decimal). Offset 0DH is the start of the 3-byte extension field in the directory entry.
4F61
ADD HL,DE 19
ADD DE to HL. HL now points to the extension field (offset 0DH) of the current directory entry.
4F62
LD DE,4E0EH 11 0E 4E
Point Register Pair DE to 4E0EH, the extension filter buffer containing the user-specified extension to match.
4F65
LD B,03H 06 03
Load Register B with 03H (3 decimal). Compare 3 bytes (the full extension).

[EXTENSION COMPARE LOOP START]

4F67
LD A,(DE) 1A
[COMPARE LOOP] Load Register A with the current filter character from the extension filter buffer at DE.
4F68
CP (HL) BE
Compare Register A against the corresponding extension character at HL. If they match, the Z FLAG is set.
4F69
INC DE 13
INCrement DE to the next filter character.
4F6A
INC HL 23
INCrement HL to the next extension character in the directory entry.
4F6B
If the NZ FLAG is set (characters do not match), JUMP to 4F6FH to exit the compare loop with NZ (mismatch).
4F6D
DECrement B and loop back to 4F67H if not zero. Continue comparing the remaining extension characters. [EXTENSION COMPARE LOOP END]
4F6F
POP BC C1
Restore BC (B=option flags, C=entries-per-line counter) from the stack.
4F70
POP HL E1
Restore HL (pointer to directory entry base) from the stack.
4F71
If the NZ FLAG is set (extension did NOT match the filter), JUMP to 4F28H to skip this entry and advance to the next one.

Extension matched (or extension filter was not active). Now check the U (Updated files only) filter.

4F73
BIT 5,B CB 68
Test bit 5 of Register B (the U = show only Updated files option). If bit 5 is set, only Updated files should be displayed.
4F75
If the Z FLAG is set (U option is NOT active), JUMP to 4F7DH to proceed with displaying the entry (it passed all filters).
4F77
INC HL 23
INCrement HL to advance to byte 1 of the directory entry (additional flags byte).
4F78
BIT 5,(HL) CB 6E
Test bit 5 of byte 1 at (HL) — the Updated flag. If bit 5 is set, the file has been modified since last backup.
4F7A
DEC HL 2B
DECrement HL to restore the pointer back to byte 0 of the directory entry.
4F7B
If the Z FLAG is set (Updated flag is NOT set, meaning the file has not been updated), JUMP to 4F28H to skip this entry. The U filter requires only Updated files.

The entry passed all filters. Display it. POP the page counter from the stack, decrement the line counter, and call the format/display routine.

4F7D
POP DE D1
Restore DE from the stack (D=entries-per-page counter, saved at 4E08H).
4F7E
DEC C 0D
DECrement Register C (entries-per-line counter) by 1.
4F7F
If the NZ FLAG is set (more entries fit on the current line), JUMP to 4F93H to format and display this entry.

The line is full (C reached zero). Reset C to 4 (not 5, because the first entry on each line gets extra spacing), output a carriage return, and check the page counter.

4F81
LD C,04H 0E 04
Load Register C with 04H (4 decimal). Reset the entries-per-line counter to 4 for subsequent lines (the first line used 5).
4F83
GOSUB to 5086H to output a space + carriage return, ending the current display line.
4F86
DEC D 15
DECrement Register D (entries-per-page counter) by 1.
4F87
If the NZ FLAG is set (more entries fit on the current page), JUMP to 4F93H to format and display the entry.

The page is full (D reached zero). Reset D to 15 (0FH), call the screen-full pause routine, and check if the column header needs to be redisplayed.

4F89
LD D,0FH 16 0F
Load Register D with 0FH (15 decimal). Reset the entries-per-page counter to 15 for the next page.
4F8B
GOSUB to 506BH to pause for screen full. Displays "?" and waits for Enter (screen mode) or returns immediately (printer mode).
4F8E
BIT 3,B CB 58
Test bit 3 of Register B (the P = Printer option). If bit 3 is clear, output is to screen.
4F90
If the Z FLAG is set (output is to screen, not printer), GOSUB to 4FC7H to redisplay the column header line at the top of the new page.
4F93
JUMP to 4E11H (one byte before the format routine at 4E12H) to format and display the current directory entry. After display, execution returns to 4E84H which restores BC and HL, then falls through to 4E86H (A option check) and eventually 4F28H (advance to next entry). [DISPLAY LOOP CONTINUES]

4F96H – Mount Diskette Prompt

Displays a prompt asking the user to mount a specific diskette on the drive. The prompt format is "MOUNT [label] DISKETTE ON DRIVE n (ENTER)" where [label] is pointed to by HL (either "SYSTEM" or "TARGET"). Waits for the user to press Enter before returning.

4F96
PUSH HL E5
Save Register Pair HL (pointer to the label string: 513DH="SYSTEM" or 5144H="TARGET") onto the stack.
4F97
LD HL,5118H 21 18 51
Point Register Pair HL to 5118H, the "MOUNT " text string (terminated with 03H).
4F9A
GOSUB to SYS0 string display routine at 4467H to display "MOUNT " on screen.
4F9D
POP HL E1
Restore HL (pointer to the label string) from the stack.
4F9E
GOSUB to 4467H to display the label string ("SYSTEM" or "TARGET").
4FA1
LD HL,511FH 21 1F 51
Point Register Pair HL to 511FH, the " DISKETTE ON DRIVE 0 (ENTER)" text string (terminated with 0DH).
4FA4
GOSUB to 4467H to display " DISKETTE ON DRIVE 0 (ENTER)" followed by a carriage return.

Now wait for the user to press Enter. Poll the keyboard until 0DH (Enter) is detected.

4FA7
GOSUB to the ROM keyboard scan routine at 0049H. Scans the keyboard and returns the character in Register A, or 00H if no key is pressed.
4FAA
CP 0DH FE 0D
Compare Register A against 0DH (ASCII Enter/carriage return).
4FAC
If the NZ FLAG is set (Enter was not pressed), JUMP back to 4FAAH to keep polling the keyboard. [KEYBOARD WAIT LOOP]
4FAE
RET C9
RETURN to the caller. The user pressed Enter, confirming the diskette has been mounted.

4FAFH – End of Directory Handler

Called when all directory sectors have been scanned (the sector counter reached the limit at 4F35H). Outputs final spacing, cleans up the stack, and checks if additional screen-full pausing is needed before returning.

4FAF
GOSUB to 5086H to output a space + carriage return (end the last display line).
4FB2
POP AF F1
Restore AF from the stack. This cleans up the saved DE (entries-per-page counter) that was pushed at 4E08H. POP AF discards 2 bytes from the stack.
4FB3
CP 04H FE 04
Compare Register A (the discarded D value, entries-per-page counter) against 04H. If fewer than 4 entries remain on the page, the screen may need a pause prompt.
4FB5
If the CARRY FLAG is set (page counter < 4, meaning the page is nearly full), GOSUB to 506BH to display the screen-full pause prompt.

4FB8H – Space/Blank Line Handler (Printer Mode)

Handles extra spacing when output is directed to the printer (P option active). When the character output vector at 50A8H is 3BH (printer), outputs additional blank lines for readability. When 33H (screen), outputs spacing for the screen layout.

4FB8
LD A,(50A8H) 3A A8 50
Load Register A with the character output vector low byte from the self-modifying location at 50A8H. If A=33H, output is to screen; if A=3BH, output is to printer.
4FBB
CP 3BH FE 3B
Compare Register A against 3BH. If A=3BH, the Z FLAG is set (printer mode is active).
4FBD
If the Z FLAG is set (printer mode), GOSUB to 5086H to output an extra space + carriage return (blank line for printer formatting).
4FC0
If the Z FLAG is still set (printer mode), GOSUB to 5086H again for a second blank line. This provides extra spacing in printer output for readability.
4FC3
XOR A AF
Clear Register A to 00H. This sets the error code to zero (success) for the exit.
4FC4
JUMP to 4D43H (common exit). Since A=00H, the exit routine will return with success (Z flag set).

4FC7H – Column Header Display (A Option)

Displays the column header line "EOF LRL RECS GRANS EXTS SIUEC....UAL" when the A option is active. If not active, returns immediately.

4FC7
BIT 0,B CB 40
Test bit 0 of Register B (the A = show All attributes option). If clear, Z FLAG is set.
4FC9
RET Z C8
If the Z FLAG is set (A option not active), RETURN immediately.
4FCA
PUSH HL E5
Save Register Pair HL onto the stack.
4FCB
PUSH BC C5
Save Register Pair BC onto the stack.
4FCC
DEC D 15
DECrement Register D (entries-per-page counter) by 1. The header counts as one display line.
4FCD
LD B,14H 06 14
Load Register B with 14H (20 decimal). Output 20 leading spaces to indent the header past the filename column.
4FCF
GOSUB to 5092H to output 20 space characters.
4FD2
LD HL,51BCH 21 BC 51
Point Register Pair HL to 51BCH, the column header text: "EOF LRL RECS GRANS EXTS SIUEC....UAL" + 0DH.
4FD5
GOSUB to 508FH to display the column header string.
4FD8
POP BC C1
Restore BC from the stack.
4FD9
POP HL E1
Restore HL from the stack.
4FDA
RET C9
RETURN to the caller.

4FDBH – Disk Statistics: Select Drive and Format Summary

Selects the drive, reads its PDRIVE parameters, then reads the GAT sector to count free granules and directory entries. Formats the disk summary line with drive number, disk name, date, track count, FDE count, and free granule count. Register C holds the drive number on entry.

4FDB
LD A,C 79
Load Register A with the drive number from Register C.
4FDC
GOSUB to SYS0 at 4791H to select the drive and load its PDRIVE parameters into 4280H. Returns Z on success, NZ with error code on failure.
4FDF
RET NZ C0
If the NZ FLAG is set (drive error), RETURN with the error code in A.
4FE0
PUSH BC C5
Save BC (B=option flags, C=drive number) onto the stack.
4FE1
LD B,00H 06 00
Load Register B with 00H. BC = 00:C = drive number as a 16-bit value for formatting.
4FE3
LD HL,5153H 21 53 51
Point HL to 5153H, the drive number position in the summary template at 514EH.
4FE6
GOSUB to 50BFH to format the drive number as decimal and store it at 5153H.
4FE9
LD A,(4283H) 3A 83 42
Load Register A with the maximum track number from PDRIVE at 4283H.
4FEC
LD C,A 4F
Copy max track number to C.
4FED
LD B,00H 06 00
Clear B. BC = track count.
4FEF
LD HL,516CH 21 6C 51
Point HL to 516CH, the track count position in the summary template.
4FF2
GOSUB to 50BFH to format the track count and store it.
4FF5
XOR A AF
Clear Register A to 00H. A=00H selects the GAT sector for reading.
4FF6
GOSUB to SYS0 at 48AFH to read the GAT sector (granule allocation table) into the sector buffer. Returns HL pointing to GAT data, Z on success.
4FF9
If the NZ FLAG is set (GAT read failed), JUMP to 5056H to clean up and return with error.

[GAT SCAN LOOP] – Scan the granule allocation table to count free granules. Each bit: 1=allocated, 0=free.

4FFB
LD BC,0000H 01 00 00
Initialize free granule counter BC to zero.
4FFE
LD E,(IY+05H) FD 5E 05
Load E with (IY+05H) = 4285H, the sectors per granule. E counts granules per track byte.
5001
LD A,(HL) 7E
[BYTE LOOP] Load A with the current GAT byte at HL.
5002
INC HL 23
INCrement HL to the next GAT byte.
5003
RRCA 0F
[BIT LOOP] Rotate A right through carry. Carry=1 means allocated, Carry=0 means free.
5004
If CARRY set (allocated), JUMP to 5007H to skip the free counter.
5006
INC BC 03
INCrement BC (free granule counter) by 1.
5007
DEC E 1D
DECrement E (granules-per-track counter).
5008
If NZ (more granules in this track byte), loop back to 5003H. [BIT LOOP END]
500A
LD A,L 7D
Load A with low byte of HL (GAT position).
500B
CP (IY+01H) FD BE 01
Compare A against (IY+01H) = 4281H, the GAT boundary byte. When A reaches this value, all tracks are scanned.
500E
If CARRY set (more tracks), loop back to 4FFEH. [GAT SCAN CONTINUES]

[GAT SCAN COMPLETE] – BC = free granule count. Now format the summary display.

5010
LD HL,5180H 21 80 51
Point HL to 5180H, the free granule count position in the summary template.
5013
GOSUB to 50C4H to format the free granule count (BC) as 4-digit decimal.
5016
LD HL,43D0H 21 D0 43
Point HL to 43D0H, the disk name stored in the DOS work area (8 bytes copied from GAT sector header).
5019
LD DE,5159H 11 59 51
Point DE to 5159H, the disk name position in the summary template.
501C
LD BC,0008H 01 08 00
Load BC with 0008H (8 bytes to copy).
501F
LDIR ED B0
Block copy 8 bytes from (HL) to (DE): copy the disk name into the summary template.
5021
LD DE,5163H 11 63 51
Point DE to 5163H, the date position in the summary template.
5024
LD C,08H 0E 08
Load C with 08H (8 bytes for the date string MM/DD/YY).
5026
LDIR ED B0
Block copy 8 bytes: copy the date into the summary template.

Now read GAT sector 1 to count free directory entries (FDEs). Each bit in this sector represents one directory entry slot.

5028
LD A,01H 3E 01
Load A with 01H. A=01H selects directory sector 1 (the FDE allocation bitmap).
502A
GOSUB to 48AFH to read directory sector 1 into the buffer.
502D
If NZ (read failed), JUMP to 5056H to clean up.

[FDE COUNT LOOP] – Scan the FDE allocation bitmap. Count zero bits (free directory entry slots).

502F
LD A,(431FH) 3A 1F 43
Load A with the byte at 431FH, which contains a parameter controlling how many bytes of the FDE bitmap to scan.
5032
ADD 08H C6 08
ADD 08H to A. This computes the total number of FDE bitmap entries to scan.
5034
LD E,A 5F
Copy the FDE count limit to E.
5035
LD (4F35H),A 32 35 4F
Store A at 4F35H. [SELF-MODIFYING CODE] This writes the directory sector limit into the CP instruction operand at 4F34H, controlling when the main directory scan loop terminates.
5038
LD A,(HL) 7E
[FDE SCAN LOOP] Load A with the current FDE bitmap byte at HL.
5039
OR A B7
OR A with itself. If A=00H (all 8 slots in this byte are free), Z FLAG is set.
503A
INC HL 23
INCrement HL to the next FDE bitmap byte.
503B
If NZ (byte is not zero, some slots are allocated), JUMP to 503EH to skip the free counter.
503D
INC BC 03
INCrement BC (free FDE counter). An all-zero byte means 8 free directory entry slots. Note: this counts whole zero bytes, not individual bits.
503E
DEC E 1D
DECrement E (FDE bytes remaining).
503F
If NZ, loop back to 5038H. [FDE SCAN LOOP END]

Compute the final position in the buffer and check alignment for the number of directory sectors.

5041
LD A,L 7D
Load A with low byte of HL.
5042
ADD 1FH C6 1F
ADD 1FH (31 decimal) to A. Round up to the next 32-byte boundary.
5044
AND E0H E6 E0
AND with E0H to align to a 32-byte boundary (mask out lower 5 bits).
5046
LD L,A 6F
Store the aligned value back in L.
5047
If NZ (not at the sector boundary), JUMP back to 502FH to continue scanning.

FDE scan complete. Format and display the FDE count and the complete summary line.

5049
LD HL,5176H 21 76 51
Point HL to 5176H, the FDE count position in the summary template.
504C
GOSUB to 50BFH to format the FDE count and store it.
504F
LD HL,514EH 21 4E 51
Point HL to 514EH, the start of the complete disk summary template: "DRIVE 000 XXXXXXXXXX MM/DD/YY 000 TRKS 000 FDES 0000 GRANS".
5052
GOSUB to 508FH to display the complete summary line.
5055
XOR A AF
Clear A to 00H (success code).
5056
POP BC C1
Restore BC (B=option flags, C=drive number) from the stack.
5057
RET C9
RETURN to the caller. A=00H on success, or error code on failure.

5058H – Check for P (Printer) Option Prefix

Checks if the current command-line character is P (50H). If so, modifies the output vectors to redirect all character and string output to the printer via self-modifying code, sets bit 3 of Register B, and returns the next character. If not P, returns the current character unchanged.

5058
LD A,(HL) 7E
Load Register A with the current character from the command line at HL.
5059
CP 50H FE 50
Compare Register A against 50H (ASCII P). If A=50H, Z FLAG is set.
505B
INC HL 23
INCrement HL to advance past the current character (whether P or not).
505C
RET NZ C0
If NZ (not P), RETURN. A contains the non-P character, HL points past it.

Character is P. Redirect output to the printer by modifying two code locations.

505D
LD A,3BH 3E 3B
Load A with 3BH, the low byte of the ROM printer routine address (003BH).
505F
LD (50A8H),A 32 A8 50
Store 3BH at 50A8H. [SELF-MODIFYING CODE] Changes the CALL 0033H at 50A7H to CALL 003BH, redirecting single-character output from screen to printer.
5062
LD A,6AH 3E 6A
Load A with 6AH, the low byte of the SYS0 printer string display routine (446AH).
5064
LD (5090H),A 32 90 50
Store 6AH at 5090H. [SELF-MODIFYING CODE] Changes the JP 4467H at 508FH to JP 446AH, redirecting string display from screen to printer.
5067
SET 3,B CB D8
SET bit 3 of Register B to mark P (Printer output) as active in the option flags.
5069
LD A,(HL) 7E
Load Register A with the next character from the command line (after the P).
506A
RET C9
RETURN. A=next character, B has bit 3 set, output vectors modified for printer.

506BH – Pause for Screen Full

When output is to the screen (50A8H=33H), displays a "?" prompt and waits for the Enter or Break key. When output is to the printer (50A8H=3BH), returns immediately. Break key causes a jump to 402DH (DOS abort).

506B
BIT 5,(IY+09H) FD CB 09 6E
Test bit 5 of (IY+09H) = 4289H (disk configuration flags). If bit 5 is set, certain pause behavior is modified.
506F
RET NZ C0
If NZ (bit 5 is set), RETURN immediately without pausing.
5070
LD A,(50A8H) 3A A8 50
Load A with the character output vector byte at 50A8H.
5073
CP 33H FE 33
Compare A against 33H. If A=33H (screen output), Z FLAG is set.
5075
RET NZ C0
If NZ (A=3BH, printer mode), RETURN immediately without pausing. Printer output does not need screen-full pauses.
5076
LD A,3FH 3E 3F
Load A with 3FH (ASCII ?), the screen-full prompt character.
5078
GOSUB to 50A5H to display the "?" prompt character.

[KEYBOARD WAIT LOOP] – Wait for Enter or Break key.

507B
LD A,(3840H) 3A 40 38
Load A with the keyboard row at 3840H (Row 6: ENTER, CLEAR, BREAK, arrow keys, SPACE).
507E
AND 05H E6 05
AND with 05H (binary 00000101) to isolate bit 0 (ENTER key) and bit 2 (BREAK key). Active LOW: a 0 bit means the key is pressed.
5080
If Z (both bits are 0, meaning both keys are pressed simultaneously, or neither — actually Z means the AND result is zero, so both tested bits are 0, meaning both ENTER and BREAK are pressed), JUMP back to 507BH. Keep waiting until at least one key is released and re-pressed cleanly. [WAIT LOOP]
5082
RRCA 0F
Rotate A right. Bit 0 (ENTER status) shifts into Carry. If ENTER was the key detected (bit 0 = 1 after AND, active low inverted by the wait logic), Carry is set.
5083
If NO CARRY (ENTER was not pressed, meaning BREAK was pressed), JUMP to SYS0 at 402DH to abort the DIR command and return to NEWDOS/80 READY.

5086H – Output Space + Carriage Return

Outputs a space character (20H) followed by a carriage return (0DH). Used throughout SYS8 for line endings and blank line output.

5086
LD A,20H 3E 20
Load A with 20H (ASCII space).
5088
GOSUB to 50A5H to output the space character.
508B
LD A,0DH 3E 0D
Load A with 0DH (ASCII carriage return).
508D
JUMP to 50A5H to output the carriage return and return to the caller.

508FH – String Display Vector (Self-Modifying)

Displays the 03H-terminated string pointed to by HL. The target address is self-modifying: normally JP 4467H (screen), changed to JP 446AH (printer) when the P option is active.

508F
JUMP to the SYS0 string display routine at 4467H. [SELF-MODIFYING CODE] The byte at 5090H (the low byte of the address, currently 67H) is changed to 6AH at 5064H when printer mode is active, making this JP 446AH (printer string display).

5092H – Output B Space Characters

Outputs B space characters (20H) by looping through 50A5H.

5092
LD A,20H 3E 20
Load A with 20H (ASCII space).
5094
GOSUB to 50A5H to output one space character.
5097
DECrement B and loop back to 5092H if not zero. [SPACE OUTPUT LOOP]
5099
RET C9
RETURN to the caller.

509AH – Display B Characters from Buffer

Displays B characters from the buffer at HL. For each non-space character displayed, Register C is decremented (tracking the column count). Spaces are output directly without decrementing C.

509A
LD A,(HL) 7E
Load A with the current character from the buffer at HL.
509B
CP 20H FE 20
Compare A against 20H (space). If A=20H, Z FLAG is set.
509D
INC HL 23
INCrement HL to the next character.
509E
If NZ (character is not a space), GOSUB to 50A4H to decrement C and output the character.
50A1
DECrement B and loop back to 509AH if not zero. [DISPLAY LOOP]
50A3
RET C9
RETURN to the caller.

50A4H – Decrement Column Counter and Output Character

Decrements Register C (column counter) and falls through to 50A5H to output the character in Register A.

50A4
DEC C 0D
DECrement Register C (column counter) by 1.

50A5H – Character Output (Self-Modifying)

Outputs the character in Register A to the screen or printer. Preserves DE and AF across the call to the ROM routine. The ROM routine address is self-modifying: normally 0033H (screen), changed to 003BH (printer) when P option active.

50A5
PUSH DE D5
Save DE onto the stack.
50A6
PUSH AF F5
Save AF (character to output and flags) onto the stack.
50A7
GOSUB to ROM routine at 0033H to display the character in A. [SELF-MODIFYING CODE] The byte at 50A8H (currently 33H) is changed to 3BH at 505FH when printer mode is active, making this CALL 003BH (ROM printer output).
50AA
POP AF F1
Restore AF from the stack.
50AB
POP DE D1
Restore DE from the stack.
50AC
RET C9
RETURN to the caller.

50ADH – 24-Bit Division (AHL ÷ C)

Performs 24-bit unsigned division. Divides the 24-bit value in A:H:L by the 8-bit divisor in Register C. Uses a shift-and-subtract algorithm over 24 iterations. Returns quotient in E (or AHL depending on usage context) and remainder in A.

50AD
LD B,18H 06 18
Load B with 18H (24 decimal). Loop counter for 24 bits of the dividend.
50AF
XOR A AF
Clear A to 00H. A accumulates the running remainder during the division.

[DIVISION LOOP START] – Shift-and-subtract division: shift E:HL left one bit, shift carry into A (remainder), subtract C if possible.

50B0
SLA E CB 23
Shift Register E left. The highest bit shifts into Carry. The lowest bit becomes 0 (will be set to 1 if the subtraction succeeds).
50B2
ADC HL,HL ED 6A
ADD HL to itself with carry (shift HL left, propagating carry from E). This shifts the 24-bit dividend E:HL left by one bit.
50B4
RLA 17
Rotate A left through carry. The carry from the HL shift enters A bit 0. A accumulates the running remainder.
50B5
If CARRY set (remainder overflowed 8 bits), JUMP to 50BAH to perform the subtraction unconditionally.
50B7
CP C B9
Compare A (remainder) against C (divisor). If A ≥ C, CARRY is clear (subtraction will succeed).
50B8
If CARRY set (A < C, remainder too small), JUMP to 50BCH to skip the subtraction. The quotient bit stays 0.
50BA
SUB C 91
SUBtract C (divisor) from A (remainder). The remainder now holds A − C.
50BB
INC E 1C
INCrement E. This sets the lowest bit of the quotient to 1 (the subtraction succeeded, so this quotient bit is 1).
50BC
DECrement B and loop back to 50B0H if not zero. [DIVISION LOOP END] After 24 iterations, E:HL contains the quotient and A contains the remainder.
50BE
RET C9
RETURN. Quotient in E:HL, remainder in A.

50BFH – Format 16-Bit Number as 4-Digit Decimal

Formats the 16-bit value in BC as a 4-digit decimal ASCII string and stores it at the address in HL. Uses the divisor table at 510FH (entries: 1000, 100, 10). Leading zeros are suppressed with spaces.

50BF
LD A,B 78
Load A with B (high byte of the number).
50C0
LD B,C 41
Copy C to B. Now A:B = high:low of the 16-bit value.
50C1
LD C,00H 0E 00
Clear C. A:B:C forms a 24-bit value with C=00H as the low byte (effectively the 16-bit number × 256, but the formatting routine handles this).
50C3
LD DE,510FH 11 0F 51
Point DE to 510FH, the 4-digit divisor table (1000, 100, 10 as 16-bit signed values).

50C4H – Format 16-Bit Number (Alternate Entry)

Alternate entry point for 4-digit formatting when DE is already set to the divisor table. Falls through to the common decimal conversion loop at 50C8H.

50C4
LD A,B 78
Load A with B (high byte).
50C5
LD B,C 41
Copy C to B.
50C6
LD C,00H 0E 00
Clear C to zero.

50C7H – Format 24-Bit Number (Alternate Entry)

Alternate entry when A:B:C already holds the 24-bit value and DE already points to the divisor table. Falls through to 50C8H.

50C7
NOP 00
No operation. Placeholder to align the entry point.

50C8H – Decimal Conversion Loop

The core decimal conversion routine. Converts the 24-bit value in A:B:C into ASCII digits using a divisor table pointed to by DE. Each divisor entry is a 16-bit signed value. The routine repeatedly adds the (negative) divisor until the result goes positive, counting iterations to derive each digit. Results are stored sequentially at (HL). Leading zeros are replaced with spaces.

50C8
PUSH HL E5
Save HL (output buffer pointer) onto the stack.
50C9
LD H,A 67
Copy A to H. H:B:C is the working 24-bit value.
50CA
LD L,30H 2E 30
Load L with 30H (ASCII 0). L is the digit counter starting at ASCII '0'. Each iteration increments L; the final value is the ASCII digit.

[DIGIT EXTRACTION LOOP] – Repeatedly add the divisor (which is negative) to the 24-bit value until overflow. The count of additions = the digit value.

50CC
LD A,(DE) 1A
[ADD LOOP] Load A with the low byte of the current divisor from the table at DE.
50CD
ADD A,C 81
ADD the divisor low byte to C (low byte of the working value).
50CE
LD C,A 4F
Store the result back in C.
50CF
INC DE 13
INCrement DE to point to the high byte of the divisor.
50D0
LD A,(DE) 1A
Load A with the high byte of the current divisor.
50D1
ADC A,B 88
ADD with carry to B (middle byte of the working value). Propagates carry from the low byte addition.
50D2
LD B,A 47
Store the result back in B.
50D3
LD A,00H 3E 00
Load A with 00H. Used to propagate the carry into the high byte.
50D5
ADC A,H 8C
ADD with carry to H (high byte of the working value).
50D6
LD H,A 67
Store the result back in H.
50D7
DEC DE 1B
DECrement DE back to the low byte of the divisor (for the next iteration).
50D8
INC L 2C
INCrement L (digit counter). Each successful addition represents one unit of the current digit.
50D9
If NO CARRY (the addition did not overflow, the working value is still positive), JUMP back to 50CCH to add the divisor again. [ADD LOOP END]

The addition overflowed (went negative). The current digit value is in L. Now subtract the divisor once to undo the last addition (which caused the overflow), restoring the remainder for the next digit.

50DB
LD A,C 79
Load A with C (low byte).
50DC
INC DE 13
INCrement DE to high byte of divisor.
50DD
PUSH DE D5
Save DE (divisor table pointer, high byte) onto the stack.
50DE
LD D,(HL) 56
Load D with (HL). Note: at this point HL is not the output pointer (it was saved on stack at 50C8H). H=high working byte, L=digit counter. (HL) accesses memory at the digit counter address — this appears to be loading the high byte of the divisor for the undo step.
50DF
LD E,A 5F
Copy A (C low byte) to E.
50E0
LD A,(DE) 1A
Load A with the byte at address DE. This reads back the divisor byte for the undo subtraction.
50E1
SUB C 91
SUBtract C from A. Undo the last addition's low byte effect.
50E2
LD C,A 4F
Store result in C.
50E3
POP DE D1
Restore DE (divisor table pointer).
50E4
LD A,(DE) 1A
Load A with the high byte of the divisor.
50E5
SBC A,B 98
SUBtract with borrow: undo the high byte addition.
50E6
LD B,A 47
Store result in B.
50E7
INC DE 13
INCrement DE to advance to the next divisor entry in the table.
50E8
LD A,H 7C
Load A with H (high byte of working value, for sign propagation in the undo).
50E9
SBC A,00H DE 00
SUBtract with borrow from 00H. Propagates borrow from the B subtraction into the high byte.
50EB
LD H,A 67
Store the corrected high byte back in H.

The remainder is now correct in H:B:C. Store the digit (in L) at the output buffer and check for leading zero suppression.

50EC
LD A,L 7D
Load A with L (the ASCII digit, 30H–39H). If L=30H, this is a zero digit.
50ED
POP HL E1
Restore HL (output buffer pointer) from the stack (saved at 50C8H).
50EE
CP 31H FE 31
Compare A against 31H (ASCII 1). If A ≥ 31H, this is a non-zero digit.
50F0
If NO CARRY (A ≥ 31H, non-zero digit), JUMP to 50F6H to store the digit.
50F2
LD A,(HL) 7E
Load A with the current byte at the output buffer position. If the buffer was pre-filled with spaces (20H), this keeps the space for leading zeros.
50F3
CP 30H FE 30
Compare A against 30H. If the buffer already contains a digit (≥ 30H), a non-leading zero has been placed, so subsequent zeros are real digits.
50F5
If CARRY (buffer contains space, 20H < 30H, meaning we are still in leading zeros), JUMP to 50F8H to skip storing (keep the space).
50F6
LD A,L 7D
Reload A with L (the ASCII digit to store).
50F7
LD (HL),A 77
Store the ASCII digit at the output buffer position.
50F8
INC HL 23
INCrement HL to the next output buffer position.
50F9
LD A,(DE) 1A
Load A with the low byte of the next divisor entry. If this byte is the table terminator, we are done.
50FA
INC DE 13
INCrement DE to the high byte.
50FB
OR (DE) ?
OR A with the high byte of the next divisor. If the entire 16-bit divisor is 0000H (end of table), the Z FLAG is set.
50FC
DEC DE 1B
DECrement DE back to the low byte.
50FD
If NZ (more divisors remain), JUMP back to 50C8H to extract the next digit. [DIGIT LOOP CONTINUES]

All divisor entries exhausted. The ones digit remains in C. Convert and store it.

50FF
LD A,C 79
Load A with C (the remaining ones digit, 0–9).
5100
ADD 30H C6 30
ADD 30H to convert to ASCII.
5102
LD (HL),A 77
Store the final digit at the output buffer.
5103
INC HL 23
INCrement HL past the last digit.
5104
RET C9
RETURN. HL points past the formatted number string.

5105H – Decimal Conversion Divisor Tables

Lookup tables used by the decimal conversion routine at 50C8H. Each entry is a 16-bit signed value representing a power of 10 (negated for the subtraction-based conversion algorithm). The 6-digit table starts at 5109H; the 4-digit table starts at 510FH. Table entries are terminated by 0000H.

5105
DEFB 00H,00H 00 00
Padding / alignment bytes before the divisor tables.
5107
DEFB 00H,00H 00 00
Additional padding.
5109
DEFW 0160H 60 01
6-digit table entry 1: 0160H = +256 × 100000 encoded. This is the −100000 divisor (encoded as the complement used by the addition loop).
510B
DEFW 0D8F0H F0 D8
6-digit table entry 2: D8F0H = −10000 (signed 16-bit: 65536 − 10000 = 55536 = D8F0H).
510D
DEFW 0FC18H 18 FC
6-digit table entry 3: FC18H = −1000 (signed 16-bit: 65536 − 1000 = 64536 = FC18H).
510F
DEFW 0FF9CH 9C FF
4-digit table entry 1: FF9CH = −100 (signed 16-bit: 65536 − 100 = 65436 = FF9CH).
5111
DEFW 0FFF6H F6 FF
4-digit table entry 2: FFF6H = −10 (signed 16-bit: 65536 − 10 = 65526 = FFF6H).
5113
DEFW 0000H 00 00
Table terminator: 0000H marks the end of the divisor table.

5118H – Text String Data Area

Static text strings used by the DIR command for display output. Each string is terminated with 03H (for the 4467H display routine) or 0DH (carriage return). These strings are referenced by address throughout SYS8.

5118
DEFM "MOUNT " 4D 4F 55 4E 54 20
Text: MOUNT (6 bytes).
511E
DEFB 03H 03
String terminator (03H).
511F
DEFM " DISKETTE ON DRIVE 0 (ENTER)" 20 44 49 53 4B 45 54 54 45 20 4F 4E 20 44 52 49 56 45 20 30 20 20 28 45 4E 54 45 52 29
Text: DISKETTE ON DRIVE 0 (ENTER) (29 bytes). The "0" at offset 19 is overwritten at runtime with the actual drive number.
513C
DEFB 0DH 0D
Carriage return terminator.
513D
DEFM "SYSTEM" 53 59 53 54 45 4D
Text: SYSTEM (6 bytes). Used in the mount prompt for swap mode when remounting the system disk.
5143
DEFB 03H 03
String terminator.
5144
DEFM "TARGET" 54 41 52 47 45 54
Text: TARGET (6 bytes). Used in the mount prompt for swap mode when mounting the target disk.
514A
DEFB 03H 03
String terminator.
514B
DEFB 1CH 1C
Clear screen control code (1CH = Home cursor).
514C
DEFB 1FH 1F
Clear to end of screen control code (1FH).
514D
DEFB 03H 03
String terminator.

514EH – Disk Summary Display Template (64 Bytes)

Pre-formatted template for the disk summary line. Contains fixed text with placeholder positions for the drive number, disk name, date, track count, FDE count, and free granule count. The formatting routines at 4FDBH–5055H write numeric values into the placeholder positions before the template is displayed.

514E
DEFM " DR" 20 20 20 44 52
Template: leading spaces + "DR" (5 bytes). Start of "DRIVE" label.
5153
DEFM "000" 30 30 30
Drive number placeholder at 5153H (3 bytes "000"). Overwritten with the formatted drive number.
5156
DEFM " " 20 20 20
Separator spaces (3 bytes).
5159
DEFM " " 20 20 20 20 20 20 20 20
Disk name placeholder at 5159H (8 spaces). Overwritten with the disk name from the GAT.
5161
DEFM " " 20 20
Separator spaces (2 bytes).
5163
DEFM " " 20 20 20 20 20 20 20 20
Date placeholder at 5163H (8 spaces). Overwritten with the date string (MM/DD/YY).
516B
DEFB 20H 20
Separator space.
516C
DEFM " 000" 20 30 30 30
Track count placeholder at 516CH (4 bytes). Overwritten with the track count.
5170
DEFM " TRKS" 20 54 52 4B 53
Label: " TRKS" (5 bytes).
5175
DEFB 20H 20
Separator space.
5176
DEFM " 000" 20 30 30 30
FDE count placeholder at 5176H (4 bytes). Overwritten with the free directory entry count.
517A
DEFM " FDES" 20 46 44 45 53
Label: " FDES" (5 bytes).
517F
DEFB 20H 20
Separator space.
5180
DEFM " 0000" 20 30 30 30 30
Free granule count placeholder at 5180H (5 bytes). Overwritten with the free granule count.
5185
DEFM " GRANS" 20 47 52 41 4E 53
Label: " GRANS" (6 bytes).
518B
DEFB 0DH 0D
Carriage return terminator.

518CH – File Detail Display Template (48 Bytes)

Pre-formatted template for the detailed file information line (used with the A option). Contains placeholder positions for EOF, LRL, record count, granule count, extent count, and the 11-character attribute flag string.

518C
DEFM " 0000/" 20 20 30 30 30 30 2F
EOF position placeholder at 518CH (7 bytes). " 0000/" — overwritten with the EOF byte offset and "/" separator.
5193
DEFM "000 " 30 30 30 20
Continuation of EOF field (4 bytes). "000 " — overwritten with the sector portion.
5197
DEFM " 000" 20 30 30 30
LRL placeholder at 5197H (4 bytes). Overwritten with the Logical Record Length.
519B
DEFM " 000000" 20 30 30 30 30 30 30
Record count placeholder at 519BH (7 bytes). Overwritten with the record count (up to 6 digits).
51A2
DEFB 20H 20
Separator space.
51A3
DEFM " 0000" 20 30 30 30 30
Granule count placeholder at 51A3H (5 bytes). Overwritten with the file's granule count.
51A8
DEFB 20H 20
Separator space.
51A9
DEFM " 000" 20 30 30 30
Extent count placeholder at 51A9H (4 bytes). Overwritten with the extent count.
51AD
DEFM " " 20 20
Separator spaces (2 bytes).
51AF
DEFM "..........." 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E
Attribute flag display buffer at 51AFH (11 bytes of dots). Overwritten at runtime with "SIUEC....UAL" where letters replace dots for active flags. Positions: S=System, I=Invisible, U=Updated, E=Extended, C=Control, dots=unused, U=Update password, A=Access password, digit=access Level.
51BA
DEFB 30H 30
Access level digit position (ASCII '0' default).
51BB
DEFB 0DH 0D
Carriage return terminator.

51BCH – Column Header Text (43 Bytes)

The column header string displayed by the 4FC7H routine when the A (show All) option is active. Shows the labels for each field in the detail display template.

51BC
DEFM "EOF LRL RECS GRANS EXTS SIUEC....UAL" 45 4F 46 20 20 20 20 4C 52 4C 20 20 20 52 45 43 53 20 47 52 41 4E 53 20 45 58 54 53 20 20 53 49 55 45 43 2E 2E 2E 2E 55 41 4C
Column header text (42 bytes): labels for EOF position, Logical Record Length, record count, granule count, extent count, and attribute flags (S=System, I=Invisible, U=Updated, E=Extended, C=Control, U=Update password, A=Access password, L=access Level).
51E6
DEFB 0DH 0D
Carriage return terminator.
51E7
DEFB 00H 00
End of SYS8/SYS module. Padding byte at 51E7H.