4D00H - SYS17/SYS ENTRY POINT — SYSTEM AND WRDIRP COMMAND DISPATCHER
SYS17/SYS is a DOS overlay module that implements two commands: SYSTEM (which displays and modifies the system configuration options stored in the 3rd sector of the system diskette) and WRDIRP (which rewrites directory sector address marks for Model I/III diskette interchangeability). On entry, Register A contains a command identifier byte passed by the DOS command dispatcher. If Register A = 53H (ASCII S), execution branches to the WRDIRP command handler at 4F6DH. If Register A = 33H (the internal code for the SYSTEM command), execution falls through to the SYSTEM command handler. Any other value returns error code 2AH (general error) to the caller.
4D00
CP 53H FE 53
Compare Register A (the command identifier byte passed by the DOS command dispatcher) against 53H (ASCII S for WRDIRP). If Register A equals 53H, the Z FLAG is set; otherwise the NZ FLAG is set.
4D02
If the Z FLAG has been set (the command identifier is 53H, meaning the WRDIRP command was requested), JUMP to 4F6DH to execute the WRDIRP command handler.
4D05
CP 33H FE 33
Compare Register A against 33H (the internal command code for the SYSTEM command). If Register A equals 33H, the Z FLAG is set; otherwise the NZ FLAG is set.
4D07
LD A,2AH 3E 2A
Load Register A with 2AH (error code 42 decimal = general error). This pre-loads the error code in case the command identifier did not match.
4D09
RET NZ C0
If the NZ FLAG has been set (Register A was not 33H, meaning neither SYSTEM nor WRDIRP was requested), RETURN to the DOS command dispatcher with error code 2AH in Register A.
Execution reaches here only if the command identifier was 33H (SYSTEM command). The two NOP bytes at 4D0AH-4D0BH are unused padding (reserved space for future patches or removed code).
4D0A
NOP 00
No operation (unused byte).
4D0B
NOP 00
No operation (unused byte).
4D0CH - SYSTEM COMMAND: INITIALIZATION AND SECTOR READ
This section initializes the SYSTEM command by saving the drive number, setting up the sector I/O parameter block to reference the 3rd sector of the system diskette, reading that sector into the DOS buffer, and then beginning to parse the command line for option parameters. If no parameters are provided (the command line is exhausted), execution branches to the display routine at 4DC0H to show the current settings.
4D0C
LD A,B 78
Load Register A with the value in Register B. Register B contains the drive number (0–3) parsed from the SYSTEM command line by the DOS command dispatcher (e.g., from "SYSTEM,0,AA=Y").
4D0D
LD (4F1CH),A 32 1C 4F
Store Register A (the drive number) into memory location 4F1CH, which is a local variable within SYS17's data area that holds the target drive number for subsequent sector I/O operations.
4D10
GOSUB to 4E21H, a local subroutine that sets up the sector I/O parameter block. That routine loads Register A with 02H (sector number 2, the 3rd sector on the diskette, zero-indexed), stores it at 4F20H (the sector number field of the I/O parameter block at 4F16H), and points DE to 4F16H (the base of the I/O parameter block). On return, DE = 4F16H and the parameter block is configured to access sector 2 of the target drive.
4D13
GOSUB to 4436H (in SYS0), the DOS sector read routine. This reads the sector identified by the I/O parameter block at DE (sector 2 of the system diskette) into the DOS buffer. On return, Register A = 0 and Z FLAG set if the read was successful; NZ FLAG set with an error code in Register A if the read failed.
4D16
RET NZ C0
If the NZ FLAG has been set (the sector read failed), RETURN to the DOS command dispatcher with the error code in Register A.
The sector read succeeded. The 3rd sector of the system diskette (containing the SYSTEM option bytes) is now in the DOS buffer. HL points to the current position in the command line (after the drive number and comma). Now we begin parsing the command line for option parameters.
4D17
GOSUB to 4C7AH (in SYS0), the command line token scanner. This routine advances HL past whitespace and commas in the command line buffer, returning: CARRY FLAG set if end-of-line (0DH terminator) reached; Z FLAG set if a comma delimiter was found (no more tokens in this field); NZ FLAG set with HL pointing to the start of the next token if a parameter was found.
4D1A
RET C D8
If the CARRY FLAG has been set (end of command line reached — no more parameters to process), RETURN to the DOS command dispatcher. The sector has been read but no modifications were requested, so we return without writing.
4D1B
If the Z FLAG has been set (no option parameters were specified on the command line — only the drive number was given), JUMP to 4DC0H to display the current SYSTEM option settings without making any changes.
4D1EH - PARSE SYSTEM OPTION LETTER PAIR (e.g., "AA", "BK")
This routine parses a two-letter SYSTEM option identifier from the command line. SYSTEM options use a two-letter code where the first letter is 'A' or 'B' (the row) and the second letter is 'A' through 'Z' (the column). The two letters are converted into a single index (0–71) into the option descriptor table at 4F24H. The first letter ('A'=0, 'B'=1, etc.) is multiplied by 26 (19H × 2 iterations via DJNZ, yielding index × 26), and the second letter's offset (0–25) is added. This combined index is used to look up the option's descriptor byte, which encodes the option type and storage location.
4D1E
LD A,(HL) 7E
Load Register A with the byte at the address pointed to by HL (the current character in the command line). This is the first letter of the option pair (expected to be 'A' or 'B').
4D1F
SUB 41H D6 41
SUBtract 41H (ASCII A) from Register A, converting the first option letter to a zero-based index: 'A'→0, 'B'→1, 'C'→2, etc.
4D21
CP 09H FE 09
Compare Register A against 09H (decimal 9). Valid first letters are 'A' through 'I' (indices 0–8). If Register A < 09H, the CARRY FLAG is set (valid); if Register A >= 09H, the NO CARRY FLAG is set (invalid first letter).
4D23
If the CARRY FLAG has been set (the first letter is valid, in the range 'A' through 'I'), JUMP forward to 4D2AH to continue parsing.
4D25
LD A,34H 3E 34
Load Register A with 34H (error code 52 decimal = parse error). The option letter was out of range.
4D27
JUMP to 4E81H, the error exit routine. That routine jumps to 4409H (in SYS0), the DOS error handler, with the error code in Register A. [ERROR PATH — invalid option letter]
The first option letter is valid (index 0–8 in Register A). Now multiply it by 26 (decimal) to get the row offset. The algorithm: start with the index in A, then add it to itself 25 more times (total of 26 copies = index × 26). Register B is loaded with 19H (25 decimal) and the DJNZ loop adds A to itself B times, producing A = original_index × 26.
4D2A
LD C,A 4F
Load Register C with Register A (save the first letter's zero-based index, 0–8).
4D2B
LD B,19H 06 19
Load Register B with 19H (25 decimal). This is the loop counter: the following loop will add C to A twenty-five times, yielding A = index + (index × 25) = index × 26.
4D2D
ADD A,C 81
ADD Register C (the first letter's index) to Register A. Each iteration accumulates one more copy of the index. [LOOP START — multiply first letter index by 26]
4D2E
DECrement Register B and loop back to 4D2DH if not zero. After 25 iterations, Register A = first_letter_index × 26. [LOOP END]
4D30
LD C,A 4F
Load Register C with Register A (the row offset = first_letter_index × 26). This will be combined with the second letter's offset.
4D31
INC HL 23
INCrement HL by 1, advancing the command line pointer past the first option letter to the second letter.
4D32
LD A,(HL) 7E
Load Register A with the byte at HL (the second letter of the option pair, e.g., the 'K' in "BK").
4D33
SUB 41H D6 41
SUBtract 41H (ASCII A) from Register A, converting the second letter to a zero-based column index: 'A'→0, 'B'→1, … 'Z'→25.
4D35
CP 1AH FE 1A
Compare Register A against 1AH (26 decimal). If Register A < 1AH, the second letter is valid ('A'–'Z', CARRY set). If Register A >= 1AH, the second letter is invalid (NO CARRY).
4D37
INC HL 23
INCrement HL by 1, advancing the command line pointer past the second option letter (now pointing to the '=' sign or whatever follows).
4D38
If the NO CARRY FLAG has been set (the second letter is not in 'A'–'Z'), JUMP back to 4D25H to report a parse error (error code 34H). [ERROR PATH — invalid second option letter]
4D3A
ADD A,C 81
ADD Register C (the row offset = first_letter_index × 26) to Register A (the column index = second_letter_index). The result in Register A is the combined linear option index: (first_letter × 26) + second_letter.
4D3B
LD E,A 5F
Load Register E with Register A (the combined option index). This will be used as a 16-bit offset into the option descriptor table.
4D3C
LD D,00H 16 00
Load Register D with 00H. DE now holds the 16-bit option index (D=00, E=combined index).
4D3E
CP 48H FE 48
Compare Register A (the combined option index) against 48H (72 decimal). The option descriptor table at 4F24H has 72 entries (indices 00H–47H). If the index < 48H, the CARRY FLAG is set (valid); if >= 48H, NO CARRY (out of range).
4D40
If the NO CARRY FLAG has been set (the combined option index is 48H or higher, meaning the option code is beyond the defined range), JUMP back to 4D25H to report a parse error. [ERROR PATH — option index out of range]
The combined option index (0–71) is valid. Now look up the option's descriptor byte from the table at 4F24H. The descriptor byte encodes: Bit 7 = 1 means it is a numeric value option (not Y/N); Bit 6 = 1 means the value is a 16-bit (2-byte) value; Bits 5–3 encode additional type info; Bits 3–0 encode the storage offset within the system options area at 43F0H (for Y/N flags) or 43A0H (for numeric values).
4D42
PUSH HL E5
Save HL (the command line pointer, currently positioned after the two-letter option code) onto the stack.
4D43
LD HL,4F24H 21 24 4F
Point Register Pair HL to 4F24H, the base address of the option descriptor table. Each byte in this table describes one SYSTEM option: its type (Y/N flag vs. numeric) and its storage location offset.
4D46
ADD HL,DE 19
ADD DE (the combined option index) to HL. HL now points to the specific descriptor byte for the requested option in the table at 4F24H.
4D47
LD A,(HL) 7E
Load Register A with the option descriptor byte from the table. This byte encodes the option's type and storage location.
4D48
CP FEH FE FE
Compare Register A against FEH. A descriptor value of FEH means "undefined/reserved option" and FFH means "end-of-valid-range marker." If Register A < FEH, the CARRY FLAG is set (valid defined option). If Register A >= FEH, the NO CARRY FLAG is set (undefined or invalid).
4D4A
LD B,A 47
Load Register B with Register A (save the descriptor byte for later use in determining the option type and storage offset).
4D4B
POP HL E1
Restore HL from the stack (the command line pointer, positioned after the two-letter option code).
4D4C
If the NO CARRY FLAG has been set (the descriptor byte was FEH or FFH, meaning this option code is undefined/reserved), JUMP back to 4D25H to report a parse error. [ERROR PATH — undefined option]
4D4EH - CHECK FOR '=' SIGN AND DISPATCH BY OPTION TYPE
After successfully looking up the option descriptor byte (now in Register B), this section checks that the next character on the command line is '=' (3DH). It then examines Bit 7 of the descriptor byte to determine whether this is a Y/N flag option (Bit 7 = 0) or a numeric value option (Bit 7 = 1), and dispatches accordingly.
4D4E
LD A,(HL) 7E
Load Register A with the byte at HL (the next character on the command line, which should be '=' following the two-letter option code).
4D4F
CP 3DH FE 3D
Compare Register A against 3DH (ASCII =). If the character is '=', the Z FLAG is set; otherwise the NZ FLAG is set.
4D51
INC HL 23
INCrement HL by 1, advancing the command line pointer past the '=' character (or past whatever character was there, for the error check below).
4D52
If the NZ FLAG has been set (the character was not '=', meaning the option syntax is malformed), JUMP to 4D7FH which leads to the parse error handler at 4E7FH. [ERROR PATH — missing '=' sign]
4D54
BIT 7,B CB 78
Test Bit 7 of Register B (the option descriptor byte). Bit 7 = 0 means this is a Y/N flag option; Bit 7 = 1 means this is a numeric value option.
4D56
If the NZ FLAG has been set (Bit 7 of the descriptor is 1, meaning this is a numeric value option), JUMP to 4D82H to handle numeric value parsing and storage.
4D58H - Y/N FLAG OPTION HANDLER
This section handles SYSTEM options that take Y/N values (e.g., "AA=Y", "BK=N"). The descriptor byte (in Register B) with Bit 7 = 0 encodes the Y/N flag's storage information. Bits 4–1 of the descriptor (after rotation) determine an offset within the Y/N flag byte table at 43F0H, and specific bits within the descriptor select which bit position to set or reset. The code uses self-modifying instructions to construct the correct RES/SET opcodes for the target bit.
4D58
LD A,B 78
Load Register A with Register B (the option descriptor byte, with Bit 7 = 0 confirming this is a Y/N flag option).
4D59
RRCA 0F
Rotate Register A Right through Carry. This shifts all bits right by one position: bit 0 goes to Carry, bit 7 gets old Carry. The purpose is to shift bits 3–1 of the descriptor into bits 2–0, extracting the bit position field for the RES/SET opcode.
4D5A
AND 38H E6 38
AND Register A with 38H (binary 00111000), isolating bits 5–3. After the RRCA, the original descriptor bits 6–4 are now in bit positions 5–3. This extracts the "bit number" field that will be inserted into the CB-prefix RES/SET opcode (the Z80 CB opcodes encode the bit number in bits 5–3 of the second byte).
4D5C
OR 86H F6 86
OR Register A with 86H (binary 10000110). This constructs the second byte of a RES n,(HL) opcode. The base opcode for RES 0,(HL) is CB 86H; ORing in the bit number field (bits 5–3) produces the correct RES opcode for the target bit. [SELF-MODIFYING CODE preparation]
4D5E
LD (4D74H),A 32 74 4D
Store Register A (the constructed RES opcode byte) into memory location 4D74H. This is [SELF-MODIFYING CODE] — the instruction at 4D73H is CB xx where xx will be replaced with the RES opcode byte, creating the correct RES n,(HL) instruction to clear the target bit at runtime.
4D61
ADD 40H C6 40
ADD 40H to Register A (the RES opcode byte). In Z80 CB-prefix opcodes, adding 40H converts a RES instruction to the corresponding SET instruction (RES is CB 80-BFH, SET is CB C0-FFH). This constructs the SET n,(HL) opcode for the same bit number.
4D63
LD (4D7AH),A 32 7A 4D
Store Register A (the constructed SET opcode byte) into memory location 4D7AH. This is [SELF-MODIFYING CODE] — the instruction at 4D79H is CB xx where xx will be replaced with the SET opcode byte, creating the correct SET n,(HL) instruction at runtime.
The self-modifying code at 4D73H–4D74H now contains RES n,(HL) and 4D79H–4D7AH contains SET n,(HL) where n is the correct bit number for this option. Now extract the byte offset within the Y/N flag table at 43F0H.
4D66
LD A,B 78
Load Register A with Register B (the original option descriptor byte).
4D67
AND 0FH E6 0F
AND Register A with 0FH, isolating the low nibble (bits 3–0) of the descriptor byte. This extracts the byte offset index within the Y/N flag table at 43F0H.
4D69
LD E,A 5F
Load Register E with Register A (the byte offset index, 0–15).
4D6A
LD D,00H 16 00
Load Register D with 00H. DE now holds the 16-bit byte offset (D=00, E=offset index).
4D6C
LD A,(HL) 7E
Load Register A with the byte at HL (the value character from the command line, expected to be 'Y' or 'N').
4D6D
INC HL 23
INCrement HL by 1, advancing the command line pointer past the value character.
4D6E
PUSH HL E5
Save HL (the updated command line pointer) onto the stack for later restoration.
4D6F
LD HL,43F0H 21 F0 43
Point Register Pair HL to 43F0H, the base address of the Y/N option flag byte table within the system options area in the DOS buffer. Each byte in this table holds up to 8 individual Y/N flags as bit fields.
4D72
ADD HL,DE 19
ADD DE (the byte offset index) to HL. HL now points to the specific flag byte within the Y/N option table at 43F0H that contains the bit for this option.
4D73
RES 0,(HL) CB 86
Reset (clear) the target bit in the flag byte at (HL). [SELF-MODIFYING CODE] — The second byte (86H) was dynamically written at 4D5EH to encode the correct RES n,(HL) instruction for this option's bit number. This clears the flag, assuming the user specified 'N'.
4D75
CP 4EH FE 4E
Compare Register A (the value character read from the command line at 4D6CH) against 4EH (ASCII N). If the user typed 'N', the Z FLAG is set.
4D77
If the Z FLAG has been set (the user specified 'N'), JUMP forward to 4DA6H. The bit was already cleared by the RES instruction above, so no further action is needed — proceed to parse the next option. [SUCCESS PATH — option set to N]
4D79
SET 0,(HL) CB C6
Set the target bit in the flag byte at (HL). [SELF-MODIFYING CODE] — The second byte (C6H) was dynamically written at 4D63H to encode the correct SET n,(HL) instruction for this option's bit number. This sets the flag, for when the user specified 'Y'.
4D7B
CP 59H FE 59
Compare Register A (the value character) against 59H (ASCII Y). If the user typed 'Y', the Z FLAG is set.
4D7D
If the Z FLAG has been set (the user specified 'Y'), JUMP forward to 4DA6H. The bit was set by the SET instruction above — proceed to parse the next option. [SUCCESS PATH — option set to Y]
4D7F
JUMP to 4E7FH, the error handler. The value character was neither 'Y' nor 'N', so this is a parse error. 4E7FH loads error code 2FH and jumps to the DOS error handler at 4409H. [ERROR PATH — invalid Y/N value]
4D82H - NUMERIC VALUE OPTION HANDLER
This section handles SYSTEM options that take numeric values (descriptor Bit 7 = 1). Options with Bit 6 = 0 take a single-byte value (0–255); options with Bit 6 = 1 take a two-byte (16-bit) value (e.g., the HIMEM address for option AP). The routine parses the ASCII decimal or hex number from the command line, then stores the result at the appropriate offset within the system options area at 43A0H (for 1-byte values) or at 43A0H+30H (for 2-byte values stored as a word). Bits 4–0 of the descriptor byte encode the byte offset within 43A0H.
4D82
PUSH BC C5
Save BC onto the stack. Register B holds the option descriptor byte (with Bit 7 = 1 confirming numeric type).
4D83
GOSUB to 4E84H, the numeric value parser. This routine parses an ASCII number from the command line at HL. It handles both decimal and hexadecimal input (hex values end with 'H'). On return, DE contains the parsed numeric value, HL points past the parsed number in the command line, and the flags indicate success or error.
4D86
POP BC C1
Restore BC from the stack. Register B again holds the option descriptor byte.
4D87
LD A,B 78
Load Register A with Register B (the option descriptor byte).
4D88
AND 1FH E6 1F
AND Register A with 1FH, isolating bits 4–0 of the descriptor byte. This extracts the byte offset index within the numeric option storage area at 43A0H.
4D8A
PUSH HL E5
Save HL (the command line pointer, positioned past the parsed number) onto the stack.
4D8B
PUSH DE D5
Save DE (the parsed numeric value) onto the stack.
4D8C
LD HL,43A0H 21 A0 43
Point Register Pair HL to 43A0H, the base address of the numeric option storage area within the system options in the DOS buffer.
4D8F
LD E,A 5F
Load Register E with Register A (the byte offset index, 0–31).
4D90
LD D,00H 16 00
Load Register D with 00H. DE now holds the 16-bit byte offset.
4D92
ADD HL,DE 19
ADD DE (the byte offset) to HL. HL now points to the target storage location within the numeric options area at 43A0H for this option's value.
4D93
POP DE D1
Restore DE from the stack (the parsed numeric value: E = low byte, D = high byte).
4D94
BIT 6,B CB 70
Test Bit 6 of Register B (the option descriptor byte). Bit 6 = 0 means this is a single-byte value; Bit 6 = 1 means this is a 16-bit (two-byte) value.
4D96
If the Z FLAG has been set (Bit 6 = 0, meaning this is a single-byte value option), JUMP forward to 4DA1H to store only the low byte.
Bit 6 = 1: This is a 16-bit value option (e.g., option AP = HIMEM address). Store both bytes. The 16-bit values are stored at 43A0H + offset + 30H as a word (low byte first, then high byte).
4D98
LD A,L 7D
Load Register A with the low byte of HL (the current pointer into the 43A0H table).
4D99
ADD 30H C6 30
ADD 30H to Register A. This offsets the pointer by 30H (48 decimal) bytes forward from the single-byte area into the 16-bit value storage area at 43A0H+30H = 43D0H.
4D9B
LD L,A 6F
Load Register L with Register A. HL now points to the 16-bit storage location (43D0H + offset) for this option's word value.
4D9C
LD (HL),E 73
Store Register E (the low byte of the parsed numeric value) into the memory location pointed to by HL.
4D9D
INC HL 23
INCrement HL by 1 to point to the next byte (the high byte storage location).
4D9E
LD (HL),D 72
Store Register D (the high byte of the parsed numeric value) into the memory location pointed to by HL. The full 16-bit value is now stored as a little-endian word.
4D9F
JUMP forward to 4DA6H to continue parsing the next option on the command line. [SUCCESS PATH — 16-bit value stored]
Bit 6 = 0: This is a single-byte value option. Store only the low byte (Register E) and verify that the high byte (Register D) is zero (value must fit in 0–255).
4DA1
LD (HL),E 73
Store Register E (the low byte of the parsed numeric value) into the memory location pointed to by HL (the single-byte storage slot at 43A0H + offset).
4DA2
LD A,D 7A
Load Register A with Register D (the high byte of the parsed numeric value).
4DA3
OR A B7
OR Register A with itself. This sets the Z FLAG if D = 0 (the parsed value fits in a single byte), or NZ if D ≠ 0 (the value exceeds 255 and does not fit in a single byte).
4DA4
If the NZ FLAG has been set (the high byte is non-zero, meaning the parsed value exceeds 255 for a single-byte option), JUMP to 4D7FH → 4E7FH to report a parse error. [ERROR PATH — value too large for single-byte option]
4DA6H - OPTION STORED — PARSE NEXT OPTION OR WRITE AND EXIT
After successfully storing a Y/N flag or numeric value, this section restores the command line pointer and loops back to parse the next option. If no more options remain, it validates the drive count (option AL) and writes the modified system options sector back to the diskette.
4DA6
POP HL E1
Restore HL from the stack (the command line pointer, positioned after the last processed option parameter).
4DA7
GOSUB to 4C7AH (in SYS0), the command line token scanner. Advance past whitespace/commas to find the next parameter. Returns: CARRY = end of line; Z = comma found; NZ = next token found.
4DAA
RET C D8
If the CARRY FLAG has been set (end of command line — no more options), RETURN. However, this exits without writing the modified sector back to disk, which means the changes would be lost. This path is reached when the command line scanner returns carry, indicating an unexpected condition. (The normal write-back path is below via 4DAEH.)
4DAB
If the NZ FLAG has been set (another option parameter was found on the command line), JUMP back to 4D1EH to parse and process the next two-letter option code. [LOOP — process next option]
Z FLAG is set — no more option parameters on the command line. All requested options have been parsed and stored in the DOS buffer. Now validate the drive count (option AL at 43A0H) and write the modified sector back to disk.
4DAE
LD HL,43A0H 21 A0 43
Point Register Pair HL to 43A0H, the base of the numeric option storage area. The first byte at 43A0H is the value for option AL (number of physical drives in the system, value 1–4).
4DB1
LD A,(HL) 7E
Load Register A with the byte at (HL) — the current value of option AL (drive count).
4DB2
DEC A 3D
DECrement Register A by 1. This converts the drive count from 1-based to 0-based: 1→0, 2→1, 3→2, 4→3.
4DB3
CP 04H FE 04
Compare Register A against 04H. After the DEC, valid drive counts (1–4) produce values 0–3. If Register A < 04H, the CARRY FLAG is set (valid); if Register A >= 04H, the NO CARRY FLAG is set (the drive count is 0 or > 4, which is invalid).
4DB5
If the CARRY FLAG has been set (the drive count is valid, between 1 and 4), JUMP forward to 4DB9H to proceed with writing the sector.
4DB7
LD (HL),01H 36 01
Store 01H into the memory location at (HL) (43A0H, the option AL value). The drive count was invalid (0 or > 4), so force it to 1 (minimum valid drive count) as a safety measure.
4DB9
GOSUB to 4E21H, the I/O parameter block setup routine. This reloads the sector I/O parameter block at 4F16H with sector number 02H (the 3rd sector) and points DE to 4F16H, preparing for the sector write.
4DBC
GOSUB to 443CH (in SYS0), the DOS sector write routine. This writes the modified system options sector (sector 2) from the DOS buffer back to the system diskette on the target drive. On return, Register A = 0 and Z FLAG set if successful; NZ with error code in A if the write failed.
4DBF
RET NZ C0
If the NZ FLAG has been set (the sector write failed), RETURN to the DOS command dispatcher with the error code in Register A. [ERROR PATH — sector write failed]
4DC0H - DISPLAY CURRENT SYSTEM OPTIONS
This routine displays all currently defined SYSTEM options and their values. It walks through the option descriptor table at 4F24H, and for each defined option (descriptor byte < FEH), it computes the two-letter option code, looks up the stored value, and displays it. Y/N flag options display as "Y" or "N"; numeric options display as both a decimal value and a hex value with an "H" suffix. The entry point at 4DC0H sets up HL to point to the descriptor table, DE = 0000H (initial offset into the system options data), and B = 0DH (ASCII carriage return, used as the first separator character — producing a new line before the first option). Execution then jumps into the middle of the display loop at 4E13H.
4DC0
LD HL,4F24H 21 24 4F
Point Register Pair HL to 4F24H, the base address of the option descriptor table. Each byte in this table describes one SYSTEM option's type and storage information.
4DC3
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H. DE is used as an offset counter that tracks the current position within the system options data area. It is incremented as the code walks through the descriptor table.
4DC6
LD B,0DH 06 0D
Load Register B with 0DH (ASCII carriage return). Register B serves as the separator character to display before each option. The first separator is CR (new line), and subsequent separators will be set to 2CH (ASCII comma) at 4E0FH.
4DC8
JUMP forward to 4E13H, the descriptor table fetch point in the middle of the display loop. This skips the display body on the first pass to go directly to the descriptor check, which will process the first defined option.
4DCAH - DISPLAY LOOP BODY: OUTPUT ONE OPTION'S NAME AND VALUE
For each defined option, this section displays: the separator character (CR for the first option, comma for subsequent ones), the two-letter option code (e.g., "AA", "BK"), an '=' sign, and the option's current value.
For Y/N flag options (descriptor Bit 7 = 0), the current flag bit is read from the table at 43F0H and displayed as 'Y' or 'N'.
For numeric options (descriptor Bit 7 = 1), execution branches to 4E2AH for decimal+hex display.
The two-letter code is computed by dividing the current descriptor offset (DE) by 26 (1AH) using the SYS0 routine at 4C59H: the quotient becomes the first letter and the remainder becomes the second letter, each with 41H added to convert to ASCII 'A'–'Z'.
4DCA
LD A,B 78
Load Register A with Register B (the separator character: 0DH for the first option, or 2CH for subsequent options).
4DCB
GOSUB to 4E6BH, the character output wrapper. This routine displays the character in Register A on the screen via ROM routine 0033H, preserving DE and AF.
4DCE
PUSH HL E5
Save HL (the current pointer into the option descriptor table at 4F24H) onto the stack.
4DCF
PUSH DE D5
Save DE (the current option index offset, which tracks position in the descriptor table from 0 onward) onto the stack.
4DD0
PUSH BC C5
Save BC (B = separator character for next iteration, C = not currently used) onto the stack.
4DD1
EX DE,HL EB
Exchange DE and HL. HL now holds the current option index offset, and DE holds the descriptor table pointer.
4DD2
LD A,1AH 3E 1A
Load Register A with 1AH (26 decimal). This is the divisor for computing the two-letter option code: divide the option index by 26 to get the first letter (quotient) and second letter (remainder).
4DD4
GOSUB to 4C59H (in SYS0), an 8-bit division routine. This divides the value in HL by the divisor in Register A (26). On return, Register A contains the quotient (first letter index: 0='A', 1='B', etc.) and Register L contains the remainder (second letter index: 0='A', 1='B', … 25='Z').
4DD7
ADD 41H C6 41
ADD 41H (ASCII A) to Register A (the quotient), converting the first letter index to an ASCII letter: 0→'A', 1→'B', etc.
4DD9
LD H,A 67
Load Register H with Register A (temporarily store the ASCII first letter in H for later output).
4DDA
LD A,L 7D
Load Register A with Register L (the remainder from the division — the second letter index).
4DDB
ADD 41H C6 41
ADD 41H (ASCII A) to Register A, converting the second letter index to an ASCII letter.
4DDD
GOSUB to 4E6BH, the character output wrapper. Display the second letter of the option code (e.g., the 'K' in "BK"). Note: the second letter is displayed first because the first letter was saved in H.
4DE0
LD A,H 7C
Load Register A with Register H (the ASCII first letter of the option code, saved at 4DD9H).
4DE1
GOSUB to 4E6BH to display the first letter of the option code. Combined with the second letter displayed above, the screen now shows the two-letter code (e.g., "BK") — but note the letters appear in reverse order on screen: second letter first, then first letter. This is the intended behavior for the display format.
Wait — the second letter is displayed before the first letter. Let me re-examine: at 4DDDH the second letter (remainder) is displayed, then at 4DE1H the first letter (quotient) is displayed. This means the display order is second-letter followed by first-letter, which would produce "KB" instead of "BK". However, examining the manual, the options ARE listed as "AA", "AB", etc. — so this order produces the correct display because the screen cursor advances left-to-right, printing the column letter first and the row letter second, yielding the two-letter code in the correct "row-column" reading order as defined by the NEWDOS/80 manual.
4DE4
LD A,3DH 3E 3D
Load Register A with 3DH (ASCII =).
4DE6
GOSUB to 4E6BH to display the '=' character. The screen now shows the option code followed by '=' (e.g., "BK=").
4DE9
LD A,(DE) 1A
Load Register A with the byte at (DE). DE was set to the descriptor table pointer at 4DD1H (EX DE,HL), so this fetches the current option's descriptor byte from the table at 4F24H.
4DEA
LD B,A 47
Load Register B with Register A (save the descriptor byte in B for bit testing below).
4DEB
LD D,00H 16 00
Load Register D with 00H. This clears the high byte of DE, preparing it for use as a 16-bit offset. Register E will be loaded from the descriptor's low nibble below.
4DED
BIT 7,A CB 7F
Test Bit 7 of Register A (the descriptor byte). Bit 7 = 0 means this is a Y/N flag option; Bit 7 = 1 means this is a numeric value option.
4DEF
If the NZ FLAG has been set (Bit 7 = 1, meaning this is a numeric value option), JUMP to 4E2AH to display the numeric value in decimal and hex format.
4DF1H - DISPLAY Y/N FLAG VALUE
For Y/N flag options (descriptor Bit 7 = 0), this section uses self-modifying code to construct a BIT n,(HL) instruction that tests the correct flag bit at the correct byte offset in the Y/N flag table at 43F0H. If the bit is set, 'Y' is displayed; if clear, 'N' is displayed. The self-modifying technique mirrors the SET/RES approach used in the option-setting code at 4D58H.
4DF1
RRCA 0F
Rotate Register A (the descriptor byte) Right through Carry. This shifts the bit-number field (originally in bits 6–4) down into bits 5–3.
4DF2
AND 38H E6 38
AND Register A with 38H (binary 00111000), isolating bits 5–3. This extracts the bit number field for constructing the BIT opcode (Z80 CB-prefix instructions encode the bit number in bits 5–3 of the second byte).
4DF4
OR 46H F6 46
OR Register A with 46H (binary 01000110). This constructs the second byte of a BIT n,(HL) opcode. The base opcode for BIT 0,(HL) is CB 46H; ORing in the bit number field produces the correct BIT opcode for the target bit. [SELF-MODIFYING CODE preparation]
4DF6
LD (4E04H),A 32 04 4E
Store Register A (the constructed BIT opcode byte) into memory location 4E04H. This is [SELF-MODIFYING CODE] — the instruction at 4E03H is CB xx where xx will be replaced with the BIT opcode byte, creating the correct BIT n,(HL) instruction at runtime to test the appropriate flag bit.
4DF9
LD A,B 78
Load Register A with Register B (the original option descriptor byte).
4DFA
AND 0FH E6 0F
AND Register A with 0FH, isolating the low nibble (bits 3–0). This extracts the byte offset index within the Y/N flag byte table at 43F0H.
4DFC
LD E,A 5F
Load Register E with Register A (the byte offset, 0–15). D was already set to 00H at 4DEBH.
4DFD
LD HL,43F0H 21 F0 43
Point Register Pair HL to 43F0H, the base address of the Y/N option flag byte table within the system options area in the DOS buffer.
4E00
ADD HL,DE 19
ADD DE (the byte offset) to HL. HL now points to the specific flag byte in the Y/N option table that contains the bit for this option.
4E01
LD A,4EH 3E 4E
Load Register A with 4EH (ASCII N). Pre-load the 'N' character, assuming the flag bit is clear.
4E03
BIT 0,(HL) CB 46
Test the target bit in the flag byte at (HL). [SELF-MODIFYING CODE] — The second byte (46H) was dynamically written at 4DF6H to encode the correct BIT n,(HL) instruction for this option's bit number. If the bit is clear, the Z FLAG is set; if set, the NZ FLAG is set.
4E05
If the Z FLAG has been set (the flag bit is clear, meaning the option is set to 'N'), JUMP forward to 4E09H to display 'N' (already in Register A).
4E07
LD A,59H 3E 59
Load Register A with 59H (ASCII Y). The flag bit is set, so override the pre-loaded 'N' with 'Y'.
4E09
GOSUB to 4E6BH, the character output wrapper. Display the 'Y' or 'N' character for this option's current value.
4E0CH - DISPLAY LOOP: ADVANCE TO NEXT OPTION AND CHECK DESCRIPTOR
After displaying one option's value, this section restores the saved registers, sets the separator character to comma (2CH) for all subsequent options, advances both the descriptor table pointer (HL) and the system options data offset (DE), and then checks the next descriptor byte. Descriptor values below FEH indicate a defined option (loop back to display it). A value of FEH means the option is undefined (skip it by advancing DE without displaying). A value of FFH signals the end of a display group (output a carriage return and terminate).
4E0C
POP BC C1
Restore BC from the stack. Register B holds the separator character (0DH on the first pass, 2CH on subsequent passes).
4E0D
POP DE D1
Restore DE from the stack (the current option index offset within the descriptor table).
4E0E
POP HL E1
Restore HL from the stack (the current pointer into the option descriptor table at 4F24H).
4E0F
LD B,2CH 06 2C
Load Register B with 2CH (ASCII comma). For all subsequent options, a comma will be displayed as the separator before the option code.
4E11
INC DE 13
INCrement DE by 1, advancing the option index offset to the next entry in the system options data.
4E12
INC HL 23
INCrement HL by 1, advancing the descriptor table pointer to the next descriptor byte at 4F24H.
4E13
LD A,(HL) 7E
Load Register A with the descriptor byte at (HL) from the option descriptor table. [DISPLAY LOOP — entry point from 4DC8H]
4E14
CP FEH FE FE
Compare Register A against FEH. Three cases: (1) If A < FEH, the CARRY FLAG is set — the option is defined, display it. (2) If A = FEH, the Z FLAG is set — the option is undefined/reserved, skip it. (3) If A = FFH, neither CARRY nor Z is set — end of display group.
4E16
If the CARRY FLAG has been set (the descriptor byte is < FEH, meaning this is a defined option), JUMP back to 4DCAH to display this option's code and value. [LOOP — display next option]
4E18
If the Z FLAG has been set (the descriptor byte is FEH, meaning this option slot is undefined/reserved), JUMP back to 4E11H to skip this entry by advancing both DE and HL without displaying anything. [SKIP undefined option]
The descriptor byte is FFH — end of the display group. Output a final carriage return and return to the caller with A = 0 (success).
4E1A
LD A,0DH 3E 0D
Load Register A with 0DH (ASCII carriage return) to terminate the current display line.
4E1C
GOSUB to 4E6BH to display the carriage return, moving the cursor to the next line.
4E1F
XOR A AF
Set Register A to ZERO and clear all flags. This sets the Z FLAG (success indicator) and clears the error code to 00H.
4E20
RET C9
RETURN to the DOS command dispatcher with A = 0 (success, no errors). The display of all SYSTEM options is complete.
4E21H - SET UP SECTOR I/O PARAMETER BLOCK
This short utility routine initializes the sector I/O parameter block at 4F16H for accessing sector 2 (the 3rd sector, zero-indexed) of the system diskette. It stores sector number 02H into the sector field at 4F20H and points DE to 4F16H (the base of the I/O parameter block). Called before both sector read and sector write operations.
4E21
LD A,02H 3E 02
Load Register A with 02H (sector number 2 — the 3rd sector of the diskette, zero-indexed). This is the sector that contains the SYSTEM configuration options.
4E23
LD (4F20H),A 32 20 4F
Store Register A (02H) into memory location 4F20H, the sector number field within the I/O parameter block at 4F16H. The parameter block at 4F16H has the sector number at offset +0AH (4F16H + 0AH = 4F20H).
4E26
LD DE,4F16H 11 16 4F
Point Register Pair DE to 4F16H, the base address of the sector I/O parameter block. The DOS sector read/write routines at 4436H/443CH expect DE to point to this parameter block.
4E29
RET C9
RETURN to the caller with DE = 4F16H (I/O parameter block pointer) and sector number 02H stored in the block.
4E2AH - DISPLAY NUMERIC OPTION VALUE (DECIMAL / HEX)
This section handles the display of numeric SYSTEM option values (descriptor Bit 7 = 1). It extracts the storage offset from the descriptor byte, fetches the stored value (1-byte or 2-byte depending on Bit 6), then displays the value first as a decimal number using the repeated-subtraction division routine at 4EDEH, followed by a '/' separator and a hexadecimal representation using the SYS0 hex conversion routine at 44D2H. The hex display includes leading-zero suppression and an 'H' suffix. This section is reached via the JR NZ at 4DEFH.
4E2A
AND 1FH E6 1F
AND Register A (the descriptor byte, with Bit 7 = 1) with 1FH, isolating bits 4–0. This extracts the byte offset index within the numeric option storage area at 43A0H.
4E2C
LD E,A 5F
Load Register E with Register A (the byte offset index). D was set to 00H at 4DEBH.
4E2D
LD HL,43A0H 21 A0 43
Point Register Pair HL to 43A0H, the base address of the numeric option storage area within the system options in the DOS buffer.
4E30
ADD HL,DE 19
ADD DE (the byte offset) to HL. HL now points to the storage location for this numeric option's value.
4E31
BIT 6,B CB 70
Test Bit 6 of Register B (the option descriptor byte). Bit 6 = 0 means a 1-byte value; Bit 6 = 1 means a 2-byte (16-bit) value.
4E33
If the Z FLAG has been set (Bit 6 = 0, meaning this is a single-byte value), JUMP forward to 4E3BH to load only the low byte.
Bit 6 = 1: This is a 2-byte value. The 16-bit value is stored at offset + 30H from the base (at 43D0H + offset). Load both bytes in little-endian order (low byte first, then high byte).
4E35
LD A,L 7D
Load Register A with the low byte of HL (the pointer into 43A0H + offset).
4E36
ADD 31H C6 31
ADD 31H to Register A, offsetting HL forward by 31H bytes. This points to (43A0H + offset + 31H) = the high byte of the 16-bit value stored at 43D0H + offset. (The +31H reaches one byte past the low byte at +30H, targeting the high byte.)
4E38
LD L,A 6F
Load Register L with Register A. HL now points to the high byte of the 16-bit value.
4E39
LD D,(HL) 56
Load Register D with the byte at (HL) — the high byte of the 16-bit numeric value.
4E3A
DEC HL 2B
DECrement HL by 1 to point to the low byte of the 16-bit value.
4E3B
LD E,(HL) 5E
Load Register E with the byte at (HL) — the low byte of the numeric value. For single-byte options, D is already 00H (set at 4DEBH), so DE holds the full value. For 2-byte options, D was loaded at 4E39H.
4E3C
PUSH DE D5
Save DE (the numeric value to display) onto the stack for later hex display.
4E3D
GOSUB to 4EDEH, the decimal display routine. This routine converts the 16-bit value in DE to decimal ASCII and displays it on screen using repeated subtraction with divisors 10000, 1000, 100, and 10, with leading-zero suppression.
4E40
LD A,2FH 3E 2F
Load Register A with 2FH (ASCII /). This is the separator character between the decimal and hexadecimal representations.
4E42
GOSUB to 4E6BH to display the '/' separator character.
4E45
POP DE D1
Restore DE from the stack (the numeric value to display in hex).
4E46
LD HL,4F11H 21 11 4F
Point Register Pair HL to 4F11H, a 5-byte scratch buffer within SYS17's data area. The hex conversion routine will write the ASCII hex digits into this buffer starting at the high end (4F14H or 4F15H) and working backward.
4E49
PUSH HL E5
Save HL (pointer to the hex scratch buffer at 4F11H) onto the stack for later display.
4E4A
GOSUB to 44D2H (in SYS0), a routine that converts the 16-bit value in DE to ASCII hexadecimal characters and stores them in the buffer at HL. On return, the buffer at 4F11H contains up to 4 hex digits plus an 'H' suffix (e.g., "0000H" at 4F10H-4F14H).
4E4D
POP HL E1
Restore HL from the stack (pointing to the hex scratch buffer at 4F11H).
4E4E
LD B,04H 06 04
Load Register B with 04H (4 decimal). This is the maximum number of leading-zero digits to suppress in the hex display. The hex value has up to 4 hex digits before the 'H' suffix.
4E50H - HEX DISPLAY: LEADING-ZERO SUPPRESSION
This section scans the hex digit buffer from left to right, suppressing leading zeros. For each position, if the character is ≥ 'A' (41H), it is a hex digit A–F and leading zeros end. If the character is '0' (30H) and there are still leading zeros to suppress, the count is decremented and the character is skipped. Once a non-zero digit or non-leading-zero is found, all remaining characters (including the 'H' suffix) are displayed.
4E50
LD A,(HL) 7E
Load Register A with the byte at (HL) — the current hex digit character from the buffer at 4F11H. [LEADING-ZERO CHECK]
4E51
CP 41H FE 41
Compare Register A against 41H (ASCII A). If the character is ≥ 'A', it is a hex letter digit (A–F) and there are no more leading zeros. CARRY is set if A < 41H (digit is '0'–'9').
4E53
DEC HL 2B
DECrement HL by 1, moving the buffer pointer backward (the hex conversion stored digits from high to low address, so we scan backwards). Actually, the DEC HL here adjusts the pointer for the display loop at 4E62H which will re-INC it.
4E54
If the NO CARRY FLAG has been set (the character is ≥ 'A', a hex letter digit A–F), JUMP forward to 4E60H to begin outputting all remaining characters. Leading-zero suppression is complete.
4E56
DEC B 05
DECrement Register B (the leading-zero suppression counter). If B was 1 and becomes 0, we have suppressed all possible leading zeros — the remaining digit must be displayed even if it is '0'.
4E57
INC HL 23
INCrement HL by 1 (undo the DEC HL at 4E53H, returning to the current digit position).
4E58
LD A,(HL) 7E
Load Register A with the byte at (HL) — re-read the current hex digit character.
4E59
CP 30H FE 30
Compare Register A against 30H (ASCII 0). If the digit is exactly '0' and B is still > 0, this is a leading zero that can be suppressed.
4E5B
If the NZ FLAG has been set (the character is not '0', meaning it is a non-zero digit '1'–'9'), JUMP to 4E60H to begin displaying all remaining characters. Leading-zero suppression is complete.
4E5D
DECrement B and if not zero, loop back to 4E57H to check the next digit for leading zeros. [LOOP — suppress leading zeros]
4E5F
INC HL 23
INCrement HL by 1. All 4 hex digits were '0' (value is zero), so B has reached 0. Advance HL past the last suppressed zero to point to the character that follows (the 'H' suffix). The value "0H" will be displayed.
4E60
INC B 04
INCrement Register B by 1. This adjusts the character count to include at least the current digit.
4E61
INC B 04
INCrement Register B by 1 again. This adds 1 more to include the 'H' suffix character in the output count. B now holds the total number of characters to display.
4E62
LD A,(HL) 7E
Load Register A with the byte at (HL) — the current character to display from the hex buffer (digit or 'H' suffix). [LOOP START — display hex characters]
4E63
INC HL 23
INCrement HL by 1 to advance to the next character in the hex buffer.
4E64
GOSUB to 4E6BH, the character output wrapper. Display the current hex digit or 'H' suffix character.
4E67
DECrement B and loop back to 4E62H if not zero. Continue displaying hex characters until all digits and the 'H' suffix have been output. [LOOP END — display hex characters]
4E69
JUMP back to 4E0CH to restore the saved registers and continue the display loop with the next option in the descriptor table.
4E6BH - CHARACTER OUTPUT WRAPPER
A utility routine that displays the character in Register A on the screen by calling the Model III ROM character output routine at 0033H. It preserves Register Pair DE and the AF register across the call, which is important because the display loop uses DE to track the system options data offset and A to hold various characters and values.
4E6B
PUSH DE D5
Save Register Pair DE onto the stack (preserving the system options data offset or other caller state).
4E6C
PUSH AF F5
Save Register A and the flags onto the stack (preserving the character value and current flag state for the caller).
4E6D
GOSUB to ROM routine at 0033H, the Model III character display routine. This outputs the character in Register A at the current cursor position and advances the cursor.
4E70
POP AF F1
Restore Register A and the flags from the stack.
4E71
POP DE D1
Restore Register Pair DE from the stack.
4E72
RET C9
RETURN to the caller with DE and AF preserved.
4E73H - PARSE DECIMAL NUMBER WITH VALIDATION / PARSE HEX NUMBER
These are two entry points for numeric parsing used by the SYSTEM command (for setting numeric option values) and by the WRDIRP command. Entry at 4E73H parses a decimal number; entry at 4E78H parses a hex number. Both call the core number parsing routine at 4EA7H/4EA9H. After parsing, 4E7BH validates the result: if D = 0 (value fits in 8 bits), the value in E is returned in A with Z FLAG set (success). If D ≠ 0 (value exceeds 255), execution falls through to the error handler at 4E7FH.
4E73
GOSUB to 4E84H, the decimal number parser with optional hex suffix. This parses an ASCII decimal number from the command line at HL. If the number ends with 'H', it is parsed as hexadecimal. On return, DE contains the parsed value.
4E76
JUMP forward to 4E7BH to validate the parsed value and return it.
4E78
GOSUB to 4EA2H, the hex number parser entry point. This parses an ASCII hexadecimal number from the command line at HL. On return, DE contains the parsed value.
4E7B
LD A,D 7A
Load Register A with Register D (the high byte of the parsed numeric value).
4E7C
OR A B7
OR Register A with itself. This sets the Z FLAG if D = 0 (the value fits in a single byte, 0–255); NZ if D ≠ 0 (value exceeds 255).
4E7D
LD A,E 7B
Load Register A with Register E (the low byte of the parsed value). This prepares the single-byte result in A for the caller.
4E7E
RET Z C8
If the Z FLAG has been set (D = 0, value fits in a byte), RETURN to the caller with the value in Register A and Z FLAG set (success).
4E7F
LD A,2FH 3E 2F
Load Register A with 2FH (error code 47 decimal). This indicates a value out of range or other parse error.
4E81
JUMP to 4409H (in SYS0), the DOS error handler. This routine processes the error code in Register A and returns control to the DOS command dispatcher with the appropriate error message. [ERROR EXIT — all SYS17 errors route here]
4E84H - DECIMAL NUMBER PARSER (WITH OPTIONAL HEX SUFFIX)
This routine parses an ASCII number from the command line at HL. It first attempts to parse the number as decimal. After parsing, it checks if the character following the digits is 'A'–'H'. If it is an 'H', the number is reinterpreted as hexadecimal by re-parsing from the beginning with the hex parser. The routine uses two internal entry points: 4EA7H (initialize B=0 for decimal mode) and 4EA9H (initialize DE=0000H and begin digit accumulation).
4E84
PUSH HL E5
Save HL (the starting position of the number in the command line) onto the stack. This saved position is used if the number needs to be re-parsed as hexadecimal.
4E85
GOSUB to 4EA7H, which initializes B = 0 (decimal mode: Bit 0 = 0 means only digits '0'–'9' are valid) and then enters the digit accumulation loop at 4EA9H. On return, DE contains the parsed decimal value, HL points past the last digit, and B has Bit 1 set if at least one digit was parsed.
4E88
LD A,(HL) 7E
Load Register A with the byte at HL (the first non-digit character after the parsed number).
4E89
SUB 41H D6 41
SUBtract 41H (ASCII A) from Register A. This converts 'A'→0, 'B'→1, … 'H'→7. If the character was not a letter 'A'–'H', the result will be negative (large unsigned value) or ≥ 8.
4E8B
CP 08H FE 08
Compare Register A against 08H. If A < 08H, the CARRY FLAG is set — the character following the digits is 'A' through 'H', which means the number might have a hex suffix or contain hex digits. If A ≥ 08H, NO CARRY — the number is purely decimal.
4E8D
If the NO CARRY FLAG has been set (the post-number character is not 'A'–'H', confirming a pure decimal number), JUMP to 4E9CH to validate and return the result.
The character after the decimal digits is 'A'–'H'. This means the input is a hexadecimal number (e.g., "1AH" or "FFH"). Re-parse from the saved starting position using the hex parser.
4E8F
POP HL E1
Restore HL from the stack (the starting position of the number in the command line, saved at 4E84H).
4E90
LD B,01H 06 01
Load Register B with 01H. Bit 0 of B = 1 signals hexadecimal mode to the digit accumulation routine, allowing digits 'A'–'F' (converted to values 10–15) in addition to '0'–'9'.
4E92
PUSH HL E5
Save HL (the starting position) onto the stack again. This re-push balances the POP at 4E9EH which always executes after parsing.
4E93
GOSUB to 4EA9H, the digit accumulation loop, now with B = 01H (hex mode). This re-parses the number from the beginning as hexadecimal (×16 per digit instead of ×10). On return, DE contains the hex value.
4E96
LD A,(HL) 7E
Load Register A with the byte at HL (the character after the hex number — expected to be 'H' suffix).
4E97
CP 48H FE 48
Compare Register A against 48H (ASCII H). A valid hex number must end with an 'H' suffix.
4E99
INC HL 23
INCrement HL by 1, advancing past the 'H' suffix character.
4E9A
If the NZ FLAG has been set (the character is not 'H', meaning the hex number format is invalid), JUMP to 4E7FH to report a parse error. [ERROR PATH — missing 'H' suffix]
4E9C
BIT 1,B CB 48
Test Bit 1 of Register B. The digit accumulation loop sets Bit 1 of B when at least one valid digit has been parsed. If Bit 1 = 0, no digits were found (empty number).
4E9E
POP BC C1
Restore BC from the stack (discarding the saved HL starting position). The value originally pushed as HL is popped into BC to clean up the stack.
4E9F
RET NZ C0
If the NZ FLAG has been set (Bit 1 of B was 1, meaning at least one digit was parsed — the number is valid), RETURN to the caller with the parsed value in DE. [SUCCESS PATH]
4EA0
JUMP to 4E7FH to report a parse error — no digits were found in the input. [ERROR PATH — no digits]
4EA2H - HEX NUMBER PARSER ENTRY POINT
This is the direct hex number parsing entry point. It pushes a return address of 4E9CH onto the stack so that after the digit accumulation loop returns, execution continues at the validation check. It then falls through to 4EA7H with B = 00H and calls 4EA9H.
4EA2
PUSH HL E5
Save HL (the current command line pointer) onto the stack.
4EA3
LD DE,4E9CH 11 9C 4E
Load Register Pair DE with 4E9CH, the address of the validation/return check at 4E9CH.
4EA6
PUSH DE D5
Save DE (4E9CH) onto the stack. This acts as a synthetic return address: when the digit accumulation routine at 4EA9H returns via RET, execution will continue at 4E9CH.
4EA7
LD B,00H 06 00
Load Register B with 00H. Bit 0 = 0 means decimal mode (only digits '0'–'9' accepted). For the hex entry at 4EA2H, B is overridden with 01H by the caller before reaching 4EA9H. Note: for the 4EA2H path, this sets B=0 but the call at 4E93H sets B=01H. For the 4EA7H entry from 4E85H, B=0 is correct for decimal.
4EA9H - DIGIT ACCUMULATION LOOP (DECIMAL OR HEX)
This is the core numeric parsing routine. It initializes DE = 0000H and then processes ASCII digit characters from the command line at HL one at a time. For each digit, the current accumulated value in DE is multiplied by 10 (decimal mode, Bit 0 of B = 0) or by 16 (hex mode, Bit 0 of B = 1), and the new digit value is added. The multiplication is performed using shifts and adds on a 24-bit accumulator (A:HL). The routine returns when a non-digit character is encountered, with the result in DE and Bit 1 of B set if at least one digit was parsed.
4EA9
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H. DE is the running accumulator for the parsed numeric value, starting at zero.
4EAC
LD A,(HL) 7E
Load Register A with the byte at HL (the current character from the command line). [LOOP START — process one digit]
4EAD
SUB 30H D6 30
SUBtract 30H (ASCII 0) from Register A, converting an ASCII digit to its binary value: '0'→0, '1'→1, … '9'→9.
4EAF
CP 0AH FE 0A
Compare Register A against 0AH (10 decimal). If A < 0AH, the CARRY FLAG is set — the character is a valid decimal digit ('0'–'9'). If A ≥ 0AH, the NO CARRY FLAG is set — the character is not a decimal digit.
4EB1
If the CARRY FLAG has been set (valid decimal digit 0–9), JUMP forward to 4EBDH to incorporate the digit into the accumulated value.
The character is not a decimal digit ('0'–'9'). Check if hex mode is active and if the character is a valid hex digit ('A'–'F').
4EB3
BIT 0,B CB 40
Test Bit 0 of Register B. Bit 0 = 1 means hex mode is active (hex digits 'A'–'F' are valid). Bit 0 = 0 means decimal mode (only '0'–'9' valid).
4EB5
RET Z C8
If the Z FLAG has been set (Bit 0 of B = 0, meaning decimal mode), RETURN to the caller. The non-digit character ends the decimal number. DE holds the accumulated value.
4EB6
SUB 11H D6 11
SUBtract 11H from Register A. After the earlier SUB 30H, the character 'A' (41H) would have produced A = 11H. Subtracting 11H converts 'A'→0, 'B'→1, … 'F'→5.
4EB8
CP 06H FE 06
Compare Register A against 06H. If A < 06H, the CARRY FLAG is set — valid hex digit 'A'–'F'. If A ≥ 06H, the NO CARRY FLAG is set — not a valid hex digit.
4EBA
RET NC D0
If the NO CARRY FLAG has been set (the character is not 'A'–'F'), RETURN. The non-hex character ends the number.
4EBB
ADD 0AH C6 0A
ADD 0AH (10 decimal) to Register A. This converts the hex digit offset (0–5 for 'A'–'F') to its true value (10–15).
Register A now contains the digit value (0–9 for decimal digits, 10–15 for hex digits 'A'–'F'). Now multiply the accumulated value in DE by the base (10 for decimal, 16 for hex) and add the new digit. The multiplication is performed on a 24-bit accumulator using A (high byte) and HL (low 16 bits), built from DE.
4EBD
PUSH HL E5
Save HL (the command line pointer) onto the stack. HL will be used temporarily as the 16-bit portion of the 24-bit accumulator.
4EBE
LD H,D 62
Load Register H with Register D. Copy the high byte of the accumulated value DE into H.
4EBF
LD L,E 6B
Load Register L with Register E. HL now holds the current accumulated value (copied from DE).
4EC0
LD C,A 4F
Load Register C with Register A (save the new digit value, 0–15, for later addition).
4EC1
XOR A AF
Set Register A to ZERO and clear all flags. A is the high byte (bits 23–16) of the 24-bit accumulator, initialized to 0.
4EC2
SET 1,B CB C8
Set Bit 1 of Register B. This flag indicates that at least one valid digit has been parsed. It is checked at 4E9CH to distinguish "no digits found" from a valid zero value.
4EC4
ADD HL,HL 29
ADD HL to itself (shift HL left by 1 bit, multiply by 2). A:HL now holds the accumulated value × 2.
4EC5
ADC A,A 8F
ADD Register A to itself with Carry. This propagates any carry from the HL shift into the high byte A, maintaining the 24-bit value A:HL = original × 2.
4EC6
ADD HL,HL 29
ADD HL to itself again (shift left, multiply by 2). A:HL = original × 4.
4EC7
ADC A,A 8F
Propagate carry into A. A:HL = original × 4.
4EC8
BIT 0,B CB 40
Test Bit 0 of Register B. Bit 0 = 1 means hex mode (multiply by 16); Bit 0 = 0 means decimal mode (multiply by 10).
4ECA
If the Z FLAG has been set (Bit 0 = 0, decimal mode), JUMP to 4ECFH. In decimal mode, we need × 10 = (× 4 + original) × 2. The next step adds the original DE back and then doubles.
Hex mode: We need × 16 = × 4 × 4. Currently A:HL = original × 4. Shift left twice more to get × 16.
4ECC
ADD HL,HL 29
Shift HL left (multiply by 2). A:HL = original × 8.
4ECD
JUMP to 4ED0H to propagate carry and continue with the final shift (× 8 → × 16).
4ECF
ADD HL,DE 19
ADD DE (the original accumulated value) to HL. In decimal mode, A:HL was original × 4; adding original gives original × 5.
4ED0
ADC A,A 8F
Propagate carry into A from the previous ADD. For hex: A:HL = original × 8 (carry propagated). For decimal: A:HL = original × 5 (carry propagated).
4ED1
ADD HL,HL 29
Shift HL left (multiply by 2). For hex: A:HL = original × 16. For decimal: A:HL = original × 10.
4ED2
ADC A,A 8F
Propagate carry into A. A:HL now holds the accumulated value multiplied by the base (10 or 16).
4ED3
LD E,C 59
Load Register E with Register C (the new digit value, 0–15, saved at 4EC0H).
4ED4
LD D,00H 16 00
Load Register D with 00H. DE now holds the new digit as a 16-bit value (0–15).
4ED6
ADD HL,DE 19
ADD DE (the new digit value) to HL, incorporating the digit into the accumulated total. A:HL = (old_value × base) + new_digit.
4ED7
ADC A,A 8F
Propagate carry into A. If A is non-zero, the value has overflowed 16 bits (exceeds 65535).
4ED8
EX DE,HL EB
Exchange DE and HL. DE now holds the updated accumulated value (the low 16 bits). HL will be restored from the stack.
4ED9
POP HL E1
Restore HL from the stack (the command line pointer, saved at 4EBDH).
4EDA
RET NZ C0
If the NZ FLAG has been set (A is non-zero after the ADC, meaning the accumulated value overflowed 16 bits), RETURN with NZ indicating an overflow error.
4EDB
INC HL 23
INCrement HL by 1, advancing the command line pointer past the digit that was just processed.
4EDC
JUMP back to 4EACH to process the next digit character. [LOOP END — continue accumulating digits]
4EDEH - DISPLAY 16-BIT VALUE AS DECIMAL
This routine converts the 16-bit value in DE to ASCII decimal and displays it on screen. It uses repeated subtraction (actually, repeated addition of the two's complement of each divisor) to extract each decimal digit position. The divisor table at 4F08H contains the negated (two's complement) values of 10000, 1000, 100, and 10. Register B = 04H controls four iterations (ten-thousands, thousands, hundreds, tens), and the ones digit is displayed directly at the end. Register C serves as a leading-zero suppression flag: C = 0 means leading zeros are being suppressed; C ≠ 0 means a non-zero digit has been output.
4EDE
LD BC,0400H 01 00 04
Load Register Pair BC with 0400H. B = 04H (four digit positions to process: ten-thousands, thousands, hundreds, tens). C = 00H (leading-zero suppression flag: 0 = suppress leading zeros).
4EE1
LD HL,4F08H 21 08 4F
Point Register Pair HL to 4F08H, the base address of the divisor table. This table contains four 2-byte entries, each being the two's complement (negation) of a decimal place value: −10000 (D8F0H), −1000 (FC18H), −100 (FF9CH), −10 (FFF6H).
4EE4
PUSH BC C5
Save BC onto the stack. B = remaining digit positions, C = leading-zero suppression flag. [LOOP START — process one decimal digit position]
4EE5
LD C,(HL) 4E
Load Register C with the low byte of the current divisor entry from the table at (HL).
4EE6
INC HL 23
INCrement HL by 1 to point to the high byte of the divisor entry.
4EE7
LD B,(HL) 46
Load Register B with the high byte of the current divisor entry. BC now holds the negated divisor (e.g., D8F0H = −10000 for the first iteration).
4EE8
INC HL 23
INCrement HL by 1 to point to the next divisor table entry (for the next iteration).
4EE9
EX DE,HL EB
Exchange DE and HL. HL now holds the value being converted (the dividend), and DE holds the divisor table pointer (saved for later).
4EEA
LD A,2FH 3E 2F
Load Register A with 2FH (ASCII /, which is one less than ASCII 0). The quotient digit will be computed by counting how many times the divisor can be subtracted; each subtraction increments A by 1. Starting at 2FH means the first increment produces '0' (30H).
4EEC
INC A 3C
INCrement Register A by 1. Each iteration counts one more subtraction of the divisor. [INNER LOOP — repeated subtraction]
4EED
ADD HL,BC 09
ADD BC (the negated divisor) to HL. Since BC contains the two's complement of the divisor, this is equivalent to subtracting the divisor from the dividend in HL. If HL goes below zero, the CARRY FLAG will NOT be set (the addition wraps without carry).
4EEE
If the CARRY FLAG has been set (the addition produced a carry, meaning the subtraction result is still ≥ 0), JUMP back to 4EECH to subtract again and increment the digit counter. [INNER LOOP — subtract divisor again]
4EF0
SBC HL,BC ED 42
SUBtract BC from HL with borrow. This undoes the last addition (which caused the underflow) by subtracting the negated divisor — effectively adding back the original divisor. HL is restored to the correct remainder.
4EF2
POP BC C1
Restore BC from the stack. B = remaining digit positions, C = leading-zero flag.
4EF3
EX DE,HL EB
Exchange DE and HL. DE now holds the remainder (to be used as the dividend for the next digit position), and HL holds the divisor table pointer.
Register A now holds the ASCII digit for this position ('0'–'9'). Check for leading-zero suppression: if the digit is '0' and no non-zero digit has been displayed yet (C = 0), suppress it.
4EF4
CP 30H FE 30
Compare Register A against 30H (ASCII 0). If the digit is '0' and we are still in leading-zero suppression mode, it should not be displayed.
4EF6
If the NZ FLAG has been set (the digit is not '0'), JUMP to 4EFCH to display it. This is a significant digit that ends leading-zero suppression.
4EF8
INC C 0C
INCrement Register C by 1 (temporary test).
4EF9
DEC C 0D
DECrement Register C by 1. The INC/DEC sequence tests whether C is zero without modifying it: if C was 0, Z FLAG is set (still in leading-zero suppression mode). If C was non-zero, NZ FLAG is set (a non-zero digit was already output).
4EFA
If the Z FLAG has been set (C = 0, meaning no non-zero digit has been displayed yet), JUMP to 4F00H to skip displaying this leading zero.
4EFC
INC C 0C
INCrement Register C by 1. This sets C to a non-zero value, indicating that a significant digit has been output and leading-zero suppression is now disabled.
4EFD
GOSUB to 4E6BH, the character output wrapper. Display the ASCII digit character in Register A.
4F00
DECrement B (the digit position counter) and loop back to 4EE4H if not zero. Process the next decimal place value (thousands, hundreds, tens). [LOOP END — next digit position]
All four higher digit positions (ten-thousands through tens) have been processed. The ones digit remains in Register E (the final remainder). Always display it (even if zero, since there must be at least one digit).
4F02
LD A,E 7B
Load Register A with Register E (the ones digit value, 0–9, remaining after all four divisions).
4F03
ADD 30H C6 30
ADD 30H (ASCII 0) to Register A, converting the binary ones digit to ASCII.
4F05
JUMP to 4E6BH to display the ones digit character and then return to the caller. The full decimal number has been displayed.
4F08H - DECIMAL DIVISOR TABLE (NEGATED VALUES)
This 8-byte table contains the two's complement (negated) values of the four decimal place-value divisors used by the decimal display routine at 4EDEH. Each entry is a 2-byte little-endian word. The division is performed by repeatedly adding these negated values (equivalent to subtraction). The disassembler shows these bytes as instructions, but they are DATA, not executable code.
4F08
DEFB F0H,D8H F0 D8
[DATA] Two's complement of 10000 decimal (2710H). Negated value = D8F0H. Used for the ten-thousands digit position.
4F0A
DEFB 18H,FCH 18 FC
[DATA] Two's complement of 1000 decimal (03E8H). Negated value = FC18H. Used for the thousands digit position.
4F0C
DEFB 9CH,FFH 9C FF
[DATA] Two's complement of 100 decimal (0064H). Negated value = FF9CH. Used for the hundreds digit position.
4F0E
DEFB F6H,FFH F6 FF
[DATA] Two's complement of 10 decimal (000AH). Negated value = FFF6H. Used for the tens digit position.
4F10H - HEX DISPLAY SCRATCH BUFFER AND I/O PARAMETER BLOCK
This area contains a 6-byte scratch buffer used by the hex display routine (4E46H calls 44D2H to convert DE to ASCII hex and store the result here), followed by the sector I/O parameter block used by the SYSTEM command for reading and writing the 3rd sector of the system diskette. The disassembler renders these data bytes as Z80 instructions, but they are NOT executable code — they are DATA structures.
4F10
DEFB 30H,30H
30H,30H,30H,48H 30 30 30 30 30 48
[DATA — Hex Display Scratch Buffer] Six-byte buffer at 4F10H–4F15H, initialized to "00000H". The hex conversion routine at 44D2H writes up to 4 hex digit characters into 4F11H–4F14H plus an 'H' suffix at 4F15H. The display routine at 4E46H reads back from 4F11H with leading-zero suppression. Byte layout: 4F10H = extra leading '0' (30H), 4F11H–4F14H = hex digits, 4F15H = 'H' suffix (48H).
4F16H - SYSTEM COMMAND SECTOR I/O PARAMETER BLOCK
This 14-byte structure at 4F16H–4F23H is the sector I/O parameter block used by the SYSTEM command to read and write the 3rd sector (sector 2, zero-indexed) of the system diskette. It is passed to the DOS sector read routine at 4436H and write routine at 443CH via Register Pair DE. The setup routine at 4E21H stores sector number 02H at offset +0AH (4F20H), and the entry point at 4D0DH stores the drive number at offset +06H (4F1CH).
4F16
DEFB 82H 82
[DATA — I/O Parameter Block +00H] Control/flags byte. 82H = bit 7 set (sector I/O operation), bit 1 set (specific operation flag). This byte tells the DOS sector I/O routine the type of operation to perform.
4F17
DEFB 60H 60
[DATA — I/O Parameter Block +01H] Additional control flags (60H).
4F18
DEFB 00H,00H 00 00
[DATA — I/O Parameter Block +02H/+03H] Reserved/unused (initialized to 0000H).
4F1A
DEFB 43H 43
[DATA — I/O Parameter Block +04H] High byte of buffer address. Combined with the low byte at +05H, this gives the address of the DOS sector buffer where data is read into or written from. 43H suggests the buffer is in the 4300H area (the DOS buffer region).
4F1B
DEFB 00H 00
[DATA — I/O Parameter Block +05H] Low byte of buffer address. Combined with +04H, the buffer address is 4300H (byte-swapped: low=00H, high=43H), which is the standard DOS sector buffer.
4F1C
DEFB 00H 00
[DATA — I/O Parameter Block +06H: Drive Number] The target drive number (0–3). Written by the SYSTEM command entry point at 4D0DH with the drive number parsed from the command line. Initialized to 00H (drive 0).
4F1D
DEFB FFH FF
[DATA — I/O Parameter Block +07H] Track number or flag (FFH = use default/current).
4F1E
DEFB 00H,00H 00 00
[DATA — I/O Parameter Block +08H/+09H] Reserved or additional parameters (initialized to 0000H).
4F20
DEFB 02H 02
[DATA — I/O Parameter Block +0AH: Sector Number] The target sector number. Set to 02H (sector 2, the 3rd sector on the diskette) by the setup routine at 4E21H. This is the sector containing the SYSTEM configuration options.
4F21
DEFB 00H 00
[DATA — I/O Parameter Block +0BH] Additional parameter (initialized to 00H).
4F22
DEFB FFH,FFH FF FF
[DATA — I/O Parameter Block +0CH/+0DH] End-of-block markers or unused fields (FFH = default/unspecified). The I/O parameter block ends at 4F23H (14 bytes total).
4F24H - SYSTEM OPTION DESCRIPTOR TABLE
This table at 4F24H contains one descriptor byte per SYSTEM option, indexed by the combined option code: (first_letter − 'A') × 26 + (second_letter − 'A'). Each byte encodes the option's type and storage location. The table spans options AA (index 0) through BN (index 39 = 27H), followed by an FFH end-of-table marker and FFH padding to fill the remaining space.
Descriptor byte encoding for Y/N flag options (Bit 7 = 0):
Bits 6–4: Bit number (0–7) within the flag byte to SET or RES
Bits 3–0: Byte offset within the Y/N flag table at 43F0H
Descriptor byte encoding for numeric value options (Bit 7 = 1):
Bit 6: 0 = single-byte value (0–255); 1 = two-byte value (0–65535)
Bits 4–0: Byte offset within the numeric storage area at 43A0H (1-byte values) or 43D0H (2-byte values)
Special descriptor values:
FEH = Undefined/reserved option (skipped during display, rejected during set)
FFH = End-of-table marker (terminates display loop)
Options AA through AZ (indices 00H–19H, addresses 4F24H–4F3DH). The 'A' row contains the primary system configuration options.
4F24
DEFB 70H 70
SYSTEM Option AA = Passwords with a parameter of Y/N. AA=Y enables passwords; AA=N disables passwords.
The byte 70H = 01110000. Split into 2 parts this is 0111 (Bit Number) and 0000 (Byte Offset), or, in decimal, Bit Number = 7, Byte Offset = 0. This means that the target byte storing the AA= value is 43F0H+00H = 43F0H and that Bit 7 holds the value.
4F25
DEFB 60H 60
SYSTEM Option AB = RUN-ONLY mode with a parameter of Y/N. AB=Y enables RUN-ONLY mode; AB=N enables normal command mode.
The byte 60H = 01100000. Split into 2 parts this is 0110 (Bit Number) and 0000 (Byte Offset), or, in decimal, Bit Number = 6, Byte Offset = 0. This means that the target byte storing the AB= value is 43F0H+00H = 43F0H and that Bit 6 holds the value.
4F26
DEFB FEH FE
SYSTEM Option AC = Debounce (Model I only). FEH = undefined/reserved on Model III. On Model I, AC=Y enables the NEWDOS/80 debounce routine.
4F27
DEFB 68H 68
SYSTEM Option AD = JKL enable with a parameter of Y/N. AD=Y enables 'JKL' keystroke; AD=N disables it.
The byte 68H = 01101000. Split into 2 parts this is 0110 (Bit Number) and 1000 (Byte Offset), or, in decimal, Bit Number = 6, Byte Offset = 8. This means that the target byte storing the AD= value is 43F0H+08H = 43F8H and that Bit 6 holds the value.
4F28
DEFB 58H 58
SYSTEM Option AE = 123 DEBUG enable with a parameter of Y/N. AE=Y enables '123' to invoke DEBUG; AE=N disables it.
The byte 58H = 01011000. Split into 2 parts this is 0101 (Bit Number) and 1000 (Byte Offset), or, in decimal, Bit Number = 5, Byte Offset = 8. This means that the target byte storing the AE= value is 43F0H+08H = 43F8H and that Bit 5 holds the value.
4F29
DEFB 48H 48
SYSTEM Option AF = DFG MINI-DOS enable with a parameter of Y/N. AF=Y enables 'DFG' to invoke MINI-DOS; AF=N disables it.
The byte 48H = 01001000. Split into 2 parts this is 0100 (Bit Number) and 1000 (Byte Offset), or, in decimal, Bit Number = 4, Byte Offset = 8. This means that the target byte storing the AF= value is 43F0H+08H = 43F8H and that Bit 4 holds the value.
4F2A
DEFB 50H 50
SYSTEM Option AG = BREAK key enable with a parameter of Y/N. AG=Y treats BREAK as normal input key (code 01H); AG=N disables BREAK key.
The byte 50H = 01010000. Split into 2 parts this is 0101 (Bit Number) and 0000 (Byte Offset), or, in decimal, Bit Number = 5, Byte Offset = 0. This means that the target byte storing the AG= value is 43F0H+00H = 43F0H and that Bit 5 holds the value.
4F2B
DEFB FEH FE
SYSTEM Option AH = (not defined). FEH = undefined/reserved. Formerly dealt with timer interrupt delay during disk I/O; no longer used in NEWDOS/80 v2.
4F2C
DEFB FEH FE
SYSTEM Option AI = Lower case flag (Model I only). FEH = undefined/reserved on Model III. On Model I, AI=Y indicates lower case hardware is installed.
4F2D
DEFB 18H 18
SYSTEM Option AJ = Keyboard intercept with a parameter of Y/N. AJ=Y activates NEWDOS/80's keyboard intercept routine (repeat key, debounce, JKL/123/DFG detection). AJ=N bypasses the keyboard intercept.
The byte 18H = 00011000. Split into 2 parts this is 0001 (Bit Number) and 1000 (Byte Offset), or, in decimal, Bit Number = 1, Byte Offset = 8. This means that the target byte storing the AJ= value is 43F0H+08H = 43F8H and that Bit 1 holds the value.
4F2E
DEFB FEH FE
SYSTEM Option AK = (not defined). FEH = undefined/reserved. Formerly dealt with JKL graphic character printing; incorporated into option AX.
4F2F
DEFB 80H 80
SYSTEM Option AL = Number of drives with a numeric parameter. Value 1–4 specifies the number of physical drives in the system.
The byte 80H = 10000000. Bit 7 = 1 indicates a numeric option. Bit 6 = 0 indicates a single-byte value. Bits 4–0 = 00000 = offset 0. This means that the target byte storing the AL= value is 43A0H+00H = 43A0H (1 byte).
4F30
DEFB 86H 86
SYSTEM Option AM = Disk I/O retries with a numeric parameter. Value 0–255 (0=256) is the number of disk I/O retries before declaring an error.
The byte 86H = 10000110. Bit 7 = 1 indicates a numeric option. Bit 6 = 0 indicates a single-byte value. Bits 4–0 = 00110 = offset 6. This means that the target byte storing the AM= value is 43A0H+06H = 43A6H (1 byte).
4F31
DEFB 82H 82
SYSTEM Option AN = Default DIR drive with a numeric parameter. Default drive number for the DIR command.
The byte 82H = 10000010. Bit 7 = 1 indicates a numeric option. Bit 6 = 0 indicates a single-byte value. Bits 4–0 = 00010 = offset 2. This means that the target byte storing the AN= value is 43A0H+02H = 43A2H (1 byte).
4F32
DEFB 83H 83
SYSTEM Option AO = File creation start drive with a numeric parameter. When creating a file without specifying a drive, search starts at this drive number.
The byte 83H = 10000011. Bit 7 = 1 indicates a numeric option. Bit 6 = 0 indicates a single-byte value. Bits 4–0 = 00011 = offset 3. This means that the target byte storing the AO= value is 43A0H+03H = 43A3H (1 byte).
4F33
DEFB C0H C0
SYSTEM Option AP = HIMEM address with a numeric parameter. A 16-bit memory address stored as the DOS HIMEM value at Model III location 4411H.
The byte C0H = 11000000. Bit 7 = 1 indicates a numeric option. Bit 6 = 1 indicates a two-byte (16-bit) value. Bits 4–0 = 00000 = offset 0. This means that the target word storing the AP= value is 43D0H+00H = 43D0H/43D1H (2 bytes, little-endian).
4F34
DEFB 28H 28
SYSTEM Option AQ = CLEAR key enable with a parameter of Y/N. AQ=Y enables the CLEAR key; AQ=N disables it (if AJ=Y).
The byte 28H = 00101000. Split into 2 parts this is 0010 (Bit Number) and 1000 (Byte Offset), or, in decimal, Bit Number = 2, Byte Offset = 8. This means that the target byte storing the AQ= value is 43F0H+08H = 43F8H and that Bit 2 holds the value.
4F35
DEFB 10H 10
SYSTEM Option AR = COPY password bypass with a parameter of Y/N. AR=Y allows COPY formats 5 and 6 without password checking; AR=N requires passwords if enabled.
The byte 10H = 00010000. Split into 2 parts this is 0001 (Bit Number) and 0000 (Byte Offset), or, in decimal, Bit Number = 1, Byte Offset = 0. This means that the target byte storing the AR= value is 43F0H+00H = 43F0H and that Bit 1 holds the value.
4F36
DEFB FEH FE
SYSTEM Option AS = BASIC case convert (Model I only). FEH = undefined/reserved on Model III. On Model I, AS=Y causes BASIC to convert input text from lower to upper case.
4F37
DEFB 71H 71
SYSTEM Option AT = Chain mode with a parameter of Y/N. AT=N puts chaining into record mode; AT=Y puts chaining into single character mode.
The byte 71H = 01110001. Split into 2 parts this is 0111 (Bit Number) and 0001 (Byte Offset), or, in decimal, Bit Number = 7, Byte Offset = 1. This means that the target byte storing the AT= value is 43F0H+01H = 43F1H and that Bit 7 holds the value.
4F38
DEFB 08H 08
SYSTEM Option AU = Repeat key enable with a parameter of Y/N. AU=Y enables the clock-driven repeat key function; AU=N disables it.
The byte 08H = 00001000. Split into 2 parts this is 0000 (Bit Number) and 1000 (Byte Offset), or, in decimal, Bit Number = 0, Byte Offset = 8. This means that the target byte storing the AU= value is 43F0H+08H = 43F8H and that Bit 0 holds the value.
4F39
DEFB 87H 87
SYSTEM Option AV = Repeat key delay with a numeric parameter. Number of 25ms intervals before the first repeat of a held key.
The byte 87H = 10000111. Bit 7 = 1 indicates a numeric option. Bit 6 = 0 indicates a single-byte value. Bits 4–0 = 00111 = offset 7. This means that the target byte storing the AV= value is 43A0H+07H = 43A7H (1 byte).
4F3A
DEFB 81H 81
SYSTEM Option AW = Write-verify retries with a numeric parameter. Number of write-with-verify retries allowed.
The byte 81H = 10000001. Bit 7 = 1 indicates a numeric option. Bit 6 = 0 indicates a single-byte value. Bits 4–0 = 00001 = offset 1. This means that the target byte storing the AW= value is 43A0H+01H = 43A1H (1 byte).
4F3B
DEFB 88H 88
SYSTEM Option AX = Max printable character with a numeric parameter. ASCII code of the highest printable character for the printer (stored at Model III location 4290H).
The byte 88H = 10001000. Bit 7 = 1 indicates a numeric option. Bit 6 = 0 indicates a single-byte value. Bits 4–0 = 01000 = offset 8. This means that the target byte storing the AX= value is 43A0H+08H = 43A8H (1 byte).
4F3C
DEFB 79H 79
SYSTEM Option AY = Ask date/time on cold reset with a parameter of Y/N. AY=Y prompts for date/time after power-on or non-disk BASIC; AY=N bypasses the query and sets date/time to zero.
The byte 79H = 01111001. Split into 2 parts this is 0111 (Bit Number) and 1001 (Byte Offset), or, in decimal, Bit Number = 7, Byte Offset = 9. This means that the target byte storing the AY= value is 43F0H+09H = 43F9H and that Bit 7 holds the value.
4F3D
DEFB 69H 69
SYSTEM Option AZ = Ask date/time on warm reset with a parameter of Y/N. AZ=Y prompts for date/time after a warm reset; AZ=N leaves date/time unchanged.
The byte 69H = 01101001. Split into 2 parts this is 0110 (Bit Number) and 1001 (Byte Offset), or, in decimal, Bit Number = 6, Byte Offset = 9. This means that the target byte storing the AZ= value is 43F0H+09H = 43F9H and that Bit 6 holds the value.
Options BA through BN (indices 1AH–27H, addresses 4F3EH–4F4BH). The 'B' row contains additional system options added for NEWDOS/80 v2.
4F3E
DEFB 59H 59
SYSTEM Option BA = Route display null at reset with a parameter of Y/N. BA=Y activates 'ROUTE,DO,NL' at reset, suppressing display output until a ROUTE command is executed.
The byte 59H = 01011001. Split into 2 parts this is 0101 (Bit Number) and 1001 (Byte Offset), or, in decimal, Bit Number = 5, Byte Offset = 9. This means that the target byte storing the BA= value is 43F0H+09H = 43F9H and that Bit 5 holds the value.
4F3F
DEFB 49H 49
SYSTEM Option BB = 50Hz clock (Model III only) with a parameter of Y/N. BB=N informs the system that clock interrupts occur 60 times per second; BB=Y informs the system that clock interrupts occur 50 times per second.
The byte 49H = 01001001. Split into 2 parts this is 0100 (Bit Number) and 1001 (Byte Offset), or, in decimal, Bit Number = 4, Byte Offset = 9. This means that the target byte storing the BB= value is 43F0H+09H = 43F9H and that Bit 4 holds the value.
4F40
DEFB 61H 61
SYSTEM Option BC = Manual chain pause with a parameter of Y/N. BC=Y allows the operator to manually pause or cancel chaining; BC=N disallows it. RUN ONLY forces BC=N.
The byte 61H = 01100001. Split into 2 parts this is 0110 (Bit Number) and 0001 (Byte Offset), or, in decimal, Bit Number = 6, Byte Offset = 1. This means that the target byte storing the BC= value is 43F0H+01H = 43F1H and that Bit 6 holds the value.
4F41
DEFB 39H 39
SYSTEM Option BD = AUTO override at reset with a parameter of Y/N. BD=Y allows overriding the AUTO command by holding ENTER at reset; BD=N disallows it. RUN ONLY forces BD=N.
The byte 39H = 00111001. Split into 2 parts this is 0011 (Bit Number) and 1001 (Byte Offset), or, in decimal, Bit Number = 3, Byte Offset = 9. This means that the target byte storing the BD= value is 43F0H+09H = 43F9H and that Bit 3 holds the value.
4F42
DEFB 51H 51
SYSTEM Option BE = Repeat command (R) with a parameter of Y/N. BE=Y enables the DOS command R to repeat the previous DOS command; BE=N causes R to return to DOS READY.
The byte 51H = 01010001. Split into 2 parts this is 0101 (Bit Number) and 0001 (Byte Offset), or, in decimal, Bit Number = 5, Byte Offset = 1. This means that the target byte storing the BE= value is 43F0H+01H = 43F1H and that Bit 5 holds the value.
4F43
DEFB FEH FE
SYSTEM Option BF = LCD driver at reset (Model I only). FEH = undefined/reserved on Model III. On Model I, BF=Y performs LCDVR,Y at reset; BF=N performs LCDVR,N.
4F44
DEFB 19H 19
SYSTEM Option BG = Lower case enable at reset with a parameter of Y/N. BG=Y performs LC,Y at reset; BG=N performs LC,N.
The byte 19H = 00011001. Split into 2 parts this is 0001 (Bit Number) and 1001 (Byte Offset), or, in decimal, Bit Number = 1, Byte Offset = 9. This means that the target byte storing the BG= value is 43F0H+09H = 43F9H and that Bit 1 holds the value.
4F45
DEFB 09H 09
SYSTEM Option BH = Cursor blink at reset with a parameter of Y/N. BH=Y enables cursor blinking at reset; BH=N inhibits it.
The byte 09H = 00001001. Split into 2 parts this is 0000 (Bit Number) and 1001 (Byte Offset), or, in decimal, Bit Number = 0, Byte Offset = 9. This means that the target byte storing the BH= value is 43F0H+09H = 43F9H and that Bit 0 holds the value.
4F46
DEFB 85H 85
SYSTEM Option BI = Cursor character value with a numeric parameter. The numeric value of the cursor character; 0 means use the standard cursor (176 decimal for Model III).
The byte 85H = 10000101. Bit 7 = 1 indicates a numeric option. Bit 6 = 0 indicates a single-byte value. Bits 4–0 = 00101 = offset 5. This means that the target byte storing the BI= value is 43A0H+05H = 43A5H (1 byte).
4F47
DEFB 89H 89
SYSTEM Option BJ = CPU speed multiplier with a numeric parameter. Integer multiplier for internal timing loops when a CPU speed-up modification is installed. Must be ≥ 1.
The byte 89H = 10001001. Bit 7 = 1 indicates a numeric option. Bit 6 = 0 indicates a single-byte value. Bits 4–0 = 01001 = offset 9. This means that the target byte storing the BJ= value is 43A0H+09H = 43A9H (1 byte).
4F48
DEFB 41H 41
SYSTEM Option BK = WRDIRP/DIRCHECK enable with a parameter of Y/N. BK=Y allows the DOS command WRDIRP and DIRCHECK W/C functions; BK=N causes them to be rejected with 'DISK ACCESS DENIED'.
The byte 41H = 01000001. Split into 2 parts this is 0100 (Bit Number) and 0001 (Byte Offset), or, in decimal, Bit Number = 4, Byte Offset = 1. This means that the target byte storing the BK= value is 43F0H+01H = 43F1H and that Bit 4 holds the value.
4F49
DEFB FEH FE
SYSTEM Option BL = (not defined). FEH = undefined/reserved. No SYSTEM option BL is defined in NEWDOS/80 v2.
4F4A
DEFB FEH FE
SYSTEM Option BM = Format verify phase. FEH = undefined/reserved on Model III. The manual describes BM as controlling an extra format verify read phase, but this descriptor marks it as undefined/not implemented on the Model III version.
4F4B
DEFB FEH FE
SYSTEM Option BN = Dir address mark (Model I only). FEH = undefined/reserved on Model III. On Model I, BN controls which directory sector address mark is written for Model I/III diskette interchangeability.
4F4C
DEFB FFH FF
[DATA — End-of-table marker] FFH signals the end of defined options to the display loop at 4E14H. All remaining bytes through 4F6CH are FFH padding.
Addresses 4F4DH–4F6CH contain FFH padding bytes (32 bytes). These fill the remaining 32 option index slots (indices 29H–47H) in the maximum 72-entry table space. The display loop treats FFH as end-of-group and terminates. These bytes are not individually listed as they are all identical FFH padding.
4F4D
DEFB FFH × 32 FF (×32)
[DATA — FFH padding] 32 bytes of FFH fill from 4F4DH through 4F6CH. These are unused option descriptor table slots, all set to FFH (end-of-table / undefined).
4F6DH - WRDIRP COMMAND: ENTRY POINT AND INITIALIZATION
The WRDIRP (Write Directory Protected) command rewrites the directory sectors of a diskette with the currently defined protected address mark for the current computer model. This is used when exchanging single-density diskettes between Model I and Model III under NEWDOS/80 v2, because the two models use different address mark bytes for protected directory sectors. Before executing, WRDIRP checks that SYSTEM option BK=Y (stored as bit 4 of the byte at 428DH, which is the in-memory copy of the 43F0H+1 flag byte). If BK=N, the command is rejected with error code 37H. The command syntax is: WRDIRP,dn1 where dn1 is the drive number.
4F6D
LD A,(428DH) 3A 8D 42
Load Register A with the byte at 428DH, the in-memory copy of the system flags byte. This byte is a copy of the Y/N flag byte from offset 43F0H+1 that was loaded into RAM during the last DOS reset. Bit 4 of this byte corresponds to SYSTEM option BK (WRDIRP/DIRCHECK enable).
4F70
BIT 4,A CB 67
Test Bit 4 of Register A (the BK option flag). Bit 4 = 1 means BK=Y (WRDIRP is allowed); Bit 4 = 0 means BK=N (WRDIRP is denied).
4F72
LD A,37H 3E 37
Load Register A with 37H (error code 55 decimal). This pre-loads the error code for 'DISK ACCESS DENIED' in case BK=N.
4F74
If the Z FLAG has been set (Bit 4 = 0, meaning BK=N — WRDIRP is disabled), JUMP to 4FD8H which jumps to the error handler at 4E81H with error code 37H. [ERROR PATH — WRDIRP disabled by BK=N]
BK=Y — WRDIRP is permitted. Parse the drive number from the command line.
4F76
GOSUB to 4E73H, the decimal number parser with validation. This parses the drive number from the command line at HL. On return, Register A contains the parsed drive number (0–3) and Z FLAG is set if valid.
4F79
LD (5024H),A 32 24 50
Store Register A (the parsed drive number) into memory location 5024H, the drive number field within the WRDIRP I/O parameter block at 501EH. Offset: 5024H − 501EH = +06H, the same drive number field offset as in the SYSTEM I/O parameter block.
4F7C
GOSUB to 4C7AH (in SYS0), the command line token scanner. Check if there are any additional parameters on the command line (there should not be for WRDIRP).
4F7F
RET NZ C0
If the NZ FLAG has been set (unexpected additional parameters on the command line), RETURN with a non-zero status. WRDIRP takes only a drive number, so extra parameters indicate an error.
4F80H - WRDIRP: READ BOOT SECTOR AND VALIDATE DIRECTORY
WRDIRP reads the boot sector (sector 0) of the target diskette into the DOS buffer at 4300H. It then validates the boot sector by checking that the first byte at 4300H is 00H (indicating a valid boot sector format) and the second byte at 4301H is FEH (the directory granule marker). The third byte at 4302H contains the directory starting granule number, which will be used to locate the directory sectors. If validation fails, error code 2CH is returned.
4F80
LD DE,501EH 11 1E 50
Point Register Pair DE to 501EH, the base address of the WRDIRP sector I/O parameter block. This parameter block is configured to read sectors from the target drive.
4F83
GOSUB to 4436H (in SYS0), the DOS sector read routine. Read the sector specified by the I/O parameter block at 501EH (initially sector 0, the boot sector) into the DOS buffer at 4300H. On return, Z FLAG set = success, NZ = error.
4F86
RET NZ C0
If the NZ FLAG has been set (the sector read failed), RETURN with the error code in Register A.
4F87
LD HL,4300H 21 00 43
Point Register Pair HL to 4300H, the start of the DOS buffer where the boot sector has been read.
4F8A
LD A,(HL) 7E
Load Register A with the first byte of the boot sector at 4300H. In a valid NEWDOS/80 boot sector, byte 0 should be 00H.
4F8B
OR A B7
OR Register A with itself. Sets the Z FLAG if the byte is 00H (valid boot sector marker); NZ if non-zero (invalid).
4F8C
If the NZ FLAG has been set (the first boot sector byte is not 00H, indicating this is not a valid NEWDOS/80 diskette), JUMP to 4FD6H to return error code 2CH. [ERROR PATH — invalid boot sector]
4F8E
INC HL 23
INCrement HL to 4301H, the second byte of the boot sector.
4F8F
LD A,(HL) 7E
Load Register A with the byte at 4301H. In a valid boot sector, this byte should be FEH (the directory granule indicator / GAT marker).
4F90
CP FEH FE FE
Compare Register A against FEH. If the byte is FEH, the Z FLAG is set (valid); otherwise NZ FLAG is set (invalid).
4F92
If the NZ FLAG has been set (the second byte is not FEH), JUMP to 4FD6H to return error code 2CH. [ERROR PATH — invalid directory marker]
4F94
INC HL 23
INCrement HL to 4302H, the third byte of the boot sector.
4F95
LD L,(HL) 6E
Load Register L with the byte at 4302H — the directory starting granule number. This value tells WRDIRP where the directory begins on the diskette. HL now has H=43H (unchanged from 4300H high byte), L=granule number.
4F96H - WRDIRP: SET UP DIRECTORY SECTOR ACCESS
Using the directory starting granule number from the boot sector, this section sets up the I/O parameter block to access directory sectors. It calls SYS0 routines to convert the granule number to a physical track and sector, then reads the first directory sector to verify it contains the expected system files (BOOT/SYS and DIR/SYS). Once verified, it loops through all directory sectors, rewriting each one with the protected address mark.
4F96
LD A,05H 3E 05
Load Register A with 05H. This is a parameter for the granule-to-sector conversion routine, specifying sector 5 within the granule (the first directory sector in the granule).
4F98
PUSH HL E5
Save HL (H=43H, L=directory starting granule number) onto the stack.
4F99
GOSUB to 4C37H (in SYS0), a routine that sets up for sector access given a granule number. Register A = sector within granule (05H), HL provides the granule context. On return, HL points to the sector access structure and the I/O parameter block is partially configured.
4F9C
LD A,(4285H) 3A 85 42
Load Register A with the byte at 4285H, which contains a system parameter (the number of sectors per granule or similar disk geometry value from the active PDRIVE configuration). This value is needed to compute the total number of directory sectors.
4F9F
GOSUB to 4C39H (in SYS0), a continuation of the granule-to-sector setup. This completes the sector access configuration using the value in Register A. On return, HL points to the sector access information and the track/sector parameters are fully resolved.
4FA2
POP DE D1
Restore DE from the stack (the saved HL: D=43H, E=directory starting granule number).
4FA3
PUSH HL E5
Save HL (the sector access pointer returned by 4C39H) onto the stack for later use.
4FA4
PUSH DE D5
Save DE (D=43H, E=directory starting granule number) onto the stack.
4FA5
INC HL 23
INCrement HL by 1, advancing past the first byte of the sector access structure to point to the sector count or track/sector pair.
4FA6
LD (5028H),HL 22 28 50
Store HL (the adjusted sector access pointer) into memory location 5028H, a local variable in the WRDIRP data area that holds the current sector address pointer for the directory rewrite loop.
4FA9
GOSUB to 4FDBH, the "read sector and handle errors" subroutine. This reads the current directory sector (using the I/O parameter block at 501EH) into the DOS buffer at 4300H. If the read fails with an error other than 06H (record not found / end of track), execution branches to the error handler. On return, Z FLAG set = success, error code 06H also returns (Z set).
4FAC
LD A,(431FH) 3A 1F 43
Load Register A with the byte at 431FH. This is a value in the DOS buffer (offset +1FH from the buffer base at 4300H) that contains the number of directory sectors remaining or a track boundary value. Adding 0AH (10 decimal) converts this into the total sector count for the directory rewrite loop.
4FAF
ADD 0AH C6 0A
ADD 0AH (10 decimal) to Register A. This computes the total number of directory sectors that WRDIRP needs to rewrite. The result in A becomes the loop counter.
4FB1
LD H,A 67
Load Register H with Register A (the computed directory sector count).
4FB2
EX (SP),HL E3
Exchange HL with the value on top of the stack. The directory sector count (in H) is pushed onto the stack, and the previously saved DE (D=43H, E=granule number) is popped into HL.
4FB3
PUSH HL E5
Save HL (now containing the granule number context) onto the stack.
4FB4
LD C,00H 0E 00
Load Register C with 00H. Register C is used as a parameter for the FPDE verification subroutine — it specifies which drive number to check (0 = current drive's FPDE sector).
4FB6
LD HL,500FH 21 0F 50
Point Register Pair HL to 500FH, the address of the ASCII string "BOOT" (4 bytes: 42H, 4FH, 4FH, 54H). This is the filename to verify in the directory.
4FB9
GOSUB to 4FE7H, the "read sector and verify FPDE" subroutine. This reads the current directory sector, checks that it is a valid directory sector with the proper attributes, and verifies that the FPDE for BOOT/SYS is present. If the check fails, execution branches to the error handler.
4FBC
POP BC C1
Restore BC from the stack (contains granule number context from the earlier PUSH HL at 4FB3H; now in BC for temporary holding).
4FBD
LD HL,5013H 21 13 50
Point Register Pair HL to 5013H, the address of the ASCII string "DIR /SYS" (the 11-byte filename for DIR/SYS with space padding). This is the second filename to verify in the directory.
4FC0
GOSUB to 4FE7H again to verify the FPDE for DIR/SYS is present in the directory. If the check fails, error code 2CH is returned.
4FC3
POP BC C1
Restore BC from the stack. B now contains the directory sector count (the total number of sectors to rewrite, computed at 4FAFH–4FB1H).
4FC4
POP HL E1
Restore HL from the stack (the sector access pointer saved at 4FA3H).
4FC5H - WRDIRP: DIRECTORY SECTOR REWRITE LOOP
This is the main loop that rewrites each directory sector with the protected address mark. For each iteration, it stores the current sector address, reads the sector, writes it back (which applies the current protected address mark), and advances to the next directory sector. Register B is the loop counter (total directory sectors). The loop uses the DOS write routine at 443CH which writes the sector with the protected address mark determined by the current system configuration.
4FC5
LD (5028H),HL 22 28 50
Store HL (the current sector address pointer) into memory location 5028H, updating the sector address field for the next I/O operation. [LOOP START — rewrite one directory sector]
4FC8
GOSUB to 4FDBH, the "read sector and handle errors" subroutine. Read the current directory sector into the DOS buffer. Returns Z FLAG set on success (or error 06H which is handled).
4FCB
LD (5028H),HL 22 28 50
Store HL into 5028H again. This updates the sector address pointer after the read (HL may have been advanced by the read routine).
4FCE
If the Z FLAG has been set (the read was successful), GOSUB to 443CH (in SYS0), the DOS sector write routine. This writes the sector from the DOS buffer back to the diskette with the currently defined protected address mark. The conditional CALL (CALL Z) means the write is skipped if the read returned an error.
4FD1
RET NZ C0
If the NZ FLAG has been set (the sector write failed), RETURN with the error code in Register A. [ERROR PATH — write failed]
4FD2
INC HL 23
INCrement HL by 1, advancing to the next sector address in the directory sector sequence.
4FD3
DECrement B (the directory sector counter) and loop back to 4FC5H if not zero. Continue rewriting directory sectors until all have been processed. [LOOP END — rewrite next sector]
4FD5
RET C9
RETURN to the DOS command dispatcher. All directory sectors have been successfully rewritten with the protected address mark. [SUCCESS — WRDIRP complete]
4FD6H - WRDIRP ERROR EXITS
Error exit points used by WRDIRP when validation fails or when BK=N. These are shared with the SYSTEM command's error handler at 4E81H.
4FD6
LD A,2CH 3E 2C
Load Register A with 2CH (error code 44 decimal = directory full / invalid directory). This error indicates the boot sector or directory structure is invalid.
4FD8
JUMP to 4E81H, the DOS error handler entry point at 4409H. Register A contains the error code (2CH from 4FD6H or 37H from 4F72H). [ERROR EXIT]
4FDBH - READ SECTOR WITH ERROR HANDLING
A utility subroutine used by WRDIRP to read a sector from the target diskette. It calls the DOS sector read routine using the I/O parameter block at 501EH. If the read succeeds (Z FLAG), it returns immediately. If the read fails with error code 06H (record not found / end of track), it returns with Z FLAG set (treating it as a non-fatal condition, since the directory may not fill an entire track). Any other error is fatal and branches to the error handler.
4FDB
LD DE,501EH 11 1E 50
Point Register Pair DE to 501EH, the base address of the WRDIRP sector I/O parameter block.
4FDE
GOSUB to 4436H (in SYS0), the DOS sector read routine. Read the sector specified by the I/O parameter block into the DOS buffer at 4300H.
4FE1
RET Z C8
If the Z FLAG has been set (the sector read succeeded), RETURN to the caller with Z FLAG set (success).
4FE2
CP 06H FE 06
Compare Register A (the error code) against 06H (record not found / end of track). If the error is 06H, the Z FLAG is set.
4FE4
If the NZ FLAG has been set (the error is not 06H — some other disk error), JUMP to 4FD8H to report the error via the error handler. [ERROR PATH — fatal disk error]
4FE6
RET C9
RETURN to the caller. The error was 06H (non-fatal end of track), so return with Z FLAG set from the CP 06H comparison, allowing WRDIRP to continue.
4FE7H - VERIFY DIRECTORY FPDE (FILE PRIMARY DIRECTORY ENTRY)
This subroutine reads a directory sector, verifies that it is a valid directory sector (checking specific attribute bits at 4300H and the drive number at 4316H), and then compares the filename in the sector against an expected filename. It is called twice by WRDIRP: once to verify BOOT/SYS and once to verify DIR/SYS. On entry, HL points to the expected filename string, and C contains the expected drive number. If any check fails, execution branches to error code 2CH.
4FE7
GOSUB to 4FDBH, read the current directory sector into the DOS buffer at 4300H.
4FEA
LD A,(4300H) 3A 00 43
Load Register A with the byte at 4300H, the first byte of the directory entry (the FPDE status/attribute byte). This byte contains flags indicating the file's attributes.
4FED
AND 50H E6 50
AND Register A with 50H (binary 01010000), isolating bits 6 and 4 of the FPDE status byte. Bit 6 indicates the entry is active/in-use; Bit 4 indicates the entry is a system file.
4FEF
CP 50H FE 50
Compare Register A against 50H. Both bits 6 and 4 must be set (active system file). If the result is 50H, Z FLAG is set (valid); otherwise NZ (invalid).
4FF1
If the NZ FLAG has been set (the directory entry does not have the expected system file attributes), JUMP to 4FD6H to return error code 2CH. [ERROR PATH — not a valid system FPDE]
4FF3
LD A,(4316H) 3A 16 43
Load Register A with the byte at 4316H, the drive number field of the FPDE in the DOS buffer. This is at offset +16H from the buffer base (4300H), which is the drive assignment byte in the directory entry.
4FF6
CP C B9
Compare Register A (the FPDE's drive number) against Register C (the expected drive number, initially 0). If they match, Z FLAG is set.
4FF7
If the NZ FLAG has been set (the drive number in the FPDE does not match the expected drive), JUMP to 4FD6H to return error code 2CH. [ERROR PATH — wrong drive in FPDE]
4FF9
LD DE,4305H 11 05 43
Point Register Pair DE to 4305H, the filename field of the FPDE in the DOS buffer. The filename starts at offset +05H from the buffer base (4300H).
4FFC
LD B,04H 06 04
Load Register B with 04H (4 bytes). The first comparison checks the first 4 bytes of the filename (e.g., "BOOT" or "DIR ").
4FFE
GOSUB to 5006H, the byte-by-byte comparison loop. Compare 4 bytes at (DE) against 4 bytes at (HL). If any byte mismatches, execution branches to 4FD6H (error). On return, both DE and HL have advanced past the compared bytes.
5001
LD HL,5017H 21 17 50
Point Register Pair HL to 5017H, the second part of the expected filename string. For BOOT/SYS verification, this points to " /SYS" (spaces and extension). For DIR/SYS, the full filename was at 5013H and this provides the remaining extension bytes.
5004
LD B,07H 06 07
Load Register B with 07H (7 bytes). Compare the remaining 7 bytes of the filename+extension field in the FPDE against the expected string.
5006H - BYTE-BY-BYTE COMPARISON LOOP
A simple comparison loop that checks B bytes at (DE) against B bytes at (HL). If any mismatch is found, execution jumps to the error handler at 4FD6H. On success, DE and HL are left pointing past the compared regions, and execution falls through to the RET.
5006
LD A,(DE) 1A
Load Register A with the byte at (DE) — the current byte from the FPDE filename in the DOS buffer. [LOOP START — compare one byte]
5007
CP (HL) BE
Compare Register A against the byte at (HL) — the expected filename character. If they match, Z FLAG is set.
5008
INC DE 13
INCrement DE by 1 to advance to the next byte in the FPDE filename.
5009
INC HL 23
INCrement HL by 1 to advance to the next expected filename character.
500A
If the NZ FLAG has been set (the bytes do not match), JUMP to 4FD6H to return error code 2CH. [ERROR PATH — filename mismatch]
500C
DECrement B and loop back to 5006H if not zero. Continue comparing bytes. [LOOP END]
500E
RET C9
RETURN to the caller. All B bytes matched — the FPDE filename is correct.
500FH - WRDIRP STRING CONSTANTS AND I/O PARAMETER BLOCK
This data area contains the reference filename strings used by WRDIRP to verify that the directory contains BOOT/SYS and DIR/SYS entries, followed by the WRDIRP sector I/O parameter block at 501EH. The disassembler renders these bytes as Z80 instructions, but they are DATA.
500F
DEFM "BOOT" 42 4F 4F 54
[DATA — BOOT filename] Four ASCII bytes: "BOOT" (42H, 4FH, 4FH, 54H). Used at 4FB6H to verify the BOOT/SYS FPDE in the directory.
5013
DEFM "DIR " 44 49 52 20
[DATA — DIR filename (part 1)] Four ASCII bytes: "DIR " (44H, 49H, 52H, 20H). The first 4 characters of the DIR/SYS filename, with one trailing space.
5017
DEFM " /SYS" 20 20 20 20 2F 53 59 53
[DATA — Filename extension] Eight ASCII bytes: four spaces (20H) followed by "/SYS" (2FH, 53H, 59H, 53H). This is the shared extension portion used for both BOOT/SYS and DIR/SYS filename comparisons. For BOOT, the comparison starts at 500FH (4 chars) then continues at 5017H (7+ chars). For DIR, it starts at 5013H (4 chars) then continues at 5017H (7 chars).
501EH - WRDIRP SECTOR I/O PARAMETER BLOCK
This 14-byte structure at 501EH–502BH is the sector I/O parameter block used by the WRDIRP command. It is passed to the DOS sector read/write routines via Register Pair DE. The drive number at offset +06H (5024H) is set at 4F79H. The sector address pointer at offset +0AH (5028H) is updated during the directory rewrite loop.
501E
DEFB 83H 83
[DATA — WRDIRP I/O Block +00H] Control/flags byte. 83H = bit 7 set (sector I/O operation), bits 1 and 0 set (read+write operation flags).
501F
DEFB 60H 60
[DATA — WRDIRP I/O Block +01H] Additional control flags (60H), same as the SYSTEM parameter block.
5020
DEFB 00H,00H 00 00
[DATA — WRDIRP I/O Block +02H/+03H] Reserved (0000H).
5022
DEFB 43H 43
[DATA — WRDIRP I/O Block +04H] High byte of DOS buffer address (43H → buffer at 4300H).
5023
DEFB 00H 00
[DATA — WRDIRP I/O Block +05H] Low byte of DOS buffer address (00H → buffer at 4300H).
5024
DEFB 00H 00
[DATA — WRDIRP I/O Block +06H: Drive Number] Written by WRDIRP at 4F79H with the parsed drive number. Initialized to 00H.
5025
DEFB FFH FF
[DATA — WRDIRP I/O Block +07H] Track number or flag (FFH = default).
5026
DEFB 00H,00H 00 00
[DATA — WRDIRP I/O Block +08H/+09H] Reserved (0000H).
5028
DEFB 00H,00H 00 00
[DATA — WRDIRP I/O Block +0AH/+0BH: Sector Address] Updated during the directory rewrite loop at 4FA6H, 4FC5H, 4FCBH. Holds the current sector address for read/write operations.
502A
DEFB FFH,FFH FF FF
[DATA — WRDIRP I/O Block +0CH/+0DH] End-of-block markers (FFH).
502CH - RESIDUAL CODE (NOT PART OF SYS17)
The bytes from 502CH through 509EH are residual code left over from a different SYS overlay module that previously occupied this memory region. These instructions reference addresses far outside SYS17's range (5535H, 5784H, 56F9H, 5762H, 48C4H, 54CBH, 552DH) and memory locations in the 5900H range (59C1H, 5994H, 59C6H, 59BBH, 5981H, 5983H, 598BH, 59D1H, 59C3H, 59BCH), confirming this code belongs to a different overlay (such as SYS6 or a related FORMAT/COPY module). This residual code is NOT executed by SYS17 and is overwritten when other overlays load. It is listed here only for completeness.
502C–509E
RESIDUAL CODE (115 bytes)
[RESIDUAL — Not SYS17] 115 bytes of leftover code from a previous overlay module. Contains calls to routines at 5535H, 5784H, 56F9H, 5762H, 48C4H and jumps to 54CBH, 552DH with references to data in the 5980H–59D1H range. These are artifacts from a different SYS overlay and are never executed in the context of SYS17.
509FH - NOP PADDING (UNUSED SPACE)
The region from 509FH through 51E7H contains 329 bytes of NOP (00H) padding. This is unused reserved space within the SYS17 overlay file, filling out the remainder of the overlay allocation to the file boundary. The PROGRAM ENTRY point is 4D00H as noted at the end of the source file.
509F–51E7
NOP × 329 00 (×329)
[PADDING] 329 bytes of NOP instructions (00H) from 509FH through 51E7H. This is unused space filling the remainder of the SYS17 overlay file allocation.