TRS-80 DOS - LDOS 5.3.1 for the Model I - SYS7/SYS Disassembled

Page Customization

Summary:

LDOS 5.3.1 SYS7/SYS Disassembly - Library B Command Set (Model I)

SYS7/SYS holds the second half of the LDOS 5.3.1 command library. Like SYS6/SYS (Library A), it is not a single overlay but a partitioned file of independent command overlays, each assembled with .ORG 5200H. Every overlay loads at 5200H and runs one at a time. The resident RST 28H dispatcher at 4BCDH recognizes request code 89H as "Library B", and the resident overlay loader at 4BF5H brings the requested command overlay into 5200H (in register B) and enters it at its first byte. The command name a user types is mapped to a (library, command-number) pair by the resident command interpreter (SYS1) through its command-name table at 4EBDH; SYS7 itself never sees the typed name, only the loaded overlay and the command number.

SYS7/SYS contains 13 overlays that together serve 15 command codes. Two overlays each serve a related pair of commands: the DATE/TIME overlay and the DEBUG/VERIFY overlay each expose two entry points at the top of the overlay, one per command number. The file is framed as an LDOS load module: a type 05 header (module name "sys7 "), a type 1F comment ("(C) 1982-4,6,90 MISOSYS"), then fifteen 6-byte type 08 directory entries (one per command code, giving the command code and the file offset of its overlay), then the 13 overlays as runs of type 01 load records, and a closing type 02 transfer record. The entire memory image of all 13 overlays was rebuilt from the binary through these load records and compared byte-for-byte against the disassembly listing: 0 mismatches.

Every overlay follows the common LDOS command shape: it saves the caller's stack pointer with a self-modifying LD (nnnnH),SP at entry (patching the operand of the exit's LD SP,nnnn), skips leading blanks on the command line, parses its keyword parameters, performs its work through the resident SYS0 supervisor services, and exits by returning to the RST 28H dispatcher (or aborting to @ABORT at 4030H when it is invoked from something other than the LDOS command level). The resident system flag SFLAG$ at 430FH bit 5 ("not at LDOS command level") gates the commands that are only valid at command level.

Command / Overlay Directory (verified against the SYS7/SYS load module)

Cmd CodeLoad RangeBytesCommand / Function
11H5200-5351H338AUTO
Set, display, or clear the diskette's auto-execute command line (stored in the GAT sector at offset E0H). Documented below.
15H / 16H5200-548DH654DATE / TIME
Display or set the system date (15H) and time/clock (16H); shares one overlay with two entry points (5200H JP for DATE, 5203H JP for TIME). Carries the 3-letter day and month name tables.
13H5200-53D2H467CREATE
Pre-allocate a file to a fixed size and set its record attributes (SIZE/HRS/HRREC/ARR/ARLRL/WRL/WRFILL/RF/RSHRINK); message "Creating: ".
14H / 1BH5200-5349H330DEBUG / VERIFY
Arm/disarm the DEBUG breakpoint re-entry (writes "JP 400FH" at 4315-4317, issues RST 28H code 8BH) and patch the @WRITE vector for write-verification; two entry points (5200H / 5203H). Command-code binding to be confirmed against the SYS1 4EBDH table.
1CH5200-552FH816SYSGEN
Build or delete the stored system configuration file CONFIG/SYS.CCC:0; messages "User configuration built/deleted", "*** CONFIGURING ***".
22H5200-55A3H932FREE
Display drive free-space and diskette information ("Drive :d packname packdate cyldh Free=sssss.s/sssss.s Fi=nnn/nnn").
A1H5200-5EE6H3303SYSTEM
System configuration command (SYSGEN/SYSRES/DRIVE/TYPE-ahead and more); "Can't SYSGEN with active SPOOLER!", "New SYSTEM drive installed", "Insert SYSTEM diskette in drive". Largest overlay in the file.
33H5200-5402H515BUILD
Build or append a keystroke/JCL file ("Building: ", "Appending: *KI to "), with HEX and APPEND options; "Odd # of hex digits!".
51H5200-56D5H1238ATTRIB
Set file/diskette attributes and passwords (PW/LOCK/UNLOCK/NAME/MPW); "New Master password ?", "Invalid master password!", "ATTRIB aborted!".
71H5200-5405H518DUMP
Dump memory to a file in CIM/TXT format with START/END/TRA/LRL/ASCII/ETX options; "Dumping: ", "START or END error!", "Start less than X'5500'!".
72H5200-577CH1405PURGE
Selectively delete files with INV/SYS/MPW/QUERY options and date filtering; "Purge file: ", "Purging: ", "Master password ?".
B1H5200-5525H806FORMS
Set the Forms printer-filter parameters (LINES/PAGE/CHARS/INDENT/ADDLF/FFHARD/TAB/XLATE/MARGIN); "Forms Filter not Resident".
B2H5200-569CH1181SETCOM
Set the RS-232 driver parameters (BAUD/WORD/STOP/PARITY/BREAK/DTR/RTS/DSR/CTS); "RS232/DVR not installed".

Cross-Reference Notes

SYS7/SYS is loaded and dispatched by the resident RST 28H supervisor in SYS0/SYS (dispatcher 4BCDH, overlay loader 4BF5H) in response to request code 89H. The command name to command-number mapping is performed by the SYS1/SYS command interpreter through its command-name table at 4EBDH. The AUTO overlay calls the following resident SYS0 services: @LOGOT (447BH, display a carriage-return-terminated string), @CKDRV (44B8H, validate a drive number), @ERROR (4409H, report an error code), @ABORT (4030H, return to DOS), DIRCYL (4B65H, seek the directory cylinder), RDSSEC (4B45H, read a directory-track sector), WRPROT (4768H, write a directory sector with a deleted-data address mark), and VERSEC (4772H, verify a sector). The "=" path additionally jumps to the resident entry at 4451H to re-execute the stored auto command line.

Overlay 1 - AUTO

AUTO (Command 11H) - Variables and Self-Modifying Cells

Address RangePurpose
5220H
2 bytes
Saved stack pointer. Written by the entry LD (5220H),SP at 5200H and consumed both as the operand of LD SP,nnnn at 521FH and by LD SP,(5220H) at 525AH to restore the caller's stack. Self-Modifying Code.
5268H
1 byte
Drive-valid flag. The operand of LD A,00H at 5267H, patched by the drive-check routine at 52A1H to 00H when the target drive is valid or FFH when it is not. Self-Modifying Code.
52A2H
1 byte
Parsed drive number. The operand of LD C,00H at 52A1H, patched by the ":d" drive parser at 52B4H (default 0). Read back at 528DH to select which drive's GAT to write. Self-Modifying Code.
42E0H
32 bytes
The auto-execute command field inside the shared directory/sector buffer SBUFF$ (4200H). LDOS stores the AUTO command string at offset E0H of the diskette's GAT sector; AUTO reads that sector into 4200H so 42E0H holds the current auto command, terminated by 0DH.

AUTO (Command 11H) - Major Routines

AddressName / Purpose
5200HAUTO Entry
Save SP, skip blanks, and branch on the first command-line character: "?" displays the current auto command, "=" re-executes the stored auto command, anything else stores a new auto command.
52A1HValidate Drive and Read GAT
Load C with the parsed drive number, call @CKDRV (44B8H), record the valid/invalid result, and (when valid) read the GAT sector into 4200H via 52D0H.
52B4HParse Optional Drive Spec
If the next command-line character is ":", read the following digit as the drive number and store it in the 52A2H cell; validate it is 0-7.
52D0HRead GAT Sector
Seek the directory cylinder (DIRCYL 4B65H) and read sector 0 (the GAT, which holds the auto command at offset E0H) into 4200H via RDSSEC (4B45H). Returns error code 14H on failure.
52E3HWrite GAT Sector
Write the 4200H buffer back to the directory cylinder's sector 0 with a deleted-data address mark (WRPROT 4768H) and verify it (VERSEC 4772H). Returns error code 15H on failure.

5200H - AUTO Command (RST 28H Code 89H, Command 11H)

Set, display, or re-execute the diskette's auto-execute command line. On entry from the resident overlay loader HL points to the command line just past the command name, and register B held the command number (11H) used by the loader to select this overlay. The auto command is stored in the diskette's GAT sector at offset E0H, which AUTO reads into the shared buffer at 42E0H.

5200
LD (5220H),SP ED 73 20 52
Self-Modifying Code
Save the caller's stack pointer into 5220H, which is simultaneously the operand of the LD SP,nnnn instruction at 521FH and the source read by LD SP,(5220H) at 525AH. This lets AUTO restore the caller's stack on the way out.
5204
DEC HL 2B
Back HL (the command-line pointer, pointing just past the command name) up by one byte so that the first INC HL of the blank-skip loop at 5205H lands on the original first character.
5205
INC HL 23
Loop Start
Advance HL to the next command-line character. HL is the running command-line pointer.
5206
LD A,(HL) 7E
Fetch the current command-line character (addressed by HL) into Register A.
5207
CP 20H FE 20
Compare Register A (the current command-line character) against 20H (ASCII space). If Register A equals 20H the Z FLAG is set; otherwise the NZ FLAG is set.
5209
If the Z FLAG is set (the character was a blank), LOOP BACK to 5205H to skip it. Loop End
520B
CP 3FH FE 3F
Compare Register A (the first non-blank command-line character) against 3FH (ASCII ?). If Register A equals 3FH the Z FLAG is set; otherwise the NZ FLAG is set.
520D
If the NZ FLAG is set (the character is not ?), JUMP to 522EH to test for the "=" form. Otherwise fall through to display the current auto command.
520F
INC HL 23
Consume the ? character by advancing the command-line pointer HL past it.
5210
GOSUB to 52B4H to parse an optional ":d" drive specifier from the command line (HL) into the drive-number cell 52A2H.
5213
GOSUB to 52A1H to validate the selected drive and read that drive's GAT sector (which contains the auto command at offset E0H) into the buffer at 4200H.
5216
LD HL,42E0H 21 E0 42
Point HL to 42E0H, the auto-execute command field within the GAT sector buffer that 52A1H just filled. This is a carriage-return-terminated string holding the current auto command.
5219
GOSUB to the resident SYS0 service @LOGOT (447BH) to display the carriage-return-terminated string at HL (42E0H), showing the current auto command to the user.
521C
LD HL,0000H 21 00 00
Set HL to 0000H, the success return/error code (0 means no error). This point is reached both after displaying the auto command and after a successful write.
521F
LD SP,0000H 31 00 00
Self-Modifying Code
Restore the caller's stack pointer. The operand at 5220H was overwritten at 5200H with the caller's SP, so this loads SP with the caller's stack pointer.
5222
LD A,H 7C
Copy the high byte of HL (the error code) into Register A to begin testing whether the code is zero.
5223
OR L B5
OR Register A (error code high byte) with L (error code low byte). If HL was 0000H the Z FLAG is set; any non-zero error code leaves the NZ FLAG set.
5224
RET Z C8
If the Z FLAG is set (error code 0, success), RETurn to the RST 28H dispatcher.
5225
LD A,(430FH) 3A 0F 43
Fetch the resident system flag byte SFLAG$ from 430FH into Register A to test the command-level flag.
5228
BIT 5,A CB 6F
Test bit 5 of Register A (SFLAG$ from 430FH). Bit 5 set means the system is NOT at the LDOS command level (for example, running under a program or JCL). If bit 5 is 0 the Z FLAG is set.
522A
RET Z C8
If the Z FLAG is set (bit 5 of SFLAG$ clear, meaning AUTO was run at the LDOS command level), RETurn to the dispatcher, letting the non-zero error code propagate normally.
522B
Otherwise (bit 5 of SFLAG$ set, meaning AUTO was invoked from something other than the command level and an error occurred), JUMP to the resident SYS0 service @ABORT (4030H) to abort back to DOS.
522E
CP 3DH FE 3D
Compare Register A (the first non-blank command-line character) against 3DH (ASCII =). If Register A equals 3DH the Z FLAG is set; otherwise the NZ FLAG is set.
5230
If the NZ FLAG is set (the character is not =), JUMP to 5261H to store a new auto command. Otherwise fall through to re-execute the stored auto command.
5232
INC HL 23
Consume the = character by advancing the command-line pointer HL past it.
5233
GOSUB to 52B4H to parse an optional ":d" drive specifier from the command line (HL) into the drive-number cell 52A2H.
5236
GOSUB to 52A1H to validate the selected drive and read its GAT sector (containing the stored auto command at offset E0H) into the buffer at 4200H.
5239
LD HL,42E0H 21 E0 42
Point HL to 42E0H, the stored auto command inside the GAT buffer, to prepare to re-execute it.
523C
LD A,(HL) 7E
Fetch the first character of the stored auto command (addressed by HL at 42E0H) into Register A.
523D
CP 2AH FE 2A
Compare Register A (the first stored-command character) against 2AH (ASCII *). A leading * is the LDOS marker that flags a special auto command. If equal the Z FLAG is set.
523F
If the NZ FLAG is set (no leading *), JUMP to 524AH. Otherwise fall through to set the SFLAG$ marker bit.
5241
INC HL 23
Consume the * marker by advancing HL past it, so the command that follows can be executed.
5242
LD IY,430FH FD 21 0F 43
Point IY to the resident system flag byte SFLAG$ at 430FH so its marker bit can be set.
5246
SET 4,(IY+00H) FD CB 00 E6
Set bit 4 of SFLAG$ (430FH, addressed by IY+0) to record that the auto command was flagged with a leading *.
524A
LD A,(HL) 7E
Fetch the next character of the stored auto command (addressed by HL) into Register A to check for an empty command.
524B
CP 0EH FE 0E
Compare Register A (the stored-command character) against 0EH. LDOS treats any byte below 0EH as an end-of-string terminator. If Register A is below 0EH the CARRY FLAG is set.
524D
If the CARRY FLAG is set (the stored command is empty), JUMP to 5285H to report "No AUTO command installed!".
5250
LD DE,5261H 11 61 52
Load Register Pair DE with 5261H, which is pushed next as the return address so control comes back into this overlay's store path after the stored command has been copied.
5253
PUSH DE D5
Save 5261H (Register Pair DE) onto the stack as the return address for the block copy that follows.
5254
LD BC,0040H 01 40 00
Load Register Pair BC with 0040H (64), the byte count for the block copy of the stored auto command.
5257
LDIR ED B0
Block-copy 64 bytes: Source is HL (the stored auto command at 42E0H), Destination is DE (5261H), count is BC (64), incrementing. This moves the stored command out of the GAT buffer into a scratch area so the command interpreter can run it after the overlay releases the buffer.
5259
POP HL E1
Restore HL from the stack (5261H, the start of the copied command string) so it can be handed to the command executor.
525A
LD SP,(5220H) ED 7B 20 52
Self-Modifying Code
Restore the caller's stack pointer from 5220H, where it was saved at 5200H, before transferring to the resident command executor.
525E
JUMP to the resident SYS0 entry at 4451H to execute the copied auto command string (HL points to it at 5261H). This is the re-execute path for the "AUTO=" form.
5261
Store path. GOSUB to 52B4H to parse an optional ":d" drive specifier from the command line (HL) into the drive-number cell 52A2H.
5264
GOSUB to 52A1H to validate the selected drive and read its GAT sector into the buffer at 4200H so the auto command field at 42E0H can be rewritten.
5267
LD A,00H 3E 00
Self-Modifying Code
Load Register A with the drive-valid flag. The operand at 5268H was patched by 52A1H to 00H (drive valid) or FFH (drive invalid).
5269
OR A B7
Test Register A (the drive-valid flag). If it is 00H (drive valid) the Z FLAG is set; if FFH the NZ FLAG is set.
526A
If the NZ FLAG is set (the target drive is write protected or otherwise not writable), JUMP to 5281H to report "Destination disk is write protected!".
526C
LD DE,42E0H 11 E0 42
Point Register Pair DE to 42E0H, the auto command field in the GAT buffer, as the destination for the new command string being stored.
526F
LD A,(HL) 7E
Loop Start
Fetch the next source character of the new command from the command line (addressed by HL) into Register A.
5270
LD (DE),A 12
Store the command character (Register A) into the auto command field (addressed by DE within the GAT buffer).
5271
CP 0DH FE 0D
Compare Register A (the just-stored character) against 0DH (carriage return, the end-of-line marker). If equal the Z FLAG is set.
5273
If the Z FLAG is set (end of the command line), JUMP to 528DH to write the updated GAT sector back to disk.
5275
CP 03H FE 03
Compare Register A (the just-stored character) against 03H (ETX, the alternate end-of-string marker). If equal the Z FLAG is set.
5277
If the Z FLAG is set (end of the command string), JUMP to 528DH to write the updated GAT sector back to disk.
5279
INC HL 23
Advance the command-line source pointer HL to the next character.
527A
INC E 1C
Advance only the low byte of the destination pointer DE (E) to the next byte of the auto command field. E started at E0H, so it wraps to 00H after 32 characters.
527B
If the NZ FLAG is set (E has not yet wrapped past the 32-byte field), LOOP BACK to 526FH for the next character. If E has wrapped to 00H the command was too long and execution falls through. Loop End
527D
LD HL,5320H 21 20 53
The command line overflowed the 32-byte auto command field. Point HL to the message text "Command line too long!" at 5320H for display.
5280
LD IX,52FBH DD 21 FB 52
Overlapping Code
On straight fall-through from 527DH this loads IX with 52FBH and has no effect on the message (HL already points to "Command line too long!"). Entered at 5281H (skipping the DD prefix) the bytes 21 FB 52 decode instead as LD HL,52FBH, pointing HL at the message "Destination disk is write protected!". 5281H is the write-protect error entry reached from 526AH.
5284
LD IX,5337H DD 21 37 53
Overlapping Code
On fall-through this loads IX with 5337H with no effect. Entered at 5285H (skipping the DD prefix) the bytes 21 37 53 decode as LD HL,5337H, pointing HL at the message "No AUTO command installed!". 5285H is the empty-command entry reached from 524DH.
5288
GOSUB to the resident SYS0 service @LOGOT (447BH) to display the carriage-return-terminated error message pointed to by HL (5320H, 52FBH, or 5337H depending on the entry point above).
528B
JUMP to 529BH to set the failure return code and exit.
528D
LD A,(52A2H) 3A A2 52
Fetch the parsed drive number from the 52A2H cell into Register A, to tell the GAT-write routine which drive to update.
5290
LD C,A 4F
Copy the drive number (Register A) into Register C, the drive argument expected by the GAT-write routine.
5291
GOSUB to 52E3H to write the updated GAT sector (buffer at 4200H, now holding the new auto command at 42E0H) back to the directory cylinder of drive C. On success it returns with the Z FLAG set; on failure Register A holds an error code.
5294
If the Z FLAG is set (the GAT sector was written successfully), JUMP to 521CH to set the success code and exit.
5296
OR 0C0H F6 C0
Set bits 7 and 6 of the error code in Register A. These bits tell the @ERROR service to display the message and return to the caller rather than abort. This point is also the shared error tail reached from the drive parser and drive check.
5298
GOSUB to the resident SYS0 service @ERROR (4409H) to display the system error message for the code in Register A.
529B
LD HL,0FFFFH 21 FF FF
Set HL to FFFFH, the non-zero failure return/error code checked at the exit tail.
529E
JUMP to the exit tail at 521FH to restore the caller's stack and return (or abort) with the failure code in HL.

52A1H - Validate Drive and Read GAT Sector

Load Register C with the parsed drive number, validate it with the resident @CKDRV service, record whether the drive is usable in the self-modifying flag at 5268H, and (when the drive is valid) read the drive's GAT sector into the buffer at 4200H.

52A1
LD C,00H 0E 00
Self-Modifying Code
Load Register C with the drive number. The operand at 52A2H is patched by the drive parser at 52B4H, so C receives the parsed drive number (default 0).
52A3
GOSUB to the resident SYS0 service @CKDRV (44B8H) to validate the drive number in Register C and confirm the drive is enabled. It reports validity through the Z and CARRY flags.
52A6
PUSH AF F5
Save Register A and the flags returned by @CKDRV onto the stack so the validity result can be recorded without losing the flags.
52A7
SBC A,A 9F
Subtract-with-carry Register A from itself, producing 00H when @CKDRV left the CARRY FLAG clear (drive valid) or FFH when CARRY was set (drive invalid).
52A8
LD (5268H),A 32 68 52
Self-Modifying Code
Store the 00H/FFH drive-valid flag (Register A) into 5268H, the operand of the LD A,00H at 5267H, so the store path can later branch on drive validity.
52AB
POP AF F1
Restore Register A and the @CKDRV flags from the stack so the Z FLAG can gate the GAT read below.
52AC
LD A,20H 3E 20
Load Register A with 20H, the pre-set error code used if the drive check indicated an illegal drive number (error 20H = illegal drive number).
52AE
If the Z FLAG is set (the drive is valid), GOSUB to 52D0H to read the drive's GAT sector into the buffer at 4200H. On return the Z FLAG reflects whether the read succeeded.
52B1
RET Z C8
If the Z FLAG is set (the GAT sector was read successfully), RETurn to the caller with the buffer at 4200H filled.
52B2
Otherwise (illegal drive or a read error, error code in Register A), JUMP to the shared error tail at 5296H to report the error.

52B4H - Parse Optional Drive Specifier

If the command line at HL continues with a ":d" drive specifier, read the drive digit, store it in the drive-number cell 52A2H, and validate the range 0-7. If there is no drive specifier the routine returns leaving the default in place.

52B4
LD A,(HL) 7E
Fetch the next command-line character (addressed by HL) into Register A to test for a drive specifier.
52B5
CP 0EH FE 0E
Compare Register A (the command-line character) against 0EH. Any byte below 0EH is an end-of-line terminator. If below 0EH the CARRY FLAG is set.
52B7
RET C D8
If the CARRY FLAG is set (end of the command line, no drive specifier), RETurn leaving the default drive in the 52A2H cell.
52B8
CP 3AH FE 3A
Compare Register A (the command-line character) against 3AH (ASCII :), the drive-specifier introducer. If equal the Z FLAG is set.
52BA
RET NZ C0
If the NZ FLAG is set (the character is not :, so there is no drive specifier), RETurn leaving the default drive in place.
52BB
INC HL 23
Consume the : by advancing the command-line pointer HL past it.
52BC
LD B,(HL) 46
Load Register B with the drive digit character that follows the : (addressed by HL).
52BD
INC HL 23
Loop Start
Advance the command-line pointer HL past the drive digit (and past any trailing blanks on subsequent iterations).
52BE
LD A,(HL) 7E
Fetch the next command-line character (addressed by HL) into Register A to skip trailing blanks after the drive digit.
52BF
CP 20H FE 20
Compare Register A against 20H (ASCII space). If equal the Z FLAG is set.
52C1
If the Z FLAG is set (a trailing blank), LOOP BACK to 52BDH to skip it. Loop End
52C3
LD A,B 78
Copy the drive digit character (Register B) into Register A to convert it to a numeric drive number.
52C4
SUB 30H D6 30
Subtract 30H (ASCII 0) from Register A to convert the ASCII drive digit into its binary value 0-9.
52C6
LD (52A2H),A 32 A2 52
Self-Modifying Code
Store the binary drive number (Register A) into 52A2H, the operand of the LD C,00H at 52A1H, so the drive-check routine uses this drive.
52C9
CP 08H FE 08
Compare the drive number (Register A) against 08H. Valid Model I drives are 0-7, so a value below 08H is in range and sets the CARRY FLAG.
52CB
RET C D8
If the CARRY FLAG is set (drive number 0-7, in range), RETurn to the caller.
52CC
LD A,20H 3E 20
The drive number was 8 or greater. Load Register A with error code 20H (illegal drive number).
52CE
JUMP to the shared error tail at 5296H to report the illegal drive number.

52D0H - Read GAT Sector

Seek the directory cylinder of the current drive and read its sector 0 (the Granule Allocation Table, which carries the auto command at offset E0H) into the shared buffer at 4200H. Returns error code 14H (GAT read error) on failure.

52D0
PUSH DE D5
Save Register Pair DE (the caller's destination pointer into the auto command field) onto the stack across the disk read.
52D1
PUSH HL E5
Save Register Pair HL (the caller's command-line pointer) onto the stack across the disk read.
52D2
GOSUB to the resident SYS0 service DIRCYL (4B65H) to seek the directory cylinder of the current drive and prepare its geometry for a sector read.
52D5
LD E,00H 1E 00
Load Register E with 00H, selecting sector 0 of the directory cylinder (the GAT sector) for the read.
52D7
LD HL,4200H 21 00 42
Point HL to the shared directory/sector buffer SBUFF$ at 4200H, the destination for the GAT sector.
52DA
GOSUB to the resident SYS0 service RDSSEC (4B45H) to read sector E (0, the GAT) of the directory cylinder into the buffer at HL (4200H). The Z FLAG is set on a successful read.
52DD
POP HL E1
Restore the caller's command-line pointer (Register Pair HL) from the stack.
52DE
POP DE D1
Restore the caller's destination pointer (Register Pair DE) from the stack.
52DF
RET Z C8
If the Z FLAG is set (the GAT sector was read successfully), RETurn to the caller.
52E0
LD A,14H 3E 14
The read failed. Load Register A with error code 14H (GAT read error).
52E2
RET C9
RETurn to the caller with the error code in Register A and the NZ FLAG indicating the failure.

52E3H - Write GAT Sector

Write the updated buffer at 4200H (now holding the new auto command at 42E0H) back to sector 0 of the directory cylinder, using a deleted-data address mark as all directory sectors require, and verify the write. Returns error code 15H (GAT write error) on failure.

52E3
PUSH DE D5
Save Register Pair DE onto the stack across the disk write.
52E4
PUSH HL E5
Save Register Pair HL onto the stack across the disk write.
52E5
GOSUB to the resident SYS0 service DIRCYL (4B65H) to seek the directory cylinder of the current drive and prepare its geometry for the sector write.
52E8
LD HL,4200H 21 00 42
Point HL to the shared buffer SBUFF$ at 4200H, the source of the GAT sector data to be written.
52EB
LD E,L 5D
Copy the low byte of HL (00H) into Register E, selecting sector 0 (the GAT sector) for the write.
52EC
GOSUB to the resident SYS0 service WRPROT (4768H) to write the buffer at HL to sector E (0) of the directory cylinder with a deleted-data address mark, as all LDOS directory sectors require. The Z FLAG is set on a successful write.
52EF
If the NZ FLAG is set (the write failed), JUMP to 52F6H to load the GAT write-error code.
52F1
GOSUB to the resident SYS0 service VERSEC (4772H) to verify the sector just written by reading its ID field.
52F4
CP 06H FE 06
Compare the verify status (Register A) against 06H. This sets the flags the caller inspects to decide whether the verify succeeded.
52F6
LD A,15H 3E 15
Load Register A with error code 15H (GAT write error), used when the write or verify above failed.
52F8
POP HL E1
Restore Register Pair HL from the stack.
52F9
POP DE D1
Restore Register Pair DE from the stack.
52FA
RET C9
RETurn to the caller. The Z FLAG (set by the successful write/verify path) indicates success; otherwise Register A holds error code 15H.

52FBH - AUTO Message Text

The three carriage-return-terminated message strings displayed by @LOGOT (447BH). These are data, not code; the disassembler renders the bytes as spurious instructions. The strings are reached through the overlapping LD IX / LD HL entry points at 5280H, 5284H, and the direct load at 527DH.

52FB-531F
DEFM 'Destination disk is write protected!' 44 65 73 74 ...
Error message shown when the target diskette cannot be written (reached via 5281H). The final byte at 531FH is 0DH (carriage return) terminating the string for @LOGOT.
5320-5336
DEFM 'Command line too long!' 43 6F 6D 6D ...
Error message shown when the new auto command exceeds the 32-byte field (reached via 527DH). Terminated by 0DH at 5336H.
5337-5351
DEFM 'No AUTO command installed!' 4E 6F 20 41 ...
Message shown for the "AUTO=" re-execute form when no auto command is stored (reached via 5285H). Terminated by 0DH at 5350H; the byte at 5351H is the 00H module pad ending the overlay image.

Disassembly - Overlay 2 - DATE and TIME

5200H - DATE and TIME Command Entry Vectors and Data Tables (Commands 15H/16H)

This overlay serves two commands from the SYS7 directory: DATE (command 15H) and TIME (command 16H). It opens with two jump vectors; the resident overlay loader enters the vector for the requested command. 5200H (JP 52CEH) is the TIME command (display or set the time, and install or remove the on-screen clock). 5203H (JP 524CH) is the DATE command. Following the vectors are three read-only data tables: the three-letter day-of-week names, the three-letter month names, and a days-per-month table used for date validation and the day-of-week calculation.

5200
TIME command entry (command 16H). JUMP to 52CEH to display or set the time or toggle the on-screen clock.
5203
DATE command entry (command 15H). JUMP to 524CH to display or set the system date.
5206-521A
DEFM 'SunMonTueWedThuFriSat' 53 75 6E 4D ...
Day-of-week name table: seven three-letter abbreviations (Sun, Mon, Tue, Wed, Thu, Fri, Sat). Indexed by the computed weekday at 5392H to build the date string.
521B-523E
DEFM 'JanFebMarAprMayJunJulAugSepOctNovDec' 4A 61 6E 46 ...
Month name table: twelve three-letter abbreviations. Indexed by the month byte at 53A2H to build the date string.
523F-524B
DEFB 00,1FH,1CH,1FH,1EH,1FH,1EH,1FH,1FH,1EH,1FH,1EH,1FH 00 1F 1C 1F ...
Days-per-month table (a leading 00H, then 31,28,31,30,31,30,31,31,30,31,30,31 in hex). Used to validate the day of the month and to accumulate the day-of-year for the day-of-week calculation. The February entry at 5241H is incremented to 29 in a leap year.

524CH - DATE Command

Display or set the system date. With no argument the current date in DATE$ (4044H-4046H) is displayed. With an "MM/DD/YY" argument the fields are parsed, range-checked against the days-per-month table (with leap-year adjustment), and stored into DATE$ and the derived resident date words (SVDAT1$ 4306H, SVDAT2$ 4307H, 4048H, 4466H). The error tail displays "Date not in system" or "Bad format".

524C
LD A,(HL) 7E
Fetch the first command-line character (addressed by HL, the command-line pointer) into Register A.
524D
CP 0EH FE 0E
Compare Register A (the command-line character) against 0EH. Any byte below 0EH is an end-of-line terminator, meaning no date argument was supplied. If below 0EH the CARRY FLAG is set.
524F
LD DE,4044H 11 44 40
Point Register Pair DE at DATE$ (4044H), the resident date workspace whose bytes are the year (4044H), day (4045H) and month (4046H), for the no-argument display path.
5252
If the CARRY FLAG is set (no date argument), JUMP to 528DH to display the current date.
5255
LD C,30H 0E 30
Load Register C with 30H (ASCII 0), the delimiter threshold used by the number parser to tell a field separator from a digit.
5257
GOSUB to the field parser at 53FAH to read the three "MM/DD/YY" fields from the command line (HL) into the scratch cells 52CDH (month), 52CCH (day) and 52CBH (year). Returns the NZ FLAG on a malformed field.
525A
If the NZ FLAG is set (the date field was malformed), JUMP to 52B9H to report "Bad format".
525C
LD A,(DE) 1A
On return from the parser DE addresses the year field (52CBH). Fetch the parsed two-digit year into Register A.
525D
CP 0CH FE 0C
Compare the year (Register A) against 0CH (12). Years 00-11 are treated as 2000-2011, so if below 0CH the CARRY FLAG is set to route the century adjustment.
525F
If the NO CARRY FLAG is set (year 12-99, meaning 1980-1999), JUMP to 5263H skipping the century add.
5261
ADD A,64H C6 64
Add 64H (100) to the year (Register A) to lift a 00-11 year into the 100-111 range so the following subtraction yields a 1980-relative offset in the 2000s.
5263
SUB 50H D6 50
Subtract 50H (80) from Register A, converting the year to an offset from 1980.
5265
CP 20H FE 20
Compare the 1980-relative year (Register A) against 20H (32). A value of 32 or more is out of the supported 1980-2011 range and sets the NO CARRY FLAG.
5267
If the NO CARRY FLAG is set (year out of range), JUMP to 52B9H to report "Bad format".
5269
AND 03H E6 03
Mask the 1980-relative year (Register A) to its low two bits to test for a leap year; a result of 0 means the year is divisible by 4.
526B
LD HL,5241H 21 41 52
Point HL at 5241H, the February entry of the days-per-month table (initially 28), so it can be bumped to 29 in a leap year.
526E
If the NZ FLAG is set (year not divisible by 4, not a leap year), JUMP to 5271H leaving February at 28.
5270
INC (HL) 34
Self-Modifying Code
Increment the February entry of the days-per-month table at 5241H to 29 for the leap year.
5271
LD A,(52CDH) 3A CD 52
Fetch the parsed month field from the scratch cell 52CDH into Register A.
5274
DEC A 3D
Decrement the month (Register A) to a zero-based index (0-11) for the range test and table lookup.
5275
CP 0CH FE 0C
Compare the zero-based month (Register A) against 0CH (12). A value of 12 or more means the month was outside 1-12 and sets the NO CARRY FLAG.
5277
If the NO CARRY FLAG is set (month out of range), JUMP to 52B9H to report "Bad format".
5279
DEC HL 2B
Back HL up from the February entry (5241H) to 5240H, the base of the days-per-month table indexed from month 1, so that adding the zero-based month lands on the current month's entry.
527A
ADD A,L 85
Add the low byte of HL (the table base) to the zero-based month (Register A) to form the low byte of the pointer to this month's day count.
527B
LD L,A 6F
Store the computed low byte (Register A) back into L so HL now addresses this month's entry in the days-per-month table.
527C
LD A,(52CCH) 3A CC 52
Fetch the parsed day field from the scratch cell 52CCH into Register A.
527F
DEC A 3D
Decrement the day (Register A) so it can be compared as a zero-based value against the month length.
5280
CP (HL) BE
Compare the zero-based day (Register A) against the days-in-month value at HL (this month's entry in the days-per-month table). If the day is not less than the month length the NO CARRY FLAG is set.
5281
If the NO CARRY FLAG is set (day beyond the end of the month), JUMP to 52B9H to report "Bad format".
5283
EX DE,HL EB
Exchange DE and HL so HL now points at the parsed year field (52CBH), the source of the three date bytes to be copied into DATE$.
5284
LD DE,4044H 11 44 40
Point Register Pair DE at DATE$ (4044H), the destination for the validated date.
5287
PUSH DE D5
Save the DATE$ pointer (Register Pair DE) onto the stack so it can be recovered for the derive/display path after the copy.
5288
LD C,03H 0E 03
Load Register C with 3, the byte count for the block copy (BC's high byte B is 0 here, so BC is 3).
528A
LDIR ED B0
Block-copy 3 bytes: Source HL (the parsed fields 52CBH, 52CCH, 52CDH), Destination DE (DATE$ 4044H onward), count BC (3). This stores year into 4044H, day into 4045H and month into 4046H.
528C
POP DE D1
Restore the DATE$ pointer (Register Pair DE = 4044H) from the stack for the shared derive/display path.
528D
LD A,(DE) 1A
Fetch the year byte of DATE$ (addressed by DE at 4044H) into Register A to derive the display fields. This point is shared by the no-argument display path and the after-set path.
528E
CP 0CH FE 0C
Compare the stored year (Register A) against 0CH; years below 12 (2000-2011) take the century adjustment. If below the CARRY FLAG is set.
5290
If the NO CARRY FLAG is set (year 1980-1999), JUMP to 5294H skipping the century add.
5292
ADD A,64H C6 64
Add 64H (100) to the year (Register A) for a 2000-2011 date before the 1980-relative subtraction.
5294
SUB 50H D6 50
Subtract 50H (80) from Register A to produce the 1980-relative year.
5296
LD (4466H),A 32 66 44
Store the 1980-relative year (Register A) into the resident date byte at 4466H used by the date services.
5299
LD HL,4048H 21 48 40
Point HL at 4048H, the DATE$ flags byte, so the leap-year bit can be set.
529C
AND 03H E6 03
Mask the 1980-relative year (Register A) to its low two bits again to retest for a leap year (0 = divisible by 4).
529E
If the NZ FLAG is set (not a leap year), JUMP to 52A2H leaving the leap bit clear.
52A0
SET 7,(HL) CB FE
Set bit 7 of the DATE$ flags byte at 4048H (addressed by HL) to mark the current year as a leap year.
52A2
INC DE 13
Advance DE from the year byte (4044H) to the day byte of DATE$ at 4045H.
52A3
LD A,(DE) 1A
Fetch the day byte of DATE$ (addressed by DE at 4045H) into Register A.
52A4
LD (4307H),A 32 07 43
Store the day (Register A) into SVDAT2$ at 4307H, the resident saved-date byte holding the day of the month.
52A7
INC DE 13
Advance DE from the day byte (4045H) to the month byte of DATE$ at 4046H.
52A8
LD A,(DE) 1A
Fetch the month byte of DATE$ (addressed by DE at 4046H) into Register A.
52A9
OR 50H F6 50
Set bits 6 and 4 of the month (Register A) to form the packed month value the resident date services expect.
52AB
LD (4306H),A 32 06 43
Store the packed month (Register A) into SVDAT1$ at 4306H, the resident saved-date byte holding the month.
52AE
LD A,(4046H) 3A 46 40
Fetch the month byte of DATE$ from 4046H into Register A to test whether a date has ever been set.
52B1
OR A B7
Test the month (Register A). A month of 0 means the date has never been set; the Z FLAG is then set.
52B2
If the NZ FLAG is set (a valid month, so the date is set), JUMP to 533BH to build and display the date string.
52B5
LD HL,5470H 21 70 54
The date has never been set. Point HL at the message "Date not in system" at 5470H for display.
52B8
LD IX,5483H DD 21 83 54
Overlapping Code
On fall-through from 52B5H this loads IX with 5483H and has no effect (HL already points at "Date not in system"). Entered at 52B9H (skipping the DD prefix) the bytes 21 83 54 decode as LD HL,5483H, pointing HL at the message "Bad format". 52B9H is the malformed-input entry reached from the range checks above.
52BC
GOSUB to the resident SYS0 service @LOGOT (447BH) to display the carriage-return-terminated message pointed to by HL ("Date not in system" or "Bad format").
52BF
LD HL,0FFFFH 21 FF FF
Set HL to FFFFH, the non-zero failure return code.
52C2
LD A,(430FH) 3A 0F 43
Fetch the resident system flag byte SFLAG$ from 430FH into Register A to test the command-level flag.
52C5
BIT 5,A CB 6F
Test bit 5 of SFLAG$ (Register A). Bit 5 set means the system is not at the LDOS command level. If clear the Z FLAG is set.
52C7
RET Z C8
If the Z FLAG is set (at the command level), RETurn to the dispatcher with the failure code in HL.
52C8
Otherwise (not at command level), JUMP to the resident SYS0 service @ABORT (4030H) to abort back to DOS.
52CB-52CD
DEFB 00,00,00 00 00 00
Three scratch bytes holding the parsed date/time fields: 52CDH (first field), 52CCH (second field) and 52CBH (third field), filled by the field parser at 53FAH.

52CEH - TIME Command (and On-Screen Clock)

Display or set the time, and install or remove the interrupt-driven on-screen clock. With no argument the current time is displayed via @TIME. With an "HH:MM:SS" argument the fields are parsed, range-checked, and stored into TIME$ (4041H-4043H). A "(CLOCK)" parameter installs or removes the recurring clock-display task (the SYS0 routine at 4D3AH) through @ADTSK/@RMTSK.

52CE
PUSH HL E5
Save the command-line pointer (Register Pair HL) onto the stack while the line is scanned for an opening parenthesis.
52CF
LD A,(HL) 7E
Loop Start
Fetch the current command-line character (addressed by HL) into Register A.
52D0
CP 28H FE 28
Compare Register A (the command-line character) against 28H (ASCII (), the start of a parameter list. If equal the Z FLAG is set.
52D2
If the Z FLAG is set (a parameter list begins here), JUMP to 52DBH to parse it with @PARAM.
52D4
CP 0DH FE 0D
Compare Register A against 0DH (carriage return, end of the command line). If equal the Z FLAG is set.
52D6
If the Z FLAG is set (end of line, no parameter list), JUMP to 52EDH.
52D8
INC HL 23
Advance the command-line pointer HL to the next character.
52D9
LOOP BACK to 52CFH to keep scanning for a parenthesis or end of line. Loop End
52DB
LD DE,5455H 11 55 54
Point Register Pair DE at the keyword descriptor table at 5455H (the "CLOCK" keyword and its value cell) for @PARAM.
52DE
GOSUB to the resident SYS0 service @PARAM (4476H) to parse the "(CLOCK=...)" parameter, storing its value into the cell named by the 5455H table. Returns the Z FLAG when the parameter list is valid.
52E1
LD A,2CH 3E 2C
Load Register A with error code 2CH, the parameter-error code used if @PARAM rejected the list.
52E3
If the Z FLAG is set (@PARAM accepted the parameter list), JUMP to 52EDH to act on it.
52E5
OR 0C0H F6 C0
Set bits 7 and 6 of the error code in Register A so @ERROR displays the message and returns rather than aborting.
52E7
GOSUB to the resident SYS0 service @ERROR (4409H) to report the parameter error in Register A.
52EA
JUMP to the shared failure tail at 52BFH to set the FFFFH return code and exit.
52ED
POP HL E1
Restore the command-line pointer (Register Pair HL) saved at 52CEH.
52EE
LD A,(HL) 7E
Fetch the first command-line character (addressed by HL) into Register A to decide between display, set, and clock actions.
52EF
CP 0DH FE 0D
Compare Register A against 0DH (carriage return). A bare "TIME" with no argument means display the time. If equal the Z FLAG is set.
52F1
If the Z FLAG is set (no argument), JUMP to 53E2H to display the current time.
52F4
CP 28H FE 28
Compare Register A against 28H (ASCII (). A parenthesis here means a "(CLOCK)" parameter with no time to set. If equal the Z FLAG is set.
52F6
If the Z FLAG is set (parameter list, no time value), JUMP to 5320H to apply the clock setting.
52F8
XOR A AF
Set Register A to 0 to clear the parser's terminator flag next.
52F9
LD (5417H),A 32 17 54
Self-Modifying Code
Clear the field parser's end-of-line flag at 5417H (the operand of the LD A,0FFH at 5416H) so a fresh time argument can be parsed.
52FC
LD (52CBH),A 32 CB 52
Clear the third parsed-field cell at 52CBH (the seconds field) so an "HH:MM" argument without seconds defaults to 00.
52FF
LD C,30H 0E 30
Load Register C with 30H (ASCII 0), the delimiter threshold for the field parser.
5301
GOSUB to the field parser at 53FAH to read the "HH:MM:SS" fields from the command line (HL) into 52CDH (hours), 52CCH (minutes) and 52CBH (seconds). Returns the NZ FLAG on a malformed field.
5304
If the NZ FLAG is set (a time field was malformed), JUMP to 52B9H to report "Bad format".
5306
LD HL,52CDH 21 CD 52
Point HL at the hours field at 52CDH for the range checks.
5309
LD A,17H 3E 17
Load Register A with 17H (23), the maximum valid hour.
530B
CP (HL) BE
Compare 23 (Register A) against the hours field at HL (52CDH). If the hour exceeds 23 the CARRY FLAG is set.
530C
If the CARRY FLAG is set (hour greater than 23), JUMP to 52B9H to report "Bad format".
530E
DEC HL 2B
Back HL down to the minutes field at 52CCH.
530F
LD A,3BH 3E 3B
Load Register A with 3BH (59), the maximum valid minute and second.
5311
CP (HL) BE
Compare 59 (Register A) against the minutes field at HL (52CCH). If the minute exceeds 59 the CARRY FLAG is set.
5312
If the CARRY FLAG is set (minute greater than 59), JUMP to 52B9H to report "Bad format".
5314
DEC HL 2B
Back HL down to the seconds field at 52CBH.
5315
CP (HL) BE
Compare 59 (Register A) against the seconds field at HL (52CBH). If the second exceeds 59 the CARRY FLAG is set.
5316
If the CARRY FLAG is set (second greater than 59), JUMP to 52B9H to report "Bad format".
5318
LD DE,4041H 11 41 40
Point Register Pair DE at TIME$ (4041H), the resident time workspace whose bytes are seconds (4041H), minutes (4042H) and hours (4043H).
531B
LD BC,0003H 01 03 00
Load Register Pair BC with 3, the byte count for the copy into TIME$.
531E
LDIR ED B0
Block-copy 3 bytes: Source HL (the fields 52CBH, 52CCH, 52CDH), Destination DE (TIME$ 4041H onward), count BC (3). This stores seconds into 4041H, minutes into 4042H and hours into 4043H. Execution then falls into the clock-setting code.
5320
LD HL,0001H 21 01 00
Self-Modifying Code
Load HL with the CLOCK parameter value. The operand at 5321H is set by @PARAM from a "(CLOCK=...)" parameter; its default 0001H means no CLOCK parameter was given.
5323
LD A,L 7D
Copy the low byte of the CLOCK value (L) into Register A to test for the default.
5324
DEC A 3D
Decrement Register A so the default value of 1 becomes 0 for the test that follows.
5325
OR H B4
OR the high byte of the CLOCK value (H) into Register A. The result is zero only when the CLOCK value was exactly 0001H (no CLOCK parameter given).
5326
If the Z FLAG is set (no CLOCK parameter), JUMP to 5337H to finish without changing the clock task.
5328
LD A,H 7C
Copy the high byte of the CLOCK value (H) into Register A to begin the zero test that selects install versus remove.
5329
OR L B5
OR the low byte (L) into Register A. If the CLOCK value is zero (CLOCK off) the Z FLAG is set; a non-zero value (CLOCK on) leaves the NZ FLAG set.
532A
LD A,06H 3E 06
Load Register A with 06H, the interrupt task-table slot number used for the on-screen clock.
532C
LD DE,4D3AH 11 3A 4D
Point Register Pair DE at 4D3AH, the resident SYS0 clock/date/time display routine that the task table will call on each timer tick.
532F
PUSH AF F5
Save Register A (the task slot) and the flags (the on/off result) onto the stack across the add call.
5330
If the NZ FLAG is set (CLOCK on), GOSUB to the resident SYS0 service @ADTSK (4410H) to install task slot 06H (Register A) calling the clock routine at 4D3AH (Register Pair DE).
5333
POP AF F1
Restore Register A (the task slot) and the on/off flags from the stack.
5334
If the Z FLAG is set (CLOCK off), GOSUB to the resident SYS0 service @RMTSK (4413H) to remove task slot 06H (Register A), stopping the on-screen clock.
5337
LD HL,0000H 21 00 00
Set HL to 0000H, the success return code.
533A
RET C9
RETurn to the RST 28H dispatcher with the success code in HL.

533BH - Day-of-Week Computation and Date-String Builder

Compute the day of the week for the date in DATE$ by accumulating the day-of-year from the days-per-month table (adjusted for a leap year), adding the year and its leap days, and taking the total modulo 7 with @DIV. The weekday is stored into the DATE$ flags byte and used to index the day-name table; the routine then builds the "Day, Mon dd, yyyy" string in the display buffer and shows it with @LOGOT.

533B
LD B,A 47
Copy the month (Register A, fetched from 4046H before the jump here) into Register B as the loop count for accumulating the day-of-year.
533C
LD HL,5241H 21 41 52
Point HL at the February entry of the days-per-month table at 5241H so it can be set to 29 for a leap year during this calculation.
533F
LD A,(HL) 7E
Fetch the February day count (addressed by HL at 5241H) into Register A.
5340
SUB 1DH D6 1D
Subtract 1DH (29) from the February count (Register A). If February is already 29 the Z FLAG is set, meaning the leap adjustment was already applied.
5342
If the Z FLAG is set (February already 29), JUMP to 534CH to skip the leap adjustment.
5344
LD A,(4044H) 3A 44 40
Fetch the year byte of DATE$ from 4044H into Register A to test for a leap year.
5347
AND 03H E6 03
Mask the year (Register A) to its low two bits; a result of 0 means the year is divisible by 4 (a leap year).
5349
If the NZ FLAG is set (not a leap year), JUMP to 534CH leaving February at 28.
534B
INC (HL) 34
Self-Modifying Code
Increment the February entry at 5241H to 29 for the leap year.
534C
LD A,(4045H) 3A 45 40
Fetch the day of the month from the day byte of DATE$ at 4045H into Register A to seed the day-of-year total.
534F
LD L,A 6F
Copy the day (Register A) into L, the low byte of the running day-of-year total in HL.
5350
LD H,00H 26 00
Clear H, the high byte of the day-of-year total in HL.
5352
LD DE,523FH 11 3F 52
Point Register Pair DE at 523FH, the leading entry of the days-per-month table, so the loop adds one month length per completed month.
5355
LD A,(DE) 1A
Loop Start
Fetch the next month's day count (addressed by DE) into Register A.
5356
ADD A,L 85
Add the low byte of the running total (L) to the month length (Register A).
5357
LD L,A 6F
Store the new low byte of the day-of-year total back into L.
5358
ADC A,H 8C
Add the high byte (H) plus any carry to Register A as the first step of a 16-bit add.
5359
SUB L 95
Subtract L back out of Register A, leaving just the propagated carry into the high byte.
535A
LD H,A 67
Store the updated high byte of the day-of-year total back into H.
535B
INC DE 13
Advance DE to the next month's entry in the days-per-month table.
535C
DECrement Register B (the month count) and LOOP BACK to 5355H until all completed months are summed. HL now holds the day-of-year. Loop End
535E
EX DE,HL EB
Move the day-of-year total from HL into DE so HL can address the storage word.
535F
LD HL,4047H 21 47 40
Point HL at 4047H, the resident day-of-year word (low byte at 4047H, high bits shared with the DATE$ flags at 4048H).
5362
LD (HL),E 73
Store the low byte of the day-of-year (E) into 4047H.
5363
INC HL 23
Advance HL to 4048H, the DATE$ flags byte that also carries the day-of-year high bits.
5364
LD A,D 7A
Copy the high byte of the day-of-year (D) into Register A.
5365
OR (HL) B6
OR the existing flags byte at 4048H (addressed by HL) into Register A so the leap-year bit set earlier is preserved.
5366
LD (HL),A 77
Store the combined high-bits-plus-flags value (Register A) back into 4048H.
5367
EX DE,HL EB
Move the day-of-year total back from DE into HL for the weekday arithmetic.
5368
LD A,(4044H) 3A 44 40
Fetch the year byte of DATE$ from 4044H into Register A.
536B
CP 0CH FE 0C
Compare the year (Register A) against 0CH; years below 12 are in the 2000s and take the century add. If below the CARRY FLAG is set.
536D
If the NO CARRY FLAG is set (year 1980-1999), JUMP to 5371H skipping the century add.
536F
ADD A,64H C6 64
Add 64H (100) to the year (Register A) for a 2000s date.
5371
SUB 50H D6 50
Subtract 50H (80) from Register A to produce the 1980-relative year.
5373
LD E,A 5F
Copy the 1980-relative year (Register A) into E to hold the year contribution to the weekday total.
5374
ADD A,03H C6 03
Add 3 to the year (Register A) so the divide-by-four that follows counts leap years since 1980 with the correct rounding.
5376
RRCA 0F
Rotate Register A right, the first of two rotates that divide it by four.
5377
RRCA 0F
Rotate Register A right again; combined with the previous rotate this divides by four.
5378
AND 0FH E6 0F
Mask Register A to its low nibble to keep only the leap-day count (the rotates moved stray bits into the high nibble).
537A
ADD A,E 83
Add the year (E) to the leap-day count (Register A), forming the year-plus-leap-days contribution to the weekday total.
537B
LD E,A 5F
Store the combined year contribution (Register A) into E.
537C
LD D,00H 16 00
Clear D so DE holds the year contribution as a 16-bit value.
537E
ADD HL,DE 19
Add the year contribution (DE) to the day-of-year total (HL), forming the running weekday total.
537F
INC HL 23
Add 1 to HL for the January 1, 1980 weekday offset so the modulo-7 result lands on the correct day name.
5380
LD A,07H 3E 07
Load Register A with 7, the divisor for the modulo-7 weekday computation.
5382
GOSUB to the resident SYS0 divide helper @DIV (44C4H) to divide the weekday total (HL) by 7 (Register A). The remainder returned in Register A is the day-of-week index 0-6.
5385
INC A 3C
Increment the weekday remainder (Register A) to a one-based index 1-7 for the name-copy helper.
5386
LD B,A 47
Copy the one-based weekday (Register A) into Register B, the index expected by the name-copy helper at 53EBH.
5387
RLCA 07
Rotate Register A left to double the weekday, forming the value packed into the DATE$ flags below.
5388
LD C,A 4F
Copy the doubled weekday (Register A) into Register C for packing into the flags byte.
5389
LD A,(4048H) 3A 48 40
Fetch the DATE$ flags byte from 4048H into Register A to insert the weekday field.
538C
AND 0F1H E6 F1
Clear bits 1-3 of the flags byte (Register A), the field that holds the day of the week.
538E
OR C B1
OR the doubled weekday (Register C) into bits 1-3 of the flags byte (Register A).
538F
LD (4048H),A 32 48 40
Store the updated flags byte with the weekday field (Register A) back into 4048H.
5392
LD HL,5206H 21 06 52
Point HL at the day-of-week name table at 5206H for the name-copy helper.
5395
LD DE,545EH 11 5E 54
Point Register Pair DE at 545EH, the start of the display buffer where the "Day, Mon dd, yyyy" string is built.
5398
PUSH DE D5
Save the buffer start (Register Pair DE) onto the stack so it can be recovered for display after the string is built.
5399
GOSUB to the name-copy helper at 53EBH to copy the three-letter day name (indexed by Register B) from HL (5206H) into the buffer at DE.
539C
INC DE 13
Advance DE past the comma already present in the buffer template.
539D
INC DE 13
Advance DE past the space after the comma, leaving DE at the month-name position in the buffer.
539E
LD A,(4046H) 3A 46 40
Fetch the month byte of DATE$ from 4046H into Register A to index the month-name table.
53A1
LD B,A 47
Copy the month (Register A) into Register B, the index for the name-copy helper.
53A2
LD HL,521BH 21 1B 52
Point HL at the month-name table at 521BH for the name-copy helper.
53A5
GOSUB to the name-copy helper at 53EBH to copy the three-letter month name (indexed by Register B) from HL (521BH) into the buffer at DE.
53A8
INC DE 13
Advance DE past the space after the month name, leaving DE at the day-number position in the buffer.
53A9
LD A,(4045H) 3A 45 40
Fetch the day of the month from 4045H into Register A to convert it to two decimal digits.
53AC
LD B,0FFH 06 FF
Initialize Register B to FFH so the tens loop that follows counts up from zero on its first increment.
53AE
INC B 04
Loop Start
Increment Register B, the running count of tens in the day value.
53AF
SUB 0AH D6 0A
Subtract 10 from the day (Register A). While the result stays non-negative the NO CARRY FLAG is set.
53B1
If the NO CARRY FLAG is set, LOOP BACK to 53AEH to keep subtracting tens. On exit Register B holds the tens digit and Register A holds the units minus 10. Loop End
53B3
PUSH AF F5
Save the units remainder (Register A) and flags onto the stack while the tens digit is written.
53B4
LD A,B 78
Copy the tens digit (Register B) into Register A for conversion to ASCII.
53B5
ADD A,30H C6 30
Add 30H (ASCII 0) to the tens digit (Register A) to make it an ASCII character.
53B7
CP 30H FE 30
Compare the tens character (Register A) against 30H (ASCII 0). A leading zero is blanked for a one-digit day. If equal the Z FLAG is set.
53B9
If the NZ FLAG is set (a real tens digit), JUMP to 53BDH to store it as is.
53BB
LD A,20H 3E 20
Replace the leading-zero tens digit with 20H (ASCII space) so a one-digit day is space-padded.
53BD
LD (DE),A 12
Store the tens character (Register A) into the buffer at DE.
53BE
INC DE 13
Advance DE to the units-digit position in the buffer.
53BF
POP AF F1
Restore the units remainder (Register A) from the stack.
53C0
ADD A,3AH C6 3A
Add 3AH to the units remainder (Register A). Since the remainder was the units digit minus 10, this yields the ASCII units character ('0' + units).
53C2
LD (DE),A 12
Store the units character (Register A) into the buffer at DE.
53C3
INC DE 13
Advance DE past the day number, leaving DE at the year position in the buffer.
53C4
LD A,(4044H) 3A 44 40
Fetch the year byte of DATE$ from 4044H into Register A to form the four-digit year.
53C7
LD HL,076CH 21 6C 07
Load HL with 076CH (1900), the base century added to the two-digit year to form a full year.
53CA
CP 0CH FE 0C
Compare the year (Register A) against 0CH; a year below 12 is in the 2000s and needs the extra century. If below the CARRY FLAG is set.
53CC
If the NO CARRY FLAG is set (year 1980-1999), JUMP to 53D0H skipping the century add.
53CE
ADD A,64H C6 64
Add 64H (100) to the year (Register A) so a 2000s year adds correctly to 1900.
53D0
ADD A,L 85
Add the low byte of the base year (L) to the two-digit year (Register A).
53D1
LD L,A 6F
Store the resulting low byte back into L.
53D2
ADC A,H 8C
Add the high byte (H) plus carry to Register A for the 16-bit add.
53D3
SUB L 95
Subtract L back out, leaving just the propagated carry in Register A.
53D4
LD H,A 67
Store the updated high byte into H, so HL now holds the full four-digit year.
53D5
LD DE,546AH 11 6A 54
Point Register Pair DE at 546AH, the year position in the display buffer, for the decimal writer.
53D8
GOSUB to the decimal writer at 543CH to write the full year (HL) as decimal digits into the buffer at DE.
53DB
POP HL E1
Restore the display buffer start (5455H/545EH) from the stack into HL for display. This point is shared with the time-display path.
53DC
GOSUB to the resident SYS0 service @LOGOT (447BH) to display the carriage-return-terminated string at HL (the built date or time).
53DF
JUMP to 5337H to set the success code and return.
53E2
LD HL,5467H 21 67 54
Point HL at 5467H, the scratch position in the display buffer where @TIME writes the time string.
53E5
PUSH HL E5
Save the buffer position (Register Pair HL) onto the stack for the shared display path.
53E6
GOSUB to the resident SYS0 service @TIME (446DH) to write the current time as an "HH:MM:SS" string into the buffer at HL (5467H).
53E9
JUMP to the shared display path at 53DBH to show the time string and return.

53EBH - Helper Routines (Name Copy, Field Parser, Decimal Writer)

The support routines shared by the DATE and TIME paths: 53EBH copies a three-letter name from a table indexed by Register B; 53FAH parses up to three colon- or slash-separated decimal fields; 541FH and 5435H read a two-digit decimal number; and 543CH writes a value as right-justified decimal digits into a buffer.

53EB
DEC B 05
Decrement the one-based index in Register B to a zero-based index for the table offset.
53EC
LD A,L 7D
Copy the low byte of the table base (L) into Register A to compute the entry offset.
53ED
ADD A,B 80
Add the zero-based index (Register B) to the base low byte (Register A), the first of three adds that multiply the index by 3 (three characters per name).
53EE
ADD A,B 80
Add the index (Register B) a second time (index times 2 so far).
53EF
ADD A,B 80
Add the index (Register B) a third time, so Register A is the base plus index times 3.
53F0
LD L,A 6F
Store the computed offset back into L so HL addresses the three-letter name for this index.
53F1
LD B,03H 06 03
Load Register B with 3, the number of characters to copy for the name.
53F3
LD A,(HL) 7E
Loop Start
Fetch the next name character (addressed by HL) into Register A.
53F4
INC HL 23
Advance HL to the next character of the name.
53F5
LD (DE),A 12
Store the name character (Register A) into the buffer at DE.
53F6
INC DE 13
Advance DE to the next buffer position.
53F7
DECrement Register B and LOOP BACK to 53F3H until all three characters are copied. Loop End
53F9
RET C9
RETurn to the caller with the name copied into the buffer.
53FA
LD DE,52CDH 11 CD 52
Point Register Pair DE at the first parsed-field cell 52CDH, where the fields are stored in descending order.
53FD
LD B,03H 06 03
Load Register B with 3, the maximum number of fields to parse.
53FF
PUSH DE D5
Loop Start
Save the current field-cell pointer (Register Pair DE) across the number parse.
5400
GOSUB to the two-digit parser at 541FH to read a decimal number from the command line (HL) into Register A. Returns the NZ FLAG on a bad digit.
5403
POP DE D1
Restore the field-cell pointer (Register Pair DE).
5404
RET NZ C0
If the NZ FLAG is set (a malformed number), RETurn to the caller signalling the error.
5405
LD (DE),A 12
Store the parsed field value (Register A) into the current field cell at DE.
5406
DEC B 05
Decrement the field counter in Register B.
5407
RET Z C8
If the Z FLAG is set (all three fields parsed), RETurn to the caller.
5408
DEC DE 1B
Move the field-cell pointer DE down to the next cell (fields are stored 52CDH, 52CCH, 52CBH).
5409
LD A,(HL) 7E
Fetch the separator character (addressed by HL) into Register A.
540A
INC HL 23
Advance the command-line pointer HL past the separator.
540B
CP 3AH FE 3A
Compare the separator (Register A) against 3AH (ASCII :), the time-field separator. If equal the Z FLAG is set.
540D
If the Z FLAG is set (a colon separator), LOOP BACK to 53FFH to parse the next field.
540F
CP C B9
Compare the separator (Register A) against Register C (30H). A character below '0' (such as the date separator '/') sets the CARRY FLAG.
5410
If the NO CARRY FLAG is set (the character is a digit or higher, not a valid separator), JUMP to 541DH to end parsing.
5412
CP 0DH FE 0D
Compare the separator (Register A) against 0DH (carriage return, end of line). If equal the Z FLAG is set.
5414
If the NZ FLAG is set (a slash-type separator, not end of line), LOOP BACK to 53FFH to parse the next field.
5416
LD A,0FFH 3E FF
Self-Modifying Code
Load Register A with the end-of-line marker value. The operand at 5417H is cleared to 0 by the time-set path at 52F9H to note that the line ended early.
5418
OR A B7
Test Register A. A non-zero value leaves the NZ FLAG set to signal the early end of line to the caller.
5419
RET NZ C0
If the NZ FLAG is set, RETurn to the caller signalling the shortened field list.
541A
LD A,B 78
Copy the remaining field count (Register B) into Register A.
541B
DEC A 3D
Decrement the count (Register A); the Z FLAG is set when exactly the expected number of fields was read.
541C
RET Z C8
If the Z FLAG is set (the right number of fields), RETurn to the caller successfully.
541D
OR A B7
Clear the CARRY FLAG and set the sign/zero flags from Register A to signal the parse result to the caller.
541E
RET C9
RETurn to the caller.
541F
GOSUB to the digit reader at 5435H to read the first decimal digit from the command line (HL) into Register A. The CARRY FLAG is set when the character was a valid digit.
5422
If the NO CARRY FLAG is set (the first character was not a digit), JUMP to 5433H to return the value gathered so far.
5424
LD E,A 5F
Copy the first digit (Register A) into E to accumulate the two-digit value.
5425
RLCA 07
Rotate Register A left, doubling the digit as the first step of multiplying by 10.
5426
RLCA 07
Rotate Register A left again (digit times 4 so far).
5427
ADD A,E 83
Add the original digit (E) to Register A (digit times 5 so far).
5428
RLCA 07
Rotate Register A left once more to reach digit times 10.
5429
LD E,A 5F
Store the tens value (digit times 10, Register A) into E.
542A
GOSUB to the digit reader at 5435H to read the second decimal digit into Register A.
542D
If the NO CARRY FLAG is set (no second digit, a one-digit number), JUMP to 5433H to return.
542F
ADD A,E 83
Add the tens value (E) to the units digit (Register A) to form the final two-digit value.
5430
LD E,A 5F
Store the completed value into E.
5431
CP A BF
Compare Register A with itself to force the Z FLAG set, signalling a successfully parsed two-digit number.
5432
RET C9
RETurn to the caller with the value in Register A (and E) and the Z FLAG set.
5433
OR A B7
Clear the CARRY FLAG and set the zero/sign flags from Register A to report the one-digit or terminating result.
5434
RET C9
RETurn to the caller.
5435
LD A,(HL) 7E
Fetch the next command-line character (addressed by HL) into Register A.
5436
INC HL 23
Advance the command-line pointer HL past the character.
5437
SUB 30H D6 30
Subtract 30H (ASCII 0) from Register A to convert an ASCII digit to its binary value.
5439
CP 0AH FE 0A
Compare the value (Register A) against 0AH (10). A result below 10 is a valid digit and sets the CARRY FLAG; anything else leaves it clear.
543B
RET C9
RETurn to the caller with the digit value in Register A and the CARRY FLAG set when it was a valid digit.
543C
LD B,05H 06 05
Load Register B with 5, the width of the decimal field to blank before writing digits.
543E
LD A,20H 3E 20
Loop Start
Load Register A with 20H (ASCII space) to blank a field position.
5440
LD (DE),A 12
Store the space (Register A) into the buffer at DE.
5441
INC DE 13
Advance DE to the next buffer position.
5442
DECrement Register B and LOOP BACK to 543EH until the five-character field is blanked. Loop End
5444
PUSH DE D5
Save the position just past the field (Register Pair DE) onto the stack; the digits are written backward from here.
5446
DEC DE 1B
Loop Start
Move DE back one position to the next digit slot (digits are written least-significant first, right to left).
5447
LD A,0AH 3E 0A
Load Register A with 10, the divisor used to peel off the low decimal digit of HL.
5448
GOSUB to the resident SYS0 divide helper @DIV (44C4H) to divide the value (HL) by 10; the quotient stays in HL and the remainder (the low digit) is returned in Register A.
544B
ADD A,30H C6 30
Add 30H (ASCII 0) to the digit remainder (Register A) to make it an ASCII character.
544D
LD (DE),A 12
Store the digit character (Register A) into the buffer at DE.
544E
DEC DE 1B
Move DE back to the next-higher digit slot.
544F
LD A,H 7C
Copy the high byte of the remaining value (H) into Register A to test whether any digits remain.
5450
OR L B5
OR the low byte (L) into Register A. If the value HL has reached zero the Z FLAG is set.
5451
If the NZ FLAG is set (more digits remain), LOOP BACK to 5446H for the next digit. Loop End
5453
POP DE D1
Restore the end-of-field position (Register Pair DE) from the stack.
5454
RET C9
RETurn to the caller with the decimal value written right-justified into the buffer.

5455H - Parameter Table, Display Buffer, and Messages

The data at the end of the overlay: the @PARAM keyword descriptor for the "CLOCK" parameter, the display buffer pre-initialized with the date template, and the two error messages. These are data, not code; the disassembler renders the bytes as spurious instructions.

5455-545D
DEFM 'CLOCK ' DEFW 5321H DEFB 00 43 4C 4F 43 4B 20 21 53 00
@PARAM keyword descriptor table for the TIME command: the six-character space-padded keyword "CLOCK " followed by the two-byte address 5321H of the value cell (the operand of the LD HL,0001H at 5320H), terminated by 00H. @PARAM stores the parsed CLOCK value at 5321H.
545E-546F
DEFM 'Day, Mon xx, 19xx' + 0DH 44 61 79 2C ...
The display buffer, pre-initialized with the date template. The builder at 533BH overwrites the day name at 545EH, the month name at 5463H, the two-digit day at 5467H and the four-digit year at 546AH; the time-display path reuses 5467H for the "HH:MM:SS" string. Terminated by 0DH at 546FH for @LOGOT.
5470-5482
DEFM 'Date not in system' + 0DH 44 61 74 65 ...
Error message displayed by the DATE command when no date has been set (reached via 52B5H). Terminated by 0DH at 5482H.
5483-548D
DEFM 'Bad format' + 0DH 42 61 64 20 ...
Error message displayed when a date or time argument is malformed or out of range (reached via 52B9H). Terminated by 0DH at 548DH, the last byte of the overlay image.

Disassembly - Overlay 3 - CREATE

5200H - CREATE Command (Command 13H)

Pre-allocate a disk file to a fixed size and set its record length and fill pattern, so the file occupies a contiguous, known amount of space. The command line is a file specification followed by parameters: SIZE (or S) sets the size in K, REC (or R) sets the size in records, LRL (or L) sets the logical record length, FILL (or F) sets the fill byte, and SHRINK reduces an over-large file. The file is opened or created via @INIT, extended to the requested length by writing fill records, then closed.

5200
LD (5325H),SP ED 73 25 53
Self-Modifying Code
Save the caller's stack pointer into 5325H, the operand of the LD SP,nnnn at 5324H, so the caller's stack can be restored on exit.
5204
LD DE,53E2H 11 E2 53
Point Register Pair DE at the file control block buffer at 53E2H, the destination for the parsed file specification.
5207
GOSUB to the resident SYS0 service @FSPEC (441CH) to parse the file specification from the command line (HL) into the FCB at DE (53E2H). Returns the NZ FLAG on a bad specification.
520A
If the NZ FLAG is set (no or bad file specification), JUMP to 534CH to report "File spec required!".
520D
LD A,(DE) 1A
Fetch the first byte of the parsed FCB (addressed by DE at 53E2H), the first character of the file name, into Register A.
520E
CP 2AH FE 2A
Compare Register A (the first name character) against 2AH (ASCII *). A leading asterisk means a device, not a disk file. If equal the Z FLAG is set.
5210
If the Z FLAG is set (a device was given, not a file), JUMP to 534CH to report "File spec required!".
5213
LD DE,5358H 11 58 53
Point Register Pair DE at the keyword descriptor table at 5358H (SIZE/REC/LRL/FILL/SHRINK) for @PARAM.
5216
GOSUB to the resident SYS0 service @PARAM (4476H) to parse the "(SIZE=.., LRL=.., ...)" parameters, storing each into the value cell named by the 5358H table. Returns the NZ FLAG on a bad parameter list.
5219
If the NZ FLAG is set (a malformed parameter), JUMP to 523BH to raise the parameter error.
521B
LD IX,5256H DD 21 56 52
Point IX at the LRL value cell region at 5256H to begin checking which size parameters were supplied.
521F
LD A,(IX+01H) DD 7E 01
Fetch the byte at 5257H (IX+1, the LRL value cell) into Register A.
5222
OR (IX+02H) DD B6 02
OR the byte at 5258H (IX+2) into Register A so the result is non-zero if an LRL value was supplied.
5225
LD IX,5240H DD 21 40 52
Point IX at 5240H, the REC (record-count) value-cell region, to fold its presence into the test.
5229
OR (IX+01H) DD B6 01
OR the byte at 5241H (IX+1, the record-count low byte) into Register A.
522C
OR (IX+02H) DD B6 02
OR the byte at 5242H (IX+2, the record-count high byte) into Register A.
522F
If the Z FLAG is set (neither LRL nor REC was given), JUMP to 5247H to check the SIZE parameter instead.
5231
LD IX,5247H DD 21 47 52
Point IX at 5247H, the SIZE value-cell region, to confirm SIZE was not also supplied.
5235
LD A,(IX+01H) DD 7E 01
Fetch the byte at 5248H (IX+1, the SIZE value low byte) into Register A.
5238
OR (IX+02H) DD B6 02
OR the byte at 5249H (IX+2, the SIZE value high byte) into Register A; a non-zero result means SIZE was given as well as REC/LRL, which is a conflict.
523B
LD A,2CH 3E 2C
Load Register A with error code 2CH, the parameter-error code.
523D
If the NZ FLAG is set (conflicting size parameters), JUMP to 52F7H to report the parameter error.
5240
LD BC,0000H 01 00 00
Self-Modifying Code
Load Register Pair BC with the REC value. The operand at 5241H-5242H is the record-count cell written by @PARAM from a REC/R parameter (default 0).
5243
LD A,B 78
Copy the high byte of the record count (B) into Register A to test whether REC was given.
5244
OR C B1
OR the low byte (C) into Register A; the Z FLAG is set only when the record count is zero (no REC parameter).
5245
If the NZ FLAG is set (a record count was supplied), JUMP to 5256H skipping the SIZE-to-records conversion.
5247
LD HL,0000H 21 00 00
Self-Modifying Code
Load HL with the SIZE value. The operand at 5248H-5249H is the size cell written by @PARAM from a SIZE/S parameter (default 0).
524A
LD A,H 7C
Copy the high byte of the SIZE value (H) into Register A to test whether SIZE was given.
524B
OR L B5
OR the low byte (L) into Register A; the Z FLAG is set when SIZE is zero.
524C
LD A,2CH 3E 2C
Load Register A with error code 2CH, the parameter-error code, in case no size at all was supplied.
524E
If the Z FLAG is set (neither SIZE nor REC was given), JUMP to 52F7H to report the parameter error.
5251
ADD HL,HL 29
Double the SIZE value (HL), the first of two doublings that multiply the K size by four to get a sector/record count.
5252
ADD HL,HL 29
Double HL again, so the SIZE value is multiplied by four to form the record count.
5253
LD (5241H),HL 22 41 52
Self-Modifying Code
Store the computed record count (HL) into the record-count cell at 5241H, the same cell REC would have set.
5256
LD BC,0000H 01 00 00
Self-Modifying Code
Load Register Pair BC with the LRL value. The operand at 5257H-5258H is the logical-record-length cell written by @PARAM from an LRL/L parameter (default 0, meaning 256).
5259
LD A,B 78
Copy the high byte of the LRL value (B) into Register A to validate the record length.
525A
OR A B7
Test Register A (the LRL high byte). A non-zero high byte would mean an LRL above 255, which is invalid.
525B
If the Z FLAG is set (LRL high byte zero, a valid one-byte length or the default), JUMP to 5263H.
525D
DEC A 3D
Decrement the LRL high byte (Register A); a value of exactly 0100H (256) leaves zero here and is allowed.
525E
If the NZ FLAG is set (LRL high byte greater than 1, an invalid length), JUMP to 523BH to raise the parameter error.
5260
OR C B1
OR the LRL low byte (C) into Register A; for a length of exactly 256 the low byte must be 0, so a non-zero result is invalid.
5261
If the NZ FLAG is set (LRL is between 257 and 511, invalid), JUMP to 523BH to raise the parameter error.
5263
OR C B1
OR the LRL low byte (C) into Register A to form the logical record length byte (0 means 256) passed to @INIT.
5264
LD DE,53E2H 11 E2 53
Point Register Pair DE at the FCB at 53E2H for the open/initialize call.
5267
LD HL,5500H 21 00 55
Point HL at the record buffer at 5500H that @INIT will associate with the file.
526A
LD B,A 47
Copy the logical record length (Register A) into Register B, the LRL argument expected by @INIT.
526B
LD (5344H),A 32 44 53
Self-Modifying Code
Save the logical record length (Register A) into 5344H for the attribute-setting helper at 5333H to store into the directory.
526E
GOSUB to the resident SYS0 service @INIT (4420H) to open the file if it exists or create it if it does not, using the FCB at DE, the buffer at HL and the LRL in Register B. Returns the NZ FLAG on error.
5271
If the NZ FLAG is set (the file could not be opened or created), JUMP to 52F7H to report the error.
5274
LD DE,53D3H 11 D3 53
Point Register Pair DE at the buffer at 53D3H where the file's name string will be built for display.
5277
LD BC,(53E8H) ED 4B E8 53
Load Register Pair BC from 53E8H (the FCB's directory locator: the directory record number and drive) as the argument for @FNAME.
527B
GOSUB to the resident SYS0 service @FNAME (44BBH) to build the "NAME/EXT:d" string of the file (located by BC) into the buffer at DE (53D3H). Returns the NZ FLAG on error.
527E
If the NZ FLAG is set (the name could not be built), JUMP to 52F7H to report the error.
5281
LD HL,53C9H 21 C9 53
Point HL at the message "Creating: " at 53C9H for display.
5284
GOSUB to the resident SYS0 service @DSPLY (4467H) to display "Creating: " followed by the file name just built at 53D3H (the two strings are adjacent).
5287
LD A,0DH 3E 0D
Load Register A with 0DH (carriage return) to end the "Creating:" line on screen.
5289
GOSUB to the ROM character output routine @DSP (0033H) to print the carriage return in Register A.
528C
LD HL,(53EEH) 2A EE 53
Load HL from 53EEH (the SHRINK parameter's target word) to carry the SHRINK setting into the self-modifying cells below.
528F
LD (5302H),HL 22 02 53
Self-Modifying Code
Store the SHRINK word (HL) into 5302H so the later fill/close logic can consult it.
5292
LD A,(53EAH) 3A EA 53
Fetch the SHRINK flag byte from 53EAH into Register A.
5295
LD (5308H),A 32 08 53
Self-Modifying Code
Store the SHRINK flag (Register A) into 5308H for the same later use.
5298
LD DE,53E2H 11 E2 53
Point Register Pair DE at the FCB at 53E2H for the length query.
529B
GOSUB to the resident SYS0 service @LOF (445DH) to return the current length of the file (in records) in Register Pair BC.
529E
LD H,B 60
Copy the high byte of the current file length (B) into H.
529F
LD L,C 69
Copy the low byte of the current file length (C) into L, so HL holds the current length in records.
52A0
LD BC,(5241H) ED 4B 41 52
Load Register Pair BC from the record-count cell at 5241H, the requested file size in records.
52A4
OR A B7
Clear the CARRY FLAG in preparation for the subtraction that compares current and requested lengths.
52A5
PUSH HL E5
Save the current length (Register Pair HL) onto the stack across the comparison.
52A6
SBC HL,BC ED 42
Subtract the requested size (BC) from the current length (HL). If the current length is at least the requested size the NO CARRY FLAG is set.
52A8
POP HL E1
Restore the current length (Register Pair HL) from the stack.
52A9
If the NO CARRY FLAG is set (the file is already at least as large as requested), JUMP to 5350H to report "File exists larger!".
52AC
DEC BC 0B
Decrement the requested record count (BC) to the highest record number to position to.
52AD
GOSUB to the resident SYS0 service @POSN (4442H) to position the file to the record number in Register Pair BC, extending the file's allocation to that record.
52B0
LD HL,5500H 21 00 55
Point HL at the record buffer at 5500H to fill it with the fill pattern.
52B3
LD DE,5501H 11 01 55
Point Register Pair DE at 5501H, one byte past the buffer start, as the destination for the propagating fill.
52B6
LD BC,00FFH 01 FF 00
Load Register Pair BC with 255, the count for propagating the fill byte across the 256-byte buffer.
52B9
LD (HL),0E5H 36 E5
Store the default fill byte E5H into the first buffer position at 5500H.
52BB
LDIR ED B0
Block-copy to propagate the fill byte: Source HL (5500H), Destination DE (5501H), count BC (255), filling the buffer at 5500H-55FFH with E5H.
52BD
LD DE,53E2H 11 E2 53
Point Register Pair DE at the FCB at 53E2H for the write of the last record.
52C0
DEC H 25
Decrement H from 55H to 54H, then the next instruction restores it, leaving HL addressing the 5500H buffer for @WRITE.
52C1
INC HL 23
Increment HL, completing the adjustment so HL points into the 5500H record buffer for the write.
52C2
GOSUB to the resident SYS0 service @WRITE (4439H) to write the fill buffer as the highest record, forcing the file's allocation out to the requested size. Returns the NZ FLAG on error.
52C5
If the NZ FLAG is set (the write failed), JUMP to 52F7H to report the error.
52C7
GOSUB to the resident SYS0 service @REW (443FH) to rewind the file back to its first record.
52CA
LD BC,(53E8H) ED 4B E8 53
Load Register Pair BC from 53E8H (the FCB directory locator) for the attribute-setting helper.
52CE
GOSUB to the directory-update helper at 5338H to set the created file's logical record length and attributes in its directory entry.
52D1
LD BC,0100H 01 00 01
Self-Modifying Code
Load Register Pair BC with the fill control word. The low byte at 52D2H is the FILL byte value (written by @PARAM from a FILL/F parameter); the high byte B is 1 when no whole-file fill is requested.
52D4
DEC B 05
Decrement Register B (the fill-enable count). When no FILL of the whole file was requested B was 1 and becomes 0.
52D5
If the Z FLAG is set (no whole-file fill requested), JUMP to 5301H to skip the fill loop.
52D7
PUSH DE D5
Save the FCB pointer (Register Pair DE) onto the stack across the buffer fill.
52D8
LD HL,5500H 21 00 55
Point HL at the record buffer at 5500H to fill it with the requested fill byte.
52DB
LD (HL),C 71
Store the FILL byte (Register C, from the 52D2H cell) into the first buffer position at 5500H.
52DC
LD DE,5501H 11 01 55
Point Register Pair DE at 5501H to propagate the fill byte across the buffer.
52DF
LD BC,01FFH 01 FF 01
Load Register Pair BC with 511 so the block move fills all 256 bytes (the extra high byte is harmless as HL/DE stay within the buffer for the first 255 copies).
52E2
LDIR ED B0
Block-copy to propagate the FILL byte across the buffer at 5500H-55FFH.
52E4
POP DE D1
Restore the FCB pointer (Register Pair DE) from the stack.
52E5
LD BC,(5241H) ED 4B 41 52
Load Register Pair BC from the record-count cell at 5241H, the number of records to fill.
52E9
LD HL,5600H 21 00 56
Point HL at 5600H, used here as a spare buffer address for the write loop.
52EC
INC BC 03
Increment the record count (BC) so the following decrement-and-test loop covers every record exactly once.
52ED
DEC BC 0B
Loop Start
Decrement the remaining record count (BC).
52EE
LD A,B 78
Copy the high byte of the remaining count (B) into Register A to test for completion.
52EF
OR C B1
OR the low byte (C) into Register A; the Z FLAG is set when all records have been written.
52F0
If the Z FLAG is set (all records filled), JUMP to 530CH to close the file.
52F2
GOSUB to the resident SYS0 service @WRITE (4439H) to write one fill record from the buffer. Returns the NZ FLAG on error.
52F5
If the Z FLAG is set (the write succeeded), LOOP BACK to 52EDH for the next record. On error execution falls through to the error tail. Loop End
52F7
OR 0C0H F6 C0
Set bits 7 and 6 of the error code in Register A so @ERROR displays the message and returns rather than aborting. This is the shared error tail.
52F9
GOSUB to the resident SYS0 service @ERROR (4409H) to display the system error message for the code in Register A.
52FC
LD HL,0FFFFH 21 FF FF
Set HL to FFFFH, the non-zero failure return code.
52FF
JUMP to the exit tail at 5324H to restore the stack and return or abort.
5301
LD HL,0000H 21 00 00
Set HL to 0000H. The operand at 5302H was overwritten at 528FH with the SHRINK word, so this also clears that self-modifying cell for a subsequent invocation.
5304
LD (53EEH),HL 22 EE 53
Clear the SHRINK target word at 53EEH so the parameter does not persist into a later CREATE.
5307
LD A,00H 3E 00
Load Register A with 0. The operand at 5308H was overwritten at 5295H with the SHRINK flag, so this clears that self-modifying cell too.
5309
LD (53EAH),A 32 EA 53
Clear the SHRINK flag byte at 53EAH so it does not persist into a later CREATE.
530C
LD DE,53E2H 11 E2 53
Point Register Pair DE at the FCB at 53E2H for the close.
530F
LD BC,(53E8H) ED 4B E8 53
Load Register Pair BC from 53E8H (the FCB directory locator) for the close.
5313
GOSUB to the resident SYS0 service @CLOSE (4428H) to close the file, writing back its directory entry. Returns the NZ FLAG on error.
5316
If the NZ FLAG is set (the close failed), JUMP to 52F7H to report the error.
5318
LD DE,0000H 11 00 00
Load Register Pair DE with 0 to test the SHRINK flag next.
531B
LD A,D 7A
Copy D (0) into Register A to build the SHRINK test.
531C
AND E A3
AND E into Register A, yielding 0 as the basis for the following increment-based test.
531D
INC A 3C
Increment Register A to 1; the Z FLAG is set only when the value was FFH, which encodes that SHRINK was requested.
531E
If the Z FLAG is set (SHRINK requested), GOSUB to the directory-update helper at 5333H to shrink the file to the written size in its directory entry.
5321
LD HL,0000H 21 00 00
Set HL to 0000H, the success return code.
5324
LD SP,0000H 31 00 00
Self-Modifying Code
Restore the caller's stack pointer. The operand at 5325H was overwritten at 5200H with the caller's SP.
5327
LD A,H 7C
Copy the high byte of the return code (H) into Register A to test for success.
5328
OR L B5
OR the low byte (L) into Register A; the Z FLAG is set for a zero (success) code.
5329
RET Z C8
If the Z FLAG is set (success), RETurn to the RST 28H dispatcher.
532A
LD A,(430FH) 3A 0F 43
Fetch the resident system flag byte SFLAG$ from 430FH into Register A to test the command-level flag.
532D
BIT 5,A CB 6F
Test bit 5 of SFLAG$ (Register A); it is set when the system is not at the LDOS command level. If clear the Z FLAG is set.
532F
RET Z C8
If the Z FLAG is set (at the command level), RETurn to the dispatcher with the failure code.
5330
Otherwise (not at command level), JUMP to the resident SYS0 service @ABORT (4030H) to abort back to DOS.
5333
LD A,0BEH 3E BE
Load Register A with BEH, the directory-record byte offset patched into the update helper for the SHRINK path.
5335
LD (533FH),A 32 3F 53
Self-Modifying Code
Store BEH into 533FH, adjusting the offset the update helper at 5338H writes to in the directory record.
5338
GOSUB to the resident SYS0 service DIRRD (4B10H) to read the file's directory record (located by Register Pair BC) into the buffer, returning HL pointing at the record. Returns the NZ FLAG on error.
533B
If the NZ FLAG is set (the directory read failed), JUMP to 52F7H to report the error.
533D
INC HL 23
Advance HL to the directory record's attribute/flags byte (offset +1).
533E
SET 7,(HL) CB FE
Set bit 7 of the directory flags byte (addressed by HL) to mark the created file's date/time stamp field. The preceding byte offset was adjusted by the 533FH self-modifying cell.
5340
INC L 2C
Advance the low byte of HL toward the logical-record-length field of the directory record.
5341
INC L 2C
Advance HL further into the directory record.
5342
INC L 2C
Advance HL to the logical-record-length byte of the directory record.
5343
LD A,00H 3E 00
Self-Modifying Code
Load Register A with the logical record length. The operand at 5344H was set at 526BH to the file's LRL.
5345
LD (HL),A 77
Store the logical record length (Register A) into the directory record's LRL field (addressed by HL).
5346
GOSUB to the resident SYS0 service DIRWR (4B1FH) to write the updated directory record back to disk. Returns the NZ FLAG on error.
5349
If the NZ FLAG is set (the directory write failed), JUMP to 52F7H to report the error.
534B
RET C9
RETurn to the caller with the directory entry updated.
534C
LD HL,53A1H 21 A1 53
Point HL at the message "File spec required!" at 53A1H for display.
534F
LD IX,53B5H DD 21 B5 53
Overlapping Code
On fall-through from 534CH this loads IX with 53B5H and has no effect (HL already points at "File spec required!"). Entered at 5350H (skipping the DD prefix) the bytes 21 B5 53 decode as LD HL,53B5H, pointing HL at "File exists larger!". 5350H is the file-too-large entry reached from 52A9H.
5353
GOSUB to the resident SYS0 service @LOGOT (447BH) to display the carriage-return-terminated message at HL ("File spec required!" or "File exists larger!").
5356
JUMP to 52FCH to set the failure return code and exit.

5358H - CREATE Parameter Table and Messages

The @PARAM keyword descriptor table and the message strings for CREATE. These are data, not code. Each 8-byte table entry is a six-character space-padded keyword followed by the two-byte address of the value cell @PARAM fills.

5358-539F
DEFM 'SIZE'/'S' 5248H, 'REC'/'R' 5241H, 'LRL'/'L' 5257H, 'FILL'/'F' 52D2H, 'SHRINK' 5319H 53 49 5A 45 ...
@PARAM keyword descriptor table: SIZE (and abbreviation S) store into the size cell 5248H; REC (R) store the record count into 5241H; LRL (L) store the logical record length into 5257H; FILL (F) store the fill byte into 52D2H; SHRINK sets the flag word at 5319H. Terminated by 00H at 53A0H.
53A1-53B4
DEFM 'File spec required!' + 0DH 46 69 6C 65 ...
Error message displayed when no disk file specification was supplied (reached via 534CH). Terminated by 0DH at 53B4H.
53B5-53C8
DEFM 'File exists larger!' + 0DH 46 69 6C 65 ...
Error message displayed when the file already exists at or above the requested size (reached via 5350H). Terminated by 0DH at 53C8H.
53C9-53D2
DEFM 'Creating: ' 43 72 65 61 ...
Prompt displayed by @DSPLY at 5284H, immediately followed on screen by the file name built into the adjacent buffer at 53D3H.

Disassembly - Overlay 4 - DEBUG and VERIFY

5200H - DEBUG and VERIFY Command Entry Vectors; DEBUG Command (Commands 14H/1BH)

This overlay serves two related commands: DEBUG (command 14H, entered at 5203H) and VERIFY (command 1BH, entered at 5200H). DEBUG arms or disarms the resident breakpoint re-entry: when turned on it writes a "JP 400FH" into the RST 30H hook area at 4315H-4317H and sets SFLAG$ bit 7, and an EXT option loads the extended debugger via RST 28H code 8BH; when turned off it writes a RET there and reclaims the debugger's high memory. VERIFY (5271H) patches the resident @WRITE vector so disk writes are read-verified. Both parse an ON/OFF/Y/N option through @PARAM (DEBUG also accepts EXT).

5200
VERIFY command entry (command 1BH). JUMP to 5271H to turn write-verification on or off.
5203
DEBUG command entry (command 14H). GOSUB to 5292H to parse the DEBUG option keywords (EXT/ON/OFF/Y/N) and save the stack pointer. On return Register A is FFH unless an OFF/N keyword was given (then 00H, Z set).
5206
LD HL,430FH 21 0F 43
Point HL at the resident system flag byte SFLAG$ at 430FH, whose bit 7 records whether DEBUG is armed and bit 5 means "not at the LDOS command level".
5209
DI F3
Disable interrupts while the breakpoint hook and flags are modified so an interrupt cannot see a half-updated state.
520A
If the Z FLAG is set (an OFF/N keyword was given, from the parse at 5292H), JUMP to 522BH to disarm DEBUG.
520C
BIT 5,(HL) CB 6E
Test bit 5 of SFLAG$ (addressed by HL at 430FH). Bit 5 set means the system is not at the LDOS command level (for example, under a DO/JCL job).
520E
If the NZ FLAG is set (not at the command level), JUMP to 52AFH to report "Invalid command during <DO> processing!".
5211
LD A,(525CH) 3A 5C 52
Fetch the EXT flag from 525CH into Register A; it is non-zero when an EXT (extended debugger) keyword was parsed.
5214
OR A B7
Test the EXT flag (Register A). If EXT was requested the NZ FLAG is set.
5215
PUSH HL E5
Save the SFLAG$ pointer (Register Pair HL) onto the stack across the extended-debugger load.
5216
If the NZ FLAG is set (EXT requested), GOSUB to 525EH to load the extended debugger via RST 28H code 8BH.
5219
POP HL E1
Restore the SFLAG$ pointer (Register Pair HL = 430FH) from the stack.
521A
SET 7,(HL) CB FE
Set bit 7 of SFLAG$ (addressed by HL at 430FH) to mark DEBUG as armed.
521C
LD HL,400FH 21 0F 40
Load HL with 400FH, the resident RST 30H breakpoint-hook entry, to be planted as the target of a jump in the hook area.
521F
LD A,0C3H 3E C3
Load Register A with C3H, the Z80 opcode for JP, to build a "JP 400FH" instruction in the hook area.
5221
LD (4316H),HL 22 16 43
Store HL (400FH) into 4316H-4317H, the address field of the hook-area jump so it targets the breakpoint entry.
5224
LD (4315H),A 32 15 43
Store Register A into 4315H, the opcode byte of the hook-area jump. With A = C3H this completes "JP 400FH", arming breakpoint re-entry; the disarm path reaches here with A = C9H (RET) to disarm.
5227
EI FB
Re-enable interrupts now that the hook and flags are consistent.
5228
JUMP to the common exit at 527FH to restore the stack and return.
522B
RES 7,(HL) CB BE
Clear bit 7 of SFLAG$ (addressed by HL at 430FH) to mark DEBUG as disarmed.
522D
LD A,(525CH) 3A 5C 52
Fetch the EXT flag from 525CH into Register A to decide whether the extended debugger's high memory should be reclaimed.
5230
OR A B7
Test the EXT flag (Register A). If EXT was not involved the Z FLAG is set and the memory reclaim below is skipped.
5231
If the Z FLAG is set (no EXT), JUMP to 5258H to finish the disarm without reclaiming memory.
5233
LD DE,(4310H) ED 5B 10 43
Load Register Pair DE from 4310H, the resident vector that points at the currently installed extended-debugger module.
5237
OR A B7
Clear the CARRY FLAG in preparation for the subtraction that tests the module address.
5238
LD HL,4876H 21 76 48
Load HL with 4876H, the expected address of the resident extended-debugger module, to compare against the installed vector.
523B
SBC HL,DE ED 52
Subtract the installed module vector (DE) from 4876H (HL). A zero result (Z FLAG set) means this module is the one at 4876H.
523D
If the Z FLAG is set (the module is exactly at 4876H, nothing above it to reclaim), JUMP to 5258H to finish.
523F
LD HL,(4049H) 2A 49 40
Load HL from HIGH$ at 4049H, the resident top-of-user-memory pointer, to test whether the debugger sits just above it.
5242
INC HL 23
Increment HL to the first byte above HIGH$, the address the debugger module would start at if it is the topmost reserved block.
5243
OR A B7
Clear the CARRY FLAG for the comparison subtraction.
5244
SBC HL,DE ED 52
Subtract the module vector (DE) from HIGH$+1 (HL). A zero result means the module is the topmost reserved block and its memory can be reclaimed.
5246
If the NZ FLAG is set (the module is not the topmost block, so other modules sit above it), JUMP to 5258H to finish without reclaiming.
5248
EX DE,HL EB
Exchange DE and HL so HL addresses the module's control block for reading its saved previous HIGH$.
5249
INC HL 23
Advance HL to offset +1 of the module block.
524A
INC HL 23
Advance HL to offset +2 of the module block, where the previous HIGH$ value is stored.
524B
LD E,(HL) 5E
Load the low byte of the saved previous HIGH$ (addressed by HL) into E.
524C
INC HL 23
Advance HL to offset +3 of the module block.
524D
LD D,(HL) 56
Load the high byte of the saved previous HIGH$ (addressed by HL) into D, so DE holds the HIGH$ to restore.
524E
LD (4049H),DE ED 53 49 40
Store the restored HIGH$ (DE) back into 4049H, returning the debugger's high memory to the free pool.
5252
LD HL,4876H 21 76 48
Load HL with 4876H, the base of the resident extended-debugger area, to reset the module vector.
5255
LD (4310H),HL 22 10 43
Store 4876H (HL) into the resident module vector at 4310H, clearing the reference to the reclaimed module.
5258
LD A,0C9H 3E C9
Load Register A with C9H, the Z80 opcode for RET, to overwrite the hook-area jump and disarm breakpoint re-entry.
525A
JUMP to 5224H to store the RET opcode (Register A) into the hook area at 4315H, completing the disarm.
525C-525D
DEFB 00,00 00 00
The EXT flag cell. @PARAM stores a non-zero value here when the EXT keyword is given; tested at 5211H and 522DH.

525EH - Extended Debugger Loader

Load the extended debugger, refusing if the debugger is already active or the system is busy. Issues RST 28H request code 8BH to bring in the extended module.

525E
LD A,(402DH) 3A 2D 40
Fetch the first byte of @EXIT at 402DH into Register A. A value of C3H (JP) indicates the debugger has already redirected the exit vector.
5261
CP 0C3H FE C3
Compare Register A (the @EXIT first byte) against C3H (JP). If equal the debugger is already active and the Z FLAG is set.
5263
If the Z FLAG is set (debugger already active), JUMP to 52B4H to report "Can't -- Only valid at LDOS command level!".
5266
LD A,(4758H) 3A 58 47
Fetch the SYS1 status byte at 4758H into Register A to test the busy flag.
5269
BIT 1,A CB 4F
Test bit 1 of the SYS1 status byte (Register A). Bit 1 set means a background operation is busy.
526B
If the NZ FLAG is set (system busy), JUMP to 52B4H to refuse the command.
526E
LD A,8BH 3E 8B
Load Register A with request code 8BH, the supervisor request that loads and enters the extended debugger overlay.
5270
RST 28H EF
Execute the supervisor call with request code 8BH (Register A), loading the extended debugger; control returns here when it is resident.

5271H - VERIFY Command

Turn disk write-verification on or off by patching the address field of the resident @WRITE vector at 443AH to point at the write routine used when verification is on (48E6H) or off (48CBH).

5271
GOSUB to 5297H to parse the VERIFY option (ON/OFF/Y/N) through @PARAM and save the stack pointer. On return the Z FLAG is set when an OFF/N keyword was given.
5274
LD HL,48CBH 21 CB 48
Load HL with 48CBH, the resident write routine used when verification is off, the target chosen if an OFF/N keyword was given.
5277
If the Z FLAG is set (an OFF/N keyword was given), JUMP to 527CH to install the verify-off writer 48CBH now in HL.
5279
LD HL,48E6H 21 E6 48
VERIFY on: load HL with 48E6H, the resident write routine used when verification is enabled.
527C
LD (443AH),HL 22 3A 44
Store HL into 443AH, the address field of the resident @WRITE vector at 4439H, so subsequent disk writes go through the verify-on writer (48E6H) or the verify-off writer (48CBH).

527FH - Common Exit and Parameter Parser

The shared exit that restores the caller's stack and returns (or aborts if not at the command level after an error), and the parameter-parse helper used by both commands: it selects the keyword table (DEBUG's includes EXT), saves the stack pointer, calls @PARAM, and reports whether an OFF/N keyword was seen.

527F
LD HL,0000H 21 00 00
Set HL to 0000H, the success return code.
5282
LD SP,0000H 31 00 00
Self-Modifying Code
Restore the caller's stack pointer. The operand at 5283H was overwritten at 529AH with the caller's SP.
5285
POP AF F1
Discard the return address that the entry CALL to 5292H/5297H pushed, since the stack pointer has been reset to the caller's frame.
5286
LD A,H 7C
Copy the high byte of the return code (H) into Register A to test for success.
5287
OR L B5
OR the low byte (L) into Register A; the Z FLAG is set for a zero (success) code.
5288
RET Z C8
If the Z FLAG is set (success), RETurn to the RST 28H dispatcher.
5289
LD A,(430FH) 3A 0F 43
Fetch SFLAG$ from 430FH into Register A to test the command-level flag on the error path.
528C
BIT 5,A CB 6F
Test bit 5 of SFLAG$ (Register A); it is set when the system is not at the LDOS command level. If clear the Z FLAG is set.
528E
RET Z C8
If the Z FLAG is set (at the command level), RETurn to the dispatcher with the failure code.
528F
Otherwise (not at command level), JUMP to the resident SYS0 service @ABORT (4030H) to abort back to DOS.
5292
LD DE,5319H 11 19 53
Point Register Pair DE at the DEBUG keyword table at 5319H (EXT, E, ON, OFF, Y, N) for @PARAM.
5295
JUMP to the shared parse code at 529AH.
5297
LD DE,5329H 11 29 53
Point Register Pair DE at the VERIFY keyword sub-table at 5329H (ON, OFF, Y, N only, skipping EXT) for @PARAM.
529A
LD (5283H),SP ED 73 83 52
Self-Modifying Code
Save the caller's stack pointer into 5283H, the operand of the LD SP,nnnn at 5282H, for the common exit.
529E
GOSUB to the resident SYS0 service @PARAM (4476H) to parse the option keywords from the command line into the flag cells named by the table at DE. Returns the NZ FLAG on a bad parameter.
52A1
LD A,2CH 3E 2C
Load Register A with error code 2CH, the parameter-error code.
52A3
If the NZ FLAG is set (a bad parameter), JUMP to 52BFH to report the parameter error.
52A5
LD BC,0000H 01 00 00
Self-Modifying Code
Load Register Pair BC with the OFF/N flag. The operand at 52A6H-52A7H is the cell @PARAM sets when an OFF or N keyword is given (default 0).
52A8
LD A,B 78
Copy the high byte of the OFF/N flag (B) into Register A.
52A9
OR C B1
OR the low byte (C) into Register A; the result is zero when no OFF/N keyword was given.
52AA
XOR 0FFH EE FF
Complement Register A so it is FFH (NZ) when the command is being turned on and 00H (Z) when an OFF/N keyword was given, the on/off result the callers test.
52AC
RET C9
RETurn to the DEBUG (5203H) or VERIFY (5271H) caller with the on/off result in Register A and the Z FLAG.
52AD-52AE
DEFB 00,00 00 00
The ON/Y flag cell. @PARAM stores a non-zero value here when an ON or Y keyword is given.

52AFH - Error Message Display

Display one of the two refusal messages and set the failure return code. The two entry points share a single display call through a DD-prefix overlap.

52AF
EI FB
Re-enable interrupts (they were disabled at 5209H on the DEBUG path) before displaying the message.
52B0
LD HL,52F1H 21 F1 52
Point HL at the message "Invalid command during <DO> processing!" at 52F1H, the message for the not-at-command-level path.
52B3
LD IX,52C6H DD 21 C6 52
Overlapping Code
On fall-through from 52B0H this loads IX with 52C6H and has no effect (HL already points at the "Invalid command" message). Entered at 52B4H (skipping the DD prefix) the bytes 21 C6 52 decode as LD HL,52C6H, pointing HL at "Can't -- Only valid at LDOS command level!". 52B4H is reached from the extended-debugger loader at 5263H and 526BH.
52B7
GOSUB to the resident SYS0 service @LOGOT (447BH) to display the carriage-return-terminated message pointed to by HL.
52BA
LD HL,0FFFFH 21 FF FF
Set HL to FFFFH, the non-zero failure return code.
52BD
JUMP to the exit tail at 5282H to restore the stack and return or abort.
52BF
OR 0C0H F6 C0
Set bits 7 and 6 of the error code in Register A so @ERROR displays the message and returns rather than aborting.
52C1
GOSUB to the resident SYS0 service @ERROR (4409H) to display the parameter-error message for the code in Register A.
52C4
JUMP to 52BAH to set the failure return code and exit.

52C6H - Messages and Parameter Table

The two refusal messages and the @PARAM keyword table. These are data, not code. DEBUG points @PARAM at the full table (5319H); VERIFY points it at 5329H so the EXT keyword is not offered.

52C6-52F0
DEFM 'Can't -- Only valid at LDOS command level!' + 0DH 43 61 6E 27 ...
Refusal message shown when DEBUG is requested but is already active or the system is busy (reached via 52B4H). Terminated by 0DH at 52F0H.
52F1-5318
DEFM 'Invalid command during <DO> processing!' + 0DH 49 6E 76 61 ...
Message shown when the command is issued while not at the LDOS command level (reached via 52AFH). Terminated by 0DH at 5318H.
5319-5349
DEFM 'EXT'/'E' 525C, 'ON' 52AD, 'OFF' 52A6, 'Y' 52AD, 'N' 52A6 45 58 54 20 ...
@PARAM keyword descriptor table (8-byte entries, six-character space-padded keyword + two-byte flag-cell address): EXT (and abbreviation E) set the EXT flag at 525CH; ON and Y set the enable flag at 52ADH; OFF and N set the disable flag at 52A6H. DEBUG uses the table from 5319H (EXT included); VERIFY uses it from 5329H (ON/OFF/Y/N only). Terminated by 00H at 5349H.

Disassembly - Overlay 5 - SYSGEN

SYSGEN is Library B command 1CH. It creates or deletes the invisible system configuration file CONFIG/SYS.CCC:d on the drive requested by the caller. On a build it snapshots the entire live system state - protected high memory, all Device Control Blocks, the DOS SVC vectors that filters and drivers have patched, the interrupt/task workspace, the keyboard-task hook, the flag bytes and the SPOOL control block - and writes it out as a standard LDOS load module so the boot loader can reload and re-apply it automatically at every power-up. On a delete it kills the file and clears the boot-time auto-configuration flag. The overlay is loaded at 5200H by the resident overlay loader (4BF5H) and entered at its first byte with the drive number in H and the ON/OFF switch in L.

5200H - Entry, Environment Check, Drive and Switch Setup

On entry H holds the target drive number (0-7, from the DRIVE= parameter parsed by SYS1) and L holds the switch (non-zero = ON = build, zero = OFF = delete). SYSGEN first suspends any active Job Control Language, then refuses to run if another module has hooked @EXIT or if SYS1 is busy, then patches the drive digit into its filename and message strings.

5200
LD (5367H),SP ED 73 67 53
Self-Modifying Code
Save the entry Stack Pointer into memory location 5367H, which is the two-byte operand field of the LD HL,0000H instruction at 5366H in the common exit code. This lets the exit recover the entry stack value.
5204
GOSUB to the local routine at 53A2H, which temporarily suspends Job Control Language (SFLAG$ 430FH bit 5) and redirects the keyboard driver so SYSGEN runs as if at LDOS command level even inside a JCL/DO file.
5207
NOP 00
No operation. One-byte filler left by the assembler between the setup call and the environment test.
5208
LD A,(402DH) 3A 2D 40
Fetch the first byte of @EXIT (the DOS exit vector at 402DH) into Register A. When a background module or filter has taken over the exit path this byte is C3H (the opcode for JP).
520B
CP 0C3H FE C3
Compare Register A (the first byte of @EXIT at 402DH) against C3H (a JP opcode). If Register A equals C3H the Z FLAG is set, meaning the exit vector has been hooked and the configuration cannot be safely generated.
520D
If the Z FLAG is set (@EXIT at 402DH begins with a C3H jump, so a module owns the exit path), JUMP to 539AH to print the command-level refusal message and quit.
5210
LD A,(4758H) 3A 58 47
Fetch the SYS1 status byte from 4758H into Register A. Bit 1 of this byte is the DOS busy flag, set while a command overlay or background operation is already in progress.
5213
BIT 1,A CB 4F
Test bit 1 of Register A (the busy flag from the SYS1 status byte at 4758H). The Z FLAG is set if the system is not busy, cleared (NZ) if it is busy.
5215
If the NZ FLAG is set (bit 1 of the SYS1 status byte at 4758H was set, so the system is busy), JUMP to 539AH to refuse the operation.
5218
LD A,H 7C
Copy the drive number (Register H, the DRIVE= value 0-7 supplied by the caller) into Register A.
5219
LD (5382H),A 32 82 53
Self-Modifying Code
Store the drive number (Register A) into 5382H, the operand of the LD C,00H instruction at 5381H inside the sector helper at 537BH. This makes every RDSECT/WRSECT the helper issues address the SYSGEN drive.
521C
ADD A,30H C6 30
Add 30H to Register A (the drive number) to convert it to its ASCII digit ('0'-'7').
521E
LD (53FCH),A 32 FC 53
Self-Modifying Code
Store the ASCII drive digit (Register A) into 53FCH, the drive position of the filename string "CONFIG/SYS.CCC:0" so it reads ":d" for the requested drive.
5221
LD (543CH),A 32 3C 54
Self-Modifying Code
Store the ASCII drive digit (Register A) into 543CH, the drive position of the "Attrib CONFIG/SYS.CCC:0 (I,P=RE)" message string.
5224
LD A,L 7D
Copy the switch value (Register L) into Register A. L is non-zero for SYSGEN ON (build) and zero for SYSGEN OFF (delete).
5225
OR A B7
OR Register A with itself to set the flags. The Z FLAG is set if Register A (the switch) is zero, meaning the OFF/delete request.
5226
If the Z FLAG is set (the switch in Register A was zero, i.e. SYSGEN OFF), JUMP to 5346H to delete the existing configuration file. Otherwise execution falls through to the build path.

5229H - Build: Create CONFIG/SYS and Write the Module Header

The build path opens (creating) CONFIG/SYS on the target drive, then writes the load-module name record: a type-05 record carrying the six-character module name "CONFIG".

5229
LD DE,53EDH 11 ED 53
Point Register Pair DE to 53EDH, the filename "CONFIG/SYS.CCC:0" which doubles as the File Control Block used by @INIT and the byte-output driver.
522C
LD HL,5600H 21 00 56
Point Register Pair HL to 5600H, the disk buffer @INIT will assign to the file's sector I/O.
522F
LD B,L 45
Load Register B with Register L (00H, the low byte of 5600H), setting the Logical Record Length parameter for @INIT to 0 which means a 256-byte record.
5230
GOSUB to the resident @INIT service at 4420H to open or create the file whose FCB is at DE (53EDH, CONFIG/SYS) using the buffer at HL (5600H). On return the Z FLAG is set on success, NZ on a disk error.
5233
If the NZ FLAG is set (@INIT at 4420H reported a disk error), JUMP to 538FH to display the error code and abort.
5236
LD A,05H 3E 05
Load Register A with 05H, the LDOS load-module record type for a module name/header record.
5238
GOSUB to the file-output helper at 538BH to write the byte in Register A (05H, the name-record type) to CONFIG/SYS.
523B
LD A,06H 3E 06
Load Register A with 06H, the length of the module name that follows (six characters).
523D
GOSUB to 538BH to write the byte in Register A (06H, the name length) to CONFIG/SYS.
5240
LD B,06H 06 06
Load Register B with 06H, the loop count for the six name characters.
5242
LD HL,542DH 21 2D 54
Point Register Pair HL to 542DH, the six characters "CONFIG" embedded in the "Attrib CONFIG/SYS..." message string, reused here as the module name.
5245
LD A,(HL) 7E
Loop Start
Fetch the next name character from the address in Register Pair HL (walking "CONFIG" from 542DH) into Register A.
5246
INC HL 23
Advance Register Pair HL to the next name character.
5247
GOSUB to 538BH to write the name character in Register A to CONFIG/SYS.
524A
DECrement Register B and LOOP BACK to 5245H until all six characters of "CONFIG" have been written. Loop End

524CH - Build: Write the Screen Banner and Interrupt-Vector Records

Two type-01 load records are written next. The first paints "*** CONFIGURING ***" into the video line at 3F96H when the file is reloaded at boot; the second forces the RST 38H interrupt vector at 4012H to a RET so interrupts are inert while the rest of the configuration loads.

524C
LD B,13H 06 13
Load Register B with 13H (19), the byte count of the first half of the banner text.
524E
LD DE,3F96H 11 96 3F
Point Register Pair DE to 3F96H, the video RAM position where the banner will be reloaded at boot. This becomes the load address of the record.
5251
LD HL,54A8H 21 A8 54
Point Register Pair HL to 54A8H, the 19-byte string "*** CONFIGURING ***" in this overlay, the data source for the record.
5254
GOSUB to the record-writer at 5324H to emit a type-01 load record: 19 bytes (Register B) taken from 54A8H (Register Pair HL) that will load at video address 3F96H (Register Pair DE) when CONFIG/SYS is booted.
5257
LD B,01H 06 01
Load Register B with 01H, the one-byte length of the interrupt-vector record.
5259
LD DE,4012H 11 12 40
Point Register Pair DE to 4012H, the RST 38H interrupt vector (normally JP 4518H). This becomes the load address of the record.
525C
LD HL,5323H 21 23 53
Point Register Pair HL to 5323H, a byte that holds C9H (the RET opcode at the end of the 52EBH helper), used here as the data source.
525F
GOSUB to 5324H to emit a type-01 record that loads the single byte C9H (from 5323H) at 4012H, so that during config load the RST 38H interrupt vector is a RET and interrupt handling stays inert until the rest of the image is in place.

5262H - Build: Size RAM and Save Protected High Memory

SYSGEN walks down from FFFFH in 16K steps to find the physical top of RAM, computes the span from HIGH$ to that ceiling, and writes the whole protected high-memory region (utility modules and user programs held above HIGH$) into the configuration file.

5262
LD HL,0FFFFH 21 FF FF
Point Register Pair HL to FFFFH, the highest possible address, as the starting point of the RAM-sizing scan.
5265
LD A,(HL) 7E
Loop Start
Read the byte at the address in Register Pair HL (the current test address) into Register A, preserving the original contents.
5266
LD B,A 47
Save the original byte (Register A) into Register B so it can be restored after the write test.
5267
CPL 2F
Complement Register A, producing a value guaranteed to differ from the original byte for the write test.
5268
LD (HL),A 77
Write the complemented value (Register A) to the test address in Register Pair HL.
5269
CP (HL) BE
Compare Register A against the byte just read back from the test address (Register Pair HL). If they match, RAM exists there and the Z FLAG is set; if not, this is ROM or empty space and the NZ FLAG is set.
526A
LD (HL),B 70
Restore the original byte (Register B) to the test address in Register Pair HL, undoing the write test.
526B
If the Z FLAG is set (the test address in Register Pair HL is writable RAM), JUMP to 5273H; the top of RAM has been found.
526D
LD A,H 7C
Copy the high byte of the test address (Register H) into Register A to step down to the next 16K boundary.
526E
SUB 40H D6 40
SUBtract 40H from Register A, moving the test address down by 16K (4000H).
5270
LD H,A 67
Store the decremented high byte (Register A) back into Register H, so Register Pair HL now points 16K lower.
5271
LOOP BACK to 5265H to test the next-lower 16K boundary for RAM. Loop End
5273
LD DE,(4049H) ED 5B 49 40
Load Register Pair DE with HIGH$, the top-of-user-memory pointer at 4049H (the highest address available to programs; everything above it is protected). HL still holds the physical top of RAM found above.
5277
XOR A AF
Set Register A to ZERO and clear the Carry flag ahead of the subtraction.
5278
SBC HL,DE ED 52
Subtract HIGH$ (Register Pair DE, from 4049H) from the top of RAM (Register Pair HL). Register Pair HL now holds the length of the protected high-memory block to be saved.
527A
LD B,H 44
Copy the high byte of the length (Register H) into Register B, building the byte count in Register Pair BC.
527B
LD C,L 4D
Copy the low byte of the length (Register L) into Register C, so Register Pair BC is the number of high-memory bytes to save.
527C
INC DE 13
Advance Register Pair DE to HIGH$+1, the first protected byte, which is both the source and the reload address for the block.
527D
If the NZ FLAG is set (Register Pair BC is non-zero, so protected memory exists), GOSUB to the block writer at 52EBH to save Register Pair BC bytes starting at HIGH$+1 (Register Pair DE) into CONFIG/SYS as type-01 records.

5284H - Build: Save the Resident Configuration Regions

A driver byte in the KI Device Control Block is cleared, then a table at 54CEH is walked. Each four-byte entry is a byte count followed by a resident address; SYSGEN saves that region in place (source address equals reload address) so every DCB, vector, flag byte and workspace listed in the table is captured. The table lists HIGH$, the KI/DO/PR DCBs, the @WRITE vector, the task control blocks, the clock/task workspace, the keyboard-task and configuration hooks, the flag bytes, the overlay-dispatcher patch cell, the module-chain head and the SPOOL control block.

5280
XOR A AF
Set Register A to ZERO to clear a driver working byte.
5281
LD (4018H),A 32 18 40
Store ZERO (Register A) into 4018H, a working byte of the KI Device Control Block (KIDCB$ at 4015H), sanitising the keyboard driver's transient state before its DCB image is snapshotted.
5284
LD HL,54CEH 21 CE 54
Point Register Pair HL to 54CEH, the start of the save-region table (four-byte count/address entries, terminated by a zero count).
5287
LD C,(HL) 4E
Loop Start
Load Register C with the low byte of the region byte count from the table entry at Register Pair HL.
5288
INC HL 23
Advance Register Pair HL to the high byte of the count.
5289
LD B,(HL) 46
Load Register B with the high byte of the count, so Register Pair BC is this region's byte count.
528A
INC HL 23
Advance Register Pair HL to the low byte of the region address.
528B
LD A,B 78
Copy the high byte of the count (Register B) into Register A to test for the table terminator.
528C
OR C B1
OR with the low byte of the count (Register C). The Z FLAG is set only if the whole count (Register Pair BC) is zero, marking the end of the table.
528D
If the Z FLAG is set (the count in Register Pair BC is zero, so the table is exhausted), JUMP to 529AH to finish the module.
528F
LD E,(HL) 5E
Load Register E with the low byte of the region address from the table entry at Register Pair HL.
5290
INC HL 23
Advance Register Pair HL to the high byte of the region address.
5291
LD D,(HL) 56
Load Register D with the high byte of the region address, so Register Pair DE is the resident address of this region (both its source and its reload address).
5292
INC HL 23
Advance Register Pair HL to the next table entry.
5293
PUSH HL E5
Save the table pointer (Register Pair HL) on the stack across the record write.
5294
GOSUB to the block writer at 52EBH to save Register Pair BC bytes from the region address in Register Pair DE into CONFIG/SYS.
5297
POP HL E1
Restore the table pointer (Register Pair HL) from the stack.
5298
LOOP BACK to 5287H to process the next table entry. Loop End

529AH - Build: Save the Device Tables, Finish the Module, Enable Auto-Config

The drive-table image is written, the banner record is completed, the type-02 transfer record ends the module and the file is closed. Finally the boot-time configuration control sector is read, its flag byte is set to enable auto-configuration, written back, and the success message is issued through @CMNDI.

529A
LD B,50H 06 50
Load Register B with 50H (80), the byte count of the drive-table image.
529C
LD DE,4152H 11 52 41
Point Register Pair DE to 4152H, the reload address the boot loader uses for the drive-table image (the staging area from which the resident configuration code moves it into place).
529F
LD HL,4700H 21 00 47
Point Register Pair HL to 4700H, the live Drive Code Table (DCT$), the data source for the record.
52A2
GOSUB to the record-writer at 5324H to emit a type-01 record: 80 bytes (Register B) taken from the Drive Code Table at 4700H (Register Pair HL) that will reload at 4152H (Register Pair DE).
52A5
LD B,01H 06 01
Load Register B with 01H. This setup is superseded before use by the reload of Register B at 52B0H.
52A7
LD DE,4012H 11 12 40
Point Register Pair DE to 4012H. This setup is superseded before use by the reload of Register Pair DE at 52B2H.
52AA
LD HL,5391H 21 91 53
Point Register Pair HL to 5391H. This setup is superseded before use by the reload of Register Pair HL at 52ADH and again at 52B5H.
52AD
LD HL,5324H 21 24 53
Point Register Pair HL to 5324H. This setup is superseded before use by the reload of Register Pair HL at 52B5H.
52B0
LD B,13H 06 13
Load Register B with 13H (19), the byte count of the second half of the banner text.
52B2
LD DE,3F96H 11 96 3F
Point Register Pair DE to 3F96H, the video reload address for the second banner record.
52B5
LD HL,54BBH 21 BB 54
Point Register Pair HL to 54BBH, the 19 trailing blanks of the banner string, the data source for the record.
52B8
GOSUB to 5324H to emit a type-01 record: 19 bytes (Register B) from 54BBH (Register Pair HL) that reload at 3F96H (Register Pair DE), completing the boot-time banner record.
52BB
GOSUB to 5389H to write the byte 02H (the LDOS transfer-record type) to CONFIG/SYS.
52BE
GOSUB to 5389H to write a second 02H, the length byte of the transfer record.
52C1
XOR A AF
Set Register A to ZERO for the low byte of the transfer address.
52C2
GOSUB to 538BH to write the byte in Register A (00H) as the low byte of the transfer address.
52C5
XOR A AF
Set Register A to ZERO for the high byte of the transfer address.
52C6
GOSUB to 538BH to write the byte in Register A (00H), completing the transfer record 02 02 00 00 (transfer address 0000H = load only, no execution).
52C9
GOSUB to the resident @CLOSE service at 4428H to close CONFIG/SYS (whose FCB is at 53EDH), flushing the finished load module to disk. On return the Z FLAG is set on success, NZ on error.
52CC
If the NZ FLAG is set (@CLOSE at 4428H reported an error), JUMP to 538FH to display the error and abort.
52CF
GOSUB to the sector helper at 537BH to read the boot-time configuration control sector on the SYSGEN drive into the buffer at 4200H.
52D2
XOR A AF
Set Register A to ZERO, the value that enables automatic configuration loading at boot.
52D3
LD (4201H),A 32 01 42
Store ZERO (Register A) into 4201H, the auto-configuration flag byte inside the control sector image at 4200H. Zero here lets the boot loader fall through and load CONFIG/SYS.
52D6
GOSUB to the resident WRSECT primitive at 4763H to write the updated control sector (buffer at 4200H) back to the SYSGEN drive. On return the Z FLAG is set on success, NZ on error.
52D9
If the NZ FLAG is set (WRSECT at 4763H reported an error), JUMP to 538FH to display the error and abort.
52DC
LD HL,540DH 21 0D 54
Point Register Pair HL to 540DH, the message "User configuration built".
52DF
GOSUB to the resident @LOGOT service at 447BH to display the carriage-return-terminated message at Register Pair HL (540DH, "User configuration built").
52E2
GOSUB to 53D6H to restore the Job Control Language context that 53A2H suspended at entry.
52E5
LD HL,5426H 21 26 54
Point Register Pair HL to 5426H, the command line "Attrib CONFIG/SYS.CCC:0 (I,P=RE)", which marks the new file Invisible and Protected.
52E8
JUMP to the resident @CMNDI service at 4405H, handing it the command line at Register Pair HL (5426H) so DOS executes the ATTRIB command and returns to command level. This ends the build path.

52EBH - Helper: Write a Large Region as 254-Byte Load Records

This routine writes an arbitrary-length block to CONFIG/SYS as one or more type-01 load records, splitting the block into chunks of at most 254 (0FEH) data bytes so each record length fits in one byte. On entry Register Pair DE is the source/reload address and Register Pair BC is the byte count.

52EB
EX DE,HL EB
Exchange Register Pairs DE and HL so Register Pair HL now holds the source/reload address that was passed in Register Pair DE.
52EC
LD DE,53EDH 11 ED 53
Point Register Pair DE to 53EDH, the CONFIG/SYS FCB used by the byte-output driver.
52EF
PUSH HL E5
Loop Start
Save the current source/reload address (Register Pair HL) on the stack.
52F0
PUSH BC C5
Save the remaining byte count (Register Pair BC) on the stack.
52F1
LD H,B 60
Copy the high byte of the remaining count (Register B) into Register H.
52F2
LD L,C 69
Copy the low byte of the remaining count (Register C) into Register L, so Register Pair HL now holds the remaining count for the chunk test.
52F3
LD BC,00FEH 01 FE 00
Load Register Pair BC with 00FEH (254), the maximum data bytes per load record.
52F6
XOR A AF
Set Register A to ZERO and clear the Carry flag for the subtraction.
52F7
SBC HL,BC ED 42
Subtract 254 (Register Pair BC) from the remaining count (Register Pair HL). The Carry flag is set if fewer than 254 bytes remain.
52F9
If the NO CARRY FLAG is set (254 or more bytes remain), JUMP to 5301H to write a full 254-byte chunk.
52FB
POP BC C1
Fewer than 254 bytes remain: restore the actual remaining count (Register Pair BC) from the stack.
52FC
LD HL,0000H 21 00 00
Point Register Pair HL to 0000H, marking this as the final chunk so the loop terminates after it.
52FF
JUMP to 5302H to write this final partial chunk.
5301
POP AF F1
A full chunk: discard the saved count from the stack (it is not needed; 254 will be used) by popping it into Register Pair AF.
5302
EX (SP),HL E3
Exchange the top of the stack with Register Pair HL: Register Pair HL becomes the saved source/reload address, and the stack now holds the remaining-count residual for the next iteration.
5303
LD B,C 41
Copy the chunk length (Register C, either 254 or the final remainder) into Register B, the per-record byte loop count.
5304
LD A,01H 3E 01
Load Register A with 01H, the load-record type.
5306
GOSUB to 538BH to write the record type (01H, Register A) to CONFIG/SYS.
5309
LD A,B 78
Copy the chunk length (Register B) into Register A to form the record length.
530A
ADD A,02H C6 02
Add 02H to Register A: the record length is the data count plus the two address bytes (a full 254-byte chunk yields 00H, meaning 256).
530C
GOSUB to 538BH to write the record length (Register A) to CONFIG/SYS.
530F
LD A,L 7D
Copy the low byte of the reload address (Register L, from Register Pair HL) into Register A.
5310
GOSUB to 538BH to write the reload address low byte (Register A) to CONFIG/SYS.
5313
LD A,H 7C
Copy the high byte of the reload address (Register H) into Register A.
5314
GOSUB to 538BH to write the reload address high byte (Register A) to CONFIG/SYS.
5317
LD A,(HL) 7E
Loop Start
Fetch the next data byte from the source address in Register Pair HL into Register A.
5318
INC HL 23
Advance Register Pair HL to the next source byte.
5319
GOSUB to 538BH to write the data byte (Register A) to CONFIG/SYS.
531C
DECrement Register B and LOOP BACK to 5317H until all bytes of this chunk have been written. Loop End
531E
POP BC C1
Restore the remaining-count residual (Register Pair BC) saved by the earlier EX (SP),HL.
531F
LD A,B 78
Copy the high byte of the remaining count (Register B) into Register A to test for completion.
5320
OR C B1
OR with the low byte of the remaining count (Register C). The Z FLAG is set when the whole block has been written.
5321
If the NZ FLAG is set (bytes still remain in Register Pair BC), LOOP BACK to 52EFH to write the next chunk. Loop End
5323
RET C9
Return to the caller; the entire block has been written. This C9H byte is also the source of the single-byte interrupt-vector record written at 525FH.

5324H - Helper: Write One Region as a Load Record

Writes a single type-01 load record of up to 255 bytes. On entry Register B is the data count, Register Pair DE is the reload address written into the record, and Register Pair HL is the source of the data bytes (source and reload address may differ, as they do for the banner and drive-table records).

5324
PUSH HL E5
Save the data source pointer (Register Pair HL) on the stack.
5325
LD H,D 62
Copy the high byte of the reload address (Register D) into Register H.
5326
LD L,E 6B
Copy the low byte of the reload address (Register E) into Register L, so Register Pair HL now holds the reload address to write into the record header.
5327
LD DE,53EDH 11 ED 53
Point Register Pair DE to 53EDH, the CONFIG/SYS FCB used by the byte-output driver.
532A
LD A,01H 3E 01
Load Register A with 01H, the load-record type.
532C
GOSUB to 538BH to write the record type (01H, Register A) to CONFIG/SYS.
532F
LD A,B 78
Copy the data count (Register B) into Register A to form the record length.
5330
ADD A,02H C6 02
Add 02H to Register A: the record length is the data count plus the two address bytes.
5332
GOSUB to 538BH to write the record length (Register A) to CONFIG/SYS.
5335
LD A,L 7D
Copy the low byte of the reload address (Register L) into Register A.
5336
GOSUB to 538BH to write the reload address low byte (Register A) to CONFIG/SYS.
5339
LD A,H 7C
Copy the high byte of the reload address (Register H) into Register A.
533A
GOSUB to 538BH to write the reload address high byte (Register A) to CONFIG/SYS.
533D
POP HL E1
Restore the data source pointer (Register Pair HL) from the stack.
533E
LD A,(HL) 7E
Loop Start
Fetch the next data byte from the source address in Register Pair HL into Register A.
533F
INC HL 23
Advance Register Pair HL to the next source byte.
5340
GOSUB to 538BH to write the data byte (Register A) to CONFIG/SYS.
5343
DECrement Register B and LOOP BACK to 533EH until all data bytes of the region have been written. Loop End
5345
RET C9
Return to the caller; the single load record has been written.

5346H - Delete: Disable Auto-Config and Kill CONFIG/SYS

The SYSGEN OFF path reads the boot control sector, sets its flag byte to C9H so the boot loader skips configuration loading, writes it back, then opens and kills CONFIG/SYS. If the file is not present it reports "No user configuration found".

5346
GOSUB to the sector helper at 537BH to read the boot-time configuration control sector on the SYSGEN drive into the buffer at 4200H.
5349
LD A,0C9H 3E C9
Load Register A with C9H (a RET opcode), the value that disables automatic configuration loading at boot.
534B
LD (4201H),A 32 01 42
Store C9H (Register A) into 4201H, the auto-configuration flag byte in the control sector image at 4200H. C9H makes the boot loader return before loading CONFIG/SYS.
534E
GOSUB to the resident WRSECT primitive at 4763H to write the updated control sector (buffer at 4200H) back to the SYSGEN drive. On return the Z FLAG is set on success, NZ on error.
5351
If the NZ FLAG is set (WRSECT at 4763H reported an error), JUMP to 538FH to display the error and abort.
5353
LD DE,53EDH 11 ED 53
Point Register Pair DE to 53EDH, the CONFIG/SYS filename/FCB.
5356
GOSUB to the resident @OPEN service at 4424H to open CONFIG/SYS (FCB at Register Pair DE, 53EDH). On return the Z FLAG is set if the file was found, NZ if it does not exist.
5359
If the NZ FLAG is set (@OPEN at 4424H did not find the file), JUMP to 5396H to report "No user configuration found".
535B
GOSUB to the resident @KILL service at 442CH to delete the open CONFIG/SYS file. On return the Z FLAG is set on success, NZ on error.
535E
If the NZ FLAG is set (@KILL at 442CH reported an error), JUMP to 538FH to display the error and abort.
5360
LD HL,5447H 21 47 54
Point Register Pair HL to 5447H, the message "User configuration deleted".
5363
GOSUB to the resident @LOGOT service at 447BH to display the carriage-return-terminated message at Register Pair HL (5447H, "User configuration deleted"), then fall into the common exit.

5369H - Common Exit and Abort Handler

The shared exit restores the Job Control context and returns to the resident RST 28H dispatcher when running at LDOS command level, or transfers to @ABORT when a JCL/DO file is active so the batch stream is terminated.

5366
LD HL,0000H 21 00 00
Self-Modifying Code
The 0000H operand was overwritten at entry (5200H) with the entry Stack Pointer, so this loads Register Pair HL with the saved entry stack value used by the exit test below.
5369
LD SP,0000H 31 00 00
Load the Stack Pointer with the operand field (0000H as assembled). This is the entry reached by the error paths that jump to 5369H before returning to the dispatcher.
536C
GOSUB to 53D6H to restore the Job Control Language context (SFLAG$ 430FH and the keyboard driver vector) suspended at entry.
536F
LD A,H 7C
Copy the high byte of the saved entry stack value (Register H) into Register A for the exit test.
5370
OR L B5
OR with the low byte (Register L). The Z FLAG is set only if the saved entry stack value in Register Pair HL is zero.
5371
RET Z C8
If the Z FLAG is set, return to the resident RST 28H dispatcher.
5372
LD A,(430FH) 3A 0F 43
Fetch the system flag byte SFLAG$ from 430FH into Register A. Bit 5 is set when the system is not at LDOS command level (a JCL/DO file is active).
5375
BIT 5,A CB 6F
Test bit 5 of Register A (the not-at-command-level flag from SFLAG$ at 430FH). The Z FLAG is set if the system is at command level, cleared (NZ) if a JCL/DO file is active.
5377
RET Z C8
If the Z FLAG is set (at LDOS command level), return to the resident RST 28H dispatcher.
5378
Otherwise (a JCL/DO file is active, SFLAG$ 430FH bit 5 set) JUMP to the resident @ABORT service at 4030H to terminate the Job Control stream.

Self-Modifying Code
The entry Stack Pointer saved at 5200H is planted into the LD HL operand at 5366H; the exit reloads it into Register Pair HL and tests it, then returns to the resident RST 28H dispatcher (RET) when at LDOS command level or transfers to @ABORT at 4030H when a JCL/DO file is active (SFLAG$ 430FH bit 5). The LD SP,0000H at 5369H is the label the error paths (5394H, 53A0H) branch to before the same return sequence.

537BH - Helpers: Read the Boot Control Sector and Write a File Byte

Two small helpers. The first reads the boot-time configuration control sector on the SYSGEN drive into the buffer at 4200H. The second writes one byte to CONFIG/SYS through the ROM output vector, and also serves as the shared disk-error entry point.

537B
LD HL,4200H 21 00 42
Point Register Pair HL to 4200H (SBUFF$), the buffer that receives the control sector.
537E
LD DE,0002H 11 02 00
Load Register Pair DE with 0002H, selecting the boot-time configuration control sector for the RDSECT primitive.
5381
LD C,00H 0E 00
Self-Modifying Code
Load Register C with the drive number. The 00H operand at 5382H was overwritten at entry (5219H) with the SYSGEN drive, so RDSECT reads from the requested drive.
5383
GOSUB to the resident RDSECT primitive at 4777H to read the control sector (Register Pair DE) from the SYSGEN drive (Register C) into the buffer at Register Pair HL (4200H). On return the Z FLAG is set on success, NZ on error.
5386
If the NZ FLAG is set (RDSECT at 4777H reported an error), JUMP to 538FH to display the error and abort.
5388
RET C9
Return to the caller with the control sector in the buffer at 4200H.
5389
LD A,02H 3E 02
Load Register A with 02H. This entry writes the transfer-record type byte; it falls straight into the byte-output helper below.
538B
GOSUB to the ROM output routine at 001BH to send the byte in Register A to the device whose control block is at Register Pair DE (53EDH, the CONFIG/SYS file). On return the Z FLAG is set if the byte was accepted.
538E
RET Z C8
If the Z FLAG is set (the byte was written successfully), return to the caller.
538F
OR 0C0H F6 C0
Disk-error entry: OR Register A (the disk status/error code) with C0H to force the sign and mark it a fatal error for @ERROR.
5391
GOSUB to the resident @ERROR service at 4409H to display the error text for the code in Register A.
5394
JUMP to the common exit at 5369H after the error has been reported.

5396H - Error Messages: No Configuration and Command-Level Refusal

A shared display tail with a deliberate DD-prefix overlap. Reached at 5396H it reports "No user configuration found"; reached at 539AH (from the entry environment check) it reports "Can't -- Valid only at LDOS command level".

5396
LD HL,5462H 21 62 54
Point Register Pair HL to 5462H, the message "No user configuration found".
5399
LD IX,547EH DD 21 7E 54
Self-Modifying Code
On the fall-through path from 5396H this loads Register Pair IX with 547EH and is inert (Register Pair HL already points at the "No user configuration found" message). When entered one byte later at 539AH the DD prefix is skipped and the bytes 21 7E 54 execute as LD HL,547EH, pointing Register Pair HL at "Can't -- Valid only at LDOS command level". The anchor for 539AH resolves to this row.
539D
GOSUB to the resident @LOGOT service at 447BH to display the carriage-return-terminated message at Register Pair HL (either 5462H or 547EH depending on the entry point).
53A0
JUMP to the common exit at 5369H after the message has been displayed.

Deliberate DD-Prefix Overlap
The entry environment check (520DH and 5215H) jumps to 539AH, one byte inside the four-byte LD IX,547EH at 5399H. Landing on the 21 7E 54 tail runs LD HL,547EH instead, so the two refusal messages "No user configuration found" (5462H) and "Can't -- Valid only at LDOS command level" (547EH) share the single @LOGOT and exit tail.

53A2H - Suspend Job Control and Enter Command-Level Context

Called at entry. If a JCL/DO file is active (SFLAG$ 430FH bit 5) this routine clears that flag, swaps an alternate @EXIT/@ABORT vector block into place, redirects the KI keyboard driver vector and resets the keyboard device so SYSGEN behaves as though it were entered at the command line. If no JCL is active it does nothing. The saved flag state is used later by 53D6H to decide whether to restore.

53A2
PUSH HL E5
Save the caller's Register Pair HL on the stack.
53A3
LD HL,430FH 21 0F 43
Point Register Pair HL to 430FH, the system flag byte SFLAG$.
53A6
LD A,(HL) 7E
Fetch SFLAG$ (the byte at Register Pair HL, 430FH) into Register A.
53A7
LD (53D7H),A 32 D7 53
Self-Modifying Code
Store the current SFLAG$ value (Register A) into 53D7H, the operand of the LD A,00H at 53D6H, so the restore routine can later re-test the original command-level state.
53AA
BIT 5,A CB 6F
Test bit 5 of Register A (the not-at-command-level flag of SFLAG$ at 430FH). The Z FLAG is set if already at command level, in which case no suspension is needed.
53AC
If the Z FLAG is set (SFLAG$ 430FH bit 5 clear, already at command level), JUMP to 53CBH to skip the JCL-suspension work.
53AE
RES 5,(HL) CB AE
Clear bit 5 of SFLAG$ (the byte at Register Pair HL, 430FH), temporarily marking the system as being at command level.
53B0
LD HL,4065H 21 65 40
Point Register Pair HL to 4065H, the alternate six-byte @EXIT/@ABORT vector block held in the DEBUG save area, the source for the vector swap.
53B3
GOSUB to the copy helper at 53CDH to move six bytes from Register Pair HL (4065H) into the @EXIT vector area at 402DH, replacing the command-level exit/abort vectors so SYSGEN returns cleanly.
53B6
LD HL,(43BEH) 2A BE 43
Load Register Pair HL with KIJCL$, the Job Control keyboard vector stored at 43BEH.
53B9
EX DE,HL EB
Move that JCL keyboard vector into Register Pair DE ahead of installing it in the KI driver.
53BA
LD HL,(4016H) 2A 16 40
Load Register Pair HL with the current KI keyboard driver vector from 4016H (KIDCB$+1), so it can be preserved.
53BD
LD (53E6H),HL 22 E6 53
Save the current KI driver vector (Register Pair HL) into 53E6H for possible restoration.
53C0
LD (4016H),DE ED 53 16 40
Store the JCL keyboard vector (Register Pair DE, from KIJCL$ 43BEH) into the KI driver vector at 4016H, redirecting keyboard input away from the live JCL stream while SYSGEN runs.
53C4
LD DE,4015H 11 15 40
Point Register Pair DE to 4015H, the KI Device Control Block (KIDCB$).
53C7
XOR A AF
Set Register A to ZERO, the control code that resets the keyboard driver.
53C8
GOSUB to the ROM control-output routine at 0023H to send control code ZERO (Register A) to the KI Device Control Block (Register Pair DE, 4015H), flushing any pending keyboard/type-ahead state.
53CB
POP HL E1
Restore the caller's Register Pair HL from the stack.
53CC
RET C9
Return to the caller (the entry code at 5207H).

53CDH - Helper: Copy Six Bytes into the @EXIT Vector Area

Copies six bytes from the address in Register Pair HL to the @EXIT/@ABORT vector block at 402DH. Used by 53A2H to install the alternate vectors and by 53D6H to restore the originals.

53CD
LD DE,402DH 11 2D 40
Point Register Pair DE to 402DH, the @EXIT vector (the start of the six-byte @EXIT/@ABORT block), the copy destination.
53D0
LD BC,0006H 01 06 00
Load Register Pair BC with 0006H, the number of vector bytes to copy.
53D3
LDIR ED B0
Block-copy: move six bytes from the source at Register Pair HL to the @EXIT area at Register Pair DE (402DH), decrementing Register Pair BC to zero. The source is 4065H (install) or 406BH (restore) depending on the caller.
53D5
RET C9
Return to the caller.

53D6H - Restore Job Control Context

Undoes what 53A2H did. If a JCL/DO file was active on entry (recorded by the self-modified test byte), this restores SFLAG$, swaps the original @EXIT/@ABORT vectors back and re-enables the JCL keyboard path; otherwise it returns immediately.

53D6
LD A,00H 3E 00
Self-Modifying Code
Load Register A with the SFLAG$ value saved at entry. The 00H operand at 53D7H was overwritten at 53A7H with the original SFLAG$ byte.
53D8
BIT 5,A CB 6F
Test bit 5 of Register A (the original not-at-command-level flag). The Z FLAG is set if JCL was not active at entry.
53DA
RET Z C8
If the Z FLAG is set (no JCL was active at entry, nothing was changed), return to the caller immediately.
53DB
LD (430FH),A 32 0F 43
Restore SFLAG$ at 430FH from Register A, re-setting the not-at-command-level flag that 53A2H cleared.
53DE
PUSH HL E5
Save the caller's Register Pair HL on the stack.
53DF
LD HL,406BH 21 6B 40
Point Register Pair HL to 406BH, the saved original six-byte @EXIT/@ABORT vector block, the source for the restore.
53E2
GOSUB to the copy helper at 53CDH to move six bytes from Register Pair HL (406BH) back into the @EXIT area at 402DH, restoring the original exit/abort vectors.
53E5
LD HL,0000H 21 00 00
Point Register Pair HL to 0000H to reset the KI driver vector marker.
53E8
LD (4016H),HL 22 16 40
Store 0000H (Register Pair HL) into the KI driver vector at 4016H, releasing the redirection installed at 53C0H so normal keyboard/JCL handling resumes.
53EB
POP HL E1
Restore the caller's Register Pair HL from the stack.
53EC
RET C9
Return to the caller.

53EDH - Data: CONFIG/SYS Filename and File Control Block

The configuration file specification, whose drive digit at 53FCH is patched at entry. It doubles as the File Control Block passed to @INIT, @OPEN, @CLOSE, @KILL and the byte-output driver. A short unloaded gap follows the string.

53ED-53FC
DEFM "CONFIG/SYS.CCC:0" 43 4F 4E 46 49 47 2F 53 59 53 2E 43 43 43 3A 30
The configuration file specification. The final digit at 53FCH is overwritten at 521EH with the SYSGEN drive number.
53FD
DEFB 00H 00
Terminating NUL for the filename string.
53FE-540C
DEFS 15 (not loaded)
Unloaded gap: these 15 bytes are not part of the load module and receive no data. They provide working space in the File Control Block that @INIT fills in at run time.

540DH - Data: Message Strings

The five carriage-return-terminated (or command-line) strings SYSGEN displays, plus the ATTRIB command line it hands to @CMNDI. Each drive digit is patched to match the target drive.

540D-5425
DEFM "User configuration built" + 0DH 55 73 65 72 20 63 6F 6E 66 69 67 75 72 61 74 69 6F 6E 20 62 75 69 6C 74 0D
Success message for a SYSGEN ON, displayed via @LOGOT at 52DFH.
5426-5446
DEFM "Attrib CONFIG/SYS.CCC:0 (I,P=RE)" + 0DH 41 74 74 72 69 62 20 43 4F 4E 46 49 47 2F 53 59 53 2E 43 43 43 3A 30 20 28 49 2C 50 3D 52 45 29 0D
The command line passed to @CMNDI at 52E8H to make the new file Invisible and Protected. The "CONFIG" at 542DH is reused as the module name; the drive digit at 543CH is patched at 5221H.
5447-5461
DEFM "User configuration deleted" + 0DH 55 73 65 72 20 63 6F 6E 66 69 67 75 72 61 74 69 6F 6E 20 64 65 6C 65 74 65 64 0D
Success message for a SYSGEN OFF, displayed via @LOGOT at 5363H.
5462-547D
DEFM "No user configuration found" + 0DH 4E 6F 20 75 73 65 72 20 63 6F 6E 66 69 67 75 72 61 74 69 6F 6E 20 66 6F 75 6E 64 0D
Displayed when a SYSGEN OFF finds no CONFIG/SYS to delete (reached at 5396H).
547E-54A7
DEFM "Can't -- Valid only at LDOS command level" + 0DH 43 61 6E 27 74 20 2D 2D 20 56 61 6C 69 64 20 6F 6E 6C 79 20 61 74 20 4C 44 4F 53 20 63 6F 6D 6D 61 6E 64 20 6C 65 76 65 6C 0D
Displayed when the environment check refuses the operation (reached at 539AH via the DD-prefix overlap).

54A8H - Data: Configuring Banner

The 38-byte banner written into video RAM (reload address 3F96H) as two type-01 records, so "*** CONFIGURING ***" appears on screen while CONFIG/SYS reloads at boot.

54A8-54BA
DEFM "*** CONFIGURING ***" 2A 2A 2A 20 43 4F 4E 46 49 47 55 52 49 4E 47 20 2A 2A 2A
First 19 bytes of the banner, written by the record at 5254H.
54BB-54CD
DEFM (19 blanks) 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
Trailing 19 blanks of the banner, written by the record at 52B8H.

54CEH - Data: Configuration Save-Region Table

The list walked at 5284H. Each four-byte entry is a byte count (DEFW) followed by a resident address (DEFW); the block at that address is saved into CONFIG/SYS to reload in place. A zero count terminates the table. Together these entries capture HIGH$, the KI/DO/PR and auxiliary DCBs, the @WRITE vector, the task control blocks, the clock/task workspace, the keyboard-task and configuration hooks, the flag bytes, the overlay-dispatcher patch cell, the module-chain head and the SPOOL control block.

54CE
DEFW 0002H, 4049H 02 00 49 40
Save 2 bytes at 4049H (HIGH$, the top-of-user-memory pointer).
54D2
DEFW 0018H, 4015H 18 00 15 40
Save 24 bytes at 4015H (KIDCB$/DODCB$/PRDCB$, the keyboard, display and printer Device Control Blocks).
54D6
DEFW 0003H, 4439H 03 00 39 44
Save 3 bytes at 4439H (the @WRITE SVC vector, which VERIFY may have patched).
54DA
DEFW 0018H, 4500H 18 00 00 45
Save 24 bytes at 4500H (TCB$, the interrupt task control block table for background tasks).
54DE
DEFW 0003H, 4300H 03 00 00 43
Save 3 bytes at 4300H (@KITSK, the keyboard-service task hook).
54E2
DEFW 0003H, 430FH 03 00 0F 43
Save 3 bytes at 430FH (SFLAG$ and the two following flag/state bytes).
54E6
DEFW 0008H, 43B8H 08 00 B8 43
Save 8 bytes at 43B8H (KISV$/DOSV$/PRSV$/KIJCL$, the saved keyboard, display, printer and JCL driver vectors).
54EA
DEFW 0003H, 4315H 03 00 15 43
Save 3 bytes at 4315H (the RST 30H breakpoint re-entry vector armed by DEBUG).
54EE
DEFW 0001H, 441FH 01 00 1F 44
Save 1 byte at 441FH (DFLAG$, the device/spooler flag byte).
54F2
DEFW 0003H, 4303H 03 00 03 43
Save 3 bytes at 4303H (@ICNFG, the interrupt-time configuration hook).
54F6
DEFW 0002H, 4310H 02 00 10 43
Save 2 bytes at 4310H (the resident unrecognised-command / DEBUG re-entry vector).
54FA
DEFW 001AH, 404BH 1A 00 4B 40
Save 26 bytes at 404BH (the clock/interrupt workspace and the task-vector table).
54FE
DEFW 0002H, 4BCFH 02 00 CF 4B
Save 2 bytes at 4BCFH (the self-modified operand cell of the resident RST 28H dispatcher).
5502
DEFW 0003H, 4BDEH 03 00 DE 4B
Save 3 bytes at 4BDEH (the high-memory module-chain head used by the overlay loader).
5506
DEFW 0010H, 4DF0H 10 00 F0 4D
Save 16 bytes at 4DF0H (the resident SPOOL control block).
550A
DEFW 0008H, 43B0H 08 00 B0 43
Save 8 bytes at 43B0H (the device link/route working vectors ahead of the saved-driver block).
550E
DEFW 0001H, 4423H 01 00 23 44
Save 1 byte at 4423H (KFLAG$, the keyboard flag byte, including the CAPS lock state).
5512
DEFW 0040H, 43C0H 40 00 C0 43
Save 64 bytes at 43C0H (JLDCB$ and the auxiliary JL/SI/SO and serial Device Control Blocks, including the RS-232 driver settings).
5516
DEFW 0003H, 45DAH 03 00 DA 45
Save 3 bytes at 45DAH (an interrupt task slot within the TCB$ table).
551A
DEFW 0001H, 46FDH 01 00 FD 46
Save 1 byte at 46FDH (the byte just below the Drive Code Table base).
551E
DEFW 0000H 00 00
Zero count: the table terminator that ends the save loop at 528DH.

5520H - Data: Module Pad

The remaining bytes of the overlay slot are zero fill.

5520-552F
NOP x 16 00 x 16
Zero padding to the end of the overlay image. END 5200H.

Disassembly - Overlay 6 - FREE

FREE is Library B command 22H. With no drive it lists, for every ready drive, a one-line summary matching the DIR header: drive number, disk name and date, geometry (cylinders / density / heads), free and total space in K, and free and total directory entries. With a drivespec (FREE :d) it draws a granule allocation map of that one floppy - six cylinders per line, one character per granule (period unused, X used, asterisk locked out, D directory). The (P) option echoes the output to the printer. The overlay is loaded at 5200H by the resident overlay loader (4BF5H) and entered at its first byte with Register Pair HL pointing at the command tail.

DCT$ Field Reference
All disk geometry is read from the Drive Code Table entry for the selected drive (IY = 4700H + drive x 10, returned by GETDCT 478FH): (IY+03) drive-spec flags (bit 6 double density, bit 5 8-inch, bit 3 rigid/hard, bit 2 fixed); (IY+04) more spec (bit 5 double-sided); (IY+05) current cylinder; (IY+06) highest cylinder number; (IY+07) highest sector / head count; (IY+08) allocation (bits 7-5 granules per track, bits 4-0 sectors per granule); (IY+09) directory cylinder. The GAT sector (directory-cylinder sector 0, read to 4200H) holds one byte per cylinder, a set bit meaning an allocated granule; the disk name and date sit at 42D0H and 42D8H within it. The HIT sector (sector 1) holds one hash byte per directory record, zero meaning a free slot.

5200H - Entry and Command-Tail Parse

The entry stack pointer is saved for the exit, then the command tail at Register Pair HL is scanned. A ":d" drivespec selects single-drive map mode; the option list is parsed by @PARAM (only the P option exists). A colon routes to the granule map, otherwise to the global multi-drive listing.

5200
LD (5504H),SP ED 73 04 55
Self-Modifying Code
Save the entry Stack Pointer into 5504H, the operand of the LD SP,0000H at 5503H in the exit, so the stack can be restored on return.
5204
LD A,(HL) 7E
Fetch the next character of the command tail (addressed by Register Pair HL) into Register A.
5205
CP 0DH FE 0D
Compare Register A (the command-tail character) against 0DH (carriage return, end of line). If equal the Z FLAG is set, meaning no drivespec was given.
5207
If the Z FLAG is set (end of line at Register A), JUMP to 5228H for the global all-drives listing.
5209
INC HL 23
Advance Register Pair HL to the next command-tail character.
520A
CP 20H FE 20
Compare Register A (the character just read) against 20H (a blank). The Z FLAG is set if it was a leading space.
520C
If the Z FLAG is set (a blank), LOOP BACK to 5200H to skip it and read the next character.
520E
CP 3AH FE 3A
Compare Register A against 3AH (a colon ':', which introduces a drivespec). The Z FLAG records whether a drivespec is present.
5210
PUSH AF F5
Save the colon-test flags (Register Pair AF) so the drivespec decision can be made after option parsing.
5211
If the NZ FLAG is set (Register A was not a colon), JUMP to 521BH to skip the drive-digit parse.
5213
LD A,(HL) 7E
Fetch the drive digit that follows the colon (addressed by Register Pair HL) into Register A.
5214
SUB 30H D6 30
SUBtract 30H from Register A to convert the ASCII digit to a binary drive number 0-9.
5216
INC HL 23
Advance Register Pair HL past the drive digit.
5217
INC HL 23
Advance Register Pair HL once more, past the character after the drive digit.
5218
LD (52C6H),A 32 C6 52
Self-Modifying Code
Store the binary drive number (Register A) into 52C6H, the operand of the LD C,0FFH at 52C5H, so the single-drive header routine loads this drive number.
521B
DEC HL 2B
Back Register Pair HL up one character so @PARAM sees the option list from the correct position.
521C
LD DE,559BH 11 9B 55
Point Register Pair DE to 559BH, the local @PARAM keyword table (the single P option).
521F
GOSUB to the resident @PARAM service at 4476H to parse the options in the command tail (Register Pair HL) against the table at Register Pair DE (559BH). On return the Z FLAG is set on success, NZ on a bad parameter.
5222
If the NZ FLAG is set (@PARAM at 4476H reported a bad parameter), JUMP to 54F4H to report the parameter error (code 2CH).
5225
POP AF F1
Restore the colon-test flags (Register Pair AF) saved at 5210H.
5226
If the Z FLAG is set (a colon drivespec was present), JUMP to 524BH for the single-drive granule map. Otherwise fall through to the global listing.

5228H - Global FREE: Loop All Ready Drives

With no drivespec, FREE steps drive numbers 0 through 7, and for each ready drive displays one summary line. The P option prefixes a blank line to the printer.

5228
LD C,00H 0E 00
Load Register C with 00H, the first drive number for the scan.
522A
LD A,(53FCH) 3A FC 53
Fetch the P-option flag from 53FCH into Register A (set non-zero by @PARAM when P was given).
522D
OR A B7
OR Register A with itself to set the flags. The Z FLAG is set if the P option was not requested.
522E
If the Z FLAG is set (no P option in Register A), JUMP to 523AH, skipping the printer priming.
5230
LD A,20H 3E 20
Load Register A with 20H (a blank) to prime the printer line.
5232
GOSUB to the ROM printer routine at 003BH to send the blank (Register A) to the printer.
5235
LD A,0DH 3E 0D
Load Register A with 0DH (carriage return) to end the primed printer line.
5237
GOSUB to the ROM printer routine at 003BH to send the carriage return (Register A) to the printer.
523A
PUSH BC C5
Loop Start
Save the current drive number (Register Pair BC) across the display call.
523B
GOSUB to the resident @CKDRV service at 44B8H to test whether the drive in Register C is present and ready. On return the Z FLAG is set if the drive is ready.
523E
If the Z FLAG is set (the drive in Register C is ready), GOSUB to 52C7H to display that drive's free-space summary line.
5241
POP BC C1
Restore the drive number (Register Pair BC).
5242
INC C 0C
INCrement Register C to the next drive number.
5243
LD A,C 79
Copy the drive number (Register C) into Register A to test the loop limit.
5244
CP 08H FE 08
Compare Register A (the drive number) against 08H, the number of drives. The Z FLAG is set once all eight have been scanned.
5246
If the NZ FLAG is set (drives remain), LOOP BACK to 523AH for the next drive. Loop End
5248
JUMP to the common exit at 5500H; the global listing is complete.

524BH - Single-Drive Granule Map: Validate and Set Up

The FREE :d path validates the drive number and readiness, then clears the screen and prints the drive header before drawing the granule grid.

524B
LD A,(52C6H) 3A C6 52
Fetch the requested drive number from 52C6H (stored at 5218H from the drivespec) into Register A.
524E
LD C,A 4F
Copy the drive number (Register A) into Register C for the readiness check.
524F
CP 08H FE 08
Compare the drive number (Register A) against 08H. If it is 8 or more the NO CARRY FLAG is set, marking an illegal drive.
5251
LD A,20H 3E 20
Load Register A with 20H (32), the "illegal drive number" error code, ready in case the drive is out of range.
5253
If the NO CARRY FLAG is set (the drive number was 8 or more), JUMP to 54F6H to report error 20H (illegal drive number).
5256
GOSUB to the resident @CKDRV service at 44B8H to test whether the drive in Register C is present and ready. On return the Z FLAG is set if ready.
5259
LD A,20H 3E 20
Load Register A with 20H (32), the illegal/not-ready drive error code, in case the drive is not ready.
525B
If the NZ FLAG is set (the drive in Register C is not ready), JUMP to 54F6H to report error 20H.
525E
GOSUB to 53DBH to clear the screen, display the drive's free-space header line and a separator, and blank the line buffer.

5261H - Granule Map: Build and Display the Grid

The map is drawn six cylinders per line. For each cylinder the GAT byte is decoded into one character per granule (X used, period free, asterisk locked out) or the whole cylinder is marked D when it is the directory cylinder. Lines are displayed as they fill, with a cylinder-range label at the left.

5261
LD HL,5553H 21 53 55
Point Register Pair HL to 5553H, the " 0- 5" first cylinder-range label, the copy source.
5264
LD DE,555AH 11 5A 55
Point Register Pair DE to 555AH, the start of the display line buffer, the copy destination.
5267
LD BC,0007H 01 07 00
Load Register Pair BC with 0007H, the length of the cylinder-range label.
526A
LDIR ED B0
Block-copy the 7-byte label from Register Pair HL (5553H) into the line buffer at Register Pair DE (555AH).
526C
LD IX,5564H DD 21 64 55
Point Register Pair IX to 5564H, the position in the line buffer where the first cylinder's granule characters go (just past the label).
5270
LD HL,4200H 21 00 42
Point Register Pair HL to 4200H, the GAT sector buffer, whose byte per cylinder drives the plot.
5273
LD B,06H 06 06
Load Register B with 06H, the six cylinders drawn per line.
5275
LD C,0FFH 0E FF
Load Register C with 0FFH so the first INC C produces cylinder 0.
5277
INC C 0C
Loop Start
INCrement Register C to the current cylinder number.
5278
LD A,C 79
Copy the cylinder number (Register C) into Register A to test for the directory cylinder.
5279
CP (IY+09H) FD BE 09
Compare Register A (the cylinder number) against the directory cylinder (IY+09H). The Z FLAG is set when this cylinder holds the directory.
527C
LD A,00H 3E 00
Self-Modifying Code
Load Register A with the granules-per-cylinder count. The 00H operand at 527DH is patched at 534BH with the computed granules per cylinder.
527E
PUSH AF F5
Save the granule count and the directory-cylinder flag (Register Pair AF).
527F
If the Z FLAG is set (this is the directory cylinder), GOSUB to 54A9H to fill the cylinder's granule positions (Register A count) with 'D'.
5282
POP AF F1
Restore the granule count and directory-cylinder flag (Register Pair AF).
5283
If the NZ FLAG is set (an ordinary cylinder), GOSUB to 5478H to plot its granule characters (Register A count) as X, period or asterisk from the GAT byte at Register Pair HL.
5286
INC HL 23
Advance Register Pair HL to the next cylinder's GAT byte.
5287
LD A,(IY+06H) FD 7E 06
Fetch the highest cylinder number (IY+06H) into Register A to test for the end of the disk.
528A
CP C B9
Compare the highest cylinder (Register A) against the current cylinder (Register C). The Z FLAG is set on the last cylinder.
528B
If the Z FLAG is set (last cylinder reached), JUMP to 52B0H to display the final line and finish.
528D
LD A,(527DH) 3A 7D 52
Fetch the granules-per-cylinder count from 527DH into Register A to compute the column advance.
5290
NEG ED 44
Negate Register A (the granule count) for the spacing subtraction.
5292
ADD A,09H C6 09
Add 09H to Register A, yielding the number of buffer columns to skip so each cylinder field is nine columns wide.
5294
LD D,00H 16 00
Clear Register D so Register Pair DE is the column advance (0 in the high byte).
5296
LD E,A 5F
Copy the column advance (Register A) into Register E, forming the 16-bit offset in Register Pair DE.
5297
ADD IX,DE DD 19
Advance Register Pair IX by Register Pair DE to the next cylinder's column position in the line buffer.
5299
DECrement Register B and LOOP BACK to 5277H until six cylinders have been placed on this line. Loop End
529B
PUSH HL E5
Save the GAT pointer (Register Pair HL) across the line output.
529C
PUSH BC C5
Save the cylinder counter (Register Pair BC).
529D
GOSUB to 53F5H to display the completed map line from the buffer at 555AH (and echo it to the printer if P is active).
52A0
GOSUB to 53E9H to blank the line buffer to spaces for the next row.
52A3
POP BC C1
Restore the cylinder counter (Register Pair BC).
52A4
LD IX,5564H DD 21 64 55
Reset Register Pair IX to 5564H, the first granule column of the fresh line buffer.
52A8
GOSUB to 54B5H to write the next cylinder-range label (for example " 6- 11") at the left of the line buffer.
52AB
POP HL E1
Restore the GAT pointer (Register Pair HL).
52AC
LD B,06H 06 06
Reload Register B with 06H for the next six-cylinder line.
52AE
LOOP BACK to 5277H to build the next line of the map.
52B0
Last cylinder: GOSUB to 53F5H to display the final map line from the buffer.
52B3
LD A,(53C7H) 3A C7 53
Fetch the remaining-lines counter from 53C7H into Register A to decide whether a final pause is needed.
52B6
CP 02H FE 02
Compare the remaining-lines count (Register A) against 02H. If two or more lines remain the NO CARRY FLAG is set and no pause is needed.
52B8
If the NO CARRY FLAG is set (room remains on screen), JUMP to 52BDH, skipping the pause.
52BA
GOSUB to the ROM key-wait routine at 0049H to pause until ENTER is pressed, so the header does not scroll off.
52BD
LD (HL),0DH 36 0D
Store a carriage return (0DH) at Register Pair HL to terminate the display.
52BF
GOSUB to the resident @DSPLY service at 4467H to output the final carriage return.
52C2
JUMP to the common exit at 5500H; the granule map is complete.

52C5H - Free-Space Line: Read the GAT and Count Free Granules

This routine builds one drive's summary line. Entered at 52C5H for the single-drive map header (drive number from the patched operand) or at 52C7H from the global loop (drive already in Register C). It reads the GAT, records the sectors-per-granule figure, and counts the free granules across all cylinders.

52C5
LD C,0FFH 0E FF
Self-Modifying Code
Single-drive header entry: load Register C with the drive number. The 0FFH operand at 52C6H was patched at 5218H with the requested drive.
52C7
LD A,C 79
Global entry: copy the drive number (Register C) into Register A to form its display digit.
52C8
ADD A,30H C6 30
Add 30H to Register A to convert the drive number to its ASCII digit.
52CA
PUSH BC C5
Save the drive number (Register Pair BC) across the line build.
52CB
LD (5519H),A 32 19 55
Self-Modifying Code
Store the drive digit (Register A) into 5519H, the "Drive :d" field of the header template at 5512H.
52CE
GOSUB to the resident GETDCT service at 478FH to point Register Pair IY at the Drive Code Table entry for the drive in Register C.
52D1
LD D,(IY+09H) FD 56 09
Load Register D with the directory cylinder number (IY+09H), the track holding the GAT.
52D4
LD E,00H 1E 00
Load Register E with 00H to select GAT sector 0 of that cylinder.
52D6
LD HL,4200H 21 00 42
Point Register Pair HL to 4200H, the buffer that receives the GAT sector.
52D9
GOSUB to the resident RDSSEC service at 4B45H to read the GAT sector (cylinder Register D, sector Register E) into the buffer at Register Pair HL (4200H). On return the Z FLAG is set on success, NZ on error.
52DC
If the NZ FLAG is set (RDSSEC at 4B45H reported an error), JUMP to 54F6H to report the disk error code in Register A.
52DF
LD A,(IY+08H) FD 7E 08
Fetch the allocation byte (IY+08H) into Register A; bits 4-0 hold the sectors per granule.
52E2
AND 1FH E6 1F
Mask Register A to bits 4-0, isolating the sectors-per-granule value.
52E4
INC A 3C
INCrement Register A so it is the true count of sectors per granule (stored one less on disk).
52E5
LD (540EH),A 32 0E 54
Self-Modifying Code
Store the sectors-per-granule count (Register A) into 540EH, the operand of the LD A,00H at 540DH used by the granules-to-K converter.
52E8
LD D,L 55
Set Register D to 00H (Register L is zero here), clearing the high byte of the free-granule counter.
52E9
LD E,L 5D
Set Register E to 00H, so Register Pair DE begins the free-granule count at zero.
52EA
LD B,(IY+06H) FD 46 06
Load Register B with the highest cylinder number (IY+06H).
52ED
INC B 04
INCrement Register B to the total cylinder count for the scan loop.
52EE
PUSH BC C5
Save the cylinder count (Register Pair BC) for later reuse.
52EF
LD A,(HL) 7E
Loop Start
Fetch this cylinder's GAT byte from Register Pair HL into Register A; a set bit marks an allocated granule.
52F0
SCF 37
Set the Carry flag as a sentinel bit that will be rotated through the GAT byte.
52F1
RRA 1F
Rotate Register A right through Carry: the low granule bit moves into Carry and the sentinel 1 fills the top. Carry set means that granule is allocated.
52F2
If the CARRY FLAG is set (the granule was allocated), JUMP to 52F5H without counting it.
52F4
INC DE 13
The granule was free: INCrement the free-granule counter in Register Pair DE.
52F5
CP 0FFH FE FF
Compare Register A against 0FFH. When the sentinel bits have filled the byte to all ones every granule bit has been examined and the Z FLAG is set.
52F7
If the NZ FLAG is set (granule bits remain in Register A), LOOP BACK to 52F0H to examine the next one. Loop End
52F9
INC L 2C
Advance Register L (Register Pair HL) to the next cylinder's GAT byte.
52FA
DECrement Register B and LOOP BACK to 52EFH until every cylinder's GAT byte has been counted. Loop End

52FCH - Free-Space Line: Free K, Cylinders, Density and Heads

The free-granule count is converted to K and placed in the Free field, then the cylinder count and the density/heads characters of the "cyldh" field are formed from the DCT geometry.

52FC
LD HL,5538H 21 38 55
Point Register Pair HL to 5538H, the free-space field of the header template.
52FF
GOSUB to 5409H to convert the free-granule count (Register Pair DE) to K and write it as "sssss.s" into the field at Register Pair HL (5538H); the tenths digit is returned in Register A.
5302
LD (553EH),A 32 3E 55
Store the free-space tenths digit (Register A) into 553EH, the fractional position of the free field.
5305
POP AF F1
Recover the cylinder count saved at 52EEH: Register A becomes the total cylinder count.
5306
LD L,A 6F
Copy the cylinder count (Register A) into Register L.
5307
LD H,00H 26 00
Clear Register H so Register Pair HL is the 16-bit cylinder count.
5309
PUSH HL E5
Save the cylinder count (Register Pair HL) across the density computation.
530A
LD DE,552DH 11 2D 55
Point Register Pair DE to 552DH, the cylinder-count position of the "cyldh" field.
530D
GOSUB to 5439H to write the cylinder count (Register Pair HL) as a blank-padded decimal into the field at Register Pair DE (552DH).
5310
LD HL,3148H 21 48 31
Load Register Pair HL with 3148H: Register L = 48H ('H', the default density letter) and Register H = 31H ('1', the default head count).
5313
BIT 3,(IY+03H) FD CB 03 5E
Test bit 3 of the drive-spec byte (IY+03H). Set means a rigid (hard) disk; the NZ FLAG selects the hard-disk head-count path.
5317
If the Z FLAG is set (a floppy, IY+03H bit 3 clear), JUMP to 5326H for the floppy density and head handling.
5319
LD A,(IY+07H) FD 7E 07
Hard disk: fetch IY+07H, whose upper bits hold the head count, into Register A.
531C
RLCA 07
Rotate Register A left to move the head-count field toward the low bits (first of three).
531D
RLCA 07
Rotate Register A left again (second of three).
531E
RLCA 07
Rotate Register A left a third time so the head-count bits sit at the bottom.
531F
AND 07H E6 07
Mask Register A to bits 2-0, isolating the head-count value.
5321
ADD A,31H C6 31
Add 31H to Register A to convert the head count to its ASCII digit ('1' upward).
5323
LD H,A 67
Store the head-count digit (Register A) into Register H (the heads character of "cyldh").
5324
JUMP to 5337H to store the completed density/heads pair.
5326
LD L,44H 2E 44
Floppy: set Register L to 44H ('D', the double-density letter) as the starting density character.
5328
BIT 6,(IY+03H) FD CB 03 76
Test bit 6 of the drive-spec byte (IY+03H). Set means double density; the NZ FLAG keeps the 'D'.
532C
If the NZ FLAG is set (double density, IY+03H bit 6 set), JUMP to 5330H, keeping 'D'.
532E
LD L,53H 2E 53
Single density: set Register L to 53H ('S') as the density character.
5330
BIT 5,(IY+04H) FD CB 04 6E
Test bit 5 of the second spec byte (IY+04H). Set means the disk is double-sided (two heads).
5334
If the Z FLAG is set (single-sided, IY+04H bit 5 clear), JUMP to 5337H, leaving the head count at '1'.
5336
INC H 24
Double-sided: INCrement Register H from '1' to '2', the head-count character.
5337
LD (5530H),HL 22 30 55
Self-Modifying Code
Store the density letter (Register L) and head-count digit (Register H) into 5530H, the "dh" positions of the "cyldh" field in the header template.
533A
POP HL E1
Restore the cylinder count (Register Pair HL) saved at 5309H.

533BH - Free-Space Line: Total K and Directory-Entry Counts

Granules per cylinder are computed (and saved for the map), multiplied by the cylinder count to give total granules, and converted to total K. The disk name and date are copied from the GAT into the header, then the HIT sector is read to count free and total directory entries. Finally the assembled line is displayed.

533B
LD A,(IY+08H) FD 7E 08
Fetch the allocation byte (IY+08H) into Register A; bits 7-5 hold the granules per track.
533E
AND 0E0H E6 E0
Mask Register A to bits 7-5, isolating the granules-per-track field.
5340
RLCA 07
Rotate Register A left to shift the granules-per-track field down (first of three).
5341
RLCA 07
Rotate Register A left again (second of three).
5342
RLCA 07
Rotate Register A left a third time so the granules-per-track value sits at the bottom.
5343
INC A 3C
INCrement Register A to the true granules-per-track count (stored one less on disk).
5344
BIT 5,(IY+04H) FD CB 04 6E
Test bit 5 of the second spec byte (IY+04H). Set means double-sided, so the granules per cylinder double.
5348
If the Z FLAG is set (single-sided, IY+04H bit 5 clear), JUMP to 534BH without doubling.
534A
ADD A,A 87
Double-sided: double Register A so it is the granules per cylinder across both heads.
534B
LD (527DH),A 32 7D 52
Self-Modifying Code
Store the granules-per-cylinder count (Register A) into 527DH, the operand of the LD A,00H at 527CH used by the granule-map plot.
534E
PUSH AF F5
Save the granules-per-cylinder count (Register Pair AF) for the sectors-per-cylinder loop.
534F
GOSUB to the resident @MULT service at 44C1H to multiply the cylinder count (Register Pair HL) by the granules per cylinder (Register A), producing the total granule count.
5352
LD D,L 55
Copy the low half of the product (Register L) into Register D toward the total-granule value in Register Pair DE.
5353
LD E,A 5F
Copy the product's remaining byte (Register A) into Register E, forming the total granule count in Register Pair DE.
5354
LD HL,5540H 21 40 55
Point Register Pair HL to 5540H, the total-space field of the header template.
5357
GOSUB to 5409H to convert the total granule count (Register Pair DE) to K and write it into the field at Register Pair HL (5540H); the tenths digit returns in Register A.
535A
LD (5546H),A 32 46 55
Store the total-space tenths digit (Register A) into 5546H, the fractional position of the total field.
535D
POP BC C1
Recover the granules-per-cylinder count into Register B (from the save at 534EH).
535E
LD A,(540EH) 3A 0E 54
Fetch the sectors-per-granule count from 540EH into Register A.
5361
LD C,A 4F
Copy the sectors per granule (Register A) into Register C for the accumulation.
5362
XOR A AF
Set Register A to ZERO to accumulate the sectors per cylinder.
5363
ADD A,C 81
Loop Start
Add the sectors per granule (Register C) to Register A.
5364
DECrement Register B (granules per cylinder) and LOOP BACK to 5363H, so Register A ends as the sectors per cylinder. Loop End
5366
LD HL,0100H 21 00 01
Point Register Pair HL to 0100H, a default directory-scan span used when the disk is small.
5369
SUB 02H D6 02
SUBtract 02H from Register A (the sectors per cylinder), discounting the GAT and HIT sectors to leave the directory-record sectors.
536B
CP 20H FE 20
Compare Register A (the directory-record sector count) against 20H (32). If it is 32 or more the NO CARRY FLAG is set and the default span is kept.
536D
If the NO CARRY FLAG is set (32 or more directory sectors), JUMP to 5378H keeping the 0100H span.
536F
SLA A CB 27
Shift Register A left (multiply by 2): eight directory entries per sector, first of three doublings.
5371
SLA A CB 27
Shift Register A left again (second doubling).
5373
SLA A CB 27
Shift Register A left a third time, so Register A is the directory-entry count (sectors x 8).
5375
LD L,A 6F
Copy the directory-entry count (Register A) into Register L.
5376
LD H,00H 26 00
Clear Register H so Register Pair HL is the 16-bit directory-entry count.
5378
LD (53A3H),HL 22 A3 53
Self-Modifying Code
Store the total directory-entry count (Register Pair HL) into 53A3H, the operand of the LD DE,0000H at 53A2H that seeds the free-entry scan.
537B
LD DE,554FH 11 4F 55
Point Register Pair DE to 554FH, the total-files field of the header template.
537E
GOSUB to 5439H to write the total directory-entry count (Register Pair HL) as a blank-padded decimal into the field at Register Pair DE (554FH).
5381
LD HL,42D0H 21 D0 42
Point Register Pair HL to 42D0H, the disk name within the GAT sector image.
5384
LD DE,551BH 11 1B 55
Point Register Pair DE to 551BH, the packname field of the header template.
5387
LD BC,0008H 01 08 00
Load Register Pair BC with 0008H, the length of the disk name.
538A
LDIR ED B0
Block-copy the 8-byte disk name from Register Pair HL (42D0H) into the header at Register Pair DE (551BH).
538C
INC DE 13
Advance Register Pair DE past the blank between the name and date fields.
538D
LD C,08H 0E 08
Load Register C with 08H, the length of the disk date.
538F
LDIR ED B0
Block-copy the 8-byte disk date from Register Pair HL (42D8H, following the name) into the packdate field at Register Pair DE.
5391
POP BC C1
Restore the drive number (Register Pair BC) saved at 52CAH.
5392
GOSUB to the resident get-directory-track service at 4B65H to position for the drive in Register C ahead of reading the HIT.
5395
LD E,01H 1E 01
Load Register E with 01H to select HIT sector 1 of the directory cylinder.
5397
LD HL,5600H 21 00 56
Point Register Pair HL to 5600H, the buffer that receives the HIT sector.
539A
GOSUB to the resident RDSSEC service at 4B45H to read the HIT sector (sector Register E) into the buffer at Register Pair HL (5600H). On return the Z FLAG is set on success.
539D
LD A,16H 3E 16
Load Register A with 16H (22), the HIT read error code, in case the read failed.
539F
If the NZ FLAG is set (the HIT read failed), JUMP to 54F6H to report error 16H.
53A2
LD DE,0000H 11 00 00
Self-Modifying Code
Load Register Pair DE with the total directory-entry count. The 0000H operand at 53A3H was patched at 5378H so DE is the scan limit / free-entry counter base.
53A5
DEC DE 1B
Loop Start
DECrement Register Pair DE, adjusting the running count as each HIT slot is examined.
53A6
LD A,(42CDH) 3A CD 42
Fetch the GAT configuration byte at 42CDH into Register A; its top bit selects how HIT slots are stepped.
53A9
RLCA 07
Rotate Register A left so the configuration flag moves into the Carry flag.
53AA
If the CARRY FLAG is set (that configuration bit was set), JUMP to 53B1H to test every HIT byte.
53AC
LD A,L 7D
Copy the low byte of the HIT index (Register L) into Register A to test its position.
53AD
AND 0D8H E6 D8
Mask Register A with D8H, isolating the HIT-position bits that mark valid directory slots.
53AF
If the Z FLAG is set (this HIT position is not a countable slot), JUMP to 53B6H to advance without testing.
53B1
LD A,(HL) 7E
Fetch the HIT hash byte addressed by Register Pair HL into Register A; zero means a free directory slot.
53B2
OR A B7
OR Register A with itself to set the flags. The Z FLAG is set if the HIT byte is zero (a free slot).
53B3
If the NZ FLAG is set (the slot is in use), JUMP to 53B6H without counting it.
53B5
INC DE 13
The slot is free: INCrement the free-entry counter in Register Pair DE.
53B6
INC L 2C
Advance Register L (Register Pair HL) to the next HIT byte.
53B7
If the NZ FLAG is set (Register L has not wrapped through all 256 HIT bytes), LOOP BACK to 53A5H. Loop End
53B9
EX DE,HL EB
Move the free-entry count (Register Pair DE) into Register Pair HL for the decimal writer.
53BA
LD DE,554BH 11 4B 55
Point Register Pair DE to 554BH, the free-files field of the header template.
53BD
GOSUB to 5439H to write the free directory-entry count (Register Pair HL) as a blank-padded decimal into the field at Register Pair DE (554BH).
53C0
LD HL,5512H 21 12 55
Point Register Pair HL to 5512H, the start of the completed header line.
53C3
JUMP to 53F8H to display the assembled header line at Register Pair HL (5512H) and return to the caller. This is the byte corrected by the official FREE patch (see the debug note).

Known FREE Patch
The byte at 53C3H is C3H (JP 53F8H) in this image, which is the corrected form. The originally shipped overlay carried CDH (CALL 53F8H) here, which re-entered the pause/printer tail with the header pointer and mis-displayed the line as " :/ ". The official correction is PATCH SYS7/SYS.SYSTEM (D0C,59=C3:F0C,59=CD), changing the CDH CALL to a C3H JP. This copy already has the patch applied.

53C6H - Screen-Pause Helper

Counts displayed lines and, every fifteen lines, pauses for ENTER (unless a JCL/DO file is active) so the header does not scroll away.

53C6
LD A,0FH 3E 0F
Load Register A with 0FH (15), the screen-line reset value (used only when the counter reaches zero below).
53C8
DEC A 3D
DECrement Register A. This entry is reached with the current counter already in Register A on the normal path; here it steps the count down.
53C9
LD (53C7H),A 32 C7 53
Self-Modifying Code
Store the decremented line counter (Register A) back into 53C7H, the counter operand read at 53C6H.
53CC
RET NZ C0
If the NZ FLAG is set (lines remain before a pause), return to the caller without pausing.
53CD
LD A,0FH 3E 0F
The screen is full: load Register A with 0FH (15) to reset the line counter.
53CF
LD (53C7H),A 32 C7 53
Store 15 (Register A) back into the line counter at 53C7H.
53D2
LD A,(430FH) 3A 0F 43
Fetch SFLAG$ from 430FH into Register A. Bit 5 is set when a JCL/DO file is active.
53D5
AND 20H E6 20
Mask Register A to bit 5 (the not-at-command-level flag). The NZ FLAG is set when a JCL/DO file is running.
53D7
RET NZ C0
If the NZ FLAG is set (a JCL/DO file is active), return without pausing, so batch operation is not blocked.
53D8
GOSUB to the ROM key-wait routine at 0049H to pause until ENTER is pressed, then fall into the screen-clear routine below.

53DBH - Clear Screen and Prepare the Line Buffer

Clears the display, prints the drive header line and a row of dashes, then blanks the line buffer to spaces. Also provides the buffer-fill helper used elsewhere.

53DB
GOSUB to the ROM clear-screen routine at 01C9H to erase the display.
53DE
GOSUB to 52C5H to build and display the drive's free-space header line at the top of the cleared screen.
53E1
LD A,2DH 3E 2D
Load Register A with 2DH ('-') to build a separator line of dashes.
53E3
GOSUB to 53EBH to fill the 64-byte line buffer with dashes (Register A).
53E6
GOSUB to 53F5H to display the dash separator line under the header.
53E9
LD A,20H 3E 20
Buffer-clear entry: load Register A with 20H (a blank) to blank the line buffer.
53EB
LD HL,555AH 21 5A 55
Fill entry: point Register Pair HL to 555AH, the start of the display line buffer.
53EE
LD B,40H 06 40
Load Register B with 40H (64), the buffer length.
53F0
LD (HL),A 77
Loop Start
Store the fill character (Register A) into the buffer position addressed by Register Pair HL.
53F1
INC HL 23
Advance Register Pair HL to the next buffer position.
53F2
DECrement Register B and LOOP BACK to 53F0H until all 64 bytes are filled. Loop End
53F4
RET C9
Return to the caller.

53F5H - Display the Line Buffer and Optional Printer Echo

Displays the line buffer through @DSPLY, then either accounts for a screen line (pause check) or, when the P option is active, echoes the line to the printer.

53F5
LD HL,555AH 21 5A 55
Point Register Pair HL to 555AH, the display line buffer to be shown.
53F8
GOSUB to the resident @DSPLY service at 4467H to display the carriage-return-terminated text at Register Pair HL. Entered here directly from 53C3H with Register Pair HL pointing at the header template at 5512H.
53FB
LD DE,0000H 11 00 00
Self-Modifying Code
Load Register Pair DE with the P-option flag. The low operand byte at 53FCH doubles as the P flag set by @PARAM: 00H when P is absent, FFH when present.
53FE
INC E 1C
INCrement Register E. When P is absent (Register E was 00H) this gives 01H (NZ); when P is present (Register E was FFH) it wraps to 00H (Z).
53FF
If the NZ FLAG is set (no P option), JUMP to the screen-pause helper at 53C6H and return; the printer echo is skipped.
5401
P option active: GOSUB to the resident @PRINT service at 446AH to send the line buffer text to the printer.
5404
LD A,0DH 3E 0D
Load Register A with 0DH (carriage return) to end the printer line.
5406
JUMP to the ROM printer routine at 003BH to send the carriage return (Register A) and return to the caller.

5409H - Helper: Convert Granules to K (with Tenths)

Converts a granule count to kilobytes. Each granule is (sectors-per-granule) sectors of 256 bytes, so K = granules x sectors-per-granule / 4. The integer part is written as a decimal field and the tenths digit (0, 2, 5 or 8, from the two low bits) is returned.

5409
LD (541EH),HL 22 1E 54
Save the field pointer (Register Pair HL) into 541EH for the decimal writer's use.
540C
EX DE,HL EB
Move the granule count (Register Pair DE) into Register Pair HL for the multiply.
540D
LD A,00H 3E 00
Self-Modifying Code
Load Register A with the sectors-per-granule count. The 00H operand at 540EH was patched at 52E5H with that value.
540F
GOSUB to the resident @MULT service at 44C1H to multiply the granule count (Register Pair HL) by the sectors per granule (Register A), giving the total sectors.
5412
PUSH AF F5
Save the low byte of the product (Register A) for the tenths calculation.
5413
LD H,L 65
Move the product's low half (Register L) into Register H to begin the divide-by-four.
5414
LD L,A 6F
Move the product's remaining byte (Register A) into Register L, forming the sector count in Register Pair HL.
5415
SRL H CB 3C
Shift Register H right (first of the divide-by-four): each 4 sectors is 1K.
5417
RR L CB 1D
Rotate Register L right through Carry, carrying the shifted bit from Register H.
5419
SRL H CB 3C
Shift Register H right again (second divide step).
541B
RR L CB 1D
Rotate Register L right through Carry, so Register Pair HL is now the K value (sectors divided by 4).
541D
LD DE,0000H 11 00 00
Self-Modifying Code
Load Register Pair DE with the destination field pointer saved at 5409H (the 0000H operand at 541EH holds that address).
5420
GOSUB to 543DH to write the integer K value (Register Pair HL) as a blank-padded decimal into the field at Register Pair DE.
5423
POP AF F1
Recover the product's low byte (Register A) for the tenths digit.
5424
AND 03H E6 03
Mask Register A to its two low bits (the sector remainder after dividing by four).
5426
LD B,A 47
Copy the remainder (Register A) into Register B to select the tenths digit.
5427
LD A,30H 3E 30
Load Register A with 30H ('0'), the tenths digit for remainder 0.
5429
RET Z C8
If the Z FLAG is set (remainder 0), return with '0' as the tenths digit.
542A
DEC B 05
DECrement Register B to test the next remainder value.
542B
LD A,32H 3E 32
Load Register A with 32H ('2'), the tenths digit for remainder 1 (0.25K rounds to .2).
542D
RET Z C8
If the Z FLAG is set (remainder 1), return with '2' as the tenths digit.
542E
DEC B 05
DECrement Register B to test the next remainder value.
542F
LD A,35H 3E 35
Load Register A with 35H ('5'), the tenths digit for remainder 2 (0.5K).
5431
RET Z C8
If the Z FLAG is set (remainder 2), return with '5' as the tenths digit.
5432
LD A,38H 3E 38
Otherwise (remainder 3) load Register A with 38H ('8'), the tenths digit for 0.75K.
5434
RET C9
Return with the tenths digit in Register A.

5435H - Helpers: Right-Justified Decimal Writers

A set of staged entry points that write Register Pair HL as a blank-padded decimal number of one to five digits into the buffer at Register Pair DE, sharing a common per-place digit extractor.

5435
LD A,20H 3E 20
Two-digit entry: load Register A with 20H (a leading blank) and fall into the tens place.
5437
JUMP to 5451H to emit the tens and units digits only.
5439
LD A,20H 3E 20
Three-digit entry: load Register A with 20H (a leading blank) and fall into the hundreds place.
543B
JUMP to 544BH to emit the hundreds, tens and units digits.
543D
LD A,20H 3E 20
Five-digit entry: load Register A with 20H (a leading blank) for the ten-thousands place.
543F
LD BC,2710H 01 10 27
Load Register Pair BC with 2710H (10000), the ten-thousands place value.
5442
GOSUB to 545DH to emit the ten-thousands digit of Register Pair HL, subtracting Register Pair BC.
5445
LD BC,03E8H 01 E8 03
Load Register Pair BC with 03E8H (1000), the thousands place value.
5448
GOSUB to 545DH to emit the thousands digit.
544B
LD BC,0064H 01 64 00
Load Register Pair BC with 0064H (100), the hundreds place value.
544E
GOSUB to 545DH to emit the hundreds digit.
5451
LD BC,000AH 01 0A 00
Load Register Pair BC with 000AH (10), the tens place value.
5454
GOSUB to 545DH to emit the tens digit.
5457
LD A,L 7D
Copy the residual units value (Register L) into Register A.
5458
ADD A,30H C6 30
Add 30H to Register A to convert the units value to its ASCII digit.
545A
LD (DE),A 12
Store the units digit (Register A) into the buffer at Register Pair DE.
545B
INC DE 13
Advance Register Pair DE past the units digit.
545C
RET C9
Return to the caller.

545DH - Helper: One Decimal Digit by Repeated Subtraction

Extracts one decimal digit for the current place value (Register Pair BC) from Register Pair HL, writing it (or a leading blank held in Register A) to the buffer at Register Pair DE. Leading zeros are shown as blanks until the first significant digit.

545D
PUSH DE D5
Save the buffer pointer (Register Pair DE) across the subtraction loop.
545E
LD E,A 5F
Preserve the current leading-blank/pad character (Register A) in Register E.
545F
LD D,0FFH 16 FF
Set Register D to 0FFH so the first INC D makes the digit count start at zero.
5461
XOR A AF
Set Register A to ZERO and clear the Carry flag before the repeated subtraction.
5462
INC D 14
Loop Start
INCrement Register D, counting how many times the place value divides into the number.
5463
SBC HL,BC ED 42
Subtract the place value (Register Pair BC) from the number (Register Pair HL). The Carry flag is set when the number goes negative.
5465
If the NO CARRY FLAG is set (the place value still fits), LOOP BACK to 5462H. Loop End
5467
ADD HL,BC 09
Add the place value (Register Pair BC) back once, correcting the final over-subtraction so Register Pair HL is the remainder.
5468
LD A,E 7B
Recover the pad/blank character (Register E) into Register A.
5469
LD B,D 42
Copy the digit value (Register D) into Register B to test whether it is zero.
546A
POP DE D1
Restore the buffer pointer (Register Pair DE).
546B
LD (DE),A 12
Store the pad character (Register A) into the buffer at Register Pair DE as a placeholder.
546C
INC B 04
INCrement Register B (the digit value) to set the flags for the zero test.
546D
DEC B 05
DECrement Register B back; the Z FLAG is now set if the digit value was zero.
546E
If the Z FLAG is set (a leading zero), JUMP to 5476H leaving the blank pad in place.
5470
LD A,B 78
Copy the digit value (Register B) into Register A.
5471
ADD A,30H C6 30
Add 30H to Register A to convert the digit to its ASCII character.
5473
LD (DE),A 12
Store the digit character (Register A) into the buffer at Register Pair DE, overwriting the pad.
5474
LD A,30H 3E 30
Load Register A with 30H ('0') so all following places print zeros rather than blanks.
5476
INC DE 13
Advance Register Pair DE to the next digit position.
5477
RET C9
Return to the caller with the pad character (Register A) updated for the next place.

5478H - Helper: Plot One Cylinder's Granules

For an ordinary cylinder, writes one character per granule from the GAT byte at Register Pair HL: X for an allocated granule, period for a free one. A second pass over the lock-out map marks locked-out granules with an asterisk on floppies.

5478
PUSH BC C5
Save Register Pair BC (the cylinder counter) across the plot.
5479
PUSH IX DD E5
Save the buffer column pointer (Register Pair IX) for the second pass.
547B
LD B,A 47
Copy the granules-per-cylinder count (Register A) into Register B, the plot loop counter.
547C
PUSH BC C5
Save the granule count (Register Pair BC) for the lock-out pass.
547D
RRC (HL) CB 0E
Loop Start
Rotate the GAT byte at Register Pair HL right circularly, moving the next granule's allocation bit into the Carry flag (and preserving the byte after eight rotations).
547F
LD A,78H 3E 78
Load Register A with 78H ('X'), the used-granule character.
5481
If the CARRY FLAG is set (the granule is allocated), JUMP to 5485H keeping 'X'.
5483
LD A,2EH 3E 2E
The granule is free: load Register A with 2EH ('.'), the unused-granule character.
5485
LD (IX+00H),A DD 77 00
Store the granule character (Register A) into the line buffer at Register Pair IX.
5488
INC IX DD 23
Advance Register Pair IX to the next granule column.
548A
DECrement Register B and LOOP BACK to 547DH until every granule of this cylinder is plotted. Loop End
548C
LD DE,0060H 11 60 00
Load Register Pair DE with 0060H, the offset from the GAT byte to the matching lock-out map byte.
548F
POP BC C1
Restore the granule count (Register Pair BC) for the lock-out pass.
5490
POP IX DD E1
Restore the buffer column pointer (Register Pair IX) to the start of this cylinder's field.
5492
PUSH HL E5
Save the GAT pointer (Register Pair HL) across the lock-out pass.
5493
ADD HL,DE 19
Add the 0060H offset (Register Pair DE) to Register Pair HL, pointing at this cylinder's lock-out map byte.
5494
BIT 3,(IY+03H) FD CB 03 5E
Loop Start
Test bit 3 of the drive-spec byte (IY+03H). Set means a hard disk, which has no floppy lock-out marking.
5498
If the NZ FLAG is set (a hard disk), JUMP to 54A2H, skipping the lock-out mark for this granule.
549A
RRC (HL) CB 0E
Rotate the lock-out map byte at Register Pair HL right circularly, moving the next granule's lock-out bit into the Carry flag.
549C
If the NO CARRY FLAG is set (the granule is not locked out), JUMP to 54A2H, leaving the existing character.
549E
LD (IX+00H),2AH DD 36 00 2A
The granule is locked out: store 2AH ('*') into the line buffer at Register Pair IX.
54A2
INC IX DD 23
Advance Register Pair IX to the next granule column.
54A4
DECrement Register B and LOOP BACK to 5494H until every granule's lock-out status is checked. Loop End
54A6
POP HL E1
Restore the GAT pointer (Register Pair HL).
54A7
POP BC C1
Restore the cylinder counter (Register Pair BC).
54A8
RET C9
Return to the caller.

54A9H - Helper: Plot a Directory Cylinder

Fills the current cylinder's granule positions with 'D' to mark the directory track.

54A9
PUSH BC C5
Save Register Pair BC (the cylinder counter) across the fill.
54AA
LD B,A 47
Copy the granules-per-cylinder count (Register A) into Register B, the fill loop counter.
54AB
LD (IX+00H),44H DD 36 00 44
Loop Start
Store 44H ('D') into the line buffer at Register Pair IX, marking a directory granule.
54AF
INC IX DD 23
Advance Register Pair IX to the next granule column.
54B1
DECrement Register B and LOOP BACK to 54ABH until all granules of the directory cylinder are marked. Loop End
54B3
POP BC C1
Restore the cylinder counter (Register Pair BC).
54B4
RET C9
Return to the caller.

54B5H - Helper: Write the Cylinder-Range Label

Writes the left-margin "start- end" cylinder range for the next map line into the line buffer, advancing the range by the six cylinders per line.

54B5
PUSH DE D5
Save Register Pair DE across the label build.
54B6
PUSH BC C5
Save the cylinder counter (Register Pair BC).
54B7
LD DE,555AH 11 5A 55
Point Register Pair DE to 555AH, the start of the line buffer where the range label goes.
54BA
INC C 0C
INCrement Register C to the first cylinder number of the new line.
54BB
GOSUB to 54D8H to write the start cylinder number (Register C) as a blank-padded decimal into the label at Register Pair DE.
54BE
LD A,(IY+06H) FD 7E 06
Fetch the highest cylinder number (IY+06H) into Register A to bound the range end.
54C1
CP C B9
Compare the highest cylinder (Register A) against the start cylinder (Register C). The Z FLAG is set if the line begins on the last cylinder.
54C2
If the Z FLAG is set (only one cylinder on this line), JUMP to 54D5H, omitting the range end.
54C4
PUSH AF F5
Save the highest-cylinder comparison (Register Pair AF).
54C5
LD A,2DH 3E 2D
Load Register A with 2DH ('-'), the range separator.
54C7
LD (DE),A 12
Store the '-' (Register A) into the label at Register Pair DE.
54C8
POP AF F1
Restore the highest-cylinder comparison (Register Pair AF).
54C9
INC DE 13
Advance Register Pair DE past the separator.
54CA
LD B,05H 06 05
Load Register B with 05H, the number of cylinders to add (to reach the sixth on the line).
54CC
INC C 0C
Loop Start
INCrement Register C toward the end cylinder of this line.
54CD
CP C B9
Compare the highest cylinder (Register A) against the running end (Register C). The Z FLAG is set when the disk's last cylinder is reached early.
54CE
If the Z FLAG is set (the last cylinder ends this line), JUMP to 54D2H to write it.
54D0
DECrement Register B and LOOP BACK to 54CCH until five cylinders have been counted. Loop End
54D2
GOSUB to 54D8H to write the end cylinder number (Register C) as a blank-padded decimal into the label.
54D5
POP BC C1
Restore the cylinder counter (Register Pair BC).
54D6
POP DE D1
Restore Register Pair DE.
54D7
RET C9
Return to the caller.
54D8
LD L,C 69
Copy the cylinder number (Register C) into Register L.
54D9
LD H,00H 26 00
Clear Register H so Register Pair HL is the 16-bit cylinder number.
54DB
PUSH BC C5
Save Register Pair BC across the decimal write.
54DC
GOSUB to 5439H to write the cylinder number (Register Pair HL) as a blank-padded decimal into the label at Register Pair DE.
54DF
POP BC C1
Restore Register Pair BC.
54E0
RET C9
Return to the caller.

54E1H - Helper: Read a Directory-Cylinder Sector

A general read of directory-cylinder sector 0 into 4200H, returning error code 14H on failure. (This helper is present in the overlay for the read used by the summary path.)

54E1
PUSH DE D5
Save Register Pair DE across the read.
54E2
PUSH HL E5
Save Register Pair HL across the read.
54E3
GOSUB to the resident get-directory-track service at 4B65H to position on the directory cylinder.
54E6
LD E,00H 1E 00
Load Register E with 00H to select sector 0 (the GAT).
54E8
LD HL,4200H 21 00 42
Point Register Pair HL to 4200H, the buffer for the sector.
54EB
GOSUB to the resident RDSSEC service at 4B45H to read the sector (Register E) into the buffer at Register Pair HL (4200H). On return the Z FLAG is set on success.
54EE
POP HL E1
Restore Register Pair HL.
54EF
POP DE D1
Restore Register Pair DE.
54F0
RET Z C8
If the Z FLAG is set (the read succeeded), return to the caller.
54F1
LD A,14H 3E 14
The read failed: load Register A with 14H (20), the GAT read error code.
54F3
RET C9
Return to the caller with the error code in Register A and the NZ FLAG set.

54F4H - Errors and Common Exit

The parameter-error and disk-error entries report through @ERROR and set a failure code, then the shared exit restores the stack and returns to the resident dispatcher, or aborts to @ABORT when a JCL/DO file is active.

54F4
LD A,2CH 3E 2C
Parameter-error entry: load Register A with 2CH (44), the "parameter error" code.
54F6
OR 0C0H F6 C0
Disk-error entry: OR Register A (the error code) with C0H to force the sign and mark it fatal for @ERROR.
54F8
GOSUB to the resident @ERROR service at 4409H to display the error text for the code in Register A.
54FB
LD HL,0FFFFH 21 FF FF
Point Register Pair HL to FFFFH, the error return code for the exit test.
54FE
JUMP to 5503H to restore the stack and take the error exit.
5500
LD HL,0000H 21 00 00
Success entry: point Register Pair HL to 0000H, the success return code.
5503
LD SP,0000H 31 00 00
Self-Modifying Code
Restore the entry Stack Pointer. The 0000H operand at 5504H was overwritten at entry (5200H) with the saved SP.
5506
LD A,H 7C
Copy the high byte of the return code (Register H) into Register A for the exit test.
5507
OR L B5
OR with the low byte (Register L). The Z FLAG is set only if the return code in Register Pair HL is zero (success).
5508
RET Z C8
If the Z FLAG is set (success), return to the resident RST 28H dispatcher.
5509
LD A,(430FH) 3A 0F 43
Fetch SFLAG$ from 430FH into Register A. Bit 5 is set when a JCL/DO file is active.
550C
BIT 5,A CB 6F
Test bit 5 of Register A (the not-at-command-level flag). The Z FLAG is set at command level, cleared (NZ) under a JCL/DO file.
550E
RET Z C8
If the Z FLAG is set (at LDOS command level), return to the resident RST 28H dispatcher.
550F
Otherwise (a JCL/DO file is active) JUMP to the resident @ABORT service at 4030H to terminate the batch stream.

5512H - Data: Header Template and Cylinder Label

The summary/header line template, whose fields are filled in place by the code above, followed by the first cylinder-range label copied into the line buffer.

5512-5552
DEFM "Drive :d packname packdate cyldh Free=sssss.s/sssss.s Fi=nnn/nnn" + 03H 44 72 69 76 65 20 3A 64 20 70 61 63 6B 6E 61 6D 65 20 70 61 63 6B 64 61 74 65 20 63 79 6C 64 68 20 46 72 65 65 3D 73 73 73 73 73 2E 73 2F 73 73 73 73 73 2E 73 20 46 69 3D 6E 6E 6E 2F 6E 6E 6E 03
The drive summary line. Fields patched in place: drive digit at 5519H; packname at 551BH and packdate at 5524H (from the GAT); "cyldh" cylinder count at 552DH and density/heads at 5530H; free K at 5538H (tenths at 553EH); total K at 5540H (tenths at 5546H); free files at 554BH and total files at 554FH.
5553-5559
DEFM " 0- 5" 20 20 30 2D 20 20 35
The first cylinder-range label, copied into the line buffer at 526AH for the granule map's opening line.

555AH - Data: Display Line Buffer (unloaded)

The 64-byte working buffer where each output line (summary or map row) is assembled. It carries no data in the load module.

555A-5599
DEFS 64 (not loaded)
Unloaded 64-byte line buffer, cleared to spaces at run time and filled by the display and plot routines before each @DSPLY.

559AH - Data: @PARAM Option Table and Pad

The keyword descriptor table passed to @PARAM, defining the single P option.

559A
DEFB 03H 03
Leading control byte preceding the @PARAM table.
559B-55A2
DEFM "P " + DEFW 53FCH 50 20 20 20 20 20 FC 53
The @PARAM keyword entry: the six-character keyword "P" (blank-padded) followed by the address 53FCH of its flag cell, which is set non-zero when P is given. That cell doubles as the low operand byte of the LD DE,0000H at 53FBH that gates the printer echo.
55A3
DEFB 00H 00
Table terminator and module pad. END 5200H.

Overlay 7 - SYSTEM

The SYSTEM library command selects DOS features and configures the user-definable areas of the operating system. It is the largest overlay in SYS7/SYS (3303 bytes, 5200H-5EE6H). On entry from the resident overlay loader (4BF5H) HL points to the command line just past the command name, and register B held the command number (A1H) the loader used to select this overlay. The command line is expected in the form SYSTEM (parm,parm,...); a single call to the resident @PARAM service (4476H) parses every keyword against the descriptor table at 5DF6H, depositing each supplied value into a two-byte cell that is the operand of a LD BC,nnnn test instruction further down. Each sub-command handler then examines its cell and acts. This section documents the first 35% of the overlay, the group of "flag / task / clock" sub-commands, ending at the RET of the ALIVE task template at 5591H, immediately before the SVC handler at 5592H.

SYSTEM (Command A1H) - Parameter Value Cells (@PARAM table 5DF6H)

Each cell below is the two-byte operand of a LD BC,nnnn instruction. @PARAM (4476H) overwrites the cell with the value the user supplied for that keyword; if the keyword is absent the assembled default remains. The handlers read a cell into BC, form A = B OR C, then DEC A: an assembled default of 0001H means "not specified" (skip), 0000H means the OFF form, and any other value (FFFFH for a bare switch, or a number) means the ON form. Only the cells used by this first-35% section are listed.

AddressKeyword / Purpose
520EH
2 bytes
SLOW value cell (operand of LD BC,nnnn at 520DH). Non-zero selects the SLOW clock (OUT to port 0FEH with bit 0 = 0). Self-Modifying Code.
5215H
2 bytes
FAST value cell (operand at 5214H). Non-zero selects the FAST clock (OUT to port 0FEH with bit 0 = 1). Self-Modifying Code.
5237H
2 bytes
BASIC2 value cell (operand at 5236H). Non-zero returns the machine to ROM BASIC. Self-Modifying Code.
5257H
2 bytes
PRTIME value cell (operand at 5256H, default 0001H). Enables/disables the printer time-out flag in the PR/FLT filter. Self-Modifying Code.
5277H
2 bytes
BREAK value cell (operand at 5276H, default 0001H). Enables/disables the BREAK key. Self-Modifying Code.
5290H
2 bytes
UPDATE value cell (operand at 528FH, default 0001H). Installs/removes the midnight date-rollover task. Self-Modifying Code.
5370H
2 bytes
DATE value cell (operand at 536FH, default 0001H). Enables/disables the power-up date prompt. Self-Modifying Code.
5387H
2 bytes
TIME value cell (operand at 5386H, default 0001H). Enables/disables the power-up time prompt. Self-Modifying Code.
539EH
2 bytes
TRACE value cell (operand at 539DH, default 0001H). Installs/removes the Program-Counter trace display task. Self-Modifying Code.
53B5H
2 bytes
BSTEP value cell (operand at 53B4H, default FFFFH). Sets the default bootstrap step rate (0-3) in the drive-0 system-information sector. Self-Modifying Code.
53DEH
2 bytes
BLINK value cell (operand at 53DDH, default 0001H). Installs/removes the blinking-cursor task; the low byte also carries an explicit cursor character. Self-Modifying Code.
5467H
2 bytes
LARGE value cell (read at 540FH). When set, the blinking cursor uses character 8FH (143). Self-Modifying Code.
541AH
2 bytes
SMALL value cell (operand at 5419H). When set, the blinking cursor uses character 88H (136). Self-Modifying Code.
54B5H
2 bytes
TYPE value cell (operand at 54B4H, default 0001H). Enables/disables keyboard type-ahead. Self-Modifying Code.
54F2H
2 bytes
SMOOTH value cell (operand at 54F1H, default 0001H). Alters the floppy driver for 300-rpm-aligned drives. Self-Modifying Code.
5504H
2 bytes
GRAPHIC value cell (operand at 5503H). Enables direct graphics reproduction during a screen print. Self-Modifying Code.
5518H
2 bytes
ALIVE value cell (operand at 5517H, default 0001H). Installs/removes the "alive" alternating-character task. Self-Modifying Code.

SYSTEM (Command A1H) - Shared Helper Routines (later in the overlay)

The handlers in this section call four shared helpers that live in the last third of the overlay (beyond this first 35%). Their behaviour is summarised here so the calls can be read in context.

AddressName / Purpose
5A61HRead System-Information Sector
Point HL to the 4200H buffer, set C = 0 (drive 0) and DE = 0002H, and call RDSECT (4777H) to read the drive-0 system-information sector (which holds the DATE/TIME power-up prompt flags and the bootstrap step rate) into 4200H. Returns with Z set on success.
5A6EHWrite System-Information Sector
Point HL to 4200H, C = 0, DE = 0002H, and call WRSECT (4763H) to write the 4200H buffer back to the drive-0 system-information sector. On a write error it drops into the @ERROR path.
5AE7HLocate Resident Module Control Block
Issue RST 28H request code BCH (5AF4H) with DE pointing at a module name; on return IX addresses the module's control block and DE = the module's saved-HIGH$ word (IX+02H/03H). Used to test whether a high-memory task module ($UP, $BL, $AL, ...) is already resident.
5AF7HHigh-Memory Allocation Guard
Test whether it is safe to reserve high memory now: if a resident program is attached (@EXIT at 402D or the register-A slot 4065H holds C3H) and the SYS1 status byte 4758H bit 1 (busy) is set, it reports the condition so the caller can refuse. Returns with the caller's original A preserved on the stack path.
5A7AH@PARAM Error Exit
Reached by JP NZ,5A7AH at 520AH when @PARAM reports a bad keyword; OR 0C0H forms the error code, calls @ERROR (4409H), then aborts.

5200H - Entry and @PARAM Parse

Save the caller's stack pointer, point @PARAM at the keyword descriptor table, and parse the whole parameter list in one call. A parse error aborts through the @PARAM error exit; otherwise every value cell has been loaded and control falls into the first sub-command test.

5200
LD (5A53H),SP ED 73 53 5A
Self-Modifying Code
Save the caller's stack pointer into 5A53H, which is the operand of the LD SP,nnnn instruction at 5A52H in the shared exit tail. This lets SYSTEM restore the caller's stack when it returns to the RST 28H dispatcher.
5204
LD DE,5DF6H 11 F6 5D
Point DE at 5DF6H, the @PARAM keyword descriptor table for SYSTEM (each 8-byte entry is a 6-character keyword followed by the two-byte address of that keyword's value cell).
5207
GOSUB to the resident SYS0 service @PARAM (4476H) to scan the command line (HL) against the table (DE), depositing each supplied value into its cell. Returns NZ if a keyword is invalid.
520A
If the NZ FLAG is set (@PARAM found a bad keyword), JUMP to the @PARAM error exit at 5A7AH to report the error and abort.

520DH - SLOW and FAST (Clock Speed, Port 0FEH)

The SLOW and FAST sub-commands switch a port-254 (0FEH) clock speed-up modification and track the state in SFLAG$ bit 3. Per the manual, FAST issues OUT 254,1 and SLOW issues OUT 254,0. A resident shadow of the control byte is kept at 4427H so the current bit pattern is preserved across the change.

520D
LD BC,0000H 01 00 00
Self-Modifying Code
Load BC from the SLOW value cell at 520EH. @PARAM set this non-zero if the user typed SLOW; the assembled default 0000H means SLOW was not requested.
5210
LD A,B 78
Copy the high byte of the SLOW cell (BC) into Register A to begin testing whether SLOW was requested.
5211
OR C B1
OR Register A (SLOW cell high byte) with C (SLOW cell low byte). If the SLOW cell is non-zero the NZ FLAG is set.
5212
If the NZ FLAG is set (SLOW was requested), JUMP to 5227H to select the slow clock. Otherwise fall through to test FAST.
5214
LD BC,0000H 01 00 00
Self-Modifying Code
Load BC from the FAST value cell at 5215H. @PARAM set this non-zero if the user typed FAST; the default 0000H means FAST was not requested.
5217
LD A,B 78
Copy the high byte of the FAST cell (BC) into Register A to test whether FAST was requested.
5218
OR C B1
OR Register A (FAST cell high byte) with C (FAST cell low byte). If the FAST cell is zero the Z FLAG is set.
5219
If the Z FLAG is set (neither SLOW nor FAST was requested), JUMP to 5236H to test the next sub-command. Otherwise fall through to select the fast clock.
521B
LD HL,430FH 21 0F 43
Point HL at the resident system flag byte SFLAG$ (430FH) so its clock-speed bit can be set.
521E
SET 3,(HL) CB DE
Set bit 3 of SFLAG$ (430FH) to record that the FAST (4 MHz) clock is now selected.
5220
LD A,(4427H) 3A 27 44
Fetch the resident shadow of the port-0FEH control byte from 4427H into Register A so the existing bits are preserved when the speed bit is changed.
5223
OR 01H F6 01
Set bit 0 of Register A (the control byte) to 1, the value FAST sends to port 0FEH.
5225
JUMP to 5231H to store the updated control byte and drive the port.
5227
LD HL,430FH 21 0F 43
Point HL at SFLAG$ (430FH) so its clock-speed bit can be cleared for the SLOW path.
522A
RES 3,(HL) CB 9E
Clear bit 3 of SFLAG$ (430FH) to record that the SLOW clock is now selected.
522C
LD A,(4427H) 3A 27 44
Fetch the resident shadow of the port-0FEH control byte from 4427H into Register A to preserve the other bits.
522F
AND 0FEH E6 FE
Clear bit 0 of Register A (the control byte) to 0, the value SLOW sends to port 0FEH.
5231
LD (4427H),A 32 27 44
Store the updated control byte (Register A) back into the resident shadow at 4427H so future changes start from the current value.
5234
OUT (0FEH),A D3 FE
Output the control byte (Register A) to port 0FEH (254) to switch the hardware clock speed: bit 0 = 1 for FAST, bit 0 = 0 for SLOW.

5236H - BASIC2 (Return to ROM BASIC)

BASIC2 abandons DOS and re-enters ROM BASIC exactly as if the reset button were pressed with BREAK held down. It builds a tiny reset stub in low RAM, clears the DOS communications region, and jumps into the ROM. None of the disk functions are available afterward and there is no return to DOS.

5236
LD BC,0000H 01 00 00
Self-Modifying Code
Load BC from the BASIC2 value cell at 5237H. @PARAM set this non-zero if the user typed BASIC2; the default 0000H means it was not requested.
5239
LD A,B 78
Copy the high byte of the BASIC2 cell (BC) into Register A to test whether BASIC2 was requested.
523A
OR C B1
OR Register A (BASIC2 cell high byte) with C (its low byte). If the cell is zero the Z FLAG is set.
523B
If the Z FLAG is set (BASIC2 not requested), JUMP to 5256H to test PRTIME. Otherwise fall through to re-enter ROM BASIC.
523D
DI F3
Disable interrupts so the DOS interrupt task chain is silenced while the reset stub is built and executed.
523E
LD SP,407DH 31 7D 40
Point SP at 407DH, a safe stack near the top of the DOS communications region, since the DOS stack is about to be discarded.
5241
LD HL,06D2H 21 D2 06
Point HL at ROM address 06D2H, the source of a 36-byte reset stub that will be copied into low RAM.
5244
LD DE,4000H 11 00 40
Point DE at 4000H, the destination for the reset stub (the base of the DOS communications region / RST 28H vector area).
5247
LD BC,0036H 01 36 00
Set BC = 0036H (54 bytes) as the block-move count for the reset stub.
524A
LDIR ED B0
Block-move the reset stub: source HL (ROM 06D2H), destination DE (4000H), count BC (0036H). This overwrites the DOS RST vectors at 4000H with the ROM power-up equivalents so that a warm restart behaves like a cold ROM entry.
524C
XOR A AF
Set Register A to ZERO, the fill byte for clearing the region just past the reset stub.
524D
LD B,27H 06 27
Set B = 27H (39) as the DJNZ counter for the clear loop; DE currently points just past the copied stub.
524F
LD (DE),A 12
Loop Start
Store 00H (Register A) at the address in DE, zeroing one byte of the communications region.
5250
INC DE 13
Advance the destination pointer DE to the next byte to clear.
5251
DECrement B and LOOP BACK to 524FH until 39 bytes have been zeroed. Loop End
5253
JUMP into the ROM at 0075H to complete the return to ROM BASIC. Control never comes back to DOS; the machine behaves as if reset with BREAK held.

5256H - PRTIME (Printer Time-out)

PRTIME enables or disables the printer time-out inside the PR/FLT printer filter. The overlay locates the filter through its resident pointer at 4DF6H, follows the pointer at filter offset 19H to the filter's time-out byte, and writes 1BH (enabled) or 00H (disabled). If the filter is not installed the request is refused.

5256
LD BC,0001H 01 01 00
Self-Modifying Code
Load BC from the PRTIME value cell at 5257H. @PARAM overwrites it with 0000H for OFF or a non-zero value for ON; the assembled default 0001H means PRTIME was not specified.
5259
LD A,C 79
Copy the low byte of the PRTIME cell (C) into Register A to test the "not specified" default.
525A
DEC A 3D
DECrement Register A. If the cell held the default 0001H, A becomes 0.
525B
OR B B0
OR Register A with B (the cell high byte). The Z FLAG is set only when the cell was exactly 0001H (PRTIME not specified).
525C
If the Z FLAG is set (PRTIME not specified), JUMP to 5276H to test BREAK. Otherwise fall through to adjust the filter.
525E
LD HL,(4DF6H) 2A F6 4D
Load HL from 4DF6H, the resident pointer to the PR/FLT printer filter's control block. HL becomes the filter base (or 0000H if the filter is not installed).
5261
LD A,H 7C
Copy the high byte of the filter pointer (H) into Register A to test whether the filter is present.
5262
OR L B5
OR Register A (pointer high byte) with L (pointer low byte). If the filter pointer is 0000H the Z FLAG is set.
5263
If the Z FLAG is set (no PR/FLT filter installed), JUMP to the "not resident" error handler at 5B11H. Otherwise the filter base is in HL.
5266
EX DE,HL EB
Move the filter base into DE so an offset can be added to reach the time-out byte.
5267
LD HL,0019H 21 19 00
Set HL = 0019H, the offset within the filter control block of the pointer to the time-out flag.
526A
ADD HL,DE 19
Add the filter base (DE) to the offset (HL) so HL addresses filter+19H.
526B
LD L,(HL) 6E
Load the low byte stored at filter+19H into L; this is the low half of the address of the filter's time-out byte.
526C
LD H,00H 26 00
Clear H to 0 so HL now holds only that low byte as an offset.
526E
ADD HL,DE 19
Add the filter base (DE) again so HL addresses the filter's time-out flag byte.
526F
LD A,B 78
Copy the high byte of the PRTIME cell (B) into Register A to decide ON versus OFF.
5270
OR C B1
OR Register A with C (the cell low byte). If the PRTIME cell was 0000H (OFF) the Z FLAG is set.
5271
If the Z FLAG is set (PRTIME=OFF), JUMP to 5275H leaving Register A = 00H to disable the time-out. Otherwise fall through to enable it.
5273
LD A,1BH 3E 1B
Load Register A with 1BH, the enabled value written to the filter's time-out byte (establishing the approximate 10-second printer time-out).
5275
LD (HL),A 77
Store Register A (1BH for ON, 00H for OFF) into the filter's time-out flag byte addressed by HL, applying the PRTIME setting.

5276H - BREAK (Enable/Disable the BREAK Key)

BREAK enables or disables the BREAK key. The state is tracked in SFLAG$ bit 4, and the resident BREAK-check vector byte at 4BF0H is set to 0C8H (RET Z, meaning "check BREAK") when enabled. Because the value cell default is 0001H, an omitted BREAK keyword leaves the key unchanged.

5276
LD BC,0001H 01 01 00
Self-Modifying Code
Load BC from the BREAK value cell at 5277H. @PARAM overwrites it with 0000H for OFF or non-zero for ON; the default 0001H means BREAK was not specified.
5279
LD A,B 78
Copy the high byte of the BREAK cell (B) into Register A to begin the ON/OFF/unspecified test.
527A
OR C B1
OR Register A with C (the cell low byte) to form A = combined value of the BREAK cell.
527B
LD HL,430FH 21 0F 43
Point HL at SFLAG$ (430FH) so the BREAK-enable bit can be set or cleared. This does not disturb the flags set by OR C.
527E
If the Z FLAG is set (the BREAK cell was 0000H, i.e. BREAK=OFF), JUMP to 5288H to disable the key. Otherwise fall through to distinguish the "not specified" default from BREAK=ON.
5280
INC A 3C
INCrement Register A. When the cell held the default 0001H, A was 1; this makes A = 2 (NZ). When the cell held FFFFH (ON), A was FFH and becomes 00H (Z).
5281
If the NZ FLAG is set (the BREAK cell was the 0001H "not specified" default), JUMP to 528FH to test UPDATE, leaving BREAK unchanged. Otherwise the cell was FFFFH (BREAK=ON).
5283
RES 4,(HL) CB A6
Clear bit 4 of SFLAG$ (430FH). With the enable path taking bit 4 the opposite way, this branch (BREAK=ON) clears the "BREAK disabled" flag so the key is active.
5285
XOR A AF
Set Register A to ZERO; the value written to the BREAK-check vector byte for the enabled case is completed at 528CH.
5286
JUMP to 528CH to store the BREAK-check vector byte.
5288
SET 4,(HL) CB E6
Set bit 4 of SFLAG$ (430FH) to mark the BREAK key as disabled (this path handles BREAK=OFF).
528A
LD A,0C8H 3E C8
Load Register A with 0C8H (the opcode RET Z), the value written to the resident BREAK-check vector byte so the BREAK test returns appropriately.
528C
LD (4BF0H),A 32 F0 4B
Store Register A into the resident BREAK-check vector byte at 4BF0H (0C8H = RET Z for enabled handling, 00H = NOP otherwise), applying the BREAK setting to the keyboard driver's break test.

528FH - UPDATE (Install/Remove the Midnight Date Task)

UPDATE=ON installs a background routine that advances the system date when the real-time clock passes midnight; UPDATE=OFF removes it. The routine is a relocatable module (name "$UP") copied into high memory below HIGH$ (4049H) and armed by writing "JP module" into the resident clock hook at 45DAH. Removal writes RET (C9H) back to 45DAH and, when the module is the topmost high-memory allocation, restores HIGH$. This facility exists on the Model I only.

528F
LD BC,0001H 01 01 00
Self-Modifying Code
Load BC from the UPDATE value cell at 5290H. @PARAM overwrites it with 0000H (OFF) or FFFFH (ON); the default 0001H means UPDATE was not specified.
5292
LD A,B 78
Copy the high byte of the UPDATE cell (B) into Register A to begin the ON/OFF/unspecified test.
5293
OR C B1
OR Register A with C (the cell low byte) so A = combined value of the UPDATE cell.
5294
DEC A 3D
DECrement Register A. If the cell held the 0001H default, A becomes 0.
5295
If the Z FLAG is set (UPDATE not specified), JUMP to the DATE handler at 536FH, leaving the date task unchanged.
5298
INC A 3C
INCrement Register A to restore the combined UPDATE value.
5299
If the NZ FLAG is set (UPDATE=ON, cell FFFFH), JUMP to 52B8H to install the task. Otherwise (cell 0000H, UPDATE=OFF) fall through to remove it.
529B
LD DE,52F8H 11 F8 52
Point DE at the module name string "$UP" at 52F8H so the resident module control block can be located.
529E
GOSUB to the module-lookup helper 5AE7H (RST 28H code BCH) to find the resident "$UP" module. On return HL addresses its control block and DE holds the saved-HIGH$ ceiling to restore; NZ means the module was not found.
52A1
If the NZ FLAG is set (the UPDATE module is not resident), JUMP to 52B0H to just disable the hook. Otherwise reclaim its memory if possible.
52A3
LD BC,(4049H) ED 4B 49 40
Load BC from HIGH$ (4049H), the current top of unprotected memory, to test whether the module sits immediately above it.
52A7
INC BC 03
Advance BC to HIGH$+1, the base address a module allocated just below HIGH$ would occupy.
52A8
SBC HL,BC ED 42
Subtract HIGH$+1 (BC) from the module control-block address (HL). A zero result means the "$UP" module is the topmost high-memory allocation and its space can be reclaimed.
52AA
If the NZ FLAG is set (the module is not the topmost allocation), JUMP to 52B0H to disable the hook without moving HIGH$. Otherwise reclaim the memory.
52AC
LD (4049H),DE ED 53 49 40
Store the saved ceiling (DE, returned by 5AE7H) into HIGH$ (4049H), returning the reclaimed high memory to the free pool.
52B0
LD A,0C9H 3E C9
Load Register A with 0C9H (the opcode RET) to disarm the clock hook.
52B2
LD (45DAH),A 32 DA 45
Store RET (0C9H) into the resident clock hook at 45DAH so the midnight update routine is no longer called.
52B5
JUMP to the DATE handler at 536FH to continue processing sub-commands.
52B8
LD DE,52F8H 11 F8 52
Point DE at the module name "$UP" (52F8H) to test whether the UPDATE module is already resident before allocating.
52BB
GOSUB to the module-lookup helper 5AE7H to find an existing "$UP" module. Z on return means it is already resident.
52BE
EX DE,HL EB
Exchange DE and HL so the lookup's status is preserved while positioning for the re-arm path.
52BF
If the Z FLAG is set (the module is already resident), JUMP to 52ECH to simply re-arm the hook. Otherwise allocate and copy the module.
52C1
LD BC,0073H 01 73 00
Set BC = 0073H (115 bytes), the size of the "$UP" module to reserve and copy.
52C4
LD HL,5364H 21 64 53
Point HL at 5364H, the February entry in the module's days-per-month table, so it can be adjusted for a leap year before copying.
52C7
LD A,(4048H) 3A 48 40
Fetch the DATE$ flags byte from 4048H into Register A; bit 7 is the leap-year flag.
52CA
RLCA 07
Rotate Register A left so the leap-year flag (bit 7) moves into the CARRY FLAG.
52CB
If the NO CARRY FLAG is set (not a leap year), JUMP to 52CEH leaving February at 28. Otherwise bump it.
52CD
INC (HL) 34
Increment the February table entry (5364H) from 28 to 29 for the leap year.
52CE
LD HL,(4049H) 2A 49 40
Load HL from HIGH$ (4049H), the current top of unprotected memory, as the basis for reserving the module's space.
52D1
LD (52FEH),HL 22 FE 52
Self-Modifying Code
Store the current HIGH$ (HL) into the module template's saved-ceiling field at 52FEH, so a later UPDATE=OFF knows how much memory to release.
52D4
XOR A AF
Set Register A to ZERO, which also clears the CARRY FLAG for the following subtraction.
52D5
SBC HL,BC ED 42
Subtract the module size (BC = 0073H) from HIGH$ (HL) to compute the new, lower ceiling below the reserved block.
52D7
LD (4049H),HL 22 49 40
Store the new ceiling into HIGH$ (4049H), protecting the reserved high memory from the rest of the system.
52DA
INC HL 23
Advance HL to HIGH$+1, the base address of the reserved block where the module will be copied.
52DB
PUSH HL E5
Save the module base address on the stack for reuse.
52DC
LD DE,0067H 11 67 00
Set DE = 0067H, the offset from the module base to the relocated days-per-month table (which sits at template offset 67H).
52DF
ADD HL,DE 19
Add the offset (DE) to the module base (HL) so HL = the relocated address the day-table will occupy in high memory.
52E0
LD (5329H),HL 22 29 53
Self-Modifying Code
Patch the template's LD HL,5363H operand at 5329H with the relocated day-table address (HL), so the copied routine points at the table in its new high-memory location.
52E3
POP HL E1
Restore the module base address into HL.
52E4
PUSH HL E5
Save the module base again for use after the copy.
52E5
EX DE,HL EB
Move the module base into DE, the LDIR destination.
52E6
LD HL,52FCH 21 FC 52
Point HL at 52FCH, the start of the module template, the LDIR source.
52E9
LDIR ED B0
Block-move the module: source HL (52FCH), destination DE (high-memory base), count BC (0073H). This copies the "$UP" module and its date routine into the reserved high memory.
52EB
POP HL E1
Restore the module base (relocated routine entry) into HL to arm the hook.
52EC
DI F3
Disable interrupts while the clock hook is rewritten so the tick handler cannot fire mid-update.
52ED
LD (45DBH),HL 22 DB 45
Store the relocated routine entry (HL) into 45DBH, the address operand of the JP at 45DAH.
52F0
LD A,0C3H 3E C3
Load Register A with 0C3H, the opcode JP, to arm the hook.
52F2
LD (45DAH),A 32 DA 45
Store JP (0C3H) into 45DAH so the resident clock tick now jumps to the relocated midnight-update routine each interrupt.
52F5
EI FB
Re-enable interrupts now that the hook is armed.
52F6
JUMP to the DATE handler at 536FH to continue processing sub-commands.

52F8H - UPDATE Module Template ("$UP", Relocated to High Memory)

This block is copied verbatim into high memory by the UPDATE=ON path above and executed there as the midnight date-advance task, called through the resident clock hook at 45DAH. The addresses shown are the assembled (pre-relocation) addresses. On entry HL points into the DATE$ workspace (4044H-4048H = year, day, month, day-of-year word, flags) set up by the resident real-time-clock task. The only internal address that is relocated is the days-per-month table pointer at 5329H (patched at 52E0H); the DATE$ references stay absolute.

52F8-52FB
DEFM "$UP",00H 24 55 50 00
Module name string "$UP", passed in DE to the 5AE7H lookup helper to find or free this module. Data, not executed.
52FC
Module entry: jump over the module header (saved-ceiling word, name length, and name) to the routine body at 5304H.
52FE-52FF
DEFW 0000H 00 00
Self-Modifying Code
Saved-HIGH$ ceiling field, written at 52D1H with the HIGH$ value that existed before this module was reserved, so UPDATE=OFF can restore it. Data.
5300
DEFB 03H 03
Module name length (3 characters). Data.
5301-5303
DEFM "$UP" 24 55 50
Module name as stored in the high-memory module chain (shown by the DEVICE/MEMORY commands). Data.
5304
INC L 2C
Advance the DATE$ pointer (HL) to the day-of-year low byte to begin the midnight advance.
5305
INC (HL) 34
Increment the day-of-year low byte addressed by HL (one more day has elapsed).
5306
INC L 2C
Advance HL to the following DATE$ byte.
5307
LD A,(HL) 7E
Read that DATE$ byte (the month index) into Register A.
5308
DEC L 2D
Step HL back to the day field.
5309
DEC A 3D
Decrement Register A to form a zero-based month index for the days-per-month table.
530A
PUSH HL E5
Save the DATE$ day pointer while the weekday and day-of-year fields are updated.
530B
LD C,A 4F
Copy the zero-based month index (Register A) into C for later use as a table offset.
530C
LD HL,4048H 21 48 40
Point HL at the DATE$ flags byte (4048H), whose bits 1-3 hold the day-of-week.
530F
LD A,(HL) 7E
Read the DATE$ flags byte into Register A to advance the weekday.
5310
RRCA 0F
Rotate Register A right so the weekday field aligns to the low bits.
5311
AND 07H E6 07
Mask Register A to the 3-bit weekday value (0-7).
5313
INC A 3C
Advance the weekday by one day.
5314
AND 07H E6 07
Mask again so a weekday of 7 wraps to 0.
5316
If the NZ FLAG is set (weekday did not wrap to 0), JUMP to 5319H. Otherwise adjust the wrapped value.
5318
INC A 3C
Bump a wrapped weekday of 0 up to 1 so the weekday numbering skips 0.
5319
RLCA 07
Rotate Register A left to move the new weekday value back into bits 1-3 of the flags byte.
531A
LD B,A 47
Save the shifted new weekday field in B.
531B
LD A,(HL) 7E
Re-read the DATE$ flags byte (4048H) into Register A.
531C
AND 0F1H E6 F1
Clear the old weekday bits (bits 1-3) of the flags byte, preserving the leap and other flags.
531E
OR B B0
Merge the new weekday field (B) into the flags byte.
531F
LD (HL),A 77
Store the updated flags byte (with the advanced weekday) back to 4048H.
5320
DEC HL 2B
Step HL back to 4047H, the day-of-year high byte.
5321
INC (HL) 34
Increment the day-of-year (this byte at 4047H); handled together with 5305H it forms a 16-bit day-of-year counter.
5322
INC HL 23
Advance HL back to 4048H.
5323
If the NZ FLAG is set (the day-of-year byte did not wrap), JUMP to 5326H. Otherwise carry into the high byte.
5325
INC (HL) 34
Propagate the carry into the day-of-year high byte at 4048H.
5326
LD B,00H 06 00
Clear B so BC = the zero-based month index (C) as a 16-bit table offset.
5328
LD HL,5363H 21 63 53
Self-Modifying Code
Point HL at the days-per-month table. The operand (5329H) was patched at 52E0H with the table's relocated high-memory address, so at run time HL addresses the copied table.
532B
ADD HL,BC 09
Index into the days-per-month table (HL) by the month offset (BC) so HL addresses the current month's day count.
532C
EX DE,HL EB
Move the table entry pointer into DE.
532D
POP HL E1
Restore the DATE$ day pointer (saved at 530AH) into HL.
532E
LD A,(DE) 1A
Load the number of days in the current month (from the table entry at DE) into Register A.
532F
CP (HL) BE
Compare the days-in-month (Register A) with the current day-of-month (at HL). If the day exceeds the month length the CARRY FLAG is set.
5330
If the NO CARRY FLAG is set (day is still within the month), JUMP to 5347H to finish. Otherwise roll over to the next month.
5332
LD (HL),01H 36 01
Reset the day-of-month (at HL) to 1 for the new month.
5334
INC L 2C
Advance HL to the month field of DATE$.
5335
INC (HL) 34
Increment the month.
5336
LD A,(HL) 7E
Read the new month value into Register A.
5337
SUB 0DH D6 0D
Subtract 13 from the month. If the month is 1-12 the result is negative and the CARRY FLAG is set.
5339
If the CARRY FLAG is set (month is 12 or less), JUMP to 5347H to finish. Otherwise the month passed December.
533B
LD (HL),01H 36 01
Reset the month (at HL) to 1 (January) for the new year.
533D
DEC L 2D
Step HL back toward the year field (past the day field).
533E
DEC L 2D
Step HL back to the DATE$ year field.
533F
INC (HL) 34
Increment the two-digit year.
5340
LD A,(HL) 7E
Read the year value into Register A.
5341
CP 64H FE 64
Compare the year (Register A) with 100 (64H). If it reached 100 the Z FLAG is set.
5343
If the NZ FLAG is set (year is under 100), JUMP to 5347H to finish. Otherwise wrap the year.
5345
LD (HL),00H 36 00
Reset the year (at HL) to 00.
5347
LD DE,4044H 11 44 40
Point DE at the DATE$ year byte (4044H) to rebuild the packed date fields the rest of DOS reads.
534A
LD A,(DE) 1A
Load the two-digit year (at 4044H) into Register A.
534B
CP 0CH FE 0C
Compare the year with 12 (0CH). Years 00-11 represent 2000-2011 and need a century adjustment.
534D
If the NO CARRY FLAG is set (year 12-99, i.e. 1980-1999), JUMP to 5351H. Otherwise adjust the century.
534F
ADD A,64H C6 64
Add 100 (64H) to a year of 00-11 so it becomes 100-111, representing 2000-2011.
5351
SUB 50H D6 50
Subtract 80 (50H) to convert the year into an offset from 1980, the value stored in the resident 1980-relative year cell.
5353
LD (4466H),A 32 66 44
Store the 1980-relative year (Register A) into 4466H, the resident year cell used when stamping files.
5356
INC DE 13
Advance DE to 4045H, the DATE$ day-of-month byte.
5357
LD A,(DE) 1A
Load the day-of-month (at 4045H) into Register A.
5358
LD (4307H),A 32 07 43
Store the day into the resident packed-date byte SVDAT2$ (4307H).
535B
INC DE 13
Advance DE to 4046H, the DATE$ month byte.
535C
LD A,(DE) 1A
Load the month (at 4046H) into Register A.
535D
OR 50H F6 50
OR the month with 50H to set the packed-date marker bits expected in SVDAT1$.
535F
LD (4306H),A 32 06 43
Store the packed month into the resident packed-date byte SVDAT1$ (4306H).
5362
RET C9
RETurn to the resident real-time-clock task that called this relocated routine through the 45DAH hook.
5363-536E
DEFB 1FH,1CH,1FH,1EH,1FH,1EH,1FH,1FH,1EH,1FH,1EH,1FH 1F 1C 1F 1E 1F 1E 1F 1F 1E 1F 1E 1F
Days-per-month table (January through December: 31,28,31,30,31,30,31,31,30,31,30,31). The February entry (5364H) is bumped to 29 for a leap year before the module is copied. Data.

536FH - DATE (Power-up Date Prompt)

DATE=ON or DATE=OFF enables or disables the prompt for the date at power up. The setting is a single flag byte in the drive-0 system-information sector: the handler reads that sector into 4200H, writes 00H (enabled) or FFH (disabled) to the date-prompt flag buffered at 42C2H, and writes the sector back. Because this alters the boot disk, the drive-0 diskette must not be write protected.

536F
LD BC,0001H 01 01 00
Self-Modifying Code
Load BC from the DATE value cell at 5370H. @PARAM overwrites it with 0000H (OFF) or FFFFH (ON); the default 0001H means DATE was not specified.
5372
LD A,B 78
Copy the high byte of the DATE cell (B) into Register A to begin the test.
5373
OR C B1
OR Register A with C (the cell low byte) so the Z FLAG reflects whether the cell was 0000H (OFF).
5374
LD B,0FFH 06 FF
Preload B with FFH, the flag value written to disable the date prompt (used if this turns out to be the OFF path). This does not disturb the flags from OR C.
5376
If the Z FLAG is set (DATE=OFF), JUMP to 537CH to write the FFH disable flag. Otherwise distinguish ON from unspecified.
5378
INC A 3C
INCrement Register A. When the cell held the 0001H default, A was 1 and becomes 2 (NZ); when it held FFFFH (ON), A was FFH and becomes 00H (Z).
5379
If the NZ FLAG is set (DATE not specified), JUMP to the TIME handler at 5386H, leaving the date prompt unchanged. Otherwise this is DATE=ON.
537B
LD B,A 47
Set B = 00H (Register A is 0 here), the flag value written to enable the date prompt.
537C
GOSUB to the read-system-information-sector helper 5A61H to bring the drive-0 configuration sector into the 4200H buffer.
537F
LD A,B 78
Copy the prepared date-prompt flag (B = 00H for ON, FFH for OFF) into Register A to store it.
5380
LD (42C2H),A 32 C2 42
Store the flag (Register A) into 42C2H, the date-prompt byte within the buffered system-information sector.
5383
GOSUB to the write-system-information-sector helper 5A6EH to write the updated configuration sector (4200H) back to drive 0.

5386H - TIME (Power-up Time Prompt)

TIME=ON or TIME=OFF enables or disables the prompt for the time at power up, using the same mechanism as DATE but a separate flag byte at 42C3H in the system-information sector. The drive-0 diskette must not be write protected.

5386
LD BC,0001H 01 01 00
Self-Modifying Code
Load BC from the TIME value cell at 5387H. @PARAM overwrites it with 0000H (OFF) or FFFFH (ON); the default 0001H means TIME was not specified.
5389
LD A,B 78
Copy the high byte of the TIME cell (B) into Register A to begin the test.
538A
OR C B1
OR Register A with C (the cell low byte) so the Z FLAG reflects whether the cell was 0000H (OFF).
538B
LD B,0FFH 06 FF
Preload B with FFH, the flag value written to disable the time prompt.
538D
If the Z FLAG is set (TIME=OFF), JUMP to 5393H to write the FFH disable flag. Otherwise distinguish ON from unspecified.
538F
INC A 3C
INCrement Register A; the 0001H default becomes 2 (NZ), while FFFFH (ON) becomes 0 (Z).
5390
If the NZ FLAG is set (TIME not specified), JUMP to the TRACE handler at 539DH, leaving the time prompt unchanged. Otherwise this is TIME=ON.
5392
LD B,A 47
Set B = 00H (Register A is 0 here), the flag value written to enable the time prompt.
5393
GOSUB to the read-system-information-sector helper 5A61H to bring the drive-0 configuration sector into the 4200H buffer.
5396
LD A,B 78
Copy the prepared time-prompt flag (B = 00H for ON, FFH for OFF) into Register A to store it.
5397
LD (42C3H),A 32 C3 42
Store the flag (Register A) into 42C3H, the time-prompt byte within the buffered system-information sector.
539A
GOSUB to the write-system-information-sector helper 5A6EH to write the updated configuration sector back to drive 0.

539DH - TRACE (Program-Counter Display Task)

TRACE=ON installs a high-priority background task that continuously displays the Z-80 Program Counter in the upper-right corner of the screen; TRACE=OFF removes it. The task routine lives in the resident kernel at 4D6AH and is registered in task slot 0BH via @ADTSK (4410H) / @RMTSK (4413H).

539D
LD BC,0001H 01 01 00
Self-Modifying Code
Load BC from the TRACE value cell at 539EH. @PARAM overwrites it with 0000H (OFF) or FFFFH (ON); the default 0001H means TRACE was not specified.
53A0
LD A,C 79
Copy the low byte of the TRACE cell (C) into Register A to test the "not specified" default.
53A1
DEC A 3D
DECrement Register A; if the cell held the 0001H default, A becomes 0.
53A2
OR B B0
OR Register A with B (the cell high byte). The Z FLAG is set only when the cell was exactly 0001H (TRACE not specified).
53A3
If the Z FLAG is set (TRACE not specified), JUMP to the BSTEP handler at 53B4H. Otherwise install or remove the trace task.
53A5
LD A,B 78
Copy the high byte of the TRACE cell (B) into Register A to decide ON versus OFF.
53A6
OR C B1
OR Register A with C (the cell low byte). The NZ FLAG marks TRACE=ON (FFFFH); the Z FLAG marks TRACE=OFF (0000H).
53A7
LD DE,4D6AH 11 6A 4D
Point DE at 4D6AH, the resident Program-Counter trace-display routine that @ADTSK will register as a task.
53AA
LD A,0BH 3E 0B
Load Register A with 0BH, the task-slot number used for the trace display.
53AC
PUSH AF F5
Save Register A (the task slot) and the ON/OFF flags so the same Z/NZ condition can gate both the add and remove calls.
53AD
If the NZ FLAG is set (TRACE=ON), GOSUB to the resident @ADTSK (4410H) to install the trace-display routine (DE = 4D6AH) in task slot 0BH (Register A).
53B0
POP AF F1
Restore Register A (task slot) and the ON/OFF flags for the removal test.
53B1
If the Z FLAG is set (TRACE=OFF), GOSUB to the resident @RMTSK (4413H) to remove the trace-display task in slot 0BH (Register A).

53B4H - BSTEP (Bootstrap Step Rate)

BSTEP=n sets the default bootstrap step rate (0-3) the FORMAT utility uses, stored in the drive-0 system-information sector. Values above 3 are rejected with "Boot step out of range <0-3>!". The step-rate byte lives at one of two offsets in the sector (73H or 23H) depending on the interface type recorded in MFLAG$ (442FH).

53B4
LD BC,0FFFFH 01 FF FF
Self-Modifying Code
Load BC from the BSTEP value cell at 53B5H. @PARAM overwrites the low byte with the requested step rate (0-3); the assembled default FFFFH means BSTEP was not specified.
53B7
INC B 04
INCrement B. When the cell held the FFFFH default, B was FFH and becomes 00H (Z), marking "not specified"; a real BSTEP value leaves B = 00H incremented to 01H (NZ).
53B8
If the Z FLAG is set (BSTEP not specified), JUMP to the BLINK handler at 53DDH. Otherwise validate and store the step rate.
53BA
LD A,C 79
Copy the requested step rate (low byte C) into Register A for range checking.
53BB
CP 04H FE 04
Compare the step rate (Register A) against 4. If it is 0-3 the CARRY FLAG is set; 4 or more leaves NO CARRY.
53BD
If the CARRY FLAG is set (step rate 0-3, valid), JUMP to 53C7H to store it. Otherwise report the range error.
53BF
LD HL,5DB8H 21 B8 5D
Point HL at the message "Boot step out of range <0-3>!" at 5DB8H.
53C2
GOSUB to the resident @LOGOT (447BH) to display the carriage-return-terminated error string at HL.
53C5
JUMP to the BLINK handler at 53DDH, having reported the invalid step rate.
53C7
LD B,A 47
Save the validated step rate (Register A, 0-3) in B for merging into the configuration byte.
53C8
GOSUB to the read-system-information-sector helper 5A61H to bring the drive-0 configuration sector into the 4200H buffer (H = 42H on return).
53CB
LD L,73H 2E 73
Set L = 73H so HL addresses 4273H, the default offset of the step-rate byte in the buffered configuration sector.
53CD
LD A,(442FH) 3A 2F 44
Fetch the interface-type flag MFLAG$ (442FH) into Register A to choose which sector offset holds the step rate.
53D0
RRCA 0F
Rotate Register A right so bit 0 of MFLAG$ moves into the CARRY FLAG.
53D1
If the NO CARRY FLAG is set (standard interface), JUMP to 53D5H keeping offset 73H. Otherwise use the alternate offset.
53D3
LD L,23H 2E 23
Set L = 23H so HL addresses 4223H, the alternate offset of the step-rate byte for the other interface type.
53D5
LD A,(HL) 7E
Read the current configuration byte (at HL) that carries the step rate in its low two bits.
53D6
AND 0FCH E6 FC
Clear the low two bits of Register A (the old step rate), preserving the other bits of the byte.
53D8
OR B B0
Merge the new step rate (B, 0-3) into the low two bits of Register A.
53D9
LD (HL),A 77
Store the updated configuration byte (Register A) back into the buffered sector at HL.
53DA
GOSUB to the write-system-information-sector helper 5A6EH to write the updated configuration sector back to drive 0.

53DDH - BLINK (Install/Remove the Blinking Cursor)

BLINK installs a blinking-cursor background task (task slot 5, module "$BL") in high memory; BLINK=OFF removes it. The cursor character is chosen from the value the user supplied: an explicit numeric character (BLINK=nn), the graphics block 0B0H (176) for a bare BLINK, character 8FH (143) for BLINK,LARGE, or character 88H (136) for BLINK,SMALL. The chosen character is patched into three points of the task body before it is copied to high memory.

53DD
LD BC,0001H 01 01 00
Self-Modifying Code
Load BC from the BLINK value cell at 53DEH. @PARAM overwrites it with 0000H (OFF), FFFFH (bare BLINK/ON) or an explicit character; the default 0001H means BLINK was not specified.
53E0
LD A,B 78
Copy the high byte of the BLINK cell (B) into Register A to begin the test.
53E1
OR C B1
OR Register A with C (the cell low byte) so A holds the combined BLINK value.
53E2
DEC A 3D
DECrement Register A; if the cell held the 0001H default, A becomes 0.
53E3
If the Z FLAG is set (BLINK not specified), JUMP to the TYPE handler at 54B4H, leaving the cursor unchanged.
53E6
INC A 3C
INCrement Register A to restore the combined BLINK value.
53E7
If the NZ FLAG is set (BLINK given a value, i.e. install), JUMP to 5406H. Otherwise (cell 0000H, BLINK=OFF) fall through to remove the task.
53E9
LD DE,546EH 11 6E 54
Point DE at the module name "$BL" (546EH) to locate the resident blinking-cursor module for removal.
53EC
GOSUB to the module-lookup helper 5AE7H to find the "$BL" module; HL = its control block, DE = the saved ceiling, NZ if not resident.
53EF
If the NZ FLAG is set (module not resident), JUMP to 5403H to just remove the task slot. Otherwise reclaim its memory if possible.
53F1
LD BC,(4049H) ED 4B 49 40
Load BC from HIGH$ (4049H) to test whether the module is the topmost high-memory allocation.
53F5
INC BC 03
Advance BC to HIGH$+1, the base a module just below HIGH$ would occupy.
53F6
SBC HL,BC ED 42
Subtract HIGH$+1 (BC) from the module control-block address (HL); a zero result means the "$BL" module is topmost and reclaimable.
53F8
If the NZ FLAG is set (not the topmost allocation), JUMP to 53FEH to remove the task without moving HIGH$. Otherwise reclaim the memory.
53FA
LD (4049H),DE ED 53 49 40
Store the saved ceiling (DE) into HIGH$ (4049H), returning the reclaimed high memory to the free pool.
53FE
LD A,05H 3E 05
Load Register A with 05H, the task-slot number of the blinking cursor.
5400
GOSUB to the resident @RMTSK (4413H) to remove the blinking-cursor task in slot 5 (Register A).
5403
JUMP to the TYPE handler at 54B4H, having removed the blinking cursor.
5406
PUSH AF F5
Save the BLINK value (Register A) while the high-memory guard is checked.
5407
GOSUB to the high-memory allocation guard 5AF7H to confirm it is safe to reserve high memory now.
540A
POP AF F1
Restore the BLINK value (Register A) to decide the cursor character.
540B
CP 0FFH FE FF
Compare the BLINK value (Register A) with FFH. FFH means a bare BLINK / BLINK=ON with no explicit character; any other value is the explicit character number.
540D
If the NZ FLAG is set (an explicit character was given), JUMP to 5421H to install it directly. Otherwise pick a default character from LARGE/SMALL.
540F
LD A,(5467H) 3A 67 54
Load the LARGE value cell (5467H) into Register A to test whether BLINK,LARGE was specified.
5412
INC A 3C
INCrement Register A. If LARGE was not specified (cell 0000H) A becomes 1 (NZ); if LARGE was specified (cell FFFFH) A becomes 0 (Z).
5413
LD A,0B0H 3E B0
Load Register A with 0B0H (character 176, the graphics block), the default cursor for a bare BLINK. This does not disturb the flags from the INC A.
5415
If the NZ FLAG is set (LARGE not specified), JUMP to 5419H keeping character 176. Otherwise use the large character.
5417
LD A,8FH 3E 8F
Load Register A with 8FH (character 143), the large blinking-cursor character for BLINK,LARGE.
5419
LD BC,0000H 01 00 00
Self-Modifying Code
Load BC from the SMALL value cell at 541AH to test whether BLINK,SMALL was specified.
541C
INC C 0C
INCrement C. If SMALL was not specified (cell low byte 00H) C becomes 1 (NZ); if SMALL was specified (cell FFFFH) the low byte FFH becomes 00H (Z).
541D
If the NZ FLAG is set (SMALL not specified), JUMP to 5421H keeping the current character. Otherwise use the small character.
541F
LD A,88H 3E 88
Load Register A with 88H (character 136), the small blinking-cursor character for BLINK,SMALL.
5421
LD (548DH),A 32 8D 54
Self-Modifying Code
Patch the chosen cursor character (Register A) into the blink-task body at 548DH (the operand of LD A,nn that writes the cursor character to the screen).
5424
LD (549AH),A 32 9A 54
Self-Modifying Code
Patch the cursor character into the blink-task body at 549AH (the operand of the CP nn that tests whether the screen still shows the blink character).
5427
LD (54ABH),A 32 AB 54
Self-Modifying Code
Patch the cursor character into the blink-task body at 54ABH (the operand of the second CP nn used while scanning for the cursor).
542A
LD DE,546EH 11 6E 54
Point DE at the module name "$BL" (546EH) to test whether the blinking-cursor module is already resident.
542D
GOSUB to the module-lookup helper 5AE7H; Z on return means the module is already resident (its stored bytes will simply be refreshed).
5430
LD BC,004BH 01 4B 00
Set BC = 004BH (75 bytes), the size of the "$BL" module template to reserve and copy.
5433
If the NZ FLAG is set (module not yet resident), JUMP to 543BH to reserve new high memory. Otherwise reuse the existing block.
5435
LD (546BH),DE ED 53 6B 54
Self-Modifying Code
The module is already resident: record its saved-ceiling word (DE) into the template's link field at 546BH so the header is consistent before recopying.
5439
JUMP to 5448H to copy the (refreshed) template into the existing high-memory block.
543B
LD HL,(4049H) 2A 49 40
Load HL from HIGH$ (4049H), the current top of unprotected memory, to reserve the module's space.
543E
OR A B7
Clear the CARRY FLAG for the following subtraction (OR A does not change HL).
543F
LD (546BH),HL 22 6B 54
Self-Modifying Code
Store the current HIGH$ (HL) into the template's saved-ceiling field at 546BH so a later BLINK=OFF can restore it.
5442
SBC HL,BC ED 42
Subtract the module size (BC = 004BH) from HIGH$ (HL) to compute the new ceiling below the reserved block.
5444
LD (4049H),HL 22 49 40
Store the new ceiling into HIGH$ (4049H), protecting the reserved high memory.
5447
INC HL 23
Advance HL to HIGH$+1, the base of the reserved block.
5448
PUSH HL E5
Save the module base address for reuse after the copy.
5449
EX DE,HL EB
Move the module base into DE, the LDIR destination.
544A
LD HL,5469H 21 69 54
Point HL at 5469H, the start of the "$BL" template, the LDIR source.
544D
LDIR ED B0
Block-move the template: source HL (5469H), destination DE (high-memory base), count BC (004BH). This copies the module header and the cursor routine (with its patched character) into high memory.
544F
POP DE D1
Restore the module base into DE to build the task control block.
5450
LD HL,0008H 21 08 00
Set HL = 0008H, the offset within the module of its task control block.
5453
ADD HL,DE 19
Add the module base (DE) to the offset (HL) so HL = base+8, the address of the task control block.
5454
EX DE,HL EB
Move the TCB address (base+8) into DE.
5455
PUSH DE D5
Save the TCB address (base+8) for the @ADTSK call.
5456
LD HL,0005H 21 05 00
Set HL = 0005H, the offset from the TCB to the cursor routine body within the module.
5459
ADD HL,DE 19
Add the TCB address (DE = base+8) to the offset so HL = base+0DH, the relocated address of the cursor routine.
545A
EX DE,HL EB
Move the routine address (base+0DH) into DE while HL again addresses the TCB (base+8).
545B
LD (HL),E 73
Store the low byte of the routine address (E) into the first byte of the task control block (base+8).
545C
INC HL 23
Advance HL to the second TCB byte (base+9).
545D
LD (HL),D 72
Store the high byte of the routine address (D) into base+9, so the TCB's routine word points at the relocated cursor routine.
545E
LD A,05H 3E 05
Load Register A with 05H, the task-slot number for the blinking cursor.
5460
POP DE D1
Restore the task control block address (base+8) into DE for @ADTSK.
5461
GOSUB to the resident @ADTSK (4410H) to register the blinking-cursor task control block (DE = base+8) in task slot 5 (Register A).
5464
JUMP to the TYPE handler at 54B4H, having installed the blinking cursor.

5467H - BLINK Cursor Task Template ("$BL", Relocated to High Memory)

The LARGE value cell precedes the "$BL" module template that the BLINK=ON path copies into high memory (75 bytes, 5469H-54B3H) and registers as the blinking-cursor interrupt task. The cursor routine at 5476H-54B3H executes from its relocated copy; nothing in the overlay calls it in place. Each interrupt it writes the chosen cursor character (patched at 548DH/549AH/54ABH) over the character at the cursor position, then on the alternate pass restores the original character, scanning video RAM to follow the cursor if it moved. The addresses shown are the assembled (pre-relocation) addresses.

5467-5468
DEFW 0000H 00 00
Self-Modifying Code
LARGE value cell, read at 540FH. @PARAM sets it FFFFH when BLINK,LARGE is specified; the default 0000H means LARGE was not requested. Data.
5469-546A
JR 5469H 18 FE
Module header self-loop placeholder (18H is also the high-memory module marker). Overwritten in the resident chain; not executed as code by the task, which is entered at its routine word. Data.
546B-546C
DEFW 0000H 00 00
Self-Modifying Code
Module link / saved-ceiling word, written at 543FH (new allocation) or 5435H (already resident). Data.
546D
DEFB 03H 03
Module name length (3 characters). Data.
546E-5470
DEFM "$BL" 24 42 4C
Module name "$BL" (the blinking-cursor module), also the string passed in DE to the 5AE7H lookup helper. Data.
5471-5475
DEFB 00H,00H,00H,00H,00H 00 00 00 00 00
Self-Modifying Code
Task control block area (module offset 8). The routine-address word at 5471H/5472H is filled at 545BH/545DH with the relocated address of the cursor routine; @ADTSK registers this control block in task slot 5. Data.
5476
Loop Start
Cursor routine entry (runs relocated in high memory). GOSUB to the resident @RPTSK (4416H) to obtain this task's control block address into IX.
5479
LD A,(4022H) 3A 22 40
Fetch the cursor-active flag from 4022H into Register A; a zero value means the cursor is currently suppressed.
547C
OR A B7
Test Register A (the cursor-active flag). If it is zero the Z FLAG is set.
547D
RET Z C8
If the Z FLAG is set (cursor suppressed), RETurn from the task without changing the screen.
547E
LD BC,(4020H) ED 4B 20 40
Load BC from 4020H, the resident video cursor position pointer, so BC addresses the character cell under the cursor.
5482
LD (IX+02H),C DD 71 02
Store the low byte of the cursor address (C) into the task control block at IX+02H to remember where the blink character was placed.
5485
LD (IX+03H),B DD 70 03
Store the high byte of the cursor address (B) into the task control block at IX+03H.
5488
LD A,(BC) 0A
Read the character currently at the cursor position (addressed by BC) into Register A so it can be saved and later restored.
5489
LD (IX+04H),A DD 77 04
Save the character under the cursor (Register A) into the task control block at IX+04H.
548C
LD A,8FH 3E 8F
Self-Modifying Code
Load Register A with the chosen cursor character (the operand at 548DH was patched at 5421H; shown here as the assembled 8FH).
548E
LD (BC),A 02
Write the cursor character (Register A) to the screen at the cursor position (BC), making the cursor visible.
548F
GOSUB to the resident @RPTSK (4416H) again to re-obtain the task control block address into IX on the following pass.
5492
LD C,(IX+02H) DD 4E 02
Reload the low byte of the saved cursor address from the control block (IX+02H) into C.
5495
LD B,(IX+03H) DD 46 03
Reload the high byte of the saved cursor address from the control block (IX+03H) into B, so BC again addresses where the blink character was written.
5498
LD A,(BC) 0A
Read the character now at that saved position (BC) into Register A to check whether it still shows the blink character.
5499
CP 8FH FE 8F
Self-Modifying Code
Compare the character (Register A) against the chosen cursor character (operand at 549AH, patched at 5424H). If it matches, the cursor has not moved and can be un-blinked in place.
549B
If the Z FLAG is set (the blink character is still at the saved position), JUMP to 54AEH to restore the original character. Otherwise the cursor moved; scan for it.
549D
LD A,C 79
Loop Start
Copy the low byte of the search address (C) into Register A to step the search back through video memory one screen row.
549E
SUB 40H D6 40
Subtract 40H (64, one screen row) from Register A to move the search pointer up one line.
54A0
LD C,A 4F
Store the decremented low byte back into C.
54A1
If the NO CARRY FLAG is set (no borrow), JUMP to 54A4H. Otherwise borrow into the high byte.
54A3
DEC B 05
Decrement the high byte of the search address (B) to complete the borrow.
54A4
LD A,3BH 3E 3B
Load Register A with 3BH, the high byte of the top of video RAM (3C00H region), to test whether the search has run off the screen.
54A6
CP B B8
Compare 3BH (Register A) with the search address high byte (B). Equality means the search reached the top of the screen.
54A7
If the Z FLAG is set (search ran off the top of video RAM), LOOP BACK to 5476H to restart the blink cycle. Loop End
54A9
LD A,(BC) 0A
Read the character at the current search position (BC) into Register A.
54AA
CP 8FH FE 8F
Self-Modifying Code
Compare the character (Register A) against the chosen cursor character (operand at 54ABH, patched at 5427H) to see whether this cell holds the blink character.
54AC
If the NZ FLAG is set (not the blink character), LOOP BACK to 549DH to keep scanning. Otherwise the blink character was found at the new position.
54AE
LD A,(IX+04H) DD 7E 04
Load the saved original character from the task control block (IX+04H) into Register A to restore it.
54B1
LD (BC),A 02
Write the original character (Register A) back to the located screen cell (BC), completing the un-blink half of the cycle.
54B2
LOOP BACK to 5476H to begin the next blink cycle. Loop End

54B4H - TYPE (Keyboard Type-Ahead)

TYPE=ON or TYPE=OFF enables or disables keyboard type-ahead by toggling bit 1 of the keyboard flag byte 441FH. Type-ahead requires the KI/DVR keyboard driver to be installed (bit 4 of 441FH) and its type-ahead task pointer at 4DF2H to be non-null; otherwise the request is refused with an explanatory message.

54B4
LD BC,0001H 01 01 00
Self-Modifying Code
Load BC from the TYPE value cell at 54B5H. @PARAM overwrites it with 0000H (OFF) or FFFFH (ON); the default 0001H means TYPE was not specified.
54B7
LD A,B 78
Copy the high byte of the TYPE cell (B) into Register A to begin the test.
54B8
OR C B1
OR Register A with C (the cell low byte) so A holds the combined TYPE value.
54B9
DEC A 3D
DECrement Register A; if the cell held the 0001H default, A becomes 0.
54BA
If the Z FLAG is set (TYPE not specified), JUMP to the SMOOTH handler at 54F1H, leaving type-ahead unchanged.
54BD
INC A 3C
INCrement Register A to restore the combined TYPE value.
54BE
If the NZ FLAG is set (TYPE=ON), JUMP to 54CAH. Otherwise (cell 0000H, TYPE=OFF) fall through to disable type-ahead.
54C0
LD HL,441FH 21 1F 44
Point HL at the keyboard flag byte 441FH so the type-ahead enable bit can be cleared.
54C3
RES 1,(HL) CB 8E
Clear bit 1 of 441FH, disabling type-ahead processing without removing the task.
54C5
LD HL,5C70H 21 70 5C
Point HL at the message "Type-ahead is now off" at 5C70H.
54C8
JUMP to 54EEH to display the "now off" message.
54CA
LD HL,441FH 21 1F 44
Point HL at the keyboard flag byte 441FH to check whether the KI/DVR driver is installed.
54CD
BIT 4,(HL) CB 66
Test bit 4 of 441FH. It is set when the KI/DVR keyboard driver (required for type-ahead) is active; clear otherwise.
54CF
LD HL,5C3DH 21 3D 5C
Point HL at the message "TYPE requires KI to be active" at 5C3DH, ready in case the driver is not installed. This does not disturb the flags from the BIT test.
54D2
If the Z FLAG is set (bit 4 clear, KI/DVR not active), JUMP to 54EEH to display "TYPE requires KI to be active".
54D4
BIT 1,(HL) CB 4E
Test bit 1 of the byte at HL. HL still points at 5C3DH (the message text), so this tests the first character of "TYPE requires...", a fixed value.
54D6
LD HL,5C5BH 21 5B 5C
Point HL at the message "Type-ahead is now on" at 5C5BH.
54D9
If the NZ FLAG is set, JUMP to 54EEH. Note
Because 54D4H tested a byte of the message text (character "T", 54H, whose bit 1 is 0), this branch is not taken; control always continues to validate the driver pointer.
54DB
LD DE,(4DF2H) ED 5B F2 4D
Load DE from 4DF2H, the KI/DVR type-ahead task pointer. DE is 0000H when the driver was installed without type-ahead support.
54DF
LD A,D 7A
Copy the high byte of the type-ahead pointer (D) into Register A to test whether it is present.
54E0
OR E B3
OR Register A (pointer high byte) with E (pointer low byte). If the pointer is 0000H the Z FLAG is set.
54E1
LD HL,5C86H 21 86 5C
Point HL at the message "Type-ahead not resident" at 5C86H, ready in case the pointer is null.
54E4
If the Z FLAG is set (no type-ahead task pointer), JUMP to 54EEH to display "Type-ahead not resident".
54E6
LD HL,441FH 21 1F 44
Point HL at the keyboard flag byte 441FH to enable type-ahead.
54E9
SET 1,(HL) CB CE
Set bit 1 of 441FH, enabling type-ahead processing.
54EB
LD HL,5C5BH 21 5B 5C
Point HL at the message "Type-ahead is now on" at 5C5BH.
54EE
GOSUB to the resident @LOGOT (447BH) to display the carriage-return-terminated status or error message addressed by HL.

54F1H - SMOOTH (Floppy I/O for 300-rpm Drives)

SMOOTH=ON patches the resident floppy sector driver at 46FDH with a DI opcode (0F3H) so interrupts are disabled earlier during disk I/O, providing faster transfers with drives precisely aligned to 300 rpm; SMOOTH=OFF writes a NOP (00H) there to restore normal behaviour. The ON and OFF cases share the store at 5500H through an instruction overlap.

54F1
LD BC,0001H 01 01 00
Self-Modifying Code
Load BC from the SMOOTH value cell at 54F2H. @PARAM overwrites it with 0000H (OFF) or FFFFH (ON); the default 0001H means SMOOTH was not specified.
54F4
LD A,B 78
Copy the high byte of the SMOOTH cell (B) into Register A to begin the test.
54F5
OR C B1
OR Register A with C (the cell low byte); A is now the combined value and is 00H for SMOOTH=OFF.
54F6
DEC A 3D
DECrement Register A; if the cell held the 0001H default, A becomes 0.
54F7
If the Z FLAG is set (SMOOTH not specified), JUMP to the GRAPHIC handler at 5503H, leaving the driver unchanged.
54FA
INC A 3C
INCrement Register A to restore the combined value: 00H for OFF, non-zero for ON.
54FB
If the NZ FLAG is set (SMOOTH=ON), JUMP to 54FEH to load the DI opcode. Otherwise (OFF) fall through with Register A = 00H.
54FD
LD BC,0F33EH 01 3E F3
Self-Modifying Code
Instruction overlap: on the OFF fall-through the 01H opcode consumes the following two bytes as LD BC,0F33EH, harmlessly skipping the LD A,0F3H and leaving Register A = 00H for the store. Entered one byte later at 54FEH, the same bytes decode as LD A,0F3H.
54FE
LD A,0F3H 3E F3
Load Register A with 0F3H (the DI opcode) for the SMOOTH=ON case. Reached only by the jump at 54FBH, which skips the 01H prefix byte at 54FDH.
5500
LD (46FDH),A 32 FD 46
Store Register A into the resident floppy sector driver at 46FDH: 0F3H (DI) enables the early interrupt-disable (SMOOTH=ON), 00H (NOP) restores normal timing (SMOOTH=OFF).

5503H - GRAPHIC (Graphics During Screen Print)

GRAPHIC=ON tells DOS that the line printer can directly reproduce TRS-80 graphics characters during a screen print, so graphics on the screen are sent to the printer; GRAPHIC=OFF turns this off. The state is bit 7 of the keyboard flag byte 441FH.

5503
LD BC,0001H 01 01 00
Self-Modifying Code
Load BC from the GRAPHIC value cell at 5504H. @PARAM overwrites it with 0000H (OFF) or FFFFH (ON); the default 0001H means GRAPHIC was not specified.
5506
LD A,B 78
Copy the high byte of the GRAPHIC cell (B) into Register A to begin the test.
5507
OR C B1
OR Register A with C (the cell low byte) so A holds the combined GRAPHIC value.
5508
LD HL,441FH 21 1F 44
Point HL at the keyboard flag byte 441FH so its graphics-print bit can be set or cleared. This does not disturb the flags from OR C.
550B
DEC A 3D
DECrement Register A; if the cell held the 0001H default, A becomes 0.
550C
If the Z FLAG is set (GRAPHIC not specified), JUMP to the ALIVE handler at 5517H, leaving the setting unchanged.
550E
INC A 3C
INCrement Register A; the OFF value 0000H becomes 0 (Z), while the ON value FFFFH stays non-zero.
550F
If the Z FLAG is set (GRAPHIC=OFF), JUMP to 5515H to clear the bit. Otherwise (GRAPHIC=ON) fall through to set it.
5511
SET 7,(HL) CB FE
Set bit 7 of 441FH, enabling graphics characters to be sent to the printer during a screen print.
5513
JUMP to the ALIVE handler at 5517H, having enabled graphics printing.
5515
RES 7,(HL) CB BE
Clear bit 7 of 441FH, disabling graphics reproduction during a screen print.

5517H - ALIVE (Install/Remove the Alive Task)

ALIVE=ON installs a background task (task slot 3, module "$AL") that alternates a character in the upper-right corner of the screen (3C3FH) to show the task processor is running; ALIVE=OFF removes it. Like the other high-memory tasks, the module is copied below HIGH$ and registered with @ADTSK.

5517
LD BC,0001H 01 01 00
Self-Modifying Code
Load BC from the ALIVE value cell at 5518H. @PARAM overwrites it with 0000H (OFF) or FFFFH (ON); the default 0001H means ALIVE was not specified.
551A
LD A,B 78
Copy the high byte of the ALIVE cell (B) into Register A to begin the test.
551B
OR C B1
OR Register A with C (the cell low byte) so A holds the combined ALIVE value.
551C
DEC A 3D
DECrement Register A; if the cell held the 0001H default, A becomes 0.
551D
If the Z FLAG is set (ALIVE not specified), JUMP to the SVC handler at 5592H (the next sub-command, beyond this section), leaving the alive task unchanged.
551F
INC A 3C
INCrement Register A to restore the combined ALIVE value.
5520
If the NZ FLAG is set (ALIVE=ON), JUMP to 553EH to install the task. Otherwise (cell 0000H, ALIVE=OFF) fall through to remove it.
5522
LD DE,557EH 11 7E 55
Point DE at the module name "$AL" (557EH) to locate the resident alive module for removal.
5525
GOSUB to the module-lookup helper 5AE7H to find the "$AL" module; HL = its control block, DE = the saved ceiling, NZ if not resident.
5528
If the NZ FLAG is set (module not resident), JUMP to 5537H to just remove the task slot. Otherwise reclaim its memory if possible.
552A
LD BC,(4049H) ED 4B 49 40
Load BC from HIGH$ (4049H) to test whether the "$AL" module is the topmost high-memory allocation.
552E
INC BC 03
Advance BC to HIGH$+1, the base a module just below HIGH$ would occupy.
552F
SBC HL,BC ED 42
Subtract HIGH$+1 (BC) from the module control-block address (HL); a zero result means the module is topmost and reclaimable.
5531
If the NZ FLAG is set (not topmost), JUMP to 5537H to remove the task without moving HIGH$. Otherwise reclaim the memory.
5533
LD (4049H),DE ED 53 49 40
Store the saved ceiling (DE) into HIGH$ (4049H), returning the reclaimed high memory to the free pool.
5537
LD A,03H 3E 03
Load Register A with 03H, the task-slot number of the alive task.
5539
GOSUB to the resident @RMTSK (4413H) to remove the alive task in slot 3 (Register A).
553C
JUMP to the SVC handler at 5592H (beyond this section), having removed the alive task.
553E
LD DE,557EH 11 7E 55
Point DE at the module name "$AL" (557EH) to test whether the alive module is already resident.
5541
GOSUB to the module-lookup helper 5AE7H; Z on return means the module is already resident.
5544
LD (557BH),DE ED 53 7B 55
Self-Modifying Code
Store the lookup's returned ceiling (DE) into the template's link field at 557BH.
5548
If the Z FLAG is set (module already resident), JUMP to 555DH to recopy into the existing block. Otherwise reserve new high memory.
554A
GOSUB to the high-memory allocation guard 5AF7H to confirm it is safe to reserve high memory now.
554D
LD HL,(4049H) 2A 49 40
Load HL from HIGH$ (4049H), the current top of unprotected memory, to reserve the module's space.
5550
LD (557BH),HL 22 7B 55
Self-Modifying Code
Store the current HIGH$ (HL) into the template's saved-ceiling field at 557BH so a later ALIVE=OFF can restore it.
5553
LD BC,0019H 01 19 00
Set BC = 0019H (25 bytes), the size of the "$AL" module template to reserve and copy.
5556
XOR A AF
Set Register A to ZERO, clearing the CARRY FLAG for the following subtraction.
5557
SBC HL,BC ED 42
Subtract the module size (BC = 0019H) from HIGH$ (HL) to compute the new ceiling below the reserved block.
5559
LD (4049H),HL 22 49 40
Store the new ceiling into HIGH$ (4049H), protecting the reserved high memory.
555C
INC HL 23
Advance HL to HIGH$+1, the base of the reserved block.
555D
PUSH HL E5
Save the module base address for reuse after the copy.
555E
LD DE,000AH 11 0A 00
Set DE = 000AH, the offset from the module base to the alive routine body.
5561
ADD HL,DE 19
Add the module base (HL) to the offset (DE) so HL = base+0AH, the relocated address of the alive routine.
5562
LD (5581H),HL 22 81 55
Self-Modifying Code
Patch the template's task-control-block routine word at 5581H with the relocated routine address (HL = base+0AH), so @ADTSK dispatches to the copied routine.
5565
POP DE D1
Restore the module base into DE, the LDIR destination.
5566
PUSH DE D5
Save the module base again for building the task control block after the copy.
5567
LD HL,5579H 21 79 55
Point HL at 5579H, the start of the "$AL" template, the LDIR source.
556A
LDIR ED B0
Block-move the template: source HL (5579H), destination DE (high-memory base), count BC (0019H). This copies the module header and the alive routine into high memory.
556C
POP DE D1
Restore the module base into DE to build the task control block.
556D
LD HL,0008H 21 08 00
Set HL = 0008H, the offset within the module of its task control block.
5570
ADD HL,DE 19
Add the module base (DE) to the offset (HL) so HL = base+8, the address of the task control block.
5571
EX DE,HL EB
Move the task control block address (base+8) into DE for @ADTSK.
5572
LD A,03H 3E 03
Load Register A with 03H, the task-slot number for the alive task.
5574
GOSUB to the resident @ADTSK (4410H) to register the alive task control block (DE = base+8) in task slot 3 (Register A).
5577
JUMP to the SVC handler at 5592H (beyond this section), having installed the alive task.

5579H - ALIVE Task Template ("$AL", Relocated to High Memory)

This 25-byte "$AL" module is copied into high memory by the ALIVE=ON path and registered as task slot 3. The routine at 5583H-5591H runs from its relocated copy; each time the task processor runs it, it alternates the upper-right screen character (3C3FH) between 86H and 89H, giving the visible "alive" indicator. The addresses shown are the assembled (pre-relocation) addresses. This is the natural end of the first-35% window; the SVC sub-command begins at 5592H.

5579-557A
JR 5583H 18 08
Module entry: jump over the header (link word, name length, name, and task-control-block word) to the alive routine body at 5583H.
557B-557C
DEFW 0000H 00 00
Self-Modifying Code
Module link / saved-ceiling word, written at 5544H (already resident) or 5550H (new allocation). Data.
557D
DEFB 03H 03
Module name length (3 characters). Data.
557E-5580
DEFM "$AL" 24 41 4C
Module name "$AL" (the alive module), also the string passed in DE to the 5AE7H lookup helper. Data.
5581-5582
DEFW 0000H 00 00
Self-Modifying Code
Task-control-block routine word (module offset 8), filled at 5562H with the relocated address of the alive routine (base+0AH); @ADTSK registers this control block in slot 3. Data.
5583
LD A,(3C3FH) 3A 3F 3C
Alive routine entry (runs relocated). Read the character currently in the upper-right corner of the screen (video RAM 3C3FH) into Register A to decide which alternate character to show next.
5586
CP 86H FE 86
Compare the corner character (Register A) with 86H. If it currently shows 86H the Z FLAG is set.
5588
LD A,89H 3E 89
Load Register A with 89H, the alternate character to show when the corner currently holds 86H. This does not disturb the flags from the CP.
558A
If the Z FLAG is set (corner shows 86H), JUMP to 558EH to write 89H. Otherwise select 86H.
558C
LD A,86H 3E 86
Load Register A with 86H, the alternate character to show when the corner does not already hold 86H.
558E
LD (3C3FH),A 32 3F 3C
Write the selected character (Register A, 86H or 89H) to the upper-right corner of the screen (3C3FH), flipping the alive indicator.
5591
RET C9
RETurn to the task processor that ran this relocated routine. This is the last instruction of the first-35% window; the SVC sub-command handler follows at 5592H.

5592H - SVC (Load the Supervisor-Call Table)

SVC (DOS version 5) copies the "$SVCKLI" supervisor-call dispatch module into high memory and points the resident SVC vector at 4BCFH into it, so programs can reach DOS and ROM services by SVC number. It is a one-shot: if the table is already resident (SFLAG$ 430F bit 0) it prints "SVC table already implemented" and does nothing. The module is 293 bytes (0125H).

5592
LD BC,0000H 01 00 00
Self-Modifying Code
Load BC from the SVC value cell at 5593H. @PARAM set it non-zero if the user typed SVC; the default 0000H means SVC was not requested.
5595
LD A,B 78
Copy the high byte of the SVC cell (B) into Register A to test whether SVC was requested.
5596
OR C B1
OR Register A with C (the cell low byte). If the SVC cell is zero the Z FLAG is set.
5597
If the Z FLAG is set (SVC not requested), JUMP to the SYSRES handler at 5705H. Otherwise install the SVC table.
559A
LD HL,430FH 21 0F 43
Point HL at SFLAG$ (430FH) so the "SVC table resident" bit can be tested and set.
559D
BIT 0,(HL) CB 46
Test bit 0 of SFLAG$ (430FH), which records whether the SVC table has already been installed. If set the Z FLAG is clear.
559F
SET 0,(HL) CB C6
Set bit 0 of SFLAG$ (430FH) to mark the SVC table as resident. This does not disturb the flags from the BIT test.
55A1
LD HL,5D82H 21 82 5D
Point HL at the message "SVC table already implemented" at 5D82H, ready in case the table was already installed.
55A4
If the NZ FLAG is set (bit 0 was already set, table already resident), JUMP to 55DAH to display the "already implemented" message and return. Otherwise install the table.
55A6
LD HL,(4049H) 2A 49 40
Load HL from HIGH$ (4049H), the current top of unprotected memory, to reserve the module's space.
55A9
LD (55E2H),HL 22 E2 55
Self-Modifying Code
Store the current HIGH$ (HL) into the "$SVCKLI" template's saved-ceiling field at 55E2H so the module records the memory it reserved.
55AC
LD BC,0125H 01 25 01
Set BC = 0125H (293 bytes), the size of the "$SVCKLI" supervisor-call module.
55AF
XOR A AF
Set Register A to ZERO, clearing the CARRY FLAG for the following subtraction.
55B0
SBC HL,BC ED 42
Subtract the module size (BC = 0125H) from HIGH$ (HL) to compute the new ceiling below the reserved block.
55B2
LD (4049H),HL 22 49 40
Store the new ceiling into HIGH$ (4049H), protecting the reserved high memory.
55B5
INC HL 23
Advance HL to HIGH$+1, the base address where the module will be copied.
55B6
PUSH HL E5
Save the module base address for reuse.
55B7
LD DE,011AH 11 1A 01
Set DE = 011AH, the offset from the module base to an internal pointer that must be relocated.
55BA
ADD HL,DE 19
Add the offset (DE) to the module base (HL) so HL = the relocated address of that internal field.
55BB
LD (56B1H),HL 22 B1 56
Self-Modifying Code
Patch the "$SVCKLI" template word at 56B1H with the relocated address (HL), fixing up one of the module's self-references before it is copied.
55BE
POP HL E1
Restore the module base into HL.
55BF
PUSH HL E5
Save the module base again for the next fix-up.
55C0
LD DE,0009H 11 09 00
Set DE = 0009H, the offset to a second internal pointer to relocate.
55C3
ADD HL,DE 19
Add the offset (DE) to the module base (HL) so HL = the relocated address of that field.
55C4
LD (56EBH),HL 22 EB 56
Self-Modifying Code
Patch the "$SVCKLI" template word at 56EBH with the relocated address (HL), fixing up the module's second self-reference.
55C7
POP HL E1
Restore the module base into HL.
55C8
PUSH HL E5
Save the module base once more for use after the copy.
55C9
LD DE,55E0H 11 E0 55
Point DE at 55E0H, the start of the "$SVCKLI" template (the LDIR source).
55CC
EX DE,HL EB
Exchange DE and HL so HL = 55E0H (source) and DE = the module base (destination) for the block move.
55CD
LDIR ED B0
Block-move the module: source HL (55E0H), destination DE (high-memory base), count BC (0125H). This copies the whole "$SVCKLI" dispatch table into high memory.
55CF
POP HL E1
Restore the module base into HL to compute the SVC entry pointer.
55D0
LD DE,0109H 11 09 01
Set DE = 0109H, the offset from the module base to the SVC dispatch entry point.
55D3
ADD HL,DE 19
Add the offset (DE) to the module base (HL) so HL = the relocated address of the SVC dispatch entry.
55D4
LD (4BCFH),HL 22 CF 4B
Store the SVC dispatch entry address (HL) into the resident SVC vector at 4BCFH, so an SVC call now routes into the newly installed high-memory table.
55D7
LD HL,5DA0H 21 A0 5D
Point HL at the message "SVC table now installed" at 5DA0H.
55DA
GOSUB to the resident @LOGOT (447BH) to display the carriage-return-terminated status message addressed by HL ("SVC table now installed" or "SVC table already implemented").
55DD
JUMP to the SYSRES handler at 5705H to continue processing sub-commands.

55E0H - "$SVCKLI" Supervisor-Call Dispatch Module (Relocated to High Memory)

This 293-byte "$SVCKLI" module is copied verbatim into high memory by the SVC=ON path and reached through the resident SVC vector 4BCFH (set to the dispatcher at module offset 109H). It is a header, then a dispatch vector table indexed by supervisor-call code, then the relocatable dispatcher. The dispatcher at 56E9H forms the entry address as table_base + 2 × code, where table_base is module offset 9 (patched at 55C4H); a supervisor call therefore reaches the two-byte entry at 55E9H + 2×code, so the first table word shown below (55EDH) is supervisor-call code 2 and each following word is the next code. Each entry is the address the dispatcher jumps to for that code; 4C4BH is the "not implemented" filler for undefined codes. These codes match the standard LDOS numbering (verified: @DSP=2, @KBD=8, @KEYIN=9, @DSPLY=10, @LOGOT=12, @PARAM=17, @ABORT=21, @EXIT=22, @ADTSK=29, @RMTSK=30, @RPTSK=31, @HIGH$=100). The addresses shown are the assembled (pre-relocation) addresses; this region is decoded from the SYS7.SYS binary (the .txt disassembler renders it as bogus instructions).

55E0-55E1
JR 55E0H 18 FE
Module header self-loop placeholder (18H is also the high-memory module marker). Data.
55E2-55E3
DEFW 0000H 00 00
Self-Modifying Code
Saved-ceiling field, written at 55A9H with the HIGH$ value in effect before this module was reserved. Data.
55E4
DEFB 04H 04
Module header byte (name length / type field). Data.
55E5-55EC
DEFM "$SVCKLI",00H 24 53 56 43 4B 4C 49 00
Module name "$SVCKLI" (the supervisor-call table module, shown by the DEVICE/MEMORY commands), null-terminated. Data.

Dispatch vector table. Each two-byte entry is the address the dispatcher jumps to for the supervisor-call code shown; codes 2-9 are ROM character-I/O routines, 10 onward are resident SYS0 services.

55ED-55EE
DEFW 0033H 33 00
Supervisor call code 2. Vectors to ROM @DSP (0033H): display the character in Register A at the cursor and advance the cursor.
55EF-55F0
DEFW 0013H 13 00
Supervisor call code 3. Vectors to ROM $GET (0013H): read one byte from the input device whose DCB is addressed by DE.
55F1-55F2
DEFW 001BH 1B 00
Supervisor call code 4. Vectors to ROM $PUT (001BH): write the byte in Register A to the output device addressed by DE.
55F3-55F4
DEFW 0023H 23 00
Supervisor call code 5. Vectors to ROM $CTL (0023H): send a control byte to a logical device or FCB (DE = FCB, A = control byte).
55F5-55F6
DEFW 003BH 3B 00
Supervisor call code 6. Vectors to ROM @PRT (003BH): send the character in Register A to the line printer.
55F7-55F8
DEFW 000BH 0B 00
Supervisor call code 7. Vectors to ROM $WHERE (000BH): resolve a relocation address, returning to the caller with its own address in HL.
55F9-55FA
DEFW 002BH 2B 00
Supervisor call code 8. Vectors to ROM @KBD (002BH): perform an instantaneous keyboard scan, returning a key (or 0) in Register A.
55FB-55FC
DEFW 0040H 40 00
Supervisor call code 9. Vectors to ROM @KEYIN (0040H): read a line of input from the keyboard into a caller-supplied buffer.
55FD-55FE
DEFW 4467H 67 44
Supervisor call code 10. Vectors to @DSPLY (4467H): display the caller's message string on the video (JP 44E3H).
55FF-5600
DEFW 447EH 7E 44
Supervisor call code 11. Vectors to @LOGER (447EH): log-error return stub (JR 44FDH).
5601-5602
DEFW 447BH 7B 44
Supervisor call code 12. Vectors to @LOGOT (447BH): display a carriage-return-terminated string (through 44E3H).
5603-5604
DEFW 4479H 79 44
Supervisor call code 13. Vectors to @MSG (4479H): display a message, reusing the display-string output loop (JR 44E6H).
5605-5606
DEFW 446AH 6A 44
Supervisor call code 14. Vectors to @PRINT (446AH): write the caller's message string to the printer (JP 44F8H).
5607-5608
DEFW 4C4BH 4B 4C
Supervisor call code 15. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
5609-560A
DEFW 0060H 60 00
Supervisor call code 16. Vectors to ROM $DELAY (0060H): loop for a calibrated time delay controlled by register pair BC.
560B-560C
DEFW 4476H 76 44
Supervisor call code 17. Vectors to @PARAM (4476H): parse a caller parameter table (issues RST 28H function code E3H).
560D-560E
DEFW 4470H 70 44
Supervisor call code 18. Vectors to @DATE (4470H): write the current date to the screen (JP 4D63H).
560F-5610
DEFW 446DH 6D 44
Supervisor call code 19. Vectors to @TIME (446DH): write the software clock time HH:MM:SS to the screen (JP 4D48H).
5611-5612
DEFW 4D7BH 7B 4D
Supervisor call code 20. Vectors to resident number formatter (4D7BH): the byte/number output helper the FORMS, SETCOM and LIST overlays share.
5613-5614
DEFW 4030H 30 40
Supervisor call code 21. Vectors to @ABORT (4030H): abort the current program back to DOS (issues RST 28H code 93H).
5615-5616
DEFW 402DH 2D 40
Supervisor call code 22. Vectors to @EXIT (402DH): exit and return to DOS.
5617-5618
DEFW 4400H 00 44
Supervisor call code 23. Vectors to @CMNDR (4400H): command supervisor / return-to-DOS entry (RST 28H code 93H).
5619-561A
DEFW 4405H 05 44
Supervisor call code 24. Vectors to @CMNDI (4405H): pass a command line to DOS for execution (RST 28H code B3H).
561B-561C
DEFW 4451H 51 44
Supervisor call code 25. Vectors to command-execute stub (4451H): issue RST 28H code A3H to execute a stored command line.
561D-561E
DEFW 4409H 09 44
Supervisor call code 26. Vectors to @ERROR (4409H): display the DOS error message for the code in Register A.
561F-5620
DEFW 440DH 0D 44
Supervisor call code 27. Vectors to @DEBUG (440DH): enter the DEBUG monitor (JP 44B4H, the RST 30H handler).
5621-5622
DEFW 4C4BH 4B 4C
Supervisor call code 28. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
5623-5624
DEFW 4410H 10 44
Supervisor call code 29. Vectors to @ADTSK (4410H): add a Task Control Block to a task slot.
5625-5626
DEFW 4413H 13 44
Supervisor call code 30. Vectors to @RMTSK (4413H): remove a background task by slot number.
5627-5628
DEFW 4416H 16 44
Supervisor call code 31. Vectors to @RPTSK (4416H): replace/install a task at a preset slot (JP 45B4H).
5629-562A
DEFW 4419H 19 44
Supervisor call code 32. Vectors to @KLTSK (4419H): kill the currently executing task.
562B-562C
DEFW 44B8H B8 44
Supervisor call code 33. Vectors to @CKDRV (44B8H): check that a drive is enabled and ready (RST 28H code C4H).
562D-562E
DEFW 4463H 63 44
Supervisor call code 34. Vectors to @DODIR (4463H): directory display/build service (RST 28H code AEH).
562F-5630
DEFW 4C4BH 4B 4C
Supervisor call code 35. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
5631-5632
DEFW 4C4BH 4B 4C
Supervisor call code 36. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
5633-5634
DEFW 4C4BH 4B 4C
Supervisor call code 37. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
5635-5636
DEFW 4C4BH 4B 4C
Supervisor call code 38. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
5637-5638
DEFW 4C4BH 4B 4C
Supervisor call code 39. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
5639-563A
DEFW 4C4BH 4B 4C
Supervisor call code 40. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
563B-563C
DEFW 4754H 54 47
Supervisor call code 41. Vectors to SELECT (4754H): select and log in a drive (disk operation code 01H).
563D-563E
DEFW 4C4BH 4B 4C
Supervisor call code 42. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
563F-5640
DEFW 4C4BH 4B 4C
Supervisor call code 43. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
5641-5642
DEFW 4C4BH 4B 4C
Supervisor call code 44. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
5643-5644
DEFW 4C4BH 4B 4C
Supervisor call code 45. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
5645-5646
DEFW 475EH 5E 47
Supervisor call code 46. Vectors to SEEK (475EH): seek the head to a track (disk operation code 06H).
5647-5648
DEFW 4759H 59 47
Supervisor call code 47. Vectors to RSELCT (4759H): re-select the drive (disk operation code 07H).
5649-564A
DEFW 4C4BH 4B 4C
Supervisor call code 48. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
564B-564C
DEFW 4777H 77 47
Supervisor call code 49. Vectors to RDSECT (4777H): read a sector (disk operation code 09H).
564D-564E
DEFW 4772H 72 47
Supervisor call code 50. Vectors to VERSEC (4772H): verify a sector (disk operation code 0AH).
564F-5650
DEFW 4C4BH 4B 4C
Supervisor call code 51. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
5651-5652
DEFW 4C4BH 4B 4C
Supervisor call code 52. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
5653-5654
DEFW 4763H 63 47
Supervisor call code 53. Vectors to WRSECT (4763H): write a sector (disk operation code 0DH).
5655-5656
DEFW 4768H 68 47
Supervisor call code 54. Vectors to WRPROT (4768H): write a sector with the deleted-data address mark (disk operation code 0EH).
5657-5658
DEFW 476DH 6D 47
Supervisor call code 55. Vectors to WRTRK (476DH): write/format a whole track (disk operation code 0FH).
5659-565A
DEFW 4C4BH 4B 4C
Supervisor call code 56. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
565B-565C
DEFW 442CH 2C 44
Supervisor call code 57. Vectors to @KILL (442CH): delete a file and free its directory entry (RST 28H code 9CH).
565D-565E
DEFW 4420H 20 44
Supervisor call code 58. Vectors to @INIT (4420H): open or create a file, making a directory entry if needed (RST 28H code A4H).
565F-5660
DEFW 4424H 24 44
Supervisor call code 59. Vectors to @OPEN (4424H): open an existing file (RST 28H code 94H).
5661-5662
DEFW 4428H 28 44
Supervisor call code 60. Vectors to @CLOSE (4428H): close an open file, flushing its buffer (RST 28H code 95H).
5663-5664
DEFW 4445H 45 44
Supervisor call code 61. Vectors to @BKSP (4445H): back the file's record pointer up by one record (JP 4816H).
5665-5666
DEFW 444BH 4B 44
Supervisor call code 62. Vectors to @CKEOF (444BH): test whether the file is at end of file (JP 4A1AH).
5667-5668
DEFW 445AH 5A 44
Supervisor call code 63. Vectors to @LOC (445AH): return the current logical record number of the open file (JP 484DH).
5669-566A
DEFW 445DH 5D 44
Supervisor call code 64. Vectors to @LOF (445DH): return the file's end-of-file record number (JP 4878H).
566B-566C
DEFW 4448H 48 44
Supervisor call code 65. Vectors to @PEOF (4448H): position the record pointer to end of file (JP 483CH).
566D-566E
DEFW 4442H 42 44
Supervisor call code 66. Vectors to @POSN (4442H): position the file's record pointer to a caller-selected record (JP 47CFH).
566F-5670
DEFW 4436H 36 44
Supervisor call code 67. Vectors to @READ (4436H): read the next logical record of the file (JP 48ADH).
5671-5672
DEFW 443FH 3F 44
Supervisor call code 68. Vectors to @REW (443FH): rewind the record pointer to the first record (JP 4835H).
5673-5674
DEFW 4454H 54 44
Supervisor call code 69. Vectors to @RREAD (4454H): re-read the current record (JP 480FH).
5675-5676
DEFW 4457H 57 44
Supervisor call code 70. Vectors to @RWRIT (4457H): re-write the current record (JP 499EH).
5677-5678
DEFW 4C4BH 4B 4C
Supervisor call code 71. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
5679-567A
DEFW 4460H 60 44
Supervisor call code 72. Vectors to @SKIP (4460H): advance the file's record pointer past one record (JP 47CBH).
567B-567C
DEFW 443CH 3C 44
Supervisor call code 73. Vectors to @VER (443CH): write a record and read it back to verify (JP 48E6H).
567D-567E
DEFW 444EH 4E 44
Supervisor call code 74. Vectors to @WEOF (444EH): write an end-of-file mark for the open file (JP 4886H).
567F-5680
DEFW 4439H 39 44
Supervisor call code 75. Vectors to @WRITE (4439H): write the caller's record as the next logical record (JP 48CBH).
5681-5682
DEFW 4430H 30 44
Supervisor call code 76. Vectors to @LOAD (4430H): load an executable file into memory without running it (JP 4C77H).
5683-5684
DEFW 4433H 33 44
Supervisor call code 77. Vectors to @RUN (4433H): load an executable file and jump to it (JP 4C5EH).
5685-5686
DEFW 441CH 1C 44
Supervisor call code 78. Vectors to @FSPEC (441CH): parse a filespec into a file control block.
5687-5688
DEFW 4473H 73 44
Supervisor call code 79. Vectors to @FEXT (4473H): apply a default file extension (RST 28H code D3H).
5689-568A
DEFW 44BBH BB 44
Supervisor call code 80. Vectors to @FNAME (44BBH): build a filename string from a directory entry (RST 28H code A5H).
568B-568C
DEFW 478FH 8F 47
Supervisor call code 81. Vectors to GETDCT (478FH): return the Drive Control Table entry for a drive number.
568D-568E
DEFW 4C4BH 4B 4C
Supervisor call code 82. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
568F-5690
DEFW 4B65H 65 4B
Supervisor call code 83. Vectors to DIRCYL (4B65H): get the directory track/cylinder from a drive block.
5691-5692
DEFW 4C4BH 4B 4C
Supervisor call code 84. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
5693-5694
DEFW 4B45H 45 4B
Supervisor call code 85. Vectors to RDSSEC (4B45H): read a sector into the directory buffer.
5695-5696
DEFW 4C4BH 4B 4C
Supervisor call code 86. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
5697-5698
DEFW 4B10H 10 4B
Supervisor call code 87. Vectors to DIRRD (4B10H): read a directory sector.
5699-569A
DEFW 4B1FH 1F 4B
Supervisor call code 88. Vectors to DIRWR (4B1FH): write a directory sector.
569B-569C
DEFW 4C4BH 4B 4C
Supervisor call code 89. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
569D-569E
DEFW 4B6CH 6C 4B
Supervisor call code 90. Vectors to MULTEA (4B6CH): eight-bit multiply primitive.
569F-56A0
DEFW 44C1H C1 44
Supervisor call code 91. Vectors to @MULT (44C1H): integer multiply vector (JP 4B8FH).
56A1-56A2
DEFW 4C4BH 4B 4C
Supervisor call code 92. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
56A3-56A4
DEFW 4B7BH 7B 4B
Supervisor call code 93. Vectors to DIVEA (4B7BH): eight-bit divide primitive.
56A5-56A6
DEFW 44C4H C4 44
Supervisor call code 94. Vectors to @DIV (44C4H): integer divide vector (JP 4BA9H).
56A7-56A8
DEFW 4C4BH 4B 4C
Supervisor call code 95. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
56A9-56AA
DEFW 4C4BH 4B 4C
Supervisor call code 96. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
56AB-56AC
DEFW 4C4BH 4B 4C
Supervisor call code 97. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
56AD-56AE
DEFW 4C4BH 4B 4C
Supervisor call code 98. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
56AF-56B0
DEFW 4C4BH 4B 4C
Supervisor call code 99. Unused - points to the 4C4BH not-implemented filler, so this supervisor call is not supported.
56B1-56B2
DEFW 56FAH FA 56
Supervisor call code 100. Vectors to @HIGH$ (56FAH): the module's own relocatable helper that reads or sets HIGH$ (4049H).
56B3-56E8
DEFW 4C4BH x27 4B 4C 4B 4C 4B 4C 4B 4C 4B 4C 4B 4C 4B 4C 4B 4C 4B 4C 4B 4C 4B 4C 4B 4C 4B 4C 4B 4C 4B 4C 4B 4C 4B 4C 4B 4C 4B 4C 4B 4C 4B 4C 4B 4C 4B 4C 4B 4C 4B 4C 4B 4C 4B 4C
Supervisor call codes 101-127. All unused - 27 words of the 4C4BH not-implemented filler for the remaining, undefined supervisor-call codes.
56E9
PUSH HL E5
Dispatcher body (runs relocated). Save the caller's HL while the supervisor-call code in Register A is turned into a table index.
56EA
LD HL,0000H 21 00 00
Self-Modifying Code
Load HL with the table base (the operand at 56EBH was relocated at 55C4H to the copied table's high-memory address, module offset 9).
56ED
ADD A,A 87
Double the supervisor-call code (Register A) to form a two-byte table offset.
56EE
ADD A,L 85
Add the low byte of the table base (L) to the offset (Register A).
56EF
LD L,A 6F
Store the resulting low byte into L.
56F0
ADC A,H 8C
Add the high byte of the table base (H) plus any carry to complete the 16-bit index.
56F1
SUB L 95
Subtract L back out so Register A holds only the corrected high byte of the table address.
56F2
LD H,A 67
Store the high byte into H, so HL now addresses the selected table entry.
56F3
LD A,(HL) 7E
Load the low byte of the routine address from the table entry (HL) into Register A.
56F4
INC HL 23
Advance HL to the high byte of the table entry.
56F5
LD H,(HL) 66
Load the high byte of the routine address into H.
56F6
LD L,A 6F
Move the saved low byte into L, so HL now holds the target routine address.
56F7
EX (SP),HL E3
Swap HL with the saved value on the stack, placing the routine address where the following RET will use it and restoring the caller's HL.
56F8
LD A,C 79
Restore Register A from C (the supervisor-call convention passes a parameter in C).
56F9
RET C9
RETurn, which transfers control to the selected service routine whose address was placed on the stack by the EX (SP),HL.
56FA-5704
DEFB (@HIGH$ get/set helper) 7C B5 28 03 22 49 40 2A 49 40 C9
The module's own @HIGH$ helper (supervisor-call code 100, reached via the 56B1H table entry): if HL is non-zero it stores HL into HIGH$ (4049H); otherwise it returns the current HIGH$ in HL. Executed from the relocated copy. Data/code tail.

5705H - SYSRES (Reside a SYS Overlay in High Memory)

SYSRES=n makes system overlay n co-resident in high memory so that later loads of it come from RAM instead of disk. Overlays 1-5 and 8-12 are allowed (0, 6, 7 and 13+ are refused). The first SYSRES allocates a control module ("$SR") holding a slot table and a resident-overlay load hook; each subsequent SYSRES loads the overlay via the resident loader (4BF5H), relocates it below HIGH$, and records its address in the slot table. 430EH holds the current overlay number.

5705
LD BC,0FFFFH 01 FF FF
Self-Modifying Code
Load BC from the SYSRES value cell at 5706H. @PARAM overwrites the low byte with the overlay number; the assembled default FFFFH means SYSRES was not specified.
5708
INC B 04
INCrement B; the FFFFH default makes B = 00H (Z), marking "not specified".
5709
If the Z FLAG is set (SYSRES not specified), JUMP to the DRIVE handler at 5825H.
570C
LD A,C 79
Copy the requested overlay number (low byte C) into Register A for validation.
570D
OR A B7
Test Register A. Overlay 0 is invalid.
570E
If the Z FLAG is set (overlay 0), JUMP to 573FH to report "Can't SYSRES requested module".
5710
CP 06H FE 06
Compare the overlay number (Register A) with 6. Overlays 1-5 are allowed.
5712
If the CARRY FLAG is set (overlay 1-5), JUMP to 571CH to install it. Otherwise keep checking.
5714
CP 08H FE 08
Compare the overlay number with 8. Overlays 6 and 7 (the library command sets) cannot be made resident.
5716
If the CARRY FLAG is set (overlay 6 or 7), JUMP to 573FH to report the error.
5718
CP 0DH FE 0D
Compare the overlay number with 13. Overlays 8-12 are allowed; 13 and above are invalid.
571A
If the NO CARRY FLAG is set (overlay 13 or higher), JUMP to 573FH to report the error. Otherwise the overlay (8-12) is valid.
571C
PUSH AF F5
Save the validated overlay number (Register A) for the install path.
571D
LD HL,4BDFH 21 DF 4B
Point HL at 4BDFH, the resident pointer to the SYSRES slot table (it reads back 4BF5H when no table has been allocated yet).
5720
LD E,(HL) 5E
Load the low byte of the SYSRES table pointer (from 4BDFH) into E.
5721
INC HL 23
Advance HL to the high byte of the pointer at 4BE0H.
5722
LD D,(HL) 56
Load the high byte into D, so DE = the current SYSRES slot-table address.
5723
LD HL,4BF5H 21 F5 4B
Point HL at 4BF5H, the resident overlay loader address, which is the sentinel 4BDFH holds when no SYSRES table exists yet.
5726
OR A B7
Clear the CARRY FLAG for the following subtraction.
5727
SBC HL,DE ED 52
Subtract the table pointer (DE) from 4BF5H (HL). A zero result means no SYSRES table has been allocated yet.
5729
If the Z FLAG is set (no table yet), JUMP to 5794H to allocate the "$SR" control module first. Otherwise index the existing table.
572B
LD HL,0FFE0H 21 E0 FF
Load HL with -20H (0FFE0H) to bias the table pointer back to its base minus the header.
572E
ADD HL,DE 19
Add the table pointer (DE) so HL = table base - 20H.
572F
RLCA 07
Double the overlay number (still in Register A) to form a two-byte slot offset.
5730
ADD A,L 85
Add the low byte of the biased base (L) to the slot offset (Register A).
5731
LD L,A 6F
Store the resulting low byte into L.
5732
If the NO CARRY FLAG is set (no overflow), JUMP to 5735H. Otherwise carry into the high byte.
5734
INC H 24
Propagate the carry into H so HL addresses the overlay's slot.
5735
INC HL 23
Advance HL to the high byte of the overlay's slot entry.
5736
LD A,(HL) 7E
Load the slot's high byte into Register A to test whether the overlay is already resident.
5737
OR A B7
Test Register A. A non-zero high byte means the slot already holds a resident address.
5738
If the Z FLAG is set (slot empty), JUMP to 5750H to load and reside the overlay. Otherwise it is already resident.
573A
POP AF F1
Discard the saved overlay number; the overlay is already resident.
573B
LD HL,5BFAH 21 FA 5B
Point HL at the message "System module already resident" at 5BFAH.
573E
LD IX,5BDCH DD 21 DC 5B
Note
Instruction overlap. On the already-resident fall-through this executes as LD IX,5BDCH (IX unused, harmless), leaving HL = 5BFAH. The error paths jump to 573FH, one byte later, where the same bytes decode as LD HL,5BDCH, pointing HL at "Can't SYSRES requested module". Both then reach the display at 5742H.
5742
GOSUB to the resident @LOGOT (447BH) to display the carriage-return-terminated message addressed by HL ("System module already resident" or "Can't SYSRES requested module").
5745
JUMP to the DRIVE handler at 5825H to continue processing sub-commands.
5748-574F
DEFB 18H,FEH,00H,00H,03H; DEFM "$S " 18 FE 00 00 03 24 53 20
The "$Sn" resident-overlay module header template (marker/link/name-length and the name "$S", whose third character at 574FH is patched at 5786H with the overlay-number digit). Data; copied above each resided overlay.
5750
LD (430EH),A 32 0E 43
Store the overlay number (Register A) into 430EH, the resident current-overlay-number byte. Reached from 5738H; the byte at 5750H is the LD (nn),A opcode (the .txt listing mis-aligns this as part of the preceding data).
5753
POP AF F1
Restore the overlay number (saved at 571CH) into Register A.
5754
PUSH AF F5
Save the overlay number again for the naming step later.
5755
ADD A,02H C6 02
Add 2 to the overlay number to form the loader's request offset.
5757
OR 80H F6 80
Set bit 7 of Register A to build the RST-28 load code (80H | (n+2)) that tells the resident loader to load this system overlay.
5759
PUSH HL E5
Save the overlay's slot-table pointer (HL) for storing the resident address after relocation.
575A
GOSUB to the resident overlay loader (4BF5H) with the load code in Register A to bring overlay n into its normal region at 4E00H.
575D
LD HL,(4049H) 2A 49 40
Load HL from HIGH$ (4049H), the current top of memory, as the destination for the relocated overlay.
5760
LD (574AH),HL 22 4A 57
Self-Modifying Code
Store the current HIGH$ (HL) into the "$Sn" header's link field at 574AH.
5763
EX DE,HL EB
Move HIGH$ into DE, the top of the destination area for the downward block copy.
5764
LD BC,(4BC9H) ED 4B C9 4B
Load BC from 4BC9H, the resident overlay length word set by the loader, giving the byte count of the overlay now at 4E00H.
5768
LD HL,4E00H 21 00 4E
Point HL at 4E00H, the base of the just-loaded overlay (the LDDR source will run from its top).
576B
ADD HL,BC 09
Add the overlay length (BC) to the base (HL) so HL points just past the overlay.
576C
DEC HL 2B
Back HL up to the last byte of the overlay, the LDDR source start.
576D
PUSH BC C5
Save the overlay length for storing after the copy.
576E
LDDR ED B8
Block-move the overlay downward: source HL (top of 4E00H image), destination DE (top of the high-memory area), count BC (overlay length). This relocates the overlay into high memory.
5770
POP BC C1
Restore the overlay length into BC.
5771
LD A,B 78
Copy the high byte of the overlay length (B) into Register A to store it after the relocated image.
5772
LD (DE),A 12
Store the length high byte (Register A) just below the relocated overlay (DE points there after LDDR).
5773
DEC DE 1B
Move DE down one byte for the length low byte.
5774
LD A,C 79
Copy the low byte of the overlay length (C) into Register A.
5775
LD (DE),A 12
Store the length low byte (Register A) below the relocated overlay, so the hook can read the overlay length.
5776
POP HL E1
Restore the overlay's slot-table pointer (saved at 5759H) into HL.
5777
LD (HL),D 72
Store the high byte of the relocated overlay's length/header address (D) into the slot's high byte.
5778
DEC HL 2B
Move HL to the slot's low byte.
5779
LD (HL),E 73
Store the low byte (E) so the slot now records where the resident overlay lives in high memory.
577A
POP AF F1
Restore the overlay number (saved at 5754H) into Register A to build its name digit.
577B
CP 0AH FE 0A
Compare the overlay number with 10. Numbers 10-12 need a hex-letter adjustment.
577D
If the CARRY FLAG is set (overlay 1-9), JUMP to 5781H to convert directly to a digit. Otherwise adjust for A-C.
577F
ADD A,07H C6 07
Add 7 so that 10-12 map onto the ASCII letters A-C after the following add.
5781
ADD A,30H C6 30
Add 30H to turn the overlay number into its ASCII character (0-9 or A-C).
5783
LD HL,574FH 21 4F 57
Point HL at 574FH, the third character of the "$S " name in the header template.
5786
LD (HL),A 77
Self-Modifying Code
Patch the name character (Register A) into the header so the resident module is named "$Sn" for overlay n.
5787
DEC DE 1B
Move DE down one byte to point below the stored length, the destination for the header copy.
5788
LD BC,0008H 01 08 00
Set BC = 8, the size of the "$Sn" header to copy.
578B
LDDR ED B8
Block-move the 8-byte "$Sn" header (source HL at 574FH downward, destination DE) into high memory just below the relocated overlay, completing the resident module.
578D
LD (4049H),DE ED 53 49 40
Store DE (now just below the resident module) into HIGH$ (4049H), lowering the ceiling to protect the resided overlay.
5791
JUMP to the DRIVE handler at 5825H, having resided the overlay.
5794
LD HL,(4049H) 2A 49 40
Load HL from HIGH$ (4049H) to allocate the "$SR" SYSRES control module (this path runs once, when no table exists yet).
5797
LD (57C1H),HL 22 C1 57
Self-Modifying Code
Store the current HIGH$ (HL) into the "$SR" template's saved-ceiling field at 57C1H.
579A
LD BC,0066H 01 66 00
Set BC = 0066H (102 bytes), the size of the "$SR" control module (header, slot table and the load hook).
579D
SBC HL,BC ED 42
Subtract the module size (BC) from HIGH$ (HL) to compute the new ceiling below the "$SR" block.
579F
LD (4049H),HL 22 49 40
Store the new ceiling into HIGH$ (4049H), reserving the "$SR" control area.
57A2
PUSH HL E5
Save the reserved base address for the pointer fix-ups.
57A3
LD DE,0006H 11 06 00
Set DE = 6, an offset into the "$SR" module used to relocate the hook's table pointer.
57A6
ADD HL,DE 19
Add the offset (DE) to the base (HL) so HL = the relocated address of the hook's table reference.
57A7
LD (57F3H),HL 22 F3 57
Self-Modifying Code
Patch the hook's LD HL,57C8H operand at 57F3H with the relocated slot-table address before the module is copied.
57AA
POP HL E1
Restore the reserved base into HL.
57AB
INC HL 23
Advance HL to base+1, the LDIR destination (the module is copied one byte above the ceiling).
57AC
PUSH HL E5
Save the destination base for computing the resident table pointer.
57AD
EX DE,HL EB
Move the destination into DE for the LDIR.
57AE
LD HL,57BFH 21 BF 57
Point HL at 57BFH, the start of the "$SR" template (the LDIR source).
57B1
LDIR ED B0
Block-move the "$SR" control module: source HL (57BFH), destination DE, count BC (0066H). This copies the header, slot table and the resident-overlay load hook into high memory.
57B3
POP HL E1
Restore the module base into HL.
57B4
LD DE,0028H 11 28 00
Set DE = 28H, the offset to the slot table within the copied module.
57B7
ADD HL,DE 19
Add the offset (DE) to the base (HL) so HL = the relocated slot-table address.
57B8
LD (4BDFH),HL 22 DF 4B
Store the relocated slot-table address (HL) into the resident SYSRES pointer 4BDFH, so future SYSRES commands and the hook find the table.
57BB
POP AF F1
Restore the overlay number (saved at 571CH) into Register A.
57BC
JUMP back to 571CH to index the now-allocated table and reside the requested overlay.

57BFH - "$SR" SYSRES Control Module (Relocated to High Memory)

The 102-byte "$SR" module allocated above: a header, a slot table with one two-byte entry per SYS overlay (holding each resided overlay's high-memory address), and a resident-overlay load hook. Once installed, the resident overlay loader consults this hook: if the requested overlay is already at 4E00H, or resident in high memory, it is used directly; otherwise the hook falls through to the normal disk loader (4BF5H). The addresses shown are the assembled (pre-relocation) addresses.

57BF-57C6
DEFB 18H,FEH,00H,00H,03H; DEFM "$SR"; DEFB 01H 18 FE 00 00 03 24 53 52 01
"$SR" module header (marker/link/name-length and the name "$SR"). The saved-ceiling word at 57C1H is patched at 5797H. Data.
57C7-57E6
DEFS (SYSRES slot table) 01 00 00 00 00 00 00 00 00 00 00 00 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Slot table: two bytes per SYS overlay giving the high-memory address of each resided overlay (0000H = not resident). The resident pointer 4BDFH is set to point here. Data.
57E7
PUSH HL E5
Resident-overlay load hook (runs relocated). Save HL while the requested overlay number in Register A is checked.
57E8
PUSH AF F5
Save the requested overlay number (Register A) and flags.
57E9
LD HL,430EH 21 0E 43
Point HL at 430EH, the resident current-overlay-number byte.
57EC
XOR (HL) AE
Exclusive-OR the requested overlay number (Register A) with the current overlay number (430EH); a zero low nibble means the same overlay is already loaded.
57ED
AND 0FH E6 0F
Mask to the low nibble (the overlay number field). Zero means the requested overlay is already at 4E00H.
57EF
If the Z FLAG is set (overlay already loaded), JUMP to 5820H to fall through to the normal loader. Otherwise check the slot table.
57F1
POP AF F1
Restore the requested overlay number into Register A.
57F2
LD HL,57C8H 21 C8 57
Self-Modifying Code
Point HL at the slot table (the operand at 57F3H was relocated at 57A7H to the table's high-memory address).
57F5
PUSH AF F5
Save the overlay number again for setting the current-overlay byte later.
57F6
AND 0FH E6 0F
Mask the overlay number to its low nibble as a table index.
57F8
RLCA 07
Double the index to form a two-byte slot offset.
57F9
ADD A,L 85
Add the low byte of the table base (L) to the offset (Register A).
57FA
LD L,A 6F
Store the resulting low byte into L.
57FB
If the NO CARRY FLAG is set, JUMP to 57FEH. Otherwise carry into the high byte.
57FD
INC H 24
Propagate the carry into H so HL addresses the overlay's slot.
57FE
LD A,(HL) 7E
Load the slot's high byte into Register A to test whether the overlay is resident.
57FF
OR A B7
Test Register A. A zero high byte means the overlay is not resident.
5800
If the Z FLAG is set (overlay not resident), JUMP to 5820H to fall through to the normal disk loader. Otherwise copy it from high memory.
5802
DEC HL 2B
Move HL to the slot's low byte.
5803
LD L,(HL) 6E
Load the slot's low byte into L.
5804
LD H,A 67
Put the high byte (Register A) into H, so HL now holds the resident overlay's high-memory address (its length header).
5805
PUSH DE D5
Save DE around the copy.
5806
PUSH BC C5
Save BC around the copy.
5807
LD C,(HL) 4E
Load the low byte of the stored overlay length into C.
5808
INC HL 23
Advance HL to the length high byte.
5809
LD B,(HL) 46
Load the high byte of the overlay length into B, so BC = the overlay length.
580A
INC HL 23
Advance HL to the first byte of the resident overlay body (the LDIR source).
580B
LD DE,4E00H 11 00 4E
Point DE at 4E00H, the overlay execution region (the LDIR destination).
580E
LD (4BE5H),DE ED 53 E5 4B
Store 4E00H into 4BE5H, the resident RST-28 dispatch operand, so the dispatcher enters the overlay at 4E00H.
5812
LD (4BC9H),BC ED 43 C9 4B
Store the overlay length (BC) into 4BC9H, the resident overlay-length word.
5816
LDIR ED B0
Block-move the resident overlay from high memory (HL) to 4E00H (DE), count BC. This makes the overlay available without a disk load.
5818
POP BC C1
Restore BC.
5819
POP DE D1
Restore DE.
581A
POP AF F1
Restore the overlay number into Register A.
581B
LD (430EH),A 32 0E 43
Store the overlay number into 430EH, recording it as the current overlay.
581E
POP HL E1
Restore HL.
581F
RET C9
RETurn to the RST-28 dispatcher, which now finds the overlay already at 4E00H (no disk access needed).
5820
POP AF F1
Restore the overlay number (the requested overlay is not resident or already loaded).
5821
POP HL E1
Restore HL.
5822
JUMP to the normal resident overlay loader (4BF5H) to load the overlay from disk as usual.

5825H - DRIVE (Per-Drive Configuration: WP / CYL / DISABLE / ENABLE / STEP / DELAY)

DRIVE=d,parm,... sets parameters for one drive (or, with no DRIVE=d, all drives). It works on two structures per drive: the resident Drive Code Table (DCT) entry (IY, based at 4700H, 0AH bytes per drive) and the drive-parameter area within the system-information sector buffer (IX, based at 4270H or 4220H by interface type). The sub-parameters handled here are WP (write protect, DCT+03H bit 7), CYL (cylinder count, config+06H), DISABLE/ENABLE (DCT+00H = C9H/C3H), STEP (DCT+03H bits 0-1) and DELAY (DCT+03H bit 2). When no drive is named, the block loops over all drives.

5825
LD A,(586FH) 3A 6F 58
Load the CYL value cell (586FH) into Register A to decide whether the system-information sector needs to be read (CYL is stored there).
5828
OR A B7
Test Register A (the CYL cell). Non-zero means CYL was specified.
5829
If the NZ FLAG is set (CYL specified), GOSUB to the read-system-information-sector helper 5A61H to bring the drive-0 configuration sector into the 4200H buffer.
582C
LD BC,0FF00H 01 00 FF
Self-Modifying Code
Load BC from the DRIVE value cell at 582DH. @PARAM overwrites the low byte with the drive number; the assembled default 0FF00H (high byte FFH) means no specific drive was named (apply globally).
582F
LD IX,4270H DD 21 70 42
Point IX at 4270H, the drive-parameter area in the buffered system-information sector (default interface).
5833
LD IY,4700H FD 21 00 47
Point IY at 4700H, the base of the resident Drive Code Table (DCT).
5837
INC B 04
INCrement B; the FFH default (no drive named) makes B = 00H (Z).
5838
If the Z FLAG is set (no specific drive named), JUMP to 5845H to process all drives. Otherwise select the named drive.
583A
LD A,C 79
Copy the named drive number (low byte C) into Register A for validation.
583B
CP 08H FE 08
Compare the drive number with 8. Drives 0-7 are valid.
583D
If the NO CARRY FLAG is set (drive 8 or higher), JUMP to the @PARAM error exit at 5A7AH.
5840
GOSUB to the resident GETDCT (478FH) to set IY to the Drive Code Table entry for the drive number in C.
5843
PUSH IY FD E5
Save the selected drive's DCT pointer (IY) to balance the stack with the global-loop path.
5845
LD A,(442FH) 3A 2F 44
Fetch the interface-type flag MFLAG$ (442FH) into Register A to select the drive-parameter area within the configuration sector.
5848
RRCA 0F
Rotate Register A right so bit 0 of MFLAG$ moves into the CARRY FLAG.
5849
If the NO CARRY FLAG is set (default interface), JUMP to 584FH keeping IX at 4270H. Otherwise use the alternate area.
584B
LD IX,4220H DD 21 20 42
Point IX at 4220H, the alternate drive-parameter area for the other interface type.
584F
PUSH IY FD E5
Save the DCT base (IY) so the current drive's offset from the DCT base can be computed.
5851
POP HL E1
Recover the DCT pointer into HL.
5852
LD DE,0B900H 11 00 B9
Load DE with -4700H (0B900H) to subtract the DCT base address.
5855
ADD HL,DE 19
Add -4700H (DE) to the DCT pointer (HL) so HL = the current drive's byte offset from the DCT base.
5856
EX DE,HL EB
Move the drive offset into DE.
5857
ADD IX,DE DD 19
Add the drive offset (DE) to IX so IX points at the current drive's parameter area within the configuration sector, aligned with its DCT entry.
5859
LD BC,0001H 01 01 00
Loop Start
Self-Modifying Code
Load BC from the WP value cell at 585AH. @PARAM overwrites it with 0000H (OFF) or FFFFH (ON); the default 0001H means WP was not specified. This is the per-drive loop head.
585C
LD A,B 78
Copy the high byte of the WP cell (B) into Register A to begin the WP test.
585D
OR C B1
OR Register A with C (the cell low byte) so A holds the combined WP value.
585E
DEC A 3D
DECrement Register A; the 0001H default becomes 0.
585F
If the Z FLAG is set (WP not specified), JUMP to 586EH to test CYL. Otherwise set or clear write protect.
5861
INC A 3C
INCrement Register A; the OFF value 0000H becomes 0 (Z), while ON (FFFFH) stays non-zero.
5862
If the Z FLAG is set (WP=OFF), JUMP to 586AH to clear the write-protect bit. Otherwise (WP=ON) set it.
5864
SET 7,(IY+03H) FD CB 03 FE
Set bit 7 of DCT+03H for the current drive (IY), software write-protecting it.
5868
JUMP to 586EH to test CYL.
586A
RES 7,(IY+03H) FD CB 03 BE
Clear bit 7 of DCT+03H for the current drive (IY), removing software write protection.
586E
LD BC,0000H 01 00 00
Self-Modifying Code
Load BC from the CYL value cell at 586FH. @PARAM overwrites it with the requested cylinder count; the default 0000H means CYL was not specified.
5871
LD A,B 78
Copy the high byte of the CYL cell (B) into Register A to begin the test.
5872
OR C B1
OR Register A with C (the cell low byte). If the CYL cell is zero the Z FLAG is set.
5873
If the Z FLAG is set (CYL not specified), JUMP to 589CH to test DISABLE. Otherwise validate and store the cylinder count.
5875
BIT 5,(IX+03H) DD CB 03 6E
Test bit 5 of the current drive's config byte (IX+03H), which marks an 8-inch drive (cylinder count is fixed on 8-inch drives).
5879
If the Z FLAG is set (not an 8-inch drive), JUMP to 5887H to validate the cylinder count. Otherwise reject it.
587B
LD A,(582EH) 3A 2E 58
Load the high byte of the DRIVE cell (582EH) into Register A: FFH when no specific drive was named, 00H when one was.
587E
INC A 3C
INCrement Register A; FFH (global) becomes 0 (Z), a specific drive stays non-zero.
587F
LD HL,5B7CH 21 7C 5B
Point HL at the message 'CYL=c invalid on 8" drive' at 5B7CH.
5882
If the NZ FLAG is set (a specific drive was named), GOSUB to @LOGOT (447BH) to display the 8-inch-drive error. In the global case the error is silently skipped.
5885
JUMP to 589CH to test DISABLE.
5887
LD A,C 79
Copy the requested cylinder count (low byte C) into Register A for range checking.
5888
DEC A 3D
DECrement Register A to compare the count as a zero-based cylinder index.
5889
CP 22H FE 22
Compare with 22H (34): counts below 35 are out of range.
588B
If the CARRY FLAG is set (count too small), JUMP to 5891H to report the range error.
588D
CP 60H FE 60
Compare with 60H (96): counts of 96 or below are in range.
588F
If the CARRY FLAG is set (count within 35-96), JUMP to 5899H to store it. Otherwise report the range error.
5891
LD HL,5B96H 21 96 5B
Point HL at the message 'Cylinder count out of range <35-96>' at 5B96H.
5894
GOSUB to @LOGOT (447BH) to display the cylinder-range error.
5897
JUMP to 589CH to test DISABLE.
5899
LD (IX+06H),A DD 77 06
Store the validated cylinder index (Register A) into the current drive's config-sector parameter at IX+06H.
589C
LD BC,0000H 01 00 00
Self-Modifying Code
Load BC from the DISABLE value cell at 589DH. @PARAM sets it non-zero if DISABLE was specified; the default 0000H means it was not.
589F
LD A,B 78
Copy the high byte of the DISABLE cell (B) into Register A to begin the test.
58A0
OR C B1
OR Register A with C (the cell low byte). If DISABLE was not specified the Z FLAG is set.
58A1
If the Z FLAG is set (DISABLE not specified), JUMP to 58ADH to test ENABLE. Otherwise disable the drive.
58A3
LD A,(582EH) 3A 2E 58
Load the high byte of the DRIVE cell (582EH) into Register A to check whether a specific drive was named.
58A6
INC A 3C
INCrement Register A; FFH (global) becomes 0 (Z).
58A7
If the Z FLAG is set (no specific drive), JUMP to 58B9H to skip disabling (all drives cannot be disabled). Otherwise disable the named drive.
58A9
LD A,0C9H 3E C9
Load Register A with 0C9H (the opcode RET), the value that disables a drive's DCT driver entry.
58AB
JUMP to 58B6H to write the disable byte to the DCT entry.
58AD
LD BC,0000H 01 00 00
Self-Modifying Code
Load BC from the ENABLE value cell at 58AEH. @PARAM sets it non-zero if ENABLE was specified; the default 0000H means it was not.
58B0
LD A,B 78
Copy the high byte of the ENABLE cell (B) into Register A to begin the test.
58B1
OR C B1
OR Register A with C (the cell low byte). If ENABLE was not specified the Z FLAG is set.
58B2
If the Z FLAG is set (ENABLE not specified), JUMP to 58B9H to test STEP. Otherwise enable the drive.
58B4
LD A,0C3H 3E C3
Load Register A with 0C3H (the opcode JP), the value that enables a drive's DCT driver entry.
58B6
LD (IY+00H),A FD 77 00
Store Register A into DCT+00H for the current drive (IY): C3H (JP) enables the driver, C9H (RET) disables it so any access returns "Illegal Drive Number".
58B9
LD BC,0FFFFH 01 FF FF
Self-Modifying Code
Load BC from the STEP value cell at 58BAH. @PARAM overwrites the low byte with the step rate (0-3); the default FFFFH means STEP was not specified.
58BC
INC B 04
INCrement B; the FFFFH default makes B = 00H (Z).
58BD
If the Z FLAG is set (STEP not specified), JUMP to 58D4H to test DELAY. Otherwise set the step rate.
58BF
LD A,C 79
Copy the requested step rate (low byte C) into Register A for range checking.
58C0
CP 04H FE 04
Compare the step rate with 4. Values 0-3 are valid.
58C2
If the NO CARRY FLAG is set (step rate 4 or higher), JUMP to the @PARAM error exit at 5A7AH.
58C5
BIT 4,(IY+04H) FD CB 04 66
Test bit 4 of DCT+04H for the current drive (IY); when set the drive type does not take a software step rate.
58C9
If the NZ FLAG is set (step rate not applicable), JUMP to 58ECH. Otherwise store it.
58CB
LD A,(IY+03H) FD 7E 03
Load the current drive's DCT+03H flags byte into Register A to merge the new step rate.
58CE
AND 0FCH E6 FC
Clear the low two bits (the old step rate) of Register A, preserving the other flags.
58D0
OR C B1
Merge the new step rate (C, 0-3) into the low two bits of Register A.
58D1
LD (IY+03H),A FD 77 03
Store the updated flags byte (Register A) back into DCT+03H for the current drive.
58D4
LD BC,0001H 01 01 00
Self-Modifying Code
Load BC from the DELAY value cell at 58D5H. @PARAM overwrites it with 0000H (OFF, 0.5s) or FFFFH (ON, 1.0s); the default 0001H means DELAY was not specified.
58D7
LD A,B 78
Copy the high byte of the DELAY cell (B) into Register A to begin the test.
58D8
OR C B1
OR Register A with C (the cell low byte) so A holds the combined DELAY value.
58D9
DEC A 3D
DECrement Register A; the 0001H default becomes 0.
58DA
If the Z FLAG is set (DELAY not specified), JUMP to 58ECH to advance the loop. Otherwise set or clear the delay bit.
58DC
INC A 3C
INCrement Register A; the OFF value 0000H becomes 0 (Z), ON (FFFFH) stays non-zero.
58DD
LD B,00H 06 00
Preload B = 00H, the value that clears the delay bit (used for DELAY=OFF). This does not disturb the flags.
58DF
If the NZ FLAG is set (DELAY=ON), JUMP to 58E3H with B loaded next. Otherwise (DELAY=OFF) keep B = 0.
58E1
LD B,04H 06 04
Set B = 04H (bit 2), the value that sets the 1.0-second motor-start delay for DELAY=ON.
58E3
LD A,(IY+03H) FD 7E 03
Load the current drive's DCT+03H flags byte into Register A to merge the delay bit.
58E6
AND 0FBH E6 FB
Clear bit 2 (the old delay bit) of Register A, preserving the other flags.
58E8
OR B B0
Merge the new delay bit (B = 04H for ON, 00H for OFF) into Register A.
58E9
LD (IY+03H),A FD 77 03
Store the updated flags byte (Register A) back into DCT+03H for the current drive.
58EC
LD A,(582EH) 3A 2E 58
Load the high byte of the DRIVE cell (582EH) into Register A to decide whether to loop over all drives.
58EF
INC A 3C
INCrement Register A; a specific drive (00H) becomes non-zero, global (FFH) becomes 0 (Z).
58F0
If the NZ FLAG is set (a specific drive was named), JUMP to 5906H to finish. Otherwise advance to the next drive.
58F2
LD DE,000AH 11 0A 00
Set DE = 0AH, the size of one DCT entry (and its aligned config area), to step to the next drive.
58F5
ADD IX,DE DD 19
Advance IX (config parameter pointer) to the next drive's area.
58F7
ADD IY,DE FD 19
Advance IY (DCT pointer) to the next drive's entry.
58F9
PUSH IY FD E5
Copy IY into HL (via the stack) to test whether the last drive has been passed.
58FB
POP HL E1
Recover the advanced DCT pointer into HL.
58FC
LD A,L 7D
Copy the low byte of the DCT pointer (L) into Register A to compare against the end of the table.
58FD
CP 50H FE 50
Compare the DCT low byte with 50H (the DCT spans 4700H-474FH for 8 drives). Reaching 50H means all drives are done.
58FF
If the CARRY FLAG is set (more drives remain), LOOP BACK to 5859H to configure the next drive. Loop End
5902
LD HL,0000H 21 00 00
Load HL with 0000H, a placeholder pushed next to balance the stack with the specific-drive path.
5905
PUSH HL E5
Push the placeholder so both the global and specific-drive paths leave two words on the stack for the DRIVER handler.
5906
LD A,(586FH) 3A 6F 58
Load the CYL value cell (586FH) into Register A to decide whether the modified configuration sector must be written back.
5909
OR A B7
Test Register A (the CYL cell). Non-zero means CYL was changed and the sector needs writing.
590A
If the NZ FLAG is set (CYL was set), GOSUB to the write-system-information-sector helper 5A6EH to write the updated configuration sector back to drive 0.

590DH - DRIVER (Load a DCT Driver File)

DRIVER="filespec" loads a Drive Code Table driver program (default extension /DCT) and calls its initialization entry, letting the system support drive types other than standard floppies. A bare DRIVER prompts "Enter DCT driver <BREAK=default> :"; pressing BREAK there restores the default DCT drivers instead. On a successful load the busy flag (4758H bit 3) is set and control is passed to the driver's entry point. This is the last sub-command in this section; the SYSTEM= / SWAP handler follows at 59B3H.

590D
LD DE,0000H 11 00 00
Self-Modifying Code
Load DE from the DRIVER value cell at 590EH. @PARAM overwrites it with a pointer to the driver filespec text on the command line; 0000H means DRIVER was not specified.
5910
LD A,D 7A
Copy the high byte of the filespec pointer (D) into Register A to test whether DRIVER was given.
5911
OR E B3
OR Register A with E (the pointer low byte). If the pointer is 0000H the Z FLAG is set.
5912
If the Z FLAG is set (DRIVER not specified), JUMP to the SYSTEM=/SWAP handler at 59B3H (the next sub-command, beyond this section).
5915
INC A 3C
INCrement Register A (the pointer high byte D). When @PARAM supplied the special FFxxH "prompt" marker, D = FFH becomes 0 (Z).
5916
If the Z FLAG is set (no filespec text given, prompt marker), JUMP to 593BH to prompt for the driver name. Otherwise copy the supplied filespec.
5918
LD HL,5EE8H 21 E8 5E
Point HL at the filespec work buffer at 5EE8H, the destination for the copied driver name.
591B
PUSH HL E5
Save the buffer start for use after the copy.
591C
LD A,(DE) 1A
Loop Start
Read the next character of the driver filespec from the command line (addressed by DE) into Register A.
591D
CP 0DH FE 0D
Compare the character with 0DH (carriage return), a filespec terminator.
591F
If the Z FLAG is set (end of line), JUMP to 5936H to terminate the copied filespec.
5921
CP 2CH FE 2C
Compare the character with 2CH (comma), a parameter separator.
5923
If the Z FLAG is set (comma), JUMP to 5936H to terminate the filespec.
5925
CP 22H FE 22
Compare the character with 22H (double quote), a filespec delimiter.
5927
If the Z FLAG is set (quote), JUMP to 5936H to terminate the filespec.
5929
CP 29H FE 29
Compare the character with 29H (close parenthesis), the end of the SYSTEM parameter list.
592B
If the Z FLAG is set (close paren), JUMP to 5936H to terminate the filespec.
592D
CP 03H FE 03
Compare the character with 03H (ETX), an end-of-text terminator.
592F
If the Z FLAG is set (ETX), JUMP to 5936H to terminate the filespec.
5931
LD (HL),A 77
Store the driver filespec character (Register A) into the work buffer at HL.
5932
INC DE 13
Advance the command-line pointer DE to the next character.
5933
INC HL 23
Advance the buffer pointer HL.
5934
LOOP BACK to 591CH to copy the next character. Loop End
5936
LD (HL),0DH 36 0D
Store a carriage return (0DH) into the buffer to terminate the copied filespec.
5938
POP HL E1
Restore the buffer start (5EE8H) into HL for the load step.
5939
JUMP to 5988H to open and load the driver file.
593B
LD HL,5C19H 21 19 5C
Point HL at the prompt 'Enter DCT driver <BREAK=default> : ' at 5C19H.
593E
GOSUB to the resident @DSPLY (4467H) to display the driver prompt.
5941
LD HL,5EE8H 21 E8 5E
Point HL at the filespec work buffer at 5EE8H to receive the typed driver name.
5944
LD B,18H 06 18
Set B = 18H (24), the maximum length for the input line.
5946
GOSUB to the ROM @KEYIN (0040H) to read a line into the buffer (HL), up to B characters. The CARRY FLAG is set if BREAK is pressed.
5949
If the NO CARRY FLAG is set (a name was entered, not BREAK), JUMP to 5988H to load that file. Otherwise restore the default DCT drivers.
594B
GOSUB to the read-system-information-sector helper 5A61H (the BREAK=default path restores standard drivers using configuration data).
594E
LD HL,0FB70H 21 70 FB
Load HL with -0490H (0FB70H), a base offset used with the DCT to locate the default floppy driver vector.
5951
LD A,(442FH) 3A 2F 44
Fetch the interface-type flag MFLAG$ (442FH) into Register A to choose the driver offset.
5954
RRCA 0F
Rotate Register A right so bit 0 of MFLAG$ moves into the CARRY FLAG.
5955
If the NO CARRY FLAG is set (default interface), JUMP to 595AH keeping the 0FB70H offset. Otherwise use the alternate.
5957
LD HL,0FB20H 21 20 FB
Load HL with -04E0H (0FB20H), the alternate default-driver offset for the other interface type.
595A
LD A,(582EH) 3A 2E 58
Load the high byte of the DRIVE cell (582EH) into Register A to decide whether to reset one drive or all.
595D
INC A 3C
INCrement Register A; global (FFH) becomes 0 (Z), a specific drive stays non-zero.
595E
POP DE D1
Pop the DCT pointer saved by the DRIVE handler into DE (the current drive's DCT address).
595F
PUSH DE D5
Push it back to keep the stack balanced.
5960
If the NZ FLAG is set (a specific drive), JUMP to 5965H using that drive's DCT pointer (DE). Otherwise reset from the DCT base.
5962
LD DE,4700H 11 00 47
Point DE at 4700H, the DCT base, to reset the default driver for all drives.
5965
ADD HL,DE 19
Add the DCT address (DE) to the negative base offset (HL) so HL addresses the default driver vector for this drive.
5966
LD A,0C9H 3E C9
Load Register A with 0C9H (RET) as the default DCT driver-entry byte.
5968
LD A,E 7B
Copy the DCT low byte (E) into Register A to test which drives get an active driver.
5969
CP 28H FE 28
Compare the DCT low byte with 28H, distinguishing the first four drives (which get the active driver) from the rest.
596B
If the NO CARRY FLAG is set (a higher drive), JUMP to 596FH storing RET (C9H). Otherwise store an active driver.
596D
LD A,0C3H 3E C3
Load Register A with 0C3H (JP), enabling the default floppy driver for this drive.
596F
LD (HL),A 77
Store the driver-entry byte (C3H or C9H) into the DCT entry addressed by HL.
5970
INC L 2C
Advance HL past the driver-entry byte toward the driver vector.
5971
INC L 2C
Advance HL again.
5972
INC L 2C
Advance HL to the start of the 7-byte driver vector to replace.
5973
INC E 1C
Advance E (the DCT source offset) in step with HL.
5974
INC E 1C
Advance E again.
5975
INC E 1C
Advance E to align the source with the destination.
5976
LD BC,0007H 01 07 00
Set BC = 7, the length of the default driver vector to copy.
5979
LDIR ED B0
Block-move the 7-byte default driver vector into the drive's DCT entry.
597B
LD A,(582EH) 3A 2E 58
Load the high byte of the DRIVE cell (582EH) into Register A to decide whether to reset further drives.
597E
INC A 3C
INCrement Register A; a specific drive stays non-zero, global (FFH) becomes 0 (Z).
597F
If the NZ FLAG is set (a specific drive was reset), JUMP to the SYSTEM=/SWAP handler at 59B3H. Otherwise continue over all drives.
5981
LD A,E 7B
Copy the DCT source low byte (E) into Register A to test for the end of the table.
5982
CP 50H FE 50
Compare with 50H, the end of the DCT (past drive 7).
5984
If the NO CARRY FLAG is set... continue: LOOP BACK to 5966H to reset the next drive's default driver until the whole DCT is done.
5986
JUMP to the SYSTEM=/SWAP handler at 59B3H, having restored the default drivers.
5988
LD A,(HL) 7E
Load the first character of the driver filespec buffer (HL) into Register A to check for an empty entry.
5989
CP 0DH FE 0D
Compare with 0DH (carriage return). An empty line means no driver was given.
598B
If the Z FLAG is set (empty filespec), JUMP to 59B2H to finish without loading.
598D
LD DE,5EE7H 11 E7 5E
Point DE at the filespec control block area at 5EE7H for @FSPEC to parse the name into.
5990
GOSUB to the resident @FSPEC (441CH) to parse the driver filespec (HL) into the file control block at DE.
5993
LD HL,5DF3H 21 F3 5D
Point HL at the default extension "DCT" at 5DF3H.
5996
GOSUB to the resident @FEXT (4473H) to apply the default extension /DCT when the filespec has none.
5999
GOSUB to the resident @LOAD (4430H) to load the driver program file into memory. On return HL is its transfer/entry address and the Z FLAG indicates success.
599C
If the Z FLAG is set (the driver loaded successfully), JUMP to 59A5H to initialize it. Otherwise report the load error.
599E
OR 0C0H F6 C0
OR the load return code (Register A) with 0C0H to form the DOS error code.
59A0
GOSUB to the resident @ERROR (4409H) to display the load error message.
59A3
JUMP to the SYSTEM=/SWAP handler at 59B3H after reporting the error.
59A5
POP DE D1
Pop the DCT pointer saved by the DRIVE handler into DE for the driver's initialization.
59A6
PUSH DE D5
Push it back to keep the stack balanced.
59A7
PUSH HL E5
Save the driver's entry address (HL, from @LOAD) for the indirect call.
59A8
LD HL,4758H 21 58 47
Point HL at the SYS1 status byte 4758H to set the configuration-changed flag.
59AB
SET 3,(HL) CB DE
Set bit 3 of 4758H, recording that a driver has been installed / the configuration changed.
59AD
LD HL,59B2H 21 B2 59
Load HL with 59B2H, the return address to reach after the driver's initialization runs.
59B0
EX (SP),HL E3
Swap HL with the driver entry address on the stack, so the top of stack is now the 59B2H return address and HL holds the driver entry.
59B1
JP (HL) E9
JUMP to the loaded driver's initialization entry (HL). When it returns it will land on the 59B2H address left on the stack.
59B2
POP DE D1
Pop the balancing word left on the stack by the DRIVE handler, restoring the stack before control passes to the SYSTEM=/SWAP handler at 59B3H (beyond this section).

59B3H - SYSTEM=n and SWAP (Exchange Drive Code Tables)

SWAP=s,DRIVE=d exchanges the Drive Code Table (DCT) entries of two logical drives. SYSTEM=n is the special case of swapping drive 0 with drive n (it copies its value into the SWAP cell and forces the DRIVE cell to 0). After validating both drive numbers (0-7) and that they differ, the two 0AH-byte DCT entries are exchanged through the 4200H buffer and "Drives :S and :D now swapped" is displayed with the two drive digits patched in.

59B3
LD BC,0FFFFH 01 FF FF
Self-Modifying Code
Load BC from the SYSTEM= value cell at 59B4H. @PARAM overwrites the low byte with the new system-drive number; the assembled default FFFFH means SYSTEM= was not specified.
59B6
LD A,B 78
Copy the high byte of the SYSTEM= cell (B) into Register A to begin the test.
59B7
AND C A1
AND Register A with C (the cell low byte). The FFFFH default yields FFH; a real drive number (high byte 00H) yields 00H.
59B8
INC A 3C
INCrement Register A; the FFFFH default becomes 00H (Z), a specified drive stays non-zero.
59B9
If the Z FLAG is set (SYSTEM= not specified), JUMP to 59C5H to test SWAP directly. Otherwise translate SYSTEM=n into a SWAP.
59BB
LD (59C6H),BC ED 43 C6 59
Self-Modifying Code
Copy the SYSTEM= value (BC, the new system-drive number) into the SWAP value cell at 59C6H, so the swap logic below performs the exchange.
59BF
LD HL,0000H 21 00 00
Load HL with 0000H to force the other swap drive to 0 (SYSTEM=n swaps drive n with drive 0).
59C2
LD (582DH),HL 22 2D 58
Self-Modifying Code
Store 0000H into the DRIVE value cell at 582DH, so the swap below uses drive 0 as the second drive.
59C5
LD BC,0FFFFH 01 FF FF
Self-Modifying Code
Load BC from the SWAP value cell at 59C6H. @PARAM (or the SYSTEM= path above) sets the low byte to the swap drive number; the default FFFFH means SWAP was not specified.
59C8
LD A,B 78
Copy the high byte of the SWAP cell (B) into Register A to begin the test.
59C9
AND C A1
AND Register A with C (the cell low byte). The FFFFH default yields FFH; a real drive number yields 00H.
59CA
INC A 3C
INCrement Register A; the FFFFH default becomes 00H (Z).
59CB
If the Z FLAG is set (SWAP not specified), JUMP to 5A2FH to test SYSGEN, leaving the drive tables unchanged. Otherwise perform the swap.
59CD
LD A,C 79
Copy the swap drive number (low byte C) into Register A for validation.
59CE
CP 08H FE 08
Compare the swap drive number with 8. Drives 0-7 are valid.
59D0
If the NO CARRY FLAG is set (drive 8 or higher), JUMP to 5B1DH to display "Drive specification error <0-7>!".
59D3
LD (5A04H),A 32 04 5A
Self-Modifying Code
Store the swap drive number (Register A) into 5A04H, the operand of the LD C,nn at 5A03H that selects this drive's DCT.
59D6
ADD A,30H C6 30
Add 30H to turn the swap drive number into its ASCII digit.
59D8
LD (5D44H),A 32 44 5D
Self-Modifying Code
Patch the ASCII drive digit (Register A) into the ":S" position of the "Drives :S and :D now swapped" message at 5D44H.
59DB
LD A,(582DH) 3A 2D 58
Load the DRIVE value cell (582DH) into Register A: the second (destination) drive of the swap.
59DE
CP 08H FE 08
Compare the destination drive number with 8 for validity.
59E0
If the NO CARRY FLAG is set (drive 8 or higher), JUMP to 5B1DH to display the drive-specification error.
59E3
LD (5A0BH),A 32 0B 5A
Self-Modifying Code
Store the destination drive number (Register A) into 5A0BH, the operand of the LD C,nn at 5A0AH that selects the second DCT.
59E6
LD B,A 47
Save the destination drive number in B for the "same drive" test.
59E7
ADD A,30H C6 30
Add 30H to turn the destination drive number into its ASCII digit.
59E9
LD (5D4BH),A 32 4B 5D
Self-Modifying Code
Patch the ASCII drive digit (Register A) into the ":D" position of the swap message at 5D4BH.
59EC
LD A,B 78
Recover the destination drive number (B) into Register A.
59ED
XOR C A9
Exclusive-OR the destination drive (Register A) with the swap drive (C). A zero result means the two drives are identical.
59EE
If the Z FLAG is set (both drives the same), JUMP to 5B21H to display "Source & Destination are the same drive!".
59F1
XOR C A9
Exclusive-OR with C again to restore Register A to the destination drive number.
59F2
LD A,C 79
Load Register A with the swap drive number (C); the Z flag from 59F1H (set when the destination drive is 0) still governs the following call.
59F3
If the Z FLAG is set (the destination drive is 0, the system drive), GOSUB to 5A84H to verify the swap drive holds a system disk before swapping the system drive.
59F6
LD A,(5A04H) 3A 04 5A
Load the swap drive number from 5A04H into Register A to test whether the swap drive is drive 0.
59F9
OR A B7
Test Register A (the swap drive number). Zero means the swap drive is drive 0.
59FA
LD A,(5A0BH) 3A 0B 5A
Load the destination drive number from 5A0BH into Register A (for the system-disk check). This does not disturb the flags from 59F9H.
59FD
If the Z FLAG is set (the swap drive is drive 0), GOSUB to 5A84H to verify the destination drive holds a system disk.
5A00
GOSUB to 5AC5H to update the resident current-drive select value (435EH) to reflect the coming swap.
5A03
LD C,00H 0E 00
Self-Modifying Code
Load C with the swap drive number (the operand at 5A04H was patched at 59D3H) to fetch its DCT.
5A05
GOSUB to the resident GETDCT (478FH) to set IY to the swap drive's Drive Code Table entry.
5A08
PUSH IY FD E5
Save the swap drive's DCT pointer (IY) on the stack.
5A0A
LD C,00H 0E 00
Self-Modifying Code
Load C with the destination drive number (the operand at 5A0BH was patched at 59E3H) to fetch its DCT.
5A0C
GOSUB to GETDCT (478FH) to set IY to the destination drive's DCT entry.
5A0F
POP HL E1
Recover the swap drive's DCT pointer into HL, so HL = first DCT and IY = second DCT.
5A10
LD DE,4200H 11 00 42
Point DE at the 4200H buffer, used as the temporary area for the three-way exchange.
5A13
PUSH DE D5
Save the temp buffer address.
5A14
PUSH HL E5
Save the first DCT pointer.
5A15
LD BC,000AH 01 0A 00
Set BC = 0AH (10 bytes), the size of one DCT entry.
5A18
LDIR ED B0
Block-move the first DCT entry (HL) into the 4200H temp buffer (DE), count BC (0AH).
5A1A
PUSH IY FD E5
Push the second DCT pointer (IY) to move it into HL.
5A1C
POP HL E1
Recover the second DCT pointer into HL.
5A1D
POP DE D1
Recover the first DCT pointer into DE (the destination of the second entry).
5A1E
PUSH HL E5
Save the second DCT pointer again.
5A1F
LD C,0AH 0E 0A
Set C = 0AH (10 bytes) for the next copy (B is already 0).
5A21
LDIR ED B0
Block-move the second DCT entry (HL) into the first drive's slot (DE): the second entry now occupies the first drive's DCT.
5A23
POP DE D1
Recover the second DCT pointer into DE (the destination for the saved first entry).
5A24
POP HL E1
Recover the temp buffer address (4200H) into HL, the source of the saved first entry.
5A25
LD C,0AH 0E 0A
Set C = 0AH (10 bytes) for the final copy.
5A27
LDIR ED B0
Block-move the saved first DCT entry (from 4200H) into the second drive's slot (DE), completing the exchange of the two DCT entries.
5A29
LD HL,5D3CH 21 3C 5D
Point HL at the message "Drives :S and :D now swapped" at 5D3CH (with the two drive digits patched in at 5D44H/5D4BH).
5A2C
GOSUB to the resident @DSPLY (4467H) to display the swap-confirmation message, then fall into the SYSGEN test.

5A2FH - SYSGEN and the Shared Exit Tail

SYSGEN stores the current configuration on disk. Rather than duplicate the SYSGEN overlay, SYSTEM re-dispatches to Library B command 1CH (the SYSGEN overlay) via RST 28H, after refusing if a background spooler is active. The exit tail (5A4FH) restores the caller's stack pointer and returns to the RST 28H dispatcher, or aborts to @ABORT (4030H) when a JCL file is in control (SFLAG$ 430F bit 5).

5A2F
LD HL,0001H 21 01 00
Self-Modifying Code
Load HL from the SYSGEN value cell at 5A30H. @PARAM sets it non-zero if SYSGEN was requested; the default 0001H means SYSGEN was not specified.
5A32
LD A,H 7C
Copy the high byte of the SYSGEN cell (H) into Register A to begin the test.
5A33
OR L B5
OR Register A with L (the cell low byte) so A holds the combined SYSGEN value.
5A34
DEC A 3D
DECrement Register A; the 0001H default becomes 0.
5A35
If the Z FLAG is set (SYSGEN not specified), JUMP to the exit tail at 5A4FH. Otherwise run SYSGEN.
5A37
LD A,(441FH) 3A 1F 44
Fetch the keyboard/system flag byte 441FH into Register A to test for an active spooler.
5A3A
RRCA 0F
Rotate Register A right so bit 0 of 441FH (the spooler-active flag) moves into the CARRY FLAG.
5A3B
If the CARRY FLAG is set (a spooler is active), JUMP to 5B25H to display "Can't SYSGEN with active SPOOLER!".
5A3E
LD A,(582DH) 3A 2D 58
Load the DRIVE value cell (582DH) into Register A (the target drive for the configuration file) to pass along in H.
5A41
LD H,A 67
Place the drive number in H for the SYSGEN overlay.
5A42
PUSH HL E5
Save HL (carrying the target drive) across the message display.
5A43
LD HL,5B5BH 21 5B 5B
Point HL at the message "Preparing to alter configuration" at 5B5BH.
5A46
GOSUB to @DSPLY (4467H) to display the "Preparing to alter configuration" notice.
5A49
POP HL E1
Restore HL (the target drive) for the SYSGEN overlay.
5A4A
LD B,1CH 06 1C
Load B with 1CH, the Library B command number of the SYSGEN overlay.
5A4C
LD A,89H 3E 89
Load Register A with 89H, the RST 28H request code for a Library B command.
5A4E
RST 28H EF
Issue RST 28H with A = 89H and B = 1CH, invoking the SYSGEN overlay through the normal dispatcher to build the configuration file, then fall into the exit tail.
5A4F
LD HL,0000H 21 00 00
Set HL to 0000H, the success return code, for the return to the RST 28H dispatcher.
5A52
LD SP,0000H 31 00 00
Self-Modifying Code
Restore the caller's stack pointer. The operand at 5A53H was overwritten at 5200H with the caller's SP by the entry LD (5A53H),SP.
5A55
LD A,H 7C
Copy the high byte of HL (the return code) into Register A to test for success.
5A56
OR L B5
OR Register A with L (the return code low byte). If HL is 0000H (success) the Z FLAG is set.
5A57
RET Z C8
If the Z FLAG is set (success), RETurn to the RST 28H dispatcher.
5A58
LD A,(430FH) 3A 0F 43
Fetch SFLAG$ (430FH) into Register A to test the command-level flag on an error return.
5A5B
BIT 5,A CB 6F
Test bit 5 of SFLAG$ (430FH): set means the system is not at the LDOS command level (a JCL file is running).
5A5D
RET Z C8
If the Z FLAG is set (at command level), RETurn to the dispatcher letting it report the error.
5A5E
JUMP to the resident @ABORT (4030H) to abort the running JCL file on an error.

5A61H - Configuration-Sector Read/Write Helpers

These two helpers move the drive-0 system-information sector (which holds the DATE/TIME power-up prompt flags, the bootstrap step rate and per-drive parameters) between disk and the 4200H buffer. A write error drops into the shared error tail with error code 3EH via an instruction overlap.

5A61
LD HL,4200H 21 00 42
Point HL at the 4200H buffer, the destination for the read configuration sector.
5A64
LD C,L 4D
Set C = 00H (the low byte of 4200H), selecting drive 0 for the read.
5A65
LD DE,0002H 11 02 00
Set DE = 0002H, the system-information sector's cylinder/sector selector passed to RDSECT.
5A68
GOSUB to the resident RDSECT (4777H) to read the drive-0 system-information sector into the 4200H buffer.
5A6B
RET Z C8
If the Z FLAG is set (read succeeded), RETurn to the caller with the configuration sector in 4200H.
5A6C
On a read error, JUMP to 5A7CH to report the error (Register A holds the RDSECT error code).
5A6E
LD HL,4200H 21 00 42
Point HL at the 4200H buffer, the source for the write configuration sector.
5A71
LD C,L 4D
Set C = 00H (drive 0) for the write.
5A72
LD DE,0002H 11 02 00
Set DE = 0002H, the system-information sector selector passed to WRSECT.
5A75
GOSUB to the resident WRSECT (4763H) to write the 4200H buffer back to the drive-0 system-information sector.
5A78
RET Z C8
If the Z FLAG is set (write succeeded), RETurn to the caller.
5A79
LD BC,2C3EH 01 3E 2C
Note
Instruction overlap. On the write-error fall-through the 01H opcode consumes the next two bytes as LD BC,2C3EH, preserving the WRSECT error code in Register A. The @PARAM/drive error exits jump to 5A7AH, one byte later, where the same bytes decode as LD A,2CH (parameter error code 2CH). Both reach 5A7CH.
5A7C
OR 0C0H F6 C0
OR the error code (Register A) with 0C0H to form the DOS error code.
5A7E
GOSUB to the resident @ERROR (4409H) to display the error message for the code in Register A.
5A81
JUMP to 5B2BH to set the error return code and exit.

5A84H - Verify a Drive Holds a System Disk

Before the system drive is swapped, this helper confirms the target drive is enabled and contains a bootable system diskette (directory-sector flag bit 4). If not, it prompts "Insert SYSTEM diskette in drive X!" and waits, unless a JCL file is running (in which case it cannot prompt and errors out).

5A84
LD (5A8DH),A 32 8D 5A
Self-Modifying Code
Store the drive number (Register A) into 5A8DH... this cell is used to remember which drive is being checked. (5A8DH lies within this routine's data area.)
5A87
ADD A,30H C6 30
Add 30H to turn the drive number into its ASCII digit.
5A89
LD (5CD9H),A 32 D9 5C
Self-Modifying Code
Patch the ASCII drive digit (Register A) into the "Insert SYSTEM diskette in drive X!" prompt at 5CD9H.
5A8C
LD C,00H 0E 00
Self-Modifying Code
Load C with the drive number (the operand at 5A8DH was patched at 5A84H) for the drive-check call. This is the retry re-entry point after the prompt.
5A8E
GOSUB to the resident @CKDRV (44B8H) to check that the drive (C) is enabled and ready.
5A91
If the NZ FLAG is set (drive not ready), JUMP to 5AA9H to prompt for a disk. Otherwise check the directory.
5A93
GOSUB to GETDCT (478FH) to set IY to the drive's DCT entry so its directory cylinder can be read.
5A96
LD D,(IY+09H) FD 56 09
Load the drive's directory cylinder number from DCT+09H into D for the sector read.
5A99
LD HL,4200H 21 00 42
Point HL at the 4200H buffer for the directory sector.
5A9C
LD E,05H 1E 05
Set E = 05H, the directory sector to read (the sector carrying the disk flags).
5A9E
GOSUB to the resident RDSSEC (4B45H) to read directory cylinder D, sector E into the 4200H buffer.
5AA1
If the NZ FLAG is set (directory read error), JUMP to 5A7CH to report the error.
5AA3
LD A,(4200H) 3A 00 42
Load the first directory byte from 4200H into Register A; bit 4 marks a system (bootable) disk.
5AA6
AND 10H E6 10
Mask bit 4 of Register A, the system-disk flag.
5AA8
RET NZ C0
If the NZ FLAG is set (bit 4 set, a system disk is present), RETurn to the caller; the swap may proceed.
5AA9
LD HL,430FH 21 0F 43
Point HL at SFLAG$ (430FH) to test whether the system is at command level before prompting.
5AAC
BIT 5,(HL) CB 6E
Test bit 5 of SFLAG$ (430FH): set means a JCL file is running (no user to prompt).
5AAE
If the NZ FLAG is set (JCL running), JUMP to 5B19H to display "Can't prompt for SYSTEM disk during JCL!".
5AB1
LD HL,5CB9H 21 B9 5C
Point HL at the prompt "Insert SYSTEM diskette in drive X!" at 5CB9H (with the drive digit patched at 5CD9H).
5AB4
GOSUB to @DSPLY (4467H) to display the insert-diskette prompt.
5AB7
LD HL,4200H 21 00 42
Point HL at the 4200H buffer to receive the user's key input.
5ABA
LD BC,0000H 01 00 00
Clear BC as the input-line length/count for the key read.
5ABD
GOSUB to the ROM @KEYIN (0040H) to wait for the user to press a key (or BREAK). CARRY is set if BREAK was pressed.
5AC0
If the NO CARRY FLAG is set (a key was pressed, not BREAK), LOOP BACK to 5A8CH to recheck the drive.
5AC2
If BREAK was pressed, JUMP to 5B15H to display "Manual <BREAK> abort!".

5AC5H - Update the Resident Drive-Select Value

When a swap changes the logical drive numbering, this helper rewrites the low three bits of the resident current-drive-select byte (435EH) so the system continues to address the correct physical drive. It only acts while a JCL file is running (SFLAG$ 430F bit 5); otherwise there is nothing to fix.

5AC5
LD HL,430FH 21 0F 43
Point HL at SFLAG$ (430FH) to test the command-level flag.
5AC8
BIT 5,(HL) CB 6E
Test bit 5 of SFLAG$ (430FH): set means a JCL file is running, so the current-drive value may need updating.
5ACA
RET Z C8
If the Z FLAG is set (at command level), RETurn without changes.
5ACB
LD HL,435EH 21 5E 43
Point HL at 435EH, the resident current-drive-select byte.
5ACE
LD A,(5A04H) 3A 04 5A
Load the swap drive number from 5A04H into Register A.
5AD1
LD B,A 47
Save the swap drive number in B.
5AD2
XOR (HL) AE
Exclusive-OR the swap drive number (Register A) with the current-drive byte (435EH).
5AD3
AND 07H E6 07
Mask to the low three bits (the drive-number field). Zero means the current drive equals the swap drive.
5AD5
LD A,(5A0BH) 3A 0B 5A
Load the destination drive number from 5A0BH into Register A (the value to install if a change is needed).
5AD8
If the NZ FLAG is set (current drive is not the swap drive), JUMP to 5AE1H to test the other direction. Otherwise install the destination drive.
5ADA
LD B,A 47
Move the drive number to install (Register A) into B for merging.
5ADB
LD A,(HL) 7E
Load the current-drive-select byte (435EH) into Register A to preserve its high bits.
5ADC
AND 0F8H E6 F8
Clear the low three bits (the old drive number) of Register A.
5ADE
OR B B0
Merge the new drive number (B) into the low three bits.
5ADF
LD (HL),A 77
Store the updated current-drive-select byte back to 435EH.
5AE0
RET C9
RETurn to the caller.
5AE1
XOR (HL) AE
Exclusive-OR the destination drive number (Register A) with the current-drive byte (435EH) to test the other swap direction.
5AE2
AND 07H E6 07
Mask to the low three bits. Zero means the current drive equals the destination drive.
5AE4
If the Z FLAG is set (current drive equals the destination drive), LOOP BACK to 5ADBH to install the swap drive (Register A already holds it via the fall-through). Otherwise no change is needed.
5AE6
RET C9
RETurn without changing the current-drive-select value.

5AE7H - Module-Lookup and High-Memory Guard Helpers

These helpers support the task/module sub-commands earlier in the overlay. 5AE7H issues RST 28H request code BCH to locate a resident module's control block and returns its saved-ceiling word. 5AF7H checks whether it is safe to reserve high memory (no attached, busy resident program).

5AE7
GOSUB to 5AF4H to issue the RST 28H module-lookup (request code BCH) for the module named at DE; on return HL addresses its control block.
5AEA
PUSH HL E5
Push the control-block address to move it into IX.
5AEB
POP IX DD E1
Recover the control-block address into IX.
5AED
LD E,(IX+02H) DD 5E 02
Load the low byte of the module's saved-ceiling word from IX+02H into E.
5AF0
LD D,(IX+03H) DD 56 03
Load the high byte from IX+03H into D, so DE = the HIGH$ value to restore when the module is removed.
5AF3
RET C9
RETurn to the caller with IX = control block and DE = saved ceiling.
5AF4
LD A,0BCH 3E BC
Load Register A with 0BCH, the RST 28H request code that locates a resident module control block.
5AF6
RST 28H EF
Issue RST 28H with A = 0BCH (and DE pointing at the module name) to have the resident dispatcher return the module's control block in HL.
5AF7
LD A,(430FH) 3A 0F 43
Fetch SFLAG$ (430FH) into Register A to test the command-level flag.
5AFA
BIT 5,A CB 6F
Test bit 5 of SFLAG$ (430FH): set means a JCL file is running (checked against the register-A snapshot).
5AFC
LD A,(402DH) 3A 2D 40
Load the first byte of @EXIT (402DH) into Register A; C3H there means a resident program is attached.
5AFF
If the Z FLAG is set (at command level), JUMP to 5B04H to use the @EXIT byte. Otherwise use the register-A snapshot.
5B01
LD A,(4065H) 3A 65 40
Load the resident register-A snapshot (4065H) into Register A; C3H there means a resident program is attached under JCL.
5B04
CP 0C3H FE C3
Compare Register A with 0C3H (JP). Not equal means no resident program is attached, so high memory is free.
5B06
RET NZ C0
If the NZ FLAG is set (no attached program), RETurn to the caller; it is safe to reserve high memory.
5B07
LD A,(4758H) 3A 58 47
Load the SYS1 status byte 4758H into Register A to test the busy flag.
5B0A
BIT 1,A CB 4F
Test bit 1 of 4758H, the busy flag.
5B0C
RET Z C8
If the Z FLAG is set (not busy), RETurn to the caller; high memory may be used. Otherwise fall into the error tail to refuse.

5B0DH - Error-Message Display Tail (Seven Entry Points)

A shared tail that displays one of several error messages and exits with an error return code. Each error condition jumps to a different entry point; the entry points overlap through the DD prefix of the following LD IX,nnnn so that each loads a distinct message pointer into HL, then all reach the common CALL @LOGOT. Entering at an odd address skips the DD prefix and reinterprets the bytes as LD HL,nnnn.

5B0D
LD HL,5B31H 21 31 5B
Entry for the "not at command level" refusal: point HL at "Can't -- Valid only at LDOS command level" at 5B31H, then fall through the overlapping LD IX instructions to the display.
5B10
LD IX,5DD6H DD 21 D6 5D
Note
Fall-through executes as LD IX,5DD6H (harmless). Entered at 5B11H (the PRTIME "no filter" path), the bytes decode as LD HL,5DD6H, pointing HL at "Printer filter not resident!".
5B14
LD IX,5CDCH DD 21 DC 5C
Note
Fall-through LD IX,5CDCH. Entered at 5B15H (the BREAK-abort path), decodes as LD HL,5CDCH -> "Manual <BREAK> abort!".
5B18
LD IX,5CF2H DD 21 F2 5C
Note
Fall-through LD IX,5CF2H. Entered at 5B19H (the JCL-prompt path), decodes as LD HL,5CF2H -> "Can't prompt for SYSTEM disk during JCL!".
5B1C
LD IX,5D1BH DD 21 1B 5D
Note
Fall-through LD IX,5D1BH. Entered at 5B1DH (the drive-number error path), decodes as LD HL,5D1BH -> "Drive specification error <0-7>!".
5B20
LD IX,5D59H DD 21 59 5D
Note
Fall-through LD IX,5D59H. Entered at 5B21H (the same-drive error path), decodes as LD HL,5D59H -> "Source & Destination are the same drive!".
5B24
LD IX,5BBAH DD 21 BA 5B
Note
Fall-through LD IX,5BBAH. Entered at 5B25H (the active-spooler path), decodes as LD HL,5BBAH -> "Can't SYSGEN with active SPOOLER!".
5B28
GOSUB to the resident @LOGOT (447BH) to display the carriage-return-terminated message addressed by HL.
5B2B
LD HL,0FFFFH 21 FF FF
Set HL to FFFFH, the error return code.
5B2E
JUMP to the exit tail at 5A52H to restore the caller's stack and return the error code (or abort under JCL).

5B31H - Message Strings

The carriage-return-terminated (or ETX-terminated) status and error strings displayed by the sub-command handlers and the shared error tail. Two positions are patched at run time: the drive digit in the insert-diskette prompt (5CD9H) and the two drive digits in the swap message (5D44H/5D4BH). Data.

5B31-5B5A
DEFM "Can't -- Valid only at LDOS command level",0DH 43 61 6E 27 74 20 2D 2D 20 56 61 6C 69 64 20 6F 6E 6C 79 20 61 74 20 4C 44 4F 53 20 63 6F 6D 6D 61 6E 64 20 6C 65 76 65 6C 0D
Command-level refusal shown when a command-level-only sub-command is used during JCL.
5B5B-5B7B
DEFM "Preparing to alter configuration",0DH 50 72 65 70 61 72 69 6E 67 20 74 6F 20 61 6C 74 65 72 20 63 6F 6E 66 69 67 75 72 61 74 69 6F 6E 0D
SYSGEN progress notice, shown before the SYSGEN overlay is invoked.
5B7C-5B95
DEFM "CYL=c invalid on 8" drive",0DH 43 59 4C 3D 63 20 69 6E 76 61 6C 69 64 20 6F 6E 20 38 22 20 64 72 69 76 65 0D
Error: a cylinder count was given for an 8-inch drive (fixed geometry).
5B96-5BB9
DEFM "Cylinder count out of range <35-96>",0DH 43 79 6C 69 6E 64 65 72 20 63 6F 75 6E 74 20 6F 75 74 20 6F 66 20 72 61 6E 67 65 20 3C 33 35 2D 39 36 3E 0D
Error: the requested cylinder count is outside the valid 35-96 range.
5BBA-5BDB
DEFM "Can't SYSGEN with active SPOOLER!",0DH 43 61 6E 27 74 20 53 59 53 47 45 4E 20 77 69 74 68 20 61 63 74 69 76 65 20 53 50 4F 4F 4C 45 52 21 0D
Error: SYSGEN was requested while a background print spooler is active.
5BDC-5BF9
DEFM "Can't SYSRES requested module",0DH 43 61 6E 27 74 20 53 59 53 52 45 53 20 72 65 71 75 65 73 74 65 64 20 6D 6F 64 75 6C 65 0D
Error: the requested overlay cannot be made resident by SYSRES.
5BFA-5C18
DEFM "System module already resident",0DH 53 79 73 74 65 6D 20 6D 6F 64 75 6C 65 20 61 6C 72 65 61 64 79 20 72 65 73 69 64 65 6E 74 0D
Status: the requested SYSRES overlay is already resident in high memory.
5C19-5C3C
DEFM "Enter DCT driver <BREAK=default> : ",03H 45 6E 74 65 72 20 44 43 54 20 64 72 69 76 65 72 20 3C 42 52 45 41 4B 3D 64 65 66 61 75 6C 74 3E 20 3A 20 03
Prompt for the DCT driver filespec; BREAK selects the default drivers (ETX-terminated).
5C3D-5C5A
DEFM "TYPE requires KI to be active",0DH 54 59 50 45 20 72 65 71 75 69 72 65 73 20 4B 49 20 74 6F 20 62 65 20 61 63 74 69 76 65 0D
Error: TYPE requires the KI/DVR keyboard driver to be active.
5C5B-5C6F
DEFM "Type-ahead is now on",0DH 54 79 70 65 2D 61 68 65 61 64 20 69 73 20 6E 6F 77 20 6F 6E 0D
Status: keyboard type-ahead is now enabled.
5C70-5C85
DEFM "Type-ahead is now off",0DH 54 79 70 65 2D 61 68 65 61 64 20 69 73 20 6E 6F 77 20 6F 66 66 0D
Status: keyboard type-ahead is now disabled.
5C86-5C9D
DEFM "Type-ahead not resident",0DH 54 79 70 65 2D 61 68 65 61 64 20 6E 6F 74 20 72 65 73 69 64 65 6E 74 0D
Error: the type-ahead task is not resident.
5C9E-5CB8
DEFM "New SYSTEM drive installed",0DH 4E 65 77 20 53 59 53 54 45 4D 20 64 72 69 76 65 20 69 6E 73 74 61 6C 6C 65 64 0D
Message string for a new system drive. Not referenced by this overlay (orphan data).
5CB9-5CDB
DEFM "Insert SYSTEM diskette in drive X!",0DH 49 6E 73 65 72 74 20 53 59 53 54 45 4D 20 64 69 73 6B 65 74 74 65 20 69 6E 20 64 72 69 76 65 20 58 21 0D
Prompt to insert a system diskette; the drive digit is patched at 5CD9H.
5CDC-5CF1
DEFM "Manual <BREAK> abort!",0DH 4D 61 6E 75 61 6C 20 3C 42 52 45 41 4B 3E 20 61 62 6F 72 74 21 0D
Status: the user pressed BREAK at the insert-diskette prompt.
5CF2-5D1A
DEFM "Can't prompt for SYSTEM disk during JCL!",0DH 43 61 6E 27 74 20 70 72 6F 6D 70 74 20 66 6F 72 20 53 59 53 54 45 4D 20 64 69 73 6B 20 64 75 72 69 6E 67 20 4A 43 4C 21 0D
Error: a system-disk prompt is not possible while a JCL file is running.
5D1B-5D3B
DEFM "Drive specification error <0-7>!",0DH 44 72 69 76 65 20 73 70 65 63 69 66 69 63 61 74 69 6F 6E 20 65 72 72 6F 72 20 3C 30 2D 37 3E 21 0D
Error: a drive number outside 0-7 was given to SWAP/SYSTEM=.
5D3C-5D58
DEFM "Drives :S and :D now swapped",0DH 44 72 69 76 65 73 20 3A 53 20 61 6E 64 20 3A 44 20 6E 6F 77 20 73 77 61 70 70 65 64 0D
Status: the two drives were swapped; the digits are patched at 5D44H and 5D4BH.
5D59-5D81
DEFM "Source & Destination are the same drive!",0DH 53 6F 75 72 63 65 20 26 20 44 65 73 74 69 6E 61 74 69 6F 6E 20 61 72 65 20 74 68 65 20 73 61 6D 65 20 64 72 69 76 65 21 0D
Error: the source and destination drives of a swap are the same.
5D82-5D9F
DEFM "SVC table already implemented",0DH 53 56 43 20 74 61 62 6C 65 20 61 6C 72 65 61 64 79 20 69 6D 70 6C 65 6D 65 6E 74 65 64 0D
Status: the SVC table was already installed.
5DA0-5DB7
DEFM "SVC table now installed",0DH 53 56 43 20 74 61 62 6C 65 20 6E 6F 77 20 69 6E 73 74 61 6C 6C 65 64 0D
Status: the SVC table was installed into high memory.
5DB8-5DD5
DEFM "Boot step out of range <0-3>!",0DH 42 6F 6F 74 20 73 74 65 70 20 6F 75 74 20 6F 66 20 72 61 6E 67 65 20 3C 30 2D 33 3E 21 0D
Error: the bootstrap step rate is outside the valid 0-3 range.
5DD6-5DF2
DEFM "Printer filter not resident!",0DH 50 72 69 6E 74 65 72 20 66 69 6C 74 65 72 20 6E 6F 74 20 72 65 73 69 64 65 6E 74 21 0D
Error: the printer filter (PR/FLT) is not resident (PRTIME).
5DF3-5DF5
DEFM "DCT" 44 43 54
Default file extension /DCT applied by @FEXT to the DRIVER filespec. Data.

5DF6H - @PARAM Keyword Descriptor Table

The table @PARAM (4476H) scans at entry (DE = 5DF6H). Each 8-byte entry is a six-character, space-padded keyword followed by the two-byte address of that keyword's value cell (the operand of a LD BC,nnnn test instruction in the corresponding handler). A 00H byte terminates the table. Data.

5DF6-5DFD
DEFM "ALIVE "; DEFW 5518H 41 4C 49 56 45 20 18 55
Keyword "ALIVE" -> value cell 5518H.
5DFE-5E05
DEFM "BASIC2"; DEFW 5237H 42 41 53 49 43 32 37 52
Keyword "BASIC2" -> value cell 5237H.
5E06-5E0D
DEFM "BSTEP "; DEFW 53B5H 42 53 54 45 50 20 B5 53
Keyword "BSTEP" -> value cell 53B5H.
5E0E-5E15
DEFM "DRIVER"; DEFW 590EH 44 52 49 56 45 52 0E 59
Keyword "DRIVER" -> value cell 590EH.
5E16-5E1D
DEFM "FAST "; DEFW 5215H 46 41 53 54 20 20 15 52
Keyword "FAST" -> value cell 5215H.
5E1E-5E25
DEFM "SLOW "; DEFW 520EH 53 4C 4F 57 20 20 0E 52
Keyword "SLOW" -> value cell 520EH.
5E26-5E2D
DEFM "SVC "; DEFW 5593H 53 56 43 20 20 20 93 55
Keyword "SVC" -> value cell 5593H.
5E2E-5E35
DEFM "SWAP "; DEFW 59C6H 53 57 41 50 20 20 C6 59
Keyword "SWAP" -> value cell 59C6H.
5E36-5E3D
DEFM "SYSRES"; DEFW 5706H 53 59 53 52 45 53 06 57
Keyword "SYSRES" -> value cell 5706H.
5E3E-5E45
DEFM "SYSTEM"; DEFW 59B4H 53 59 53 54 45 4D B4 59
Keyword "SYSTEM" -> value cell 59B4H.
5E46-5E4D
DEFM "TYPE "; DEFW 54B5H 54 59 50 45 20 20 B5 54
Keyword "TYPE" -> value cell 54B5H.
5E4E-5E55
DEFM "TRACE "; DEFW 539EH 54 52 41 43 45 20 9E 53
Keyword "TRACE" -> value cell 539EH.
5E56-5E5D
DEFM "WP "; DEFW 585AH 57 50 20 20 20 20 5A 58
Keyword "WP" -> value cell 585AH.
5E5E-5E65
DEFM "BLINK "; DEFW 53DEH 42 4C 49 4E 4B 20 DE 53
Keyword "BLINK" -> value cell 53DEH.
5E66-5E6D
DEFM "BREAK "; DEFW 5277H 42 52 45 41 4B 20 77 52
Keyword "BREAK" -> value cell 5277H.
5E6E-5E75
DEFM "CYL "; DEFW 586FH 43 59 4C 20 20 20 6F 58
Keyword "CYL" -> value cell 586FH.
5E76-5E7D
DEFM "DATE "; DEFW 5370H 44 41 54 45 20 20 70 53
Keyword "DATE" -> value cell 5370H.
5E7E-5E85
DEFM "DELAY "; DEFW 58D5H 44 45 4C 41 59 20 D5 58
Keyword "DELAY" -> value cell 58D5H.
5E86-5E8D
DEFM "DISABL"; DEFW 589DH 44 49 53 41 42 4C 9D 58
Keyword "DISABL" -> value cell 589DH.
5E8E-5E95
DEFM "DRIVE "; DEFW 582DH 44 52 49 56 45 20 2D 58
Keyword "DRIVE" -> value cell 582DH.
5E96-5E9D
DEFM "ENABLE"; DEFW 58AEH 45 4E 41 42 4C 45 AE 58
Keyword "ENABLE" -> value cell 58AEH.
5E9E-5EA5
DEFM "GRAPHI"; DEFW 5504H 47 52 41 50 48 49 04 55
Keyword "GRAPHI" -> value cell 5504H.
5EA6-5EAD
DEFM "LARGE "; DEFW 5467H 4C 41 52 47 45 20 67 54
Keyword "LARGE" -> value cell 5467H.
5EAE-5EB5
DEFM "SMALL "; DEFW 541AH 53 4D 41 4C 4C 20 1A 54
Keyword "SMALL" -> value cell 541AH.
5EB6-5EBD
DEFM "STEP "; DEFW 58BAH 53 54 45 50 20 20 BA 58
Keyword "STEP" -> value cell 58BAH.
5EBE-5EC5
DEFM "SMOOTH"; DEFW 54F2H 53 4D 4F 4F 54 48 F2 54
Keyword "SMOOTH" -> value cell 54F2H.
5EC6-5ECD
DEFM "SYSGEN"; DEFW 5A30H 53 59 53 47 45 4E 30 5A
Keyword "SYSGEN" -> value cell 5A30H.
5ECE-5ED5
DEFM "TIME "; DEFW 5387H 54 49 4D 45 20 20 87 53
Keyword "TIME" -> value cell 5387H.
5ED6-5EDD
DEFM "PRTIME"; DEFW 5257H 50 52 54 49 4D 45 57 52
Keyword "PRTIME" -> value cell 5257H.
5EDE-5EE5
DEFM "UPDATE"; DEFW 5290H 55 50 44 41 54 45 90 52
Keyword "UPDATE" -> value cell 5290H.
5EE6
DEFB 00H 00
Table terminator (end of the @PARAM keyword list) and the last byte of the SYSTEM overlay. Data.

Disassembly - Overlay 8 - BUILD

5200H - BUILD Command (Command 33H)

Build a keystroke (KSM) or JCL file from lines typed at the keyboard. BUILD opens or creates the named file (default extension /JCL), reads lines with @KEYIN until BREAK, and writes them to the file. The HEX option packs typed hexadecimal digit pairs into bytes; the APPEND option adds to an existing file instead of refusing it. A /KSM file gets lettered "A=> " keystroke-label prompts.

5200
LD (535CH),SP ED 73 5C 53
Self-Modifying Code
Save the caller's stack pointer into 535CH, the operand of the LD SP,nnnn at 535BH, so the caller's stack can be restored on exit.
5204
LD DE,5403H 11 03 54
Point Register Pair DE at the file control block buffer at 5403H for the file specification.
5207
GOSUB to the resident SYS0 service @FSPEC (441CH) to parse the file specification from the command line (HL) into the FCB at DE (5403H). Returns the NZ FLAG on a bad specification.
520A
If the NZ FLAG is set (no or bad file specification), JUMP to 5349H to report "File spec required".
520D
PUSH HL E5
Save the command-line pointer (Register Pair HL) onto the stack across the default-extension call.
520E
LD HL,53DFH 21 DF 53
Point HL at the default extension string "JCL" at 53DFH for @FEXT.
5211
GOSUB to the resident SYS0 service @FEXT (4473H) to apply the default extension "JCL" (at HL) to the FCB when the user gave no extension.
5214
POP HL E1
Restore the command-line pointer (Register Pair HL) from the stack.
5215
LD DE,53E2H 11 E2 53
Point Register Pair DE at the keyword descriptor table at 53E2H (HEX and APPEND) for @PARAM.
5218
GOSUB to the resident SYS0 service @PARAM (4476H) to parse the "(HEX, APPEND)" parameters into the flag cells named by the 53E2H table. Returns the NZ FLAG on a bad parameter list.
521B
If the NZ FLAG is set (a malformed parameter), JUMP to 5314H to raise the parameter error.
521E
LD HL,5403H 21 03 54
Point HL at the FCB at 5403H to scan the file specification's extension for the "KSM" and "JCL" markers.
5221
LD A,(HL) 7E
Loop Start
Fetch the next file-specification character (addressed by HL) into Register A.
5222
INC HL 23
Advance HL to the next character of the file specification.
5223
CP 0DH FE 0D
Compare Register A against 0DH (end of the specification). If equal the Z FLAG is set.
5225
If the Z FLAG is set (end of the specification with no extension found), JUMP to 5240H.
5227
CP 2FH FE 2F
Compare Register A against 2FH (ASCII /), the extension separator. If equal the Z FLAG is set.
5229
If the NZ FLAG is set (not the extension separator yet), LOOP BACK to 5221H. Loop End
522B
PUSH HL E5
Save the pointer to the extension (Register Pair HL) so both the KSM and JCL checks can start from it.
522C
LD A,(HL) 7E
Fetch the first extension character (addressed by HL) into Register A.
522D
INC HL 23
Advance HL to the second extension character.
522E
CP 4BH FE 4B
Compare Register A (first extension character) against 4BH (ASCII K), the start of the "KSM" extension. If equal the Z FLAG is set.
5230
If the NZ FLAG is set (extension does not start with K), JUMP to 5240H to try the JCL check.
5232
LD A,(HL) 7E
Fetch the second extension character (addressed by HL) into Register A.
5233
INC HL 23
Advance HL to the third extension character.
5234
CP 53H FE 53
Compare Register A (second extension character) against 53H (ASCII S). If equal the Z FLAG is set.
5236
If the NZ FLAG is set (second character is not S), JUMP to 5240H.
5238
LD A,(HL) 7E
Fetch the third extension character (addressed by HL) into Register A.
5239
CP 4DH FE 4D
Compare Register A (third extension character) against 4DH (ASCII M), completing the "KSM" test. If equal the Z FLAG is set.
523B
If the NZ FLAG is set (extension is not KSM), JUMP to 5240H.
523D
LD (529DH),A 32 9D 52
Self-Modifying Code
Store the 'M' character (Register A) into 529DH, the operand of the LD A,00H at 529CH, marking KSM mode so the input loop shows lettered keystroke-label prompts.
5240
POP HL E1
Restore the extension pointer (Register Pair HL) for the JCL check.
5241
LD A,(HL) 7E
Fetch the first extension character (addressed by HL) into Register A.
5242
INC HL 23
Advance HL to the second extension character.
5243
CP 4AH FE 4A
Compare Register A (first extension character) against 4AH (ASCII J), the start of the "JCL" extension. If equal the Z FLAG is set.
5245
If the NZ FLAG is set (extension does not start with J), JUMP to 5257H to open the file.
5247
LD A,(HL) 7E
Fetch the second extension character (addressed by HL) into Register A.
5248
INC HL 23
Advance HL to the third extension character.
5249
CP 43H FE 43
Compare Register A (second extension character) against 43H (ASCII C). If equal the Z FLAG is set.
524B
If the NZ FLAG is set (second character is not C), JUMP to 5257H.
524D
LD A,(HL) 7E
Fetch the third extension character (addressed by HL) into Register A.
524E
CP 4CH FE 4C
Compare Register A (third extension character) against 4CH (ASCII L), completing the "JCL" test. If equal the Z FLAG is set.
5250
If the NZ FLAG is set (extension is not JCL), JUMP to 5257H.
5252
LD A,3FH 3E 3F
Load Register A with 3FH (63), the JCL line-length limit for keyboard input.
5254
LD (52BEH),A 32 BE 52
Self-Modifying Code
Store 3FH (Register A) into 52BEH, the operand of the LD B,0FFH at 52BDH, limiting JCL input lines to 63 characters.
5257
LD HL,5500H 21 00 55
Point HL at the file's record buffer at 5500H for @INIT.
525A
LD DE,5403H 11 03 54
Point Register Pair DE at the FCB at 5403H for @INIT.
525D
LD B,L 45
Copy the low byte of HL (00H) into Register B, requesting the default logical record length of 256 from @INIT.
525E
GOSUB to the resident SYS0 service @INIT (4420H) to open the file if it exists or create it if not, using the FCB at DE and buffer at HL. Returns the NZ FLAG on error, and the CARRY FLAG set when the file was newly created.
5261
If the NZ FLAG is set (the file could not be opened or created), JUMP to 5316H to report the error.
5264
PUSH AF F5
Save the @INIT result flags (Register A and flags, including the created/existed CARRY) onto the stack.
5265
LD DE,5423H 11 23 54
Point Register Pair DE at the name buffer at 5423H for the name builder.
5268
LD BC,(5409H) ED 4B 09 54
Load Register Pair BC from 5409H (the FCB directory locator) for the name builder.
526C
LD A,(5403H) 3A 03 54
Fetch the first FCB byte from 5403H into Register A; its bit 7 distinguishes an open disk file from a device.
526F
GOSUB to the name builder at 531DH to build the file or device name string into the buffer at DE (5423H). Returns the NZ FLAG on error.
5272
If the NZ FLAG is set (the name could not be built), JUMP to 5316H to report the error.
5275
POP AF F1
Restore the @INIT result flags (the created/existed CARRY) from the stack.
5276
LD HL,53C1H 21 C1 53
Point HL at the message "Building: " at 53C1H, the prompt for a newly created file.
5279
If the CARRY FLAG is set (the file was newly created), JUMP to 528BH to display "Building: ".
527B
LD BC,0000H 01 00 00
Self-Modifying Code
Load Register Pair BC with the APPEND flag. The low byte at 527CH is set to FFH by @PARAM when the APPEND keyword is given (default 0).
527E
LD DE,5403H 11 03 54
Point Register Pair DE at the FCB at 5403H for the end-of-file positioning done on the append path.
5281
INC C 0C
Increment the APPEND flag low byte (C). When APPEND was not given (C was 0) this yields 1 (NZ); when APPEND was given (C was FFH) this yields 0 (Z).
5282
If the NZ FLAG is set (the file already exists and APPEND was not given), JUMP to 534DH to report "File already exists".
5285
GOSUB to the resident SYS0 service @PEOF (4448H) to position the existing file to its end so new lines are appended.
5288
LD HL,53CCH 21 CC 53
Point HL at the message "Appending: *KI to " at 53CCH for the append path.
528B
GOSUB to the resident SYS0 service @DSPLY (4467H) to display "Building: " or "Appending: *KI to " (addressed by HL).
528E
LD HL,5423H 21 23 54
Point HL at the built file name at 5423H to display it after the prompt.
5291
GOSUB to @DSPLY (4467H) to display the file name (addressed by HL at 5423H).
5294
LD A,0DH 3E 0D
Load Register A with 0DH (carriage return) to end the prompt line.
5296
GOSUB to the ROM character output routine @DSP (0033H) to print the carriage return in Register A.

5299H - Keyboard Input Loop

Read lines from the keyboard into the buffer at 5600H until BREAK. In KSM mode each line is preceded by a lettered "A=> " prompt. In text mode the typed characters are kept as is; in HEX mode each line's hexadecimal digit pairs are packed into bytes in place.

5299
LD HL,5600H 21 00 56
Point HL at the input collection buffer at 5600H, the destination for typed lines.
529C
LD A,00H 3E 00
Self-Modifying Code
Load Register A with the KSM-mode flag. The operand at 529DH was set to 'M' at 523DH when the file extension is KSM, otherwise it is 0.
529E
OR A B7
Test the KSM flag (Register A). If it is zero (not a KSM file) the Z FLAG is set.
529F
If the Z FLAG is set (not KSM), JUMP to 52BDH to read a line without a prompt.
52A1
LD A,40H 3E 40
Self-Modifying Code
Load Register A with the current keystroke-label letter. The operand at 52A2H starts at 40H ('@') and is incremented for each KSM line.
52A3
INC A 3C
Increment the label letter (Register A) so the first prompt is 'A', the next 'B', and so on.
52A4
LD (52A2H),A 32 A2 52
Self-Modifying Code
Store the incremented label letter (Register A) back into 52A2H so the next line advances to the following letter.
52A7
CP 5BH FE 5B
Compare the label letter (Register A) against 5BH (ASCII [), the character just past 'Z'. If equal the Z FLAG is set, meaning all 26 keystroke labels are used.
52A9
If the Z FLAG is set (past label 'Z'), JUMP to 52ECH to finish and write the file.
52AB
GOSUB to the ROM output routine @DSP (0033H) to display the keystroke-label letter in Register A.
52AE
LD A,3DH 3E 3D
Load Register A with 3DH (ASCII =) for the prompt.
52B0
GOSUB to @DSP (0033H) to display the "=" of the prompt.
52B3
LD A,3EH 3E 3E
Load Register A with 3EH (ASCII >) for the prompt.
52B5
GOSUB to @DSP (0033H) to display the ">" of the prompt.
52B8
LD A,20H 3E 20
Load Register A with 20H (ASCII space) to finish the "A=> " prompt.
52BA
GOSUB to @DSP (0033H) to display the trailing space of the prompt.
52BD
LD B,0FFH 06 FF
Self-Modifying Code
Load Register B with the maximum line length for @KEYIN. The operand at 52BEH is FFH (255) normally or 3FH (63) for a JCL file.
52BF
GOSUB to the ROM line-input routine @KEYIN (0040H) to read a line of up to B characters into the buffer at HL. Returns the CARRY FLAG set if BREAK was pressed and Register B with the count of characters entered.
52C2
If the CARRY FLAG is set (BREAK pressed), JUMP to 52E8H to finish input.
52C4
LD DE,0000H 11 00 00
Self-Modifying Code
Load Register Pair DE with the HEX-mode flag. The low byte E at 52C5H is set to FFH by @PARAM when HEX is given, otherwise 0.
52C7
INC E 1C
Increment the HEX flag byte (E). When HEX was given (E was FFH) this yields 0 (Z); otherwise it yields 1 (NZ).
52C8
If the NZ FLAG is set (not HEX mode), JUMP to 52E1H to keep the typed line as text.
52CA
LD D,H 54
Copy H into D to make DE a second pointer over the same line for reading hexadecimal digits.
52CB
LD E,L 5D
Copy L into E so DE now addresses the start of the typed line, the source of hexadecimal digits.
52CC
Loop Start
GOSUB to the hex-digit reader at 5330H to read one hexadecimal digit from (DE) into the low nibble of Register A. Returns the CARRY FLAG on a non-hex character.
52CF
DEC B 05
Decrement the remaining character count (Register B). If it reaches zero after only one nibble the digit count was odd.
52D0
If the Z FLAG is set (an odd number of hex digits), JUMP to 5345H to report "Odd # of hex digits!".
52D2
RLCA 07
Rotate Register A left, the first of four rotates moving the first digit into the high nibble of the packed byte.
52D3
RLCA 07
Rotate Register A left (second of four).
52D4
RLCA 07
Rotate Register A left (third of four).
52D5
RLCA 07
Rotate Register A left (fourth), leaving the first digit in the high nibble.
52D6
LD C,A 4F
Save the high nibble (Register A) into Register C while the second digit is read.
52D7
GOSUB to the hex-digit reader at 5330H to read the second hexadecimal digit into the low nibble of Register A.
52DA
OR C B1
Combine the high nibble (Register C) with the low nibble (Register A) to form the packed byte.
52DB
LD (HL),A 77
Store the packed byte (Register A) into the buffer at HL, overwriting the two source digits in place.
52DC
INC HL 23
Advance HL to the next output byte position in the buffer.
52DD
DECrement Register B and LOOP BACK to 52CCH for the next digit pair until the line is consumed. Loop End
52DF
JUMP back to 529CH to read the next line.
52E1
LD C,B 48
Copy the line length (Register B) into C to advance the buffer pointer past the text line just entered.
52E2
LD B,00H 06 00
Clear Register B so BC holds the line length as a 16-bit value.
52E4
ADD HL,BC 09
Add the line length (BC) to the buffer pointer (HL), moving it past the text line.
52E5
INC HL 23
Advance HL one more byte past the line's terminator.
52E6
JUMP back to 529CH to read the next line.
52E8
LD A,B 78
BREAK was pressed. Copy the count of characters on the current partial line (Register B) into Register A.
52E9
OR A B7
Test the partial-line count (Register A). If any characters were entered before BREAK the NZ FLAG is set.
52EA
If the NZ FLAG is set (a partial line remains), JUMP to 52C4H to process it before finishing.

52ECH - Write Buffer to File and Close

Write the collected input from 5600H up to the current pointer out to the file byte by byte with @PUT, then close the file. The error tail displays a message and sets the failure code; the exit tail restores the stack.

52EC
LD (52F3H),HL 22 F3 52
Self-Modifying Code
Store the end-of-input pointer (HL) into 52F3H, the operand of the LD DE,nnnn at 52F2H, marking where the collected data ends.
52EF
LD HL,5600H 21 00 56
Point HL back at the start of the collected input at 5600H for the write-out loop.
52F2
LD DE,0000H 11 00 00
Self-Modifying Code
Load Register Pair DE with the end-of-input pointer saved at 52F3H, to compare against the running pointer.
52F5
EX DE,HL EB
Exchange DE and HL so HL holds the end pointer and DE holds the running pointer for the subtraction.
52F6
XOR A AF
Clear Register A and the CARRY FLAG before the pointer comparison.
52F7
SBC HL,DE ED 52
Subtract the running pointer (DE) from the end pointer (HL). A zero result (Z FLAG set) means all collected bytes have been written.
52F9
If the Z FLAG is set (all bytes written), JUMP to 5306H to close the file.
52FB
EX DE,HL EB
Exchange back so HL again addresses the next byte to write.
52FC
LD DE,5403H 11 03 54
Point Register Pair DE at the FCB at 5403H, the file the byte is written to.
52FF
LD A,(HL) 7E
Fetch the next collected byte (addressed by HL) into Register A.
5300
INC HL 23
Advance HL to the next byte to write.
5301
GOSUB to the ROM output routine @PUT (001BH) to write the byte in Register A to the file whose FCB is in DE. Returns the Z FLAG on a successful write.
5304
If the Z FLAG is set (the byte was written), LOOP BACK to 52F2H for the next byte. On error execution falls through.
5306
PUSH AF F5
Save the write result flags (Register A and flags) onto the stack across the close.
5307
LD DE,5403H 11 03 54
Point Register Pair DE at the FCB at 5403H for the close.
530A
GOSUB to the resident SYS0 service @CLOSE (4428H) to close the file, writing its directory entry. Returns the NZ FLAG on error.
530D
If the NZ FLAG is set (the close failed), JUMP to 5316H to report the error.
530F
POP AF F1
Restore the write result flags from the stack.
5310
If the Z FLAG is set (the writes and close both succeeded), JUMP to 5358H to return success.
5313
LD BC,2C3EH 01 3E 2C
The write failed with a residual error; load BC with 2C3EH so Register A becomes 2CH (parameter error) as execution falls into the error tail (the 3EH/2CH bytes double as the LD A,2CH reached by entering at 5314H).
5314
LD A,2CH 3E 2C
Load Register A with error code 2CH (parameter error). This entry is reached from the @PARAM failure at 521BH; it is the low two bytes of the LD BC,2C3EH above.
5316
OR 0C0H F6 C0
Set bits 7 and 6 of the error code in Register A so @ERROR displays the message and returns. This is the shared error tail.
5318
GOSUB to the resident SYS0 service @ERROR (4409H) to display the system error message for the code in Register A.
531B
JUMP to 5353H to set the failure return code and exit.

531DH - Name Builder Helper

Build the file or device name string. For an open disk file (FCB first byte bit 7 set) it defers to @FNAME; for a device it writes a "*XX" name from the two device characters in Register Pair BC.

531D
BIT 7,A CB 7F
Test bit 7 of the FCB first byte (Register A). Bit 7 set means an open disk file; clear means a device.
531F
If the NZ FLAG is set (an open disk file), JUMP to the resident SYS0 service @FNAME (44BBH) to build the "NAME/EXT:d" string (located by BC) into the buffer at DE, returning to BUILD's caller.
5322
LD A,2AH 3E 2A
Load Register A with 2AH (ASCII *), the device-name prefix.
5324
LD (DE),A 12
Store the "*" (Register A) into the name buffer at DE.
5325
INC DE 13
Advance DE to the next buffer position.
5326
LD A,C 79
Copy the first device-name character (Register C) into Register A.
5327
LD (DE),A 12
Store the first device character (Register A) into the buffer at DE.
5328
INC DE 13
Advance DE to the next buffer position.
5329
LD A,B 78
Copy the second device-name character (Register B) into Register A.
532A
LD (DE),A 12
Store the second device character (Register A) into the buffer at DE.
532B
INC DE 13
Advance DE to the next buffer position.
532C
LD A,03H 3E 03
Load Register A with 03H (ETX), the terminator @DSPLY expects at the end of the name.
532E
LD (DE),A 12
Store the ETX terminator (Register A) into the buffer at DE, completing the "*XX" device name.
532F
RET C9
RETurn to the caller with the Z FLAG set (Register A ETX is 03H, non-zero, but the success path relies on the built name; the caller treats a return here as success).

5330H - Hexadecimal Digit Reader

Read one character from the line at (DE), convert it from ASCII to a 0-15 value, and return the CARRY FLAG set when the character is a valid hexadecimal digit (0-9 or A-F).

5330
LD A,(DE) 1A
Fetch the next line character (addressed by DE) into Register A.
5331
INC DE 13
Advance DE to the next line character.
5332
SUB 30H D6 30
Subtract 30H (ASCII 0) from Register A to convert a decimal digit to its value. A character below '0' produces a borrow (CARRY set).
5334
If the CARRY FLAG is set (character below '0', not a digit), JUMP to 5340H to report a bad hex digit.
5336
CP 0AH FE 0A
Compare the value (Register A) against 0AH (10). A value below 10 is a decimal digit 0-9, and sets the CARRY FLAG.
5338
RET C D8
If the CARRY FLAG is set (a valid 0-9 digit), RETurn to the caller with the digit value in Register A.
5339
RES 5,A CB AF
Clear bit 5 of Register A to fold a lowercase letter to uppercase for the A-F range test.
533B
SUB 07H D6 07
Subtract 7 from Register A so the letters A-F (ASCII 41H-46H, already reduced by 30H to 11H-16H) map onto the values 0AH-0FH.
533D
CP 10H FE 10
Compare the value (Register A) against 10H (16). A value below 16 is a valid hex digit A-F and sets the CARRY FLAG.
533F
RET C D8
If the CARRY FLAG is set (a valid A-F digit), RETurn to the caller with the value in Register A. Otherwise execution falls into the bad-digit report.

5340H - Message Display and Exit

Report a bad hexadecimal digit, or (through the DD-prefix overlap) one of three other messages, then set the failure code. The exit tail restores the caller's stack and returns, or aborts to @ABORT if the command was not issued at the LDOS command level.

5340
POP AF F1
Discard the hex-reader's return address from the stack so the bad-digit report returns to the command's exit rather than back into the packing loop.
5341
LD HL,537FH 21 7F 53
Point HL at the message "Bad hex digit encountered!" at 537FH.
5344
LD IX,536AH DD 21 6A 53
Overlapping Code
On fall-through this loads IX with 536AH with no effect (HL already points at "Bad hex digit encountered!"). Entered at 5345H (skipping the DD prefix) the bytes 21 6A 53 decode as LD HL,536AH, pointing HL at "Odd # of hex digits!". 5345H is reached from the odd-digit test at 52D0H.
5348
LD IX,539AH DD 21 9A 53
Overlapping Code
On fall-through this loads IX with 539AH with no effect. Entered at 5349H the bytes 21 9A 53 decode as LD HL,539AH, pointing HL at "File spec required". 5349H is reached from the @FSPEC failure at 520AH.
534C
LD IX,53ADH DD 21 AD 53
Overlapping Code
On fall-through this loads IX with 53ADH with no effect. Entered at 534DH the bytes 21 AD 53 decode as LD HL,53ADH, pointing HL at "File already exists". 534DH is reached from the existing-file test at 5282H.
5350
GOSUB to the resident SYS0 service @LOGOT (447BH) to display the carriage-return-terminated message pointed to by HL.
5353
LD HL,0FFFFH 21 FF FF
Set HL to FFFFH, the non-zero failure return code.
5356
JUMP to the exit tail at 535BH.
5358
LD HL,0000H 21 00 00
Set HL to 0000H, the success return code.
535B
LD SP,0000H 31 00 00
Self-Modifying Code
Restore the caller's stack pointer. The operand at 535CH was overwritten at 5200H with the caller's SP.
535E
LD A,H 7C
Copy the high byte of the return code (H) into Register A to test for success.
535F
OR L B5
OR the low byte (L) into Register A; the Z FLAG is set for a zero (success) code.
5360
RET Z C8
If the Z FLAG is set (success), RETurn to the RST 28H dispatcher.
5361
LD A,(430FH) 3A 0F 43
Fetch SFLAG$ from 430FH into Register A to test the command-level flag on the error path.
5364
BIT 5,A CB 6F
Test bit 5 of SFLAG$ (Register A); it is set when the system is not at the LDOS command level. If clear the Z FLAG is set.
5366
RET Z C8
If the Z FLAG is set (at the command level), RETurn to the dispatcher with the failure code.
5367
Otherwise (not at command level), JUMP to the resident SYS0 service @ABORT (4030H) to abort back to DOS.

536AH - Messages, Parameter Table, and Default Extension

The message strings, the @PARAM keyword table, and the default extension. These are data, not code.

536A-537E
DEFM 'Odd # of hex digits!' + 0DH 4F 64 64 20 ...
Error message for an odd number of hexadecimal digits on a line in HEX mode (reached via 5345H). Terminated by 0DH at 537EH.
537F-5399
DEFM 'Bad hex digit encountered!' + 0DH 42 61 64 20 ...
Error message for a non-hexadecimal character in HEX mode (reached via 5341H). Terminated by 0DH at 5399H.
539A-53AC
DEFM 'File spec required' + 0DH 46 69 6C 65 ...
Error message when no file specification was supplied (reached via 5349H). Terminated by 0DH at 53ACH.
53AD-53C0
DEFM 'File already exists' + 0DH 46 69 6C 65 ...
Error message when the named file exists and APPEND was not given (reached via 534DH). Terminated by 0DH at 53C0H.
53C1-53CB
DEFM 'Building: ' + 03H 42 75 69 6C ...
Prompt shown by @DSPLY for a newly created file, followed by the file name. Terminated by 03H at 53CBH.
53CC-53DE
DEFM 'Appending: *KI to ' + 03H 41 70 70 65 ...
Prompt shown by @DSPLY when appending to an existing file, followed by the file name. Terminated by 03H at 53DEH.
53DF-53E1
DEFM 'JCL' 4A 43 4C
The default file extension applied by @FEXT at 5211H when the user gives no extension.
53E2-5401
DEFM 'HEX'/'H' 52C5H, 'APPEND'/'A' 527CH 48 45 58 20 ...
@PARAM keyword descriptor table (8-byte entries, six-character space-padded keyword + two-byte flag-cell address): HEX (and abbreviation H) set the hex-mode flag at 52C5H; APPEND (and abbreviation A) set the append flag at 527CH. Terminated by 00H at 5402H.

Disassembly - Overlay 9 - ATTRIB

5200H - ATTRIB Command (Command 51H)

Set the attributes and passwords of a disk file, or of a whole diskette. A file specification selects the file form: @FSPEC parses the name, @OPEN opens the file, the command line is upcased, and the parenthesized options are scanned. No file name selects the diskette form at 53C5H. The entry also records, from the resident extended-dating bitmap at 475DH, whether this drive still has a usable access-password field.

5200
LD (54BDH),SP ED 73 BD 54
Self-Modifying Code
Save the caller's stack pointer into 54BDH, the operand of the LD SP,nnnn at 54BCH, so the caller's stack can be restored when the command exits.
5204
LD DE,56D6H 11 D6 56
Point Register Pair DE at 56D6H, the file control block scratch area just above the overlay image, where @FSPEC will build the parsed file specification.
5207
GOSUB to the resident SYS0 service @FSPEC (441CH) to parse the file specification on the command line (Register Pair HL) into the FCB at DE (56D6H). Returns the NZ FLAG when there is no valid file name.
520A
If the NZ FLAG is set (no file name given, so this is a diskette-level ATTRIB), JUMP to 53C5H to handle the disk-attribute form of the command.
520D
LD A,(DE) 1A
Fetch the first byte of the parsed FCB (addressed by DE at 56D6H), the first character of the file name, into Register A.
520E
CP 2AH FE 2A
Compare Register A (the first file-name character) against 2AH (ASCII *). A leading asterisk denotes a device, which cannot be ATTRIBed. If equal the Z FLAG is set.
5210
If the Z FLAG is set (a device was named), JUMP to 5588H to report "File spec required".
5213
PUSH HL E5
Save the command-line pointer (Register Pair HL) on the stack while the file is opened.
5214
LD HL,4200H 21 00 42
Point Register Pair HL at 4200H, the resident sector buffer SBUFF$, to serve as the open file's buffer.
5217
LD B,L 45
Copy L (00H) into Register B so B holds a logical record length of 0, meaning 256 bytes, for the open.
5218
GOSUB to the resident SYS0 service @OPEN (4424H) to open the file described by the FCB at DE (56D6H) using the buffer at HL (4200H). Returns the NZ FLAG if the file cannot be opened.
521B
If the NZ FLAG is set (open failed), JUMP to 53BDH to report the DOS error code returned in Register A.
521E
LD A,(56DCH) 3A DC 56
Fetch the file's drive number from FCB+6 (56DCH, filled by @OPEN) into Register A to test that drive's extended-dating flag.
5221
LD B,A 47
Copy the drive number (Register A) into Register B as the rotate count.
5222
LD A,(475DH) 3A 5D 47
Fetch the resident extended-dating drives bitmap from 475DH (one bit per drive; a set bit means date/time stamping is enabled, which reuses the directory access-password field) into Register A.
5225
INC B 04
Increment Register B so the following rotate loop executes (drive+1) times, moving the drive's bit into the carry.
5226
RRCA 0F
Loop Start
Rotate Register A right circularly, walking the extended-dating bitmap so bit (drive) lands in the carry after B rotations.
5227
DECrement Register B and LOOP BACK to 5226H until the selected drive's bit has been rotated into the carry.
5229
SBC A,A 9F
Subtract Register A from itself with borrow, producing FFH when the carry (the drive's extended-dating bit) was set, or 00H when it was clear.
522A
LD (52FAH),A 32 FA 52
Self-Modifying Code
Store the FFH/00H result into 52FAH, the operand of the LD A,nn at 52F9H, so the ACCess-password option later knows whether this drive has an access-password field (00H) or has reused it for date stamping (FFH).
522D
POP HL E1
Restore the command-line pointer (Register Pair HL) saved before the open.
522E
LD A,(56D7H) 3A D7 56
Fetch FCB+1 from 56D7H (the second file-name character) into Register A to verify @FSPEC accepted a proper name.
5231
AND 07H E6 07
Mask Register A with 07H; a valid parsed name leaves this zero, while a residual value flags a malformed specification.
5233
LD A,25H 3E 25
Load Register A with error code 25H (illegal file name) in case the name is bad.
5235
If the NZ FLAG is set (malformed name), JUMP to 53BDH to report the illegal-file-name error.
5238
XOR A AF
Set Register A to zero to clear the visibility/protection request accumulator.
5239
LD (5381H),A 32 81 53
Self-Modifying Code
Store zero into 5381H, the operand of the LD D,nn at 5380H, clearing the change-control mask that records which attribute fields the user asked to change.
523C
PUSH HL E5
Save the command-line pointer (Register Pair HL) while the command line is upcased.
523D
LD A,(HL) 7E
Loop Start
Fetch the current command-line character (addressed by HL) into Register A.
523E
CP 0DH FE 0D
Compare Register A against 0DH (carriage return). If equal the Z FLAG is set, ending the upcase pass.
5240
If the Z FLAG is set (end of line), JUMP to 524FH to finish upcasing.
5242
CP 03H FE 03
Compare Register A against 03H (ETX end marker). If equal the Z FLAG is set.
5244
If the Z FLAG is set (end marker), JUMP to 524FH to finish upcasing.
5246
CP 61H FE 61
Compare Register A against 61H (ASCII a). If Register A is below 61H the CARRY FLAG is set (already uppercase or punctuation).
5248
If the CARRY FLAG is set (character below lowercase range), JUMP to 524CH leaving the character unchanged.
524A
RES 5,(HL) CB AE
Clear bit 5 of the character in memory (addressed by HL), folding a lowercase letter to uppercase in place.
524C
INC HL 23
Advance the command-line pointer (Register Pair HL) to the next character.
524D
LOOP BACK to 523DH to upcase the next command-line character.
524F
POP HL E1
Restore the command-line pointer (Register Pair HL) to the start of the parameter text.
5250
LD A,(HL) 7E
Loop Start
Fetch the current command-line character (addressed by HL) into Register A to search for the parameter list.
5251
CP 28H FE 28
Compare Register A against 28H (ASCII (), the start of the parameter list. If equal the Z FLAG is set.
5253
If the Z FLAG is set (open parenthesis found), JUMP to 525CH to begin scanning the file options.
5255
CP 20H FE 20
Compare Register A against 20H (space). If not a space the NZ FLAG is set.
5257
If the NZ FLAG is set (a non-space, non-parenthesis character), JUMP to 525EH to test it directly as an option letter.
5259
INC HL 23
Advance the command-line pointer (Register Pair HL) past the space.
525A
LOOP BACK to 5250H to keep searching for the parameter list.

525CH - File Attribute Option Scanner

Scan the parenthesized option list of the file form of ATTRIB. Each option is recognized by its first letter: I (INV, invisible), V (VIS, visible), A (ACCess password), O or U (OWNer password), P (PROT, protection level). Password and protection options are followed by an =value that is parsed and, for passwords, hashed; each recognized option sets a bit in the change-control mask at 5381H. The protection abbreviation is resolved against the eight-entry keyword table at 55FAH to a level value of 0 (full) through 7 (none), with READ and reNAME told apart by their third letter.

525C
INC HL 23
Loop Start
Advance the command-line pointer (Register Pair HL) past the parenthesis or comma to the next option letter.
525D
LD A,(HL) 7E
Fetch the option letter (addressed by HL) into Register A.
525E
CP 49H FE 49
Compare the option letter (Register A) against 49H (ASCII I) for the INV (invisible) option. If equal the Z FLAG is set.
5260
If the Z FLAG is set (INV), JUMP to 52D5H to set the invisible attribute.
5262
CP 56H FE 56
Compare the option letter (Register A) against 56H (ASCII V) for the VIS (visible) option. If equal the Z FLAG is set.
5264
If the Z FLAG is set (VIS), JUMP to 52E7H to set the visible attribute.
5267
CP 41H FE 41
Compare the option letter (Register A) against 41H (ASCII A), the ACCess-password option. If equal the Z FLAG is set.
5269
If the Z FLAG is set (ACCess password), JUMP to 52F9H to read and hash the new access password.
526C
CP 55H FE 55
Compare the option letter (Register A) against 55H (ASCII U), an accepted form of the owner-password option. If equal the Z FLAG is set.
526E
If the Z FLAG is set, JUMP to 5314H to read and hash the new owner password.
5271
CP 4FH FE 4F
Compare the option letter (Register A) against 4FH (ASCII O), the OWNer-password option. If equal the Z FLAG is set.
5273
If the Z FLAG is set (OWNer password), JUMP to 5314H to read and hash the new owner password.
5276
CP 50H FE 50
Compare the option letter (Register A) against 50H (ASCII P), the PROT (protection level) option. If not equal the NZ FLAG is set.
5278
If the NZ FLAG is set (unrecognized option letter), JUMP to 5590H to report "Attribute specification error!".
527B
GOSUB to 5349H to parse the "=value" that follows PROT, copying the two-letter level abbreviation into the value buffer at 51E2H. Returns the Z FLAG when no value was supplied.
527E
If the Z FLAG is set (PROT given with no value), JUMP to 5590H to report the attribute specification error.
5281
PUSH HL E5
Save the command-line pointer (Register Pair HL) while the protection abbreviation is looked up.
5282
LD B,08H 06 08
Load Register B with 08H, the number of two-character entries in the protection-keyword table.
5284
LD DE,(51E2H) ED 5B E2 51
Load Register Pair DE with the parsed level abbreviation from 51E2H (E = first letter, D = second letter).
5288
LD HL,55FAH 21 FA 55
Point Register Pair HL at the protection-keyword table at 55FAH ("NO EX RE WR .. NA KI FU").
528B
LD A,(HL) 7E
Loop Start
Fetch the current table entry's first letter (addressed by HL) into Register A.
528C
INC HL 23
Advance the table pointer (Register Pair HL) to the entry's second letter.
528D
CP E BB
Compare the table first letter (Register A) against the input first letter (Register E). If equal the Z FLAG is set.
528E
If the Z FLAG is set (first letters match), GOSUB to 5297H to check the second letter and resolve the level value.
5291
INC HL 23
Advance the table pointer (Register Pair HL) past the entry's second letter to the next entry.
5292
DECrement Register B and LOOP BACK to 528BH until all eight table entries have been tried.
5294
No table entry matched, so JUMP to 5590H to report "Attribute specification error!".
5297
LD A,(HL) 7E
Fetch the matched entry's second letter (addressed by HL) into Register A.
5298
CP D BA
Compare the entry second letter (Register A) against the input second letter (Register D). If unequal the NZ FLAG is set.
5299
RET NZ C0
If the NZ FLAG is set (second letters differ), RETurn to keep scanning the table.
529A
POP AF F1
Both letters matched: discard the loop's return address (POP AF removes the 5291H return) so control leaves the search loop with Register B holding 8 minus the matched entry index.
529B
LD A,B 78
Copy the remaining count (Register B) into Register A to derive the protection-level value.
529C
SUB 08H D6 08
Subtract 08H from Register A; combined with the following add this maps entry index i to level value 7 minus i (FU=0 through NO=7).
529E
NOP 00
NOP padding left by the assembler between the two arithmetic steps.
529F
NOP 00
NOP padding left by the assembler between the two arithmetic steps.
52A0
ADD A,07H C6 07
Add 07H to Register A, completing the level value: NO=7, EX=6, RE=5, WR=4, NA=2, KI=1, FU=0.
52A2
CP 05H FE 05
Compare the level value (Register A) against 05H (the READ level). READ shares its first two letters with reNAME, so a value of 5 needs disambiguation.
52A4
If the NZ FLAG is set (not the READ/reNAME ambiguity), JUMP to 52B1H to store the level value as computed.
52A6
LD A,(51E4H) 3A E4 51
Fetch the third letter of the input keyword from 51E4H into Register A to tell READ from reNAME.
52A9
CP 4EH FE 4E
Compare the third letter (Register A) against 4EH (ASCII N); reNAME's third letter is N.
52AB
LD A,05H 3E 05
Load Register A with 05H (the READ level) as the default when the keyword is READ.
52AD
If the NZ FLAG is set (third letter is not N, so the keyword is READ), JUMP to 52B1H keeping level 5.
52AF
LD A,02H 3E 02
The keyword was reNAME, so load Register A with 02H, the reNAME protection level.
52B1
LD (5389H),A 32 89 53
Self-Modifying Code
Store the resolved protection-level value (Register A) into 5389H, the operand of the OR nn at 5388H, which later merges the level into the directory attribute byte.
52B4
POP HL E1
Restore the command-line pointer (Register Pair HL) to the character following the parsed value.
52B5
LD B,01H 06 01
Load Register B with 01H, the change-control bit for "protection level changed".
52B7
LD A,(HL) 7E
Loop Start
Fetch the next command-line character (addressed by HL) into Register A after an option has been processed.
52B8
CP 22H FE 22
Compare Register A against 22H (ASCII ") to skip a closing quote left after a quoted password.
52BA
If the NZ FLAG is set (not a quote), JUMP to 52BDH without advancing.
52BC
INC HL 23
Advance the command-line pointer (Register Pair HL) past the closing quote.
52BD
LD A,(5381H) 3A 81 53
Fetch the accumulated change-control mask from 5381H into Register A.
52C0
OR B B0
OR the current option's control bit (Register B) into Register A, recording that this attribute field is to be changed.
52C1
LD (5381H),A 32 81 53
Store the updated change-control mask (Register A) back to 5381H.
52C4
LD A,(HL) 7E
Fetch the next command-line character (addressed by HL) into Register A to find the option separator.
52C5
CP 0DH FE 0D
Compare Register A against 0DH (carriage return, end of line). If equal the Z FLAG is set.
52C7
If the Z FLAG is set (end of line), JUMP to 52CBH to finish the parameter list.
52C9
CP 29H FE 29
Compare Register A against 29H (ASCII )), the end of the parameter list. If equal the Z FLAG is set.
52CB
If the Z FLAG is set (close parenthesis or end of line), JUMP to 5375H to apply the file attribute changes.
52CE
CP 2CH FE 2C
Compare Register A against 2CH (ASCII ,), the option separator. If equal the Z FLAG is set.
52D0
If the Z FLAG is set (comma), LOOP BACK to 525CH to scan the next option.
52D2
An unexpected character ended the option, so JUMP to 5590H to report "Attribute specification error!".
52D5
GOSUB to 5349H to consume any "=value" text after INV (there is none for a flag option). Returns with HL advanced.
52D8
If the NZ FLAG is set (unexpected value text), JUMP to 5590H to report the attribute specification error.
52DB
LD A,(5391H) 3A 91 53
Fetch the visibility-value byte from 5391H into Register A (this cell supplies the directory bit-3 value written later).
52DE
OR 08H F6 08
OR 08H into Register A, setting bit 3 so the directory visibility bit will be made invisible.
52E0
LD (5391H),A 32 91 53
Store the updated visibility value (Register A) back to 5391H.
52E3
LD B,08H 06 08
Load Register B with 08H, the change-control bit for "visibility changed".
52E5
JUMP to 52BDH to record the visibility change and continue the option scan.
52E7
GOSUB to 5349H to consume any "=value" text after VIS. Returns with HL advanced.
52EA
If the NZ FLAG is set (unexpected value text), JUMP to 5590H to report the attribute specification error.
52ED
LD A,(5391H) 3A 91 53
Fetch the visibility-value byte from 5391H into Register A.
52F0
AND 0F7H E6 F7
AND 0F7H into Register A, clearing bit 3 so the directory visibility bit will be made visible.
52F2
LD (5391H),A 32 91 53
Store the updated visibility value (Register A) back to 5391H.
52F5
LD B,08H 06 08
Load Register B with 08H, the change-control bit for "visibility changed".
52F7
JUMP to 52BDH to record the visibility change and continue the option scan.
52F9
LD A,00H 3E 00
Self-Modifying Code
Load Register A from the operand at 52FAH, which the entry code set to FFH when this drive reuses the access-password field for date stamping, or 00H when an access password may be set.
52FB
OR A B7
Test Register A for the no-access-password condition; a non-zero value sets the NZ FLAG.
52FC
If the NZ FLAG is set (drive reuses the access-password field), JUMP to 5584H to report "File has no access password!".
52FF
GOSUB to 5349H to parse the "=password" text into the value buffer at 51E2H. Returns the Z FLAG when no value was supplied.
5302
If the Z FLAG is set (no password given), JUMP to 5590H to report the attribute specification error.
5305
PUSH HL E5
Save the command-line pointer (Register Pair HL) while the password is hashed.
5306
LD DE,51E2H 11 E2 51
Point Register Pair DE at the parsed password text at 51E2H for hashing.
5309
GOSUB to 532CH to invoke the resident directory/password service (RST 28H code E4H), returning the 16-bit hash of the access password in Register Pair HL.
530C
LD (51F7H),HL 22 F7 51
Store the access-password hash (Register Pair HL) into the work cell at 51F7H, to be written to the directory access-password field.
530F
POP HL E1
Restore the command-line pointer (Register Pair HL).
5310
LD B,02H 06 02
Load Register B with 02H, the change-control bit for "access password changed".
5312
JUMP to 52B7H to record the change and continue the option scan.
5314
GOSUB to 5349H to parse the "=password" text into the value buffer at 51E2H. Returns the Z FLAG when no value was supplied.
5317
If the Z FLAG is set (no password given), JUMP to 5590H to report the attribute specification error.
531A
PUSH HL E5
Save the command-line pointer (Register Pair HL) while the password is hashed.
531B
LD DE,51E2H 11 E2 51
Point Register Pair DE at the parsed password text at 51E2H for hashing.
531E
GOSUB to 532CH to invoke the resident directory/password service (RST 28H code E4H), returning the 16-bit hash of the owner password in Register Pair HL.
5321
LD (51F5H),HL 22 F5 51
Store the owner-password hash (Register Pair HL) into the work cell at 51F5H, to be written to the directory owner-password field.
5324
POP HL E1
Restore the command-line pointer (Register Pair HL).
5325
LD B,04H 06 04
Load Register B with 04H, the change-control bit for "owner password changed".
5327
JUMP to 52B7H to record the change and continue the option scan.

5329H - Password Hash Helper, Alphanumeric Copy and =Value Parser

Three closely related helpers. The password hash helper (5329H/532CH) obtains the eight-character password text and invokes the resident directory/password service (RST 28H code E4H) to return the 16-bit password hash in HL. The alphanumeric copy subroutine (532FH/5333H) copies up to B letters and digits from a source string to a destination, stopping at the first delimiter. The =value parser (5349H) scans the command line for an "=", blank-fills the eight-byte value buffer at 51E2H, and copies the value there.

5329
GOSUB to 54FBH to obtain the eight-character master password text (prompting the user when no "=value" string was supplied) into the buffer at 5700H.
532C
LD A,0E4H 3E E4
Load Register A with request code 0E4H to select the resident directory/attribute/password service.
532E
RST 28H EF
Execute the supervisor call: the resident dispatcher (RST 28H via 400CH to 4BCDH) runs the E4H directory/password service, which hashes the password text and returns the 16-bit hash in Register Pair HL. Control returns here.
532F
LD A,(HL) 7E
Alphanumeric Copy Subroutine
Fetch the first source character (addressed by HL) into Register A. This entry is also reached by CALL from 536EH to copy a keyword value.
5330
INC HL 23
Advance the source pointer (Register Pair HL) to the next character.
5331
JUMP to 533CH to test this character against the letter range (bypassing the digit test on the first pass).
5333
LD A,(HL) 7E
Loop Start
Fetch the next source character (addressed by HL) into Register A.
5334
INC HL 23
Advance the source pointer (Register Pair HL) to the following character.
5335
CP 30H FE 30
Compare Register A against 30H (ASCII 0). If below the digit range the CARRY FLAG is set.
5337
RET C D8
If the CARRY FLAG is set (below 0, a delimiter), RETurn to the caller ending the copy.
5338
CP 3AH FE 3A
Compare Register A against 3AH (one past ASCII 9). If below, the character is a digit and the CARRY FLAG is set.
533A
If the CARRY FLAG is set (a digit 0-9), JUMP to 5342H to store it.
533C
CP 41H FE 41
Compare Register A against 41H (ASCII A). If below the letter range the CARRY FLAG is set.
533E
RET C D8
If the CARRY FLAG is set (below A, a delimiter), RETurn to the caller ending the copy.
533F
CP 5BH FE 5B
Compare Register A against 5BH (one past ASCII Z). If at or above, the character is not a letter and the NO CARRY FLAG is set.
5341
RET NC D0
If the NO CARRY FLAG is set (past Z, a delimiter), RETurn to the caller ending the copy.
5342
LD (DE),A 12
Store the accepted alphanumeric character (Register A) into the destination (addressed by DE).
5343
INC DE 13
Advance the destination pointer (Register Pair DE) to the next byte.
5344
DECrement Register B and LOOP BACK to 5333H until the maximum character count has been copied.
5346
LD A,(HL) 7E
The count is exhausted: fetch the next source character (addressed by HL) into Register A.
5347
INC HL 23
Advance the source pointer (Register Pair HL) past it.
5348
RET C9
RETurn to the caller with the copy complete.
5349
INC HL 23
Loop Start
Advance the command-line pointer (Register Pair HL) to the next character while scanning for the "=" sign.
534A
LD A,(HL) 7E
Fetch the current command-line character (addressed by HL) into Register A.
534B
CP 0DH FE 0D
Compare Register A against 0DH (carriage return). If equal the Z FLAG is set.
534D
RET Z C8
If the Z FLAG is set (end of line before "="), RETurn with the Z FLAG signalling no value.
534E
CP 29H FE 29
Compare Register A against 29H (ASCII )). If equal the Z FLAG is set.
5350
RET Z C8
If the Z FLAG is set (end of parameter list before "="), RETurn with the Z FLAG signalling no value.
5351
CP 2CH FE 2C
Compare Register A against 2CH (ASCII ,). If equal the Z FLAG is set.
5353
RET Z C8
If the Z FLAG is set (option separator before "="), RETurn with the Z FLAG signalling no value.
5354
CP 3DH FE 3D
Compare Register A against 3DH (ASCII =). If not the assignment sign the NZ FLAG is set.
5356
If the NZ FLAG is set (not "=" yet), LOOP BACK to 5349H to keep scanning.
5358
INC HL 23
Advance the command-line pointer (Register Pair HL) past the "=" to the value text.
5359
LD A,(HL) 7E
Fetch the first value character (addressed by HL) into Register A.
535A
CP 22H FE 22
Compare Register A against 22H (ASCII ") to detect a quoted value.
535C
If the NZ FLAG is set (no opening quote), JUMP to 535FH without skipping.
535E
INC HL 23
Advance the command-line pointer (Register Pair HL) past the opening quote.
535F
LD DE,51E2H 11 E2 51
Point Register Pair DE at the value buffer at 51E2H that receives the parsed value.
5362
LD B,08H 06 08
Load Register B with 08H, the maximum value length.
5364
PUSH DE D5
Save the value-buffer pointer (Register Pair DE) while it is pre-filled.
5365
PUSH BC C5
Save the count (Register Pair BC) while the buffer is pre-filled.
5366
LD A,20H 3E 20
Load Register A with 20H (space) to blank-fill the value buffer.
5368
LD (DE),A 12
Loop Start
Store a space (Register A) into the value buffer (addressed by DE).
5369
INC DE 13
Advance the value-buffer pointer (Register Pair DE) to the next byte.
536A
DECrement Register B and LOOP BACK to 5368H until all eight value bytes are blanked.
536C
POP BC C1
Restore the count (Register Pair BC).
536D
POP DE D1
Restore the value-buffer pointer (Register Pair DE) to 51E2H.
536E
GOSUB to 532FH to copy up to eight alphanumeric value characters from the command line (HL) into the value buffer (DE at 51E2H).
5371
DEC HL 2B
Back the command-line pointer (Register Pair HL) up by one so the caller re-reads the delimiter that ended the value.
5372
OR 01H F6 01
OR 01H into Register A to force the NZ FLAG, signalling to the caller that a value was found.
5374
RET C9
RETurn to the caller with the parsed value in the 51E2H buffer.

5375H - Apply File Attribute Changes

Read the file's directory record with DIRRD, then, guided by the change-control mask in Register D, rewrite the attribute byte (protection level in the low three bits, visibility in bit 3) and the owner (DIR+16/17) and access (DIR+18/19) password-hash fields, and write the record back with DIRWR. The shared error tail at 53BDH sets bits 7 and 6 of the error code so @ERROR reports and returns.

5375
LD BC,(56DCH) ED 4B DC 56
Load Register Pair BC from 56DCH: Register C = the file's drive (FCB+6), Register B = the file's directory record number (FCB+7).
5379
GOSUB to the resident SYS0 service DIRRD (4B10H) to read the file's directory record for drive C, record B, into the directory buffer (page 42H). Returns the NZ FLAG on a read error.
537C
If the NZ FLAG is set (directory read error), JUMP to 53BDH to report the error code.
537F
LD A,(HL) 7E
Fetch the directory attribute byte (DIR+0, addressed by HL) into Register A for modification.
5380
LD D,00H 16 00
Self-Modifying Code
Load Register D from the operand at 5381H, the change-control mask built during option parsing (bit0 protection, bit1 access pw, bit2 owner pw, bit3 visibility).
5382
BIT 0,D CB 42
Test bit 0 of the change-control mask (Register D): was the protection level changed?
5384
If the Z FLAG is set (protection not changed), JUMP to 538AH leaving the level bits alone.
5386
AND 0F8H E6 F8
AND 0F8H into the attribute byte (Register A), clearing the low three protection-level bits.
5388
OR 00H F6 00
Self-Modifying Code
OR the resolved protection level into the attribute byte (Register A). The operand at 5389H was set at 52B1H to the level value (0=full through 7=none).
538A
BIT 3,D CB 5A
Test bit 3 of the change-control mask (Register D): was the visibility changed?
538C
If the Z FLAG is set (visibility not changed), JUMP to 5392H leaving the visibility bit alone.
538E
AND 0F7H E6 F7
AND 0F7H into the attribute byte (Register A), clearing bit 3 (the visibility bit).
5390
OR 00H F6 00
Self-Modifying Code
OR the requested visibility bit into the attribute byte (Register A). The operand at 5391H was set by the VIS/INV handlers (08H invisible, 00H visible).
5392
LD (HL),A 77
Store the updated attribute byte (Register A) back into the directory record (DIR+0, addressed by HL).
5393
LD A,L 7D
Copy the directory-record low address (Register L) into Register A to advance to the password fields.
5394
ADD A,10H C6 10
Add 10H to Register A, moving 16 bytes forward to the owner-password field (DIR+16).
5396
LD L,A 6F
Copy the advanced low address (Register A) back into Register L so HL now points at DIR+16.
5397
BIT 2,D CB 52
Test bit 2 of the change-control mask (Register D): was the owner password changed?
5399
If the Z FLAG is set (owner password not changed), JUMP to 53A5H skipping the owner-password write.
539B
LD A,(51F5H) 3A F5 51
Fetch the owner-password hash low byte from the work cell at 51F5H into Register A.
539E
LD (HL),A 77
Store the owner-password hash low byte (Register A) into DIR+16 (addressed by HL).
539F
LD A,(51F6H) 3A F6 51
Fetch the owner-password hash high byte from the work cell at 51F6H into Register A.
53A2
INC HL 23
Advance the directory pointer (Register Pair HL) to DIR+17.
53A3
LD (HL),A 77
Store the owner-password hash high byte (Register A) into DIR+17 (addressed by HL).
53A4
DEC HL 2B
Back the directory pointer (Register Pair HL) up to DIR+16 to keep the following increments aligned.
53A5
INC HL 23
Advance the directory pointer (Register Pair HL) toward the access-password field.
53A6
INC HL 23
Advance the directory pointer (Register Pair HL) again so it points at DIR+18, the access-password field.
53A7
BIT 1,D CB 4A
Test bit 1 of the change-control mask (Register D): was the access password changed?
53A9
If the Z FLAG is set (access password not changed), JUMP to 53B4H skipping the access-password write.
53AB
LD A,(51F7H) 3A F7 51
Fetch the access-password hash low byte from the work cell at 51F7H into Register A.
53AE
LD (HL),A 77
Store the access-password hash low byte (Register A) into DIR+18 (addressed by HL).
53AF
LD A,(51F8H) 3A F8 51
Fetch the access-password hash high byte from the work cell at 51F8H into Register A.
53B2
INC HL 23
Advance the directory pointer (Register Pair HL) to DIR+19.
53B3
LD (HL),A 77
Store the access-password hash high byte (Register A) into DIR+19 (addressed by HL).
53B4
GOSUB to the resident SYS0 service DIRWR (4B1FH) to write the modified directory record back to disk. Returns the Z FLAG on success.
53B7
If the Z FLAG is set (directory write succeeded), JUMP to 54B9H to exit the command successfully.
53BA
LD BC,2C3EH 01 3E 2C
Overlapping Code
On fall-through this is LD BC,2C3EH (inert). Entered at 53BBH (skipping the 01H byte) the bytes read as LD A,2CH, loading Register A with error code 2CH (parameter error) before the shared error tail at 53BDH.
53BD
OR 0C0H F6 C0
OR 0C0H into the error code (Register A), setting bits 7 and 6 so @ERROR displays the message and returns to the overlay rather than aborting.
53BF
GOSUB to the resident SYS0 service @ERROR (4409H) to display the DOS error message for the code in Register A.
53C2
JUMP to 5596H to load the failure return code and exit the command.

53C5H - Diskette Attribute Path

The disk form "ATTRIB :d (...)" has no file name. Parse the optional ":d" drivespec, run @PARAM over the diskette keyword table at 568DH (PW, LOCK/L, UNLOCK/U, NAME/N, MPW/M), reject the command when nothing was requested, then validate the supplied master password and stage a new disk name and/or master password into the GAT buffer at 5800H.

53C5
LD C,00H 0E 00
Diskette-attribute path: set Register C to 00H as the default drive number.
53C7
DEC HL 2B
Back the command-line pointer (Register Pair HL) up to re-examine the drive specification.
53C8
LD A,(HL) 7E
Fetch the current command-line character (addressed by HL) into Register A.
53C9
CP 3AH FE 3A
Compare Register A against 3AH (ASCII :), the drive-specification marker. If not present the NZ FLAG is set.
53CB
If the NZ FLAG is set (no explicit drive), JUMP to 53D3H using the default drive 0.
53CD
INC HL 23
Advance the command-line pointer (Register Pair HL) past the colon to the drive digit.
53CE
LD A,(HL) 7E
Fetch the drive digit (addressed by HL) into Register A.
53CF
SUB 30H D6 30
Subtract 30H (ASCII 0) from Register A to convert the digit to a binary drive number.
53D1
LD C,A 4F
Copy the binary drive number (Register A) into Register C.
53D2
INC HL 23
Advance the command-line pointer (Register Pair HL) past the drive digit.
53D3
LD A,C 79
Copy the drive number (Register C) into Register A.
53D4
LD (54CCH),A 32 CC 54
Self-Modifying Code
Store the target drive number (Register A) into 54CCH, the operand of the LD A,nn instructions that reload the drive for the GAT and HIT reads.
53D7
LD DE,568DH 11 8D 56
Point Register Pair DE at the diskette-option keyword table at 568DH (PW/LOCK/L/UNLOCK/U/NAME/N/MPW/M) for @PARAM.
53DA
GOSUB to the resident SYS0 service @PARAM (4476H) to parse the diskette parameters, storing each value into the cell named by the 568DH table. Returns the NZ FLAG on a bad parameter.
53DD
If the NZ FLAG is set (malformed parameter), JUMP to 53BBH to raise the parameter error.
53E0
LD A,(540EH) 3A 0E 54
Fetch the low byte of the PW (new master password) pointer from 540EH into Register A to test whether any change was requested.
53E3
LD HL,5431H 21 31 54
Point Register Pair HL at the LOCK-flag cell at 5431H.
53E6
OR (HL) B6
OR the LOCK-flag low byte (addressed by HL) into Register A.
53E7
LD HL,543BH 21 3B 54
Point Register Pair HL at the UNLOCK-flag cell at 543BH.
53EA
OR (HL) B6
OR the UNLOCK-flag low byte (addressed by HL) into Register A.
53EB
LD HL,53F6H 21 F6 53
Point Register Pair HL at the NAME (new disk name) pointer cell at 53F6H.
53EE
OR (HL) B6
OR the NAME-pointer low byte (addressed by HL) into Register A.
53EF
If the Z FLAG is set (none of PW, LOCK, UNLOCK or NAME was given), JUMP to 558CH to report "-Nothing done-".
53F2
GOSUB to 54CBH to read the diskette GAT sector and validate the supplied master password (MPW) against the disk's current master password.
53F5
LD DE,0000H 11 00 00
Self-Modifying Code
Load Register Pair DE from the operand at 53F6H, the NAME pointer cell written by @PARAM (0000H if NAME was not given).
53F8
LD A,D 7A
Copy Register D into Register A to test the NAME pointer.
53F9
OR E B3
OR Register E into Register A; the Z FLAG is set when no new disk name was requested.
53FA
If the Z FLAG is set (no NAME parameter), JUMP to 540DH to handle the master-password change.
53FC
LD HL,5630H 21 30 56
Point Register Pair HL at the "New disk pack name ?" prompt at 5630H.
53FF
GOSUB to 54FBH to obtain the new eight-character disk name (from the NAME="..." value or by prompting) into the buffer at 5700H.
5402
LD HL,5700H 21 00 57
Point Register Pair HL at the new name text at 5700H as the copy source.
5405
LD DE,58D0H 11 D0 58
Point Register Pair DE at the disk-name field in the GAT buffer at 58D0H (GAT offset D0H).
5408
LD BC,0008H 01 08 00
Load Register Pair BC with 0008H, the eight-byte disk-name length.
540B
LDIR ED B0
Block-copy the eight-byte disk name from 5700H (HL) to the GAT buffer at 58D0H (DE).
540D
LD DE,0000H 11 00 00
Self-Modifying Code
Load Register Pair DE from the operand at 540EH, the PW pointer cell written by @PARAM (0000H if no new master password was given).
5410
LD A,D 7A
Copy Register D into Register A to test the PW pointer.
5411
OR E B3
OR Register E into Register A; the Z FLAG is set when no new master password was requested.
5412
If the Z FLAG is set (no PW parameter), JUMP to 5420H to write the GAT and run any LOCK/UNLOCK.
5414
GOSUB to 5572H to refuse the interactive change when the command is running during DO/JCL processing.
5417
LD HL,5648H 21 48 56
Point Register Pair HL at the "New Master password ?" prompt at 5648H.
541A
GOSUB to 5329H to obtain and hash the new master password, returning its 16-bit hash in Register Pair HL.
541D
LD (58CEH),HL 22 CE 58
Store the new master-password hash (Register Pair HL) into the GAT buffer at 58CEH (GAT offset CEH, the disk master-password field).

5420H - LOCK / UNLOCK Directory Scan

Write the updated GAT back, then, if LOCK or UNLOCK was requested, walk every slot of the directory Hash Index Table. For each visible non-system in-use file whose owner-password hash matches the comparison password (blank for LOCK, the master password for UNLOCK), overwrite it with the applied password (the master password for LOCK, blank for UNLOCK) and write the directory sector back. This changes every unprotected file's password to the disk master password (LOCK) or clears the password of every file protected by it (UNLOCK).

5420
GOSUB to the resident SYS0 service DIRCYL (4B65H) to seek the directory cylinder for the diskette so the GAT can be rewritten.
5423
LD A,(54CCH) 3A CC 54
Self-Modifying Code
Load Register A from the operand at 54CCH, the target drive number saved at 53D4H.
5426
LD C,A 4F
Copy the drive number (Register A) into Register C for the GAT write.
5427
GOSUB to 554FH to write the updated GAT sector (holding the new disk name and/or master password) back to the diskette. Returns the NZ FLAG on a write error.
542A
If the NZ FLAG is set (GAT write error), JUMP to 53BDH to report the error code.
542D
LD HL,(58CEH) 2A CE 58
Load Register Pair HL from 58CEH, the disk master-password hash, as the password to apply when LOCKing files.
5430
LD BC,0000H 01 00 00
Self-Modifying Code
Load Register Pair BC from the operand at 5431H, the LOCK flag (non-zero when LOCK was given).
5433
LD A,B 78
Copy Register B into Register A to test the LOCK flag.
5434
OR C B1
OR Register C into Register A; the NZ FLAG is set when LOCK was requested.
5435
LD DE,4296H 11 96 42
Point Register Pair DE at the resident blank-password value at 4296H (the "no password" hash used as the LOCK comparison password).
5438
If the NZ FLAG is set (LOCK requested), JUMP to 5443H with HL = master password to apply and DE = blank password to match.
543A
LD BC,0000H 01 00 00
Self-Modifying Code
Load Register Pair BC from the operand at 543BH, the UNLOCK flag (non-zero when UNLOCK was given).
543D
LD A,B 78
Copy Register B into Register A to test the UNLOCK flag.
543E
OR C B1
OR Register C into Register A; the Z FLAG is set when neither LOCK nor UNLOCK was requested.
543F
If the Z FLAG is set (no LOCK or UNLOCK), JUMP to 54B9H to exit successfully.
5442
EX DE,HL EB
UNLOCK requested: exchange DE and HL so HL = blank password to apply and DE = master password to match.
5443
LD (5495H),HL 22 95 54
Self-Modifying Code
Store the password to apply (Register Pair HL) into 5495H, the operand of the LD DE,nnnn at 5494H used inside the scan.
5446
LD (548CH),DE ED 53 8C 54
Self-Modifying Code
Store the password to match (Register Pair DE) into 548CH, the operand of the LD HL,nnnn at 548BH used inside the scan.
544A
LD A,(54CCH) 3A CC 54
Reload the target drive number (Register A) from 54CCH.
544D
LD C,A 4F
Copy the drive number (Register A) into Register C for the HIT read.
544E
GOSUB to the resident SYS0 service DIRCYL (4B65H) to seek the directory cylinder for the HIT read.
5451
LD HL,5900H 21 00 59
Point Register Pair HL at 5900H, the buffer for the directory Hash Index Table.
5454
LD E,01H 1E 01
Load Register E with 01H, the directory sector number of the HIT.
5456
GOSUB to the resident SYS0 service RDSSEC (4B45H) to read the HIT (directory sector 1) into 5900H. Returns the NZ FLAG on error.
5459
If the NZ FLAG is set (HIT read error), JUMP to 53BDH to report the error code.
545C
LD A,L 7D
Loop Start
Copy the HIT-slot low address (Register L) into Register A to test the slot position.
545D
AND 0D8H E6 D8
AND 0D8H into Register A; a zero result marks the reserved low HIT slots (system files) to be skipped.
545F
If the Z FLAG is set (reserved slot), JUMP to 549FH to advance to the next HIT slot.
5461
LD A,(HL) 7E
Fetch the HIT slot byte (addressed by HL) into Register A; it holds the directory hash code, or zero when the slot is empty.
5462
OR A B7
Test Register A; a zero HIT byte (empty slot) sets the Z FLAG.
5463
If the Z FLAG is set (empty slot), JUMP to 549FH to advance to the next HIT slot.
5465
LD B,L 45
Copy the HIT-slot low address (Register L) into Register B to preserve it across the directory read.
5466
PUSH BC C5
Save the HIT-slot address and count (Register Pair BC) on the stack.
5467
LD A,L 7D
Copy the HIT-slot low address (Register L) into Register A to derive the directory record number.
5468
AND 0E0H E6 E0
AND 0E0H into Register A, isolating the HIT group base (the sector portion of the slot address).
546A
LD L,A 6F
Copy the group base (Register A) back into Register L.
546B
XOR B A8
XOR Register B (the original low address) into Register A, leaving the slot's offset within its group.
546C
CP 0FFH FE FF
Compare Register A against 0FFH; the value cannot equal FFH here, so this sets the flags for the following branch.
546E
If the Z FLAG is set, JUMP to 5479H (the directory record is already in the buffer).
5470
LD (546DH),A 32 6D 54
Self-Modifying Code
Store the derived directory record number (Register A) into 546DH, the operand used by the following DIRRD call and the write-back test.
5473
GOSUB to the resident SYS0 service DIRRD (4B10H) to read the directory record for this HIT slot into the directory buffer. Returns the NZ FLAG on error.
5476
If the NZ FLAG is set (directory read error), JUMP to 53BDH to report the error code.
5479
LD H,42H 26 42
Load Register H with 42H so HL addresses the directory record in the sector buffer at page 42H.
547B
LD A,(HL) 7E
Fetch the directory attribute byte (DIR+0, addressed by HL) into Register A.
547C
AND 0F8H E6 F8
AND 0F8H into Register A, isolating the visibility and system flag bits from the protection level.
547E
CP 10H FE 10
Compare Register A against 10H; a visible, non-system, in-use primary directory entry reads as 10H (bit 4 set only).
5480
If the NZ FLAG is set (not a plain visible user file), JUMP to 549BH to skip this file.
5482
LD A,L 7D
Copy the directory-record low address (Register L) into Register A to reach the owner-password field.
5483
ADD A,10H C6 10
Add 10H to Register A, advancing 16 bytes to the owner-password field (DIR+16).
5485
LD L,A 6F
Copy the advanced low address (Register A) back into Register L so HL points at DIR+16.
5486
PUSH DE D5
Save the password-to-match pointer (Register Pair DE) on the stack.
5487
PUSH HL E5
Save the directory owner-password pointer (Register Pair HL) on the stack.
5488
LD E,(HL) 5E
Fetch the file's current owner-password low byte (DIR+16, addressed by HL) into Register E.
5489
INC HL 23
Advance the directory pointer (Register Pair HL) to DIR+17.
548A
LD D,(HL) 56
Fetch the file's current owner-password high byte (DIR+17, addressed by HL) into Register D so DE holds the file's current owner-password hash.
548B
LD HL,0000H 21 00 00
Self-Modifying Code
Load Register Pair HL with the password to match. The operand at 548CH was set at 5446H (blank password for LOCK, master password for UNLOCK).
548E
XOR A AF
Clear Register A and the carry to prepare the comparison.
548F
SBC HL,DE ED 52
Subtract the file's owner password (Register Pair DE) from the match password (Register Pair HL); the Z FLAG is set when they are equal.
5491
POP HL E1
Restore the directory owner-password pointer (Register Pair HL) to DIR+16.
5492
If the NZ FLAG is set (the file's password does not match), JUMP to 549AH to leave this file unchanged.
5494
LD DE,0000H 11 00 00
Self-Modifying Code
Load Register Pair DE with the password to apply. The operand at 5495H was set at 5443H (master password for LOCK, blank password for UNLOCK).
5497
LD (HL),E 73
Store the applied password low byte (Register E) into DIR+16 (addressed by HL).
5498
INC L 2C
Advance the directory pointer (Register L) to DIR+17.
5499
LD (HL),D 72
Store the applied password high byte (Register D) into DIR+17 (addressed by HL).
549A
POP DE D1
Restore the password-to-match pointer (Register Pair DE) from the stack.
549B
POP BC C1
Restore the HIT-slot address and count (Register Pair BC) from the stack.
549C
LD H,59H 26 59
Load Register H with 59H so HL again addresses the HIT buffer at page 59H.
549E
LD L,B 68
Copy the saved HIT-slot low address (Register B) into Register L, restoring the HIT pointer.
549F
LD A,L 7D
Copy the HIT-slot low address (Register L) into Register A to step to the next slot.
54A0
ADD A,20H C6 20
Add 20H to Register A, advancing 32 bytes to the same slot in the next HIT group.
54A2
LD L,A 6F
Copy the advanced low address (Register A) back into Register L.
54A3
If the NO CARRY FLAG is set (still within the HIT page), LOOP BACK to 545CH for the next slot.
54A5
LD A,(546DH) 3A 6D 54
Self-Modifying Code
Load Register A from 546DH, the last directory record number processed, to decide whether the current directory sector was modified.
54A8
XOR L AD
XOR the current HIT low address (Register L) into Register A to test whether a write-back is due.
54A9
If the NZ FLAG is set, JUMP to 54B3H skipping the directory write-back for this pass.
54AB
PUSH HL E5
Save the HIT pointer (Register Pair HL) while the directory sector is written.
54AC
GOSUB to the resident SYS0 service DIRWR (4B1FH) to write the modified directory record back to disk. Returns the NZ FLAG on error.
54AF
If the NZ FLAG is set (directory write error), JUMP to 53BDH to report the error code.
54B2
POP HL E1
Restore the HIT pointer (Register Pair HL).
54B3
LD A,L 7D
Copy the HIT low address (Register L) into Register A to test for the end of the HIT.
54B4
INC L 2C
Advance Register L to the next HIT slot address.
54B5
CP 1FH FE 1F
Compare Register A against 1FH, the last HIT slot offset in the page.
54B7
If the NZ FLAG is set (more HIT slots remain), LOOP BACK to 545CH to continue the LOCK/UNLOCK scan.

54B9H - Command Exit

Load the success (0000H) or failure (FFFFH) return code, restore the caller's stack pointer through the self-modified operand at 54BDH, and return to the RST 28H dispatcher. On a failure while running below the LDOS command level (SFLAG$ bit 5 set), abort the job through @ABORT instead.

54B9
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H, the success return code.
54BC
LD SP,0000H 31 00 00
Self-Modifying Code
Restore the caller's stack pointer. The operand at 54BDH was set at 5200H to the entry SP.
54BF
LD A,H 7C
Copy Register H into Register A to test the return code.
54C0
OR L B5
OR Register L into Register A; the Z FLAG is set on a success (0000H) return code.
54C1
RET Z C8
If the Z FLAG is set (success), RETurn to the resident RST 28H dispatcher.
54C2
LD A,(430FH) 3A 0F 43
On a failure return code, fetch the system flag SFLAG$ from 430FH into Register A.
54C5
BIT 5,A CB 6F
Test bit 5 of SFLAG$ (Register A): the "not at LDOS command level" flag.
54C7
RET Z C8
If the Z FLAG is set (at command level), RETurn to the dispatcher letting the error stand.
54C8
Otherwise (invoked below command level), JUMP to the resident SYS0 service @ABORT (4030H) to abandon the job.

54CBH - GAT Read and Master-Password Validation

Read the diskette GAT sector, then compare the disk's stored master-password hash (GAT offset CEH) and the user-supplied MPW against the hash of the default master password "PASSWORD" (113DH / 42E0H). The command proceeds when the disk still uses the default password or the supplied master password matches the disk; otherwise "Invalid master password!" is reported.

54CB
LD C,00H 0E 00
Set Register C to 00H (GAT sector) to prepare the read of the diskette Granule Allocation Table.
54CD
GOSUB to 554EH to read the GAT sector (directory sector 0) for the target drive into the buffer at 5800H. Returns the error code and flags.
54D0
If the NZ FLAG is set (GAT read error), JUMP to 53BDH to report the error code.
54D3
LD HL,(58CEH) 2A CE 58
Load Register Pair HL from 58CEH, the disk's current master-password hash held in the GAT buffer.
54D6
LD DE,42E0H 11 E0 42
Point Register Pair DE at 42E0H, the resident hash of the default master password "PASSWORD".
54D9
XOR A AF
Clear Register A and the carry to prepare the comparison.
54DA
SBC HL,DE ED 52
Subtract the default-password hash (DE) from the disk's master-password hash (HL); the Z FLAG is set when the disk still uses the default "PASSWORD".
54DC
RET Z C8
If the Z FLAG is set (disk uses the default master password), RETurn accepting the command without prompting.
54DD
LD DE,(54F9H) ED 5B F9 54
Self-Modifying Code
Load Register Pair DE from the operand at 54F9H, the MPW pointer cell written by @PARAM (the current master password the user supplied, or 0000H).
54E1
LD HL,564CH 21 4C 56
Point Register Pair HL at the "Master password ?" prompt text within 564CH.
54E4
GOSUB to 5329H to obtain and hash the supplied current master password, returning its 16-bit hash in Register Pair HL.
54E7
EX DE,HL EB
Exchange DE and HL so DE holds the supplied master-password hash for the comparisons.
54E8
LD HL,113DH 21 3D 11
Load Register Pair HL with 113DH, the resident hash of the default master password "PASSWORD".
54EB
XOR A AF
Clear Register A and the carry to prepare the comparison.
54EC
SBC HL,DE ED 52
Subtract the supplied hash (DE) from the default-password hash (HL); the Z FLAG is set when the user supplied nothing (the default).
54EE
RET Z C8
If the Z FLAG is set (no password supplied while the disk is protected), RETurn; the following disk-hash test will still gate the change.
54EF
LD HL,(58CEH) 2A CE 58
Load Register Pair HL from 58CEH, the disk's actual master-password hash from the GAT buffer.
54F2
XOR A AF
Clear Register A and the carry to prepare the comparison.
54F3
SBC HL,DE ED 52
Subtract the supplied hash (DE) from the disk's master-password hash (HL); the Z FLAG is set when they match.
54F5
RET Z C8
If the Z FLAG is set (supplied master password matches the disk), RETurn accepting the command.
54F6
The supplied master password is wrong, so JUMP to 557CH to report "Invalid master password!".
54F9
DEFB 00H 00
Data
Low byte of the two-byte MPW pointer cell (operand of the LD DE,nnnn at 54DDH), written by @PARAM with the address of the current-master-password text; 0000H when MPW was not given.
54FA
DEFB 00H 00
Data
High byte of the two-byte MPW pointer cell read at 54DDH.

54FBH - Prompt/Copy String and GAT Sector Helper

Two helpers. The string helper (54FBH) either copies an eight-character value supplied as ="..." or, when none was given, displays a prompt and reads the reply with the ROM @KEYIN routine, then blank-pads and upcases the field at 5700H. The GAT sector helper (554EH/554FH) reads (entry 554EH) or writes with verify (entry 554FH) the diskette GAT sector at 5800H, returning error code 14H or 15H on failure.

54FB
LD A,D 7A
Copy Register D into Register A, then combine with Register E, to test the supplied value pointer (Register Pair DE).
54FC
OR E B3
OR Register E into Register A; the Z FLAG is set when the pointer is 0000H (no value supplied).
54FD
If the Z FLAG is set (no value string), JUMP to 551CH to prompt the user.
54FF
INC A 3C
Increment Register A; the Z FLAG is set when the combined pointer bytes were FFH, another "no value" marker.
5500
If the Z FLAG is set (no value string), JUMP to 551CH to prompt the user.
5502
LD HL,5700H 21 00 57
Point Register Pair HL at the output buffer at 5700H.
5505
PUSH HL E5
Save the output-buffer start (Register Pair HL) for the later upcase pass.
5506
LD B,08H 06 08
Load Register B with 08H, the eight-character field width.
5508
LD A,(DE) 1A
Loop Start
Fetch the next source character from the supplied value (addressed by DE) into Register A.
5509
CP 0DH FE 0D
Compare Register A against 0DH (carriage return). If equal the Z FLAG is set, ending the copy.
550B
If the Z FLAG is set (end of value), JUMP to 5538H to blank-pad the remainder.
550D
CP 2CH FE 2C
Compare Register A against 2CH (comma). If equal the Z FLAG is set, ending the copy.
550F
If the Z FLAG is set (separator), JUMP to 5538H to blank-pad the remainder.
5511
CP 22H FE 22
Compare Register A against 22H (closing quote). If equal the Z FLAG is set, ending the copy.
5513
If the Z FLAG is set (closing quote), JUMP to 5538H to blank-pad the remainder.
5515
INC DE 13
Advance the source pointer (Register Pair DE) to the next character.
5516
LD (HL),A 77
Store the copied character (Register A) into the output buffer (addressed by HL).
5517
INC HL 23
Advance the output-buffer pointer (Register Pair HL) to the next byte.
5518
DECrement Register B and LOOP BACK to 5508H until eight characters have been copied.
551A
JUMP to 553DH to upcase the copied field.
551C
Prompt path: GOSUB to 5572H to refuse the prompt when the command is running during DO/JCL processing.
551F
GOSUB to the resident SYS0 service @DSPLY (4467H) to display the prompt string addressed by Register Pair HL.
5522
LD B,08H 06 08
Load Register B with 08H, the maximum reply length.
5524
LD HL,5700H 21 00 57
Point Register Pair HL at the reply buffer at 5700H.
5527
PUSH HL E5
Save the reply-buffer start (Register Pair HL) for the later upcase pass.
5528
GOSUB to the ROM keyboard-line routine @KEYIN (0040H) to read the user's reply into the buffer at HL, up to B characters. The CARRY FLAG is set if BREAK was pressed.
552B
If the CARRY FLAG is set (BREAK pressed), JUMP to 5580H to report "ATTRIB aborted!".
552D
EX DE,HL EB
Exchange DE and HL so HL holds the reply length returned by @KEYIN.
552E
LD H,00H 26 00
Load Register H with 00H so HL is just the reply length.
5530
LD L,B 68
Copy the length (Register B) into Register L; HL now holds the number of characters typed.
5531
ADD HL,DE 19
Add the buffer base (Register Pair DE) to HL so HL points just past the typed reply.
5532
LD A,08H 3E 08
Load Register A with 08H, the field width, to compute the pad count.
5534
SUB B 90
Subtract the typed length (Register B) from Register A, leaving the number of pad spaces needed.
5535
If the Z FLAG is set (reply already filled the field), JUMP to 553DH skipping the pad.
5537
LD B,A 47
Copy the pad count (Register A) into Register B for the pad loop.
5538
LD (HL),20H 36 20
Loop Start
Store a space (20H) into the output buffer (addressed by HL) to blank-fill the field.
553A
INC HL 23
Advance the output-buffer pointer (Register Pair HL) to the next byte.
553B
DECrement Register B and LOOP BACK to 5538H until the field is fully padded.
553D
POP HL E1
Restore the output-buffer start (Register Pair HL) for the upcase pass.
553E
PUSH HL E5
Save the output-buffer start (Register Pair HL) so it can be returned to the caller.
553F
LD B,08H 06 08
Load Register B with 08H, the field width, for the upcase pass.
5541
LD A,(HL) 7E
Loop Start
Fetch the next field character (addressed by HL) into Register A.
5542
CP 61H FE 61
Compare Register A against 61H (ASCII a). If below the lowercase range the CARRY FLAG is set.
5544
If the CARRY FLAG is set (not lowercase), JUMP to 5549H leaving the character unchanged.
5546
XOR 20H EE 20
Exclusive-OR 20H into Register A, folding the lowercase letter to uppercase.
5548
LD (HL),A 77
Store the upcased character (Register A) back into the buffer (addressed by HL).
5549
INC HL 23
Advance the buffer pointer (Register Pair HL) to the next character.
554A
DECrement Register B and LOOP BACK to 5541H until all eight characters are upcased.
554C
POP DE D1
Restore the output-buffer start into Register Pair DE for the caller.
554D
RET C9
RETurn to the caller with the eight-character field at 5700H (also addressed by DE).
554E
OR 0AFH F6 AF
Overlapping Code
On fall-through this is OR 0AFH (a non-zero result selects the GAT read below). Entered at 554FH (skipping the F6H byte) the single byte is XOR A, which zeroes Register A and selects the GAT write below.
5550
PUSH DE D5
Save the caller's Register Pair DE across the GAT access.
5551
PUSH HL E5
Save the caller's Register Pair HL across the GAT access.
5552
PUSH AF F5
Save the read/write selector (Register AF) computed by the entry point.
5553
GOSUB to the resident SYS0 service DIRCYL (4B65H) to seek the directory cylinder for the GAT access.
5556
LD E,00H 1E 00
Load Register E with 00H, the directory sector number of the GAT.
5558
LD HL,5800H 21 00 58
Point Register Pair HL at the GAT sector buffer at 5800H.
555B
POP AF F1
Restore the read/write selector (Register AF).
555C
If the Z FLAG is set (write was selected via 554FH), JUMP to 5565H to write the GAT.
555E
GOSUB to the resident SYS0 service RDSSEC (4B45H) to read the GAT sector into 5800H.
5561
LD A,14H 3E 14
Load Register A with error code 14H (GAT read error) to report a read failure.
5563
JUMP to 556FH to restore registers and return with the read result.
5565
GOSUB to the resident SYS0 service WRPROT (4768H) to write the GAT sector at 5800H with a directory (deleted-data) address mark.
5568
If the write succeeded (Z FLAG), GOSUB to the resident SYS0 service VERSEC (4772H) to verify the written GAT sector.
556B
CP 06H FE 06
Compare the returned status (Register A) against 06H to normalize the write/verify result.
556D
LD A,15H 3E 15
Load Register A with error code 15H (GAT write error) to report a write failure.
556F
POP HL E1
Restore the caller's Register Pair HL.
5570
POP DE D1
Restore the caller's Register Pair DE.
5571
RET C9
RETurn to the caller with the GAT access result in Register A and the flags set accordingly.

5572H - DO-Processing Guard and Message Selector

The guard (5572H) returns when the command runs at the LDOS command level and otherwise falls into the message block to report "Invalid command during DO processing!". The message selector (5578H-5592H) is a chain of deliberately overlapping instructions: read as written each is an inert LD IX,nnnn, but each real error entry point is one byte later, where the bytes read as LD HL,message; every path falls into the shared @LOGOT display and FFFFH failure exit at 5593H.

5572
LD A,(430FH) 3A 0F 43
Fetch the system flag SFLAG$ from 430FH into Register A.
5575
BIT 5,A CB 6F
Test bit 5 of SFLAG$ (Register A): the "not at LDOS command level" flag.
5577
RET Z C8
If the Z FLAG is set (at command level), RETurn allowing the interactive prompt.
5578
LD HL,560AH 21 0A 56
Not at command level: point Register Pair HL at the "Invalid command during DO processing!" message at 560AH, then fall into the shared display-and-fail tail at 5593H.
557B
LD IX,5664H DD 21 64 56
Overlapping Code
On fall-through this is LD IX,5664H (inert). Entered at 557CH (skipping the DD byte) the bytes read as LD HL,5664H, pointing Register Pair HL at the "Invalid master password!" message before the shared tail at 5593H.
557F
LD IX,567DH DD 21 7D 56
Overlapping Code
On fall-through this is LD IX,567DH (inert). Entered at 5580H the bytes read as LD HL,567DH, pointing Register Pair HL at the "ATTRIB aborted!" message before the shared tail at 5593H.
5583
LD IX,55DDH DD 21 DD 55
Overlapping Code
On fall-through this is LD IX,55DDH (inert). Entered at 5584H the bytes read as LD HL,55DDH, pointing Register Pair HL at the "File has no access password!" message before the shared tail at 5593H.
5587
LD IX,559CH DD 21 9C 55
Overlapping Code
On fall-through this is LD IX,559CH (inert). Entered at 5588H the bytes read as LD HL,559CH, pointing Register Pair HL at the "File spec required" message before the shared tail at 5593H.
558B
LD IX,55AFH DD 21 AF 55
Overlapping Code
On fall-through this is LD IX,55AFH (inert). Entered at 558CH the bytes read as LD HL,55AFH, pointing Register Pair HL at the "-Nothing done-" message before the shared tail at 5593H.
558F
LD IX,55BEH DD 21 BE 55
Overlapping Code
On fall-through this is LD IX,55BEH (inert). Entered at 5590H the bytes read as LD HL,55BEH, pointing Register Pair HL at the "Attribute specification error!" message before the shared tail at 5593H.
5593
GOSUB to the resident SYS0 service @LOGOT (447BH) to display the carriage-return-terminated message addressed by Register Pair HL.
5596
LD HL,0FFFFH 21 FF FF
Load Register Pair HL with 0FFFFH, the failure return code.
5599
JUMP to 54BCH to restore the caller's stack and exit the command with the failure code.

559CH - Messages and Protection-Keyword Table

The four carriage-return-terminated error strings displayed by the file form, followed by the eight two-character protection-level abbreviations searched at 5288H. The abbreviation index maps to a level value of 7 minus the index, giving FU=0, KI=1, NA=2, WR=4, RE=5, EX=6 and NO=7; the fifth entry (bytes 7EH 7EH) is an unreachable placeholder for level 3.

559C
DEFM "File spec required" + 0DH 46 69 6C 65 20 73 70 65 63 20 72 65 71 75 69 72 65 64 0D
Displayed when a device (leading *) was given instead of a file. Reached via entry 5588H.
55AF
DEFM "-Nothing done-" + 0DH 2D 4E 6F 74 68 69 6E 67 20 64 6F 6E 65 2D 0D
Displayed by the diskette form when no PW, LOCK, UNLOCK or NAME parameter was supplied. Reached via entry 558CH.
55BE
DEFM "Attribute specification error!" + 0DH 41 74 74 72 69 62 75 74 65 20 73 70 65 63 69 66 69 63 61 74 69 6F 6E 20 65 72 72 6F 72 21 0D
The general option-syntax error. Reached via entry 5590H.
55DD
DEFM "File has no access password!" + 0DH 46 69 6C 65 20 68 61 73 20 6E 6F 20 61 63 63 65 73 73 20 70 61 73 73 77 6F 72 64 21 0D
Displayed when an ACCess password is requested on a drive whose access-password field is reused for date stamping. Reached via entry 5584H.
55FA
DEFM "NOEXREWR~~NAKIFU" 4E 4F 45 58 52 45 57 52 7E 7E 4E 41 4B 49 46 55
Eight two-letter protection-level keywords searched at 5288H: NO, EX, RE, WR, (7EH 7EH placeholder), NA, KI, FU. The matched index yields the level value 7 minus the index.

560AH - Prompts and Diskette Messages

The interactive prompts (terminated with 03H for @KEYIN) and the remaining diskette-form messages (terminated with 0DH for @LOGOT).

560A
DEFM "Invalid command during DO processing!" + 0DH 49 6E 76 61 6C 69 64 20 63 6F 6D 6D 61 6E 64 20 64 75 72 69 6E 67 20 44 4F 20 70 72 6F 63 65 73 73 69 6E 67 21 0D
Displayed when an interactive prompt would be needed while the command runs under DO/JCL. Reached via entry 5578H.
5630
DEFM "New disk pack name ? " + 03H 4E 65 77 20 64 69 73 6B 20 70 61 63 6B 20 6E 61 6D 65 20 3F 20 20 20 03
The NAME prompt shown by 54FBH when NAME was given without an =value.
5648
DEFM "New Master password ? " + 03H 4E 65 77 20 4D 61 73 74 65 72 20 70 61 73 73 77 6F 72 64 20 3F 20 20 20 20 20 20 03
The new-master-password prompt (5417H); its tail beginning at 564CH ("Master password ?") is reused as the current-master-password prompt at 54E1H.
5664
DEFM "Invalid master password!" + 0DH 49 6E 76 61 6C 69 64 20 6D 61 73 74 65 72 20 70 61 73 73 77 6F 72 64 21 0D
Displayed when the supplied master password does not match the disk. Reached via entry 557CH.
567D
DEFM "ATTRIB aborted!" + 0DH 41 54 54 52 49 42 20 61 62 6F 72 74 65 64 21 0D
Displayed when BREAK is pressed at a prompt. Reached via entry 5580H.

568DH - Diskette Option Keyword Table (@PARAM)

The keyword descriptor table @PARAM scans for the diskette form (loaded into DE at 53D7H). Each entry is a six-character space-padded keyword followed by the two-byte (low, high) address of the cell that receives the parameter value. A 00H byte terminates the table.

568D
DEFM "PW " + DEFW 540EH 50 57 20 20 20 20 0E 54
PW keyword: the new diskette master password. Its value pointer is stored at 540EH and processed at 540DH.
5695
DEFM "LOCK " + DEFW 5431H 4C 4F 43 4B 20 20 31 54
LOCK keyword: flag cell at 5431H; sets every unprotected visible files password to the master password.
569D
DEFM "L " + DEFW 5431H 4C 20 20 20 20 20 31 54
Abbreviated LOCK; same flag cell at 5431H.
56A5
DEFM "UNLOCK" + DEFW 543BH 55 4E 4C 4F 43 4B 3B 54
UNLOCK keyword: flag cell at 543BH; clears the password of every file whose password matches the master password.
56AD
DEFM "U " + DEFW 543BH 55 20 20 20 20 20 3B 54
Abbreviated UNLOCK; same flag cell at 543BH.
56B5
DEFM "NAME " + DEFW 53F6H 4E 41 4D 45 20 20 F6 53
NAME keyword: the new diskette name. Its value pointer is stored at 53F6H and processed at 53F5H.
56BD
DEFM "N " + DEFW 53F6H 4E 20 20 20 20 20 F6 53
Abbreviated NAME; same pointer cell at 53F6H.
56C5
DEFM "MPW " + DEFW 54F9H 4D 50 57 20 20 20 F9 54
MPW keyword: the current diskette master password used for authorization. Its value pointer is stored at 54F9H and read at 54DDH.
56CD
DEFM "M " + DEFW 54F9H 4D 20 20 20 20 20 F9 54
Abbreviated MPW; same pointer cell at 54F9H.
56D5
DEFB 00H 00
Table terminator; also the last byte of the overlay image.

Disassembly - Overlay 10 - DUMP

5200H - DUMP Command (Command 71H)

Write an exact image of a block of memory to a disk file, either as a loadable LDOS load module (default extension /CIM) or as a pure ASCII text file (default extension /TXT). The overlay parses a file specification with @FSPEC, then parses the parenthesized options START, END, TRA, ASCII, LRL and ETX with @PARAM against the keyword table at 53A4H. Each option deposits its value directly into the operand cell of the instruction that later uses it, so the whole overlay is a chain of self-modifying defaults. The entry point saves the caller's stack pointer for a clean return.

5200
LD (5334H),SP ED 73 34 53
Self-Modifying Code
Save the caller's stack pointer into 5334H, the operand of the LD SP,nnnn at 5333H, so the original stack can be restored when the command finishes.
5204
LD DE,542CH 11 2C 54
Point Register Pair DE at 542CH, the file control block scratch area just above the overlay image, where @FSPEC will build the parsed file specification.
5207
GOSUB to the resident SYS0 service @FSPEC (441CH) to parse the file specification on the command line (Register Pair HL) into the FCB at DE (542CH). Returns the NZ FLAG when no valid file name is present.
520A
If the NZ FLAG is set (no valid file name was parsed), JUMP to 5352H to report "File spec required!".
520D
LD A,(DE) 1A
Fetch the first byte of the parsed FCB (addressed by DE at 542CH), the first character of the file name, into Register A.
520E
CP 2AH FE 2A
Compare Register A (the first file-name character) against 2AH (ASCII *). A leading asterisk denotes a device rather than a file. If equal the Z FLAG is set.
5210
If the Z FLAG is set (a device was named, which cannot be dumped to), JUMP to 5352H to report "File spec required!".
5213
LD DE,53A4H 11 A4 53
Point Register Pair DE at 53A4H, the base of the @PARAM keyword table (START, END, TRA, ASCII, LRL, ETX and their single-letter abbreviations), so @PARAM can match the parenthesized options.
5216
GOSUB to the resident SYS0 service @PARAM (4476H) to scan the option list (Register Pair HL) against the keyword table at DE (53A4H). Each recognized option stores its value into the operand cell named by the table entry. Returns the NZ FLAG on a syntax error or unknown keyword.
5219
If the NZ FLAG is set (a bad or unknown parameter), JUMP to 5349H to report parameter error code 2CH through @ERROR.

521CH - Validate the Start and End Addresses

The parsed END and START addresses now live in the operand cells 52D9H and 52D3H (the dump loop uses them directly). END must be greater than or equal to START, and the block is checked against the 5500H memory floor that protects the resident system and this overlay's own sector buffer at 5500H. A failure loads the address of the matching message and branches to the common message-and-exit path at 5355H.

521C
LD HL,(52D9H) 2A D9 52
Fetch the ending address of the dump (the END option value stored at 52D9H, the operand of the LD HL,nnnn at 52D8H; default 54FFH) into Register Pair HL.
521F
LD BC,(52D3H) ED 4B D3 52
Fetch the starting address of the dump (the START option value stored at 52D3H, the operand of the LD HL,nnnn at 52D2H; default 5500H) into Register Pair BC.
5223
XOR A AF
Set Register A to zero, clearing the CARRY FLAG in preparation for the subtraction that follows.
5224
SBC HL,BC ED 42
Subtract START (Register Pair BC) from END (Register Pair HL). If END is below START the CARRY FLAG is set, marking an invalid range.
5226
LD HL,535DH 21 5D 53
Point Register Pair HL at 535DH, the "START or END error!" message, so it is ready if the range test fails.
5229
If the CARRY FLAG is set (END is less than START), JUMP to 5355H to display the "START or END error!" message and abort the command.
522C
LD HL,(52D9H) 2A D9 52
Fetch the ending address again (the END option value at 52D9H; default 54FFH) into Register Pair HL to test it against the 5500H floor.
522F
LD BC,5500H 01 00 55
Load Register Pair BC with 5500H, the lowest address a dump is allowed to touch on the Model I (the resident system and this overlay's disk buffer sit below it).
5232
SBC HL,BC ED 42
Subtract 5500H (Register Pair BC) from END (Register Pair HL). The CARRY FLAG is set when END is below 5500H.
5234
If the CARRY FLAG is set (END is below the 5500H floor), JUMP to 5242H to continue building the output file. The CARRY FLAG here also leaves the flags clear for the low-memory test that follows.
5236
LD HL,5500H 21 00 55
Load Register Pair HL with 5500H, the memory floor, to form the low-memory comparison value.
5239
DEC HL 2B
Decrement Register Pair HL to 54FFH, one below the floor, so the following subtract compares the ending address against the highest illegal low-memory address. DEC of a register pair does not disturb the CARRY FLAG.
523A
SBC HL,BC ED 42
Subtract 5500H (still in Register Pair BC) from 54FFH (Register Pair HL), setting the CARRY FLAG for the branch that guards the "Start less than X'5500'!" message path.
523C
LD HL,5371H 21 71 53
Point Register Pair HL at 5371H, the "Start less than X'5500'!" message, so it is ready for the rejection path.
523F
If the NO CARRY FLAG is set, JUMP to 5355H to display the "Start less than X'5500'!" message. Otherwise execution falls through into the display-name builder at 5242H.

5242H - Build the Display Name and Apply the Default Extension

For a load-module dump the six-character file name is copied out of the FCB and cleaned to letters and digits only, to serve both as the module-name record and as the screen echo. The ASCII option flag (kept in the operand of the LD BC at 5242H) selects the default file extension: /CIM for a load module, /TXT for an ASCII text file, applied by @FEXT.

5242
LD BC,0000H 01 00 00
Self-Modifying Code
Load Register Pair BC with the ASCII option flag. The low operand byte at 5243H is set non-zero by the ASCII/A keyword through @PARAM; it defaults to 0000H (load-module mode).
5245
LD A,B 78
Copy the high byte of the ASCII flag (Register B) into Register A to test whether the ASCII option was given.
5246
OR C B1
OR the low byte of the ASCII flag (Register C) into Register A. The Z FLAG is set only when the whole flag is zero, meaning a load-module dump.
5247
If the NZ FLAG is set (the ASCII option was given), JUMP to 5274H to skip building the module name and select the /TXT extension.
5249
LD DE,5426H 11 26 54
Point Register Pair DE at 5426H, the six-byte staging area (immediately below the FCB) that will hold the cleaned module name.
524C
LD HL,542CH 21 2C 54
Point Register Pair HL at 542CH, the start of the parsed file name in the FCB, as the copy source.
524F
LD B,06H 06 06
Load Register B with 6, the number of name characters to process.
5251
LD A,(HL) 7E
Loop Start
Fetch the current name character (addressed by HL in the FCB) into Register A for validation.
5252
CP 30H FE 30
Compare Register A against 30H (ASCII 0). If Register A is below 30H the CARRY FLAG is set (not a digit or letter).
5254
If the CARRY FLAG is set (character below 0), JUMP to 5269H to pad the remainder of the name with spaces.
5256
CP 3AH FE 3A
Compare Register A against 3AH (one past ASCII 9). If Register A is below 3AH the CARRY FLAG is set, marking a valid digit.
5258
If the CARRY FLAG is set (Register A is a digit 0-9), JUMP to 5262H to store it unchanged.
525A
CP 41H FE 41
Compare Register A against 41H (ASCII A). If Register A is below 41H the CARRY FLAG is set (a punctuation character between the digits and letters).
525C
If the CARRY FLAG is set (character between 9 and A), JUMP to 5269H to pad with spaces.
525E
CP 5BH FE 5B
Compare Register A against 5BH (one past ASCII Z). If Register A is 5BH or greater the NO CARRY FLAG is set (past the uppercase letters).
5260
If the NO CARRY FLAG is set (character beyond Z), JUMP to 5269H to pad with spaces.
5262
LD (DE),A 12
Store the accepted letter or digit (Register A) into the module-name staging area (addressed by DE at 5426H onward).
5263
INC HL 23
Advance the source pointer (Register Pair HL) to the next FCB name character.
5264
INC DE 13
Advance the destination pointer (Register Pair DE) to the next staging byte.
5265
DECrement Register B and LOOP BACK to 5251H until all six name characters have been processed.
5267
All six characters copied, so JUMP to 526FH to select the load-module default extension.
5269
LD A,20H 3E 20
Loop Start
Load Register A with 20H (ASCII space) to pad the rest of the module name.
526B
LD (DE),A 12
Store the space (Register A) into the module-name staging area (addressed by DE).
526C
INC DE 13
Advance the destination pointer (Register Pair DE) to the next staging byte.
526D
DECrement Register B and LOOP BACK to 5269H until the six-character module name has been fully space-padded.
526F
LD HL,539EH 21 9E 53
Point Register Pair HL at 539EH, the default extension 'CIM', for a load-module dump.
5272
JUMP to 5277H to apply the selected default extension.
5274
LD HL,53A1H 21 A1 53
Point Register Pair HL at 53A1H, the default extension 'TXT', for an ASCII dump. (Reached directly when the ASCII option was given, bypassing the module-name builder.)
5277
LD DE,542CH 11 2C 54
Point Register Pair DE at 542CH, the FCB file name, as the target for the default extension.
527A
GOSUB to the resident SYS0 service @FEXT (4473H) to apply the default extension (Register Pair HL points at 'CIM' or 'TXT') to the FCB name at DE (542CH), only if the user did not already type an extension.

527DH - Validate the LRL and Create the Output File

The LRL option (logical record length of the file to be created) is kept in the operand of the LD BC at 527DH and must lie between 1 and 256; a value of 0000H means the standard 256-byte record. The validated length is passed in Register B to @INIT, which creates (or overwrites) the file described by the FCB, using the sector buffer at 5500H.

527D
LD BC,0000H 01 00 00
Self-Modifying Code
Load Register Pair BC with the LRL (logical record length) option. The operand at 527EH is set by the LRL/L keyword through @PARAM; it defaults to 0000H, meaning a 256-byte record.
5280
LD A,B 78
Copy the high byte of the requested LRL (Register B) into Register A to test the range.
5281
OR A B7
Test Register A (the LRL high byte). The Z FLAG is set when the high byte is zero, meaning the length is 0 to 255.
5282
If the Z FLAG is set (LRL high byte is zero), JUMP to 528CH to accept the low byte as the record length.
5284
DEC A 3D
Decrement Register A (the LRL high byte). The result is zero only when the high byte was exactly 1, the sole legal non-zero case (a length of 256).
5285
If the NZ FLAG is set (LRL high byte greater than 1, so the length exceeds 256), JUMP to 5349H to report parameter error 2CH.
5288
OR C B1
OR the LRL low byte (Register C) into Register A. With the high byte equal to 1, any non-zero low byte would make the length exceed 256.
5289
If the NZ FLAG is set (length is 257 or more), JUMP to 5349H to report parameter error 2CH.
528C
OR C B1
OR the LRL low byte (Register C) into Register A (which is zero here), leaving Register A equal to the requested record length (0 for 256, or the low byte).
528D
LD B,A 47
Copy the validated record length (Register A) into Register B, where @INIT expects the LRL.
528E
LD HL,5500H 21 00 55
Point Register Pair HL at 5500H, the 256-byte disk sector buffer that @INIT will assign to the new file. This is the same 5500H floor the address check enforced, so the dumped region never overlaps the file buffer.
5291
GOSUB to the resident SYS0 service @INIT (4420H) to create or open-and-truncate the file described by the FCB at DE (542CH), with logical record length Register B and sector buffer Register Pair HL (5500H). Returns the NZ FLAG and a DOS error code in Register A on failure.
5294
If the NZ FLAG is set (the file could not be created), JUMP to 534BH to report the DOS error code returned in Register A.

5297H - Announce the Dump on the Screen

Before writing any data the overlay echoes "Dumping: " followed by the fully resolved file specification. @FNAME reconstructs the filespec from the drive and directory-entry numbers @INIT left in the FCB, building it into the scratch buffer at 5406H which sits immediately after the "Dumping: " literal, so a single @LOGOT call prints both.

5297
PUSH DE D5
Save the FCB pointer (Register Pair DE at 542CH) on the stack across the name-formatting and announcement.
5298
LD BC,(5432H) ED 4B 32 54
Fetch the directory-entry number and drive from FCB+6 (5432H, filled in by @INIT) into Register Pair BC, which @FNAME uses to look the file up: Register C is the drive, Register B the directory record number.
529C
LD DE,5406H 11 06 54
Point Register Pair DE at 5406H, the scratch buffer directly after the "Dumping: " literal, as the destination for the reconstructed file specification.
529F
PUSH DE D5
Save the buffer pointer (Register Pair DE at 5406H) so it can be recovered after @FNAME to scan the produced string.
52A0
GOSUB to the resident SYS0 service @FNAME (44BBH) to build the file specification for the drive/record in Register Pair BC into the buffer at DE (5406H). Returns the NZ FLAG on error.
52A3
POP HL E1
Recover the buffer pointer (into Register Pair HL at 5406H) to scan for the end of the produced file specification.
52A4
If the NZ FLAG is set (@FNAME failed), JUMP to 534BH to report the DOS error code in Register A.
52A7
LD A,20H 3E 20
Load Register A with 20H (ASCII space) as the threshold for finding the end of the file-specification text.
52A9
INC HL 23
Loop Start
Advance the scan pointer (Register Pair HL) to the next character of the built file specification.
52AA
CP (HL) BE
Compare the space in Register A against the current character (addressed by HL). While the character is above a space the CARRY FLAG is set, meaning the text continues.
52AB
If the CARRY FLAG is set (still a printable character), LOOP BACK to 52A9H to keep scanning to the end of the file specification.
52AD
LD (HL),0DH 36 0D
Store 0DH (carriage return) at the end of the file specification (addressed by HL), terminating the string for @LOGOT.
52AF
LD HL,53FDH 21 FD 53
Point Register Pair HL at 53FDH, the "Dumping: " literal, which is immediately followed in memory by the file specification just built at 5406H.
52B2
GOSUB to the resident SYS0 service @LOGOT (447BH) to display the string at Register Pair HL (53FDH), printing "Dumping: " and the file specification up to the carriage return.
52B5
POP DE D1
Restore the FCB pointer (Register Pair DE at 542CH) for the writing phase.

52B6H - Write the Load-Module Name Record

A load-module dump begins with a type-05 module-name record: the byte 05H, a length of 6, and the six-character name staged earlier at 5426H. An ASCII dump has no header and skips straight to the data loop. The mode is read back from the ASCII flag cell at 5243H.

52B6
LD A,(5243H) 3A 43 52
Fetch the ASCII option flag from 5243H (the operand set by the ASCII/A keyword; non-zero means an ASCII dump) into Register A.
52B9
OR A B7
Test Register A (the ASCII flag). The NZ FLAG is set for an ASCII dump, the Z FLAG for a load-module dump.
52BA
If the NZ FLAG is set (ASCII dump), JUMP to 52D2H to begin the data loop with no load-module header.
52BC
LD A,05H 3E 05
Load Register A with 05H, the LDOS load-module record type for a module-name record.
52BE
GOSUB to the output helper at 5344H to write the record-type byte 05H (Register A) to the file.
52C1
LD A,06H 3E 06
Load Register A with 06H, the length of the name field that follows.
52C3
GOSUB to the output helper at 5344H to write the length byte 06H (Register A) to the file.
52C6
LD B,06H 06 06
Load Register B with 6, the number of module-name characters to write.
52C8
LD HL,5426H 21 26 54
Point Register Pair HL at 5426H, the cleaned six-character module name staged earlier.
52CB
LD A,(HL) 7E
Loop Start
Fetch the current module-name character (addressed by HL at 5426H onward) into Register A.
52CC
INC HL 23
Advance the name pointer (Register Pair HL) to the next character.
52CD
GOSUB to the output helper at 5344H to write the name character (Register A) to the file.
52D0
DECrement Register B and LOOP BACK to 52CBH until all six module-name characters have been written. Execution then falls into the data loop at 52D2H.

52D2H - Main Memory-to-File Dump Loop

The block of memory from START to END is written in runs of up to 254 bytes. For a load module each run is preceded by a type-01 load record header (01H, length, and the two-byte load address); for an ASCII dump the raw bytes are written with no framing. The current source pointer starts at START (in the operand of the LD HL at 52D2H) and the loop ends when it reaches END+1.

52D2
LD HL,5500H 21 00 55
Self-Modifying Code
Point Register Pair HL at the starting address of the dump. The operand at 52D3H holds the START value (default 5500H) deposited by the START/S keyword; this is executed once to seed the source pointer.
52D5
PUSH HL E5
Loop Start
Save the current source pointer (Register Pair HL) so it can be reloaded after the remaining-byte count is computed.
52D6
LD B,H 44
Copy the high byte of the source pointer (Register H) into Register B, forming the current address in Register Pair BC.
52D7
LD C,L 4D
Copy the low byte of the source pointer (Register L) into Register C, so Register Pair BC now holds the current source address.
52D8
LD HL,54FFH 21 FF 54
Self-Modifying Code
Point Register Pair HL at the ending address of the dump. The operand at 52D9H holds the END value (default 54FFH) deposited by the END/E keyword.
52DB
INC HL 23
Increment Register Pair HL to END+1 so the byte-count subtraction includes the ending address itself.
52DC
XOR A AF
Set Register A to zero, clearing the CARRY FLAG before the subtraction.
52DD
SBC HL,BC ED 42
Subtract the current source address (Register Pair BC) from END+1 (Register Pair HL), leaving the number of bytes still to be dumped in Register Pair HL. The Z FLAG is set when none remain.
52DF
If the Z FLAG is set (all bytes written), JUMP to 530FH to write the closing record and close the file.
52E1
LD B,0FEH 06 FE
Load Register B with 254, the maximum number of data bytes in one load record (a load-module length byte counts the two address bytes as well, keeping the record within 256 bytes).
52E3
LD A,H 7C
Copy the high byte of the remaining-byte count (Register H) into Register A to test whether at least 256 bytes remain.
52E4
OR A B7
Test Register A (the count high byte). The NZ FLAG is set when 256 or more bytes remain, so a full 254-byte run is used.
52E5
If the NZ FLAG is set (256 or more bytes remain), JUMP to 52EDH keeping the full 254-byte run count in Register B.
52E7
LD A,L 7D
Copy the low byte of the remaining-byte count (Register L) into Register A to compare against 255.
52E8
CP 0FFH FE FF
Compare Register A (the remaining count, now known to be under 256) against 0FFH. If it is 255 the NO CARRY FLAG is set.
52EA
If the NO CARRY FLAG is set (exactly 255 bytes remain), JUMP to 52EDH keeping the 254-byte run count, leaving one byte for the next pass.
52EC
LD B,L 45
Fewer than 254 bytes remain, so copy the remaining count (Register L) into Register B as this run's length.
52ED
POP HL E1
Restore the current source pointer (Register Pair HL) saved at the top of the loop, ready to emit this run.
52EE
LD A,(5243H) 3A 43 52
Fetch the ASCII option flag from 5243H (non-zero for an ASCII dump) into Register A to decide whether to write a load-record header.
52F1
OR A B7
Test Register A (the ASCII flag). The NZ FLAG is set for an ASCII dump.
52F2
If the NZ FLAG is set (ASCII dump), JUMP to 5306H to write the raw data bytes without any record header.
52F4
INC A 3C
Increment Register A from 0 to 01H, the LDOS load-module record type for a data (load) record.
52F5
GOSUB to the output helper at 5344H to write the record-type byte 01H (Register A) to the file.
52F8
LD A,B 78
Copy this run's data-byte count (Register B) into Register A to form the record length.
52F9
ADD A,02H C6 02
Add 2 to Register A so the length field counts the two load-address bytes that follow, as the LDOS load format requires.
52FB
GOSUB to the output helper at 5344H to write the record-length byte (Register A) to the file.
52FE
LD A,L 7D
Copy the low byte of the load address (Register L, the current source pointer) into Register A.
52FF
GOSUB to the output helper at 5344H to write the load-address low byte (Register A) to the file.
5302
LD A,H 7C
Copy the high byte of the load address (Register H) into Register A.
5303
GOSUB to the output helper at 5344H to write the load-address high byte (Register A) to the file.
5306
LD A,(HL) 7E
Loop Start
Fetch the current memory byte to be dumped (addressed by the source pointer HL) into Register A.
5307
INC HL 23
Advance the source pointer (Register Pair HL) to the next memory byte.
5308
GOSUB to the output helper at 5344H to write the memory byte (Register A) to the file.
530B
DECrement Register B and LOOP BACK to 5306H until this run of memory bytes has been written.
530D
LOOP BACK to 52D5H to start the next run, with the source pointer (Register Pair HL) now advanced past the bytes just written.

530FH - Write the Closing Record and Close the File

A load-module dump is finished with a type-02 transfer record carrying the TRA (transfer/execution address, default 402DH which is @EXIT, a return to DOS). An ASCII dump instead appends a single End-of-Text character, the ETX option (default 03H). The file is then closed and the caller's stack pointer restored.

530F
POP HL E1
Discard the source pointer that was saved at the top of the final loop pass (Register Pair HL), balancing the stack.
5310
LD A,(5243H) 3A 43 52
Fetch the ASCII option flag from 5243H (non-zero for an ASCII dump) into Register A to choose the closing record.
5313
OR A B7
Test Register A (the ASCII flag). The NZ FLAG is set for an ASCII dump, the Z FLAG for a load module.
5314
LD BC,0003H 01 03 00
Self-Modifying Code
Load Register Pair BC with the ETX option. The low operand byte at 5315H holds the End-of-Text character (default 03H) set by the ETX keyword; Register C therefore carries the ETX character for an ASCII dump.
5317
LD A,C 79
Copy the ETX character (Register C) into Register A in case this is an ASCII dump.
5318
If the NZ FLAG is set (ASCII dump), JUMP to 5328H to write the single ETX character held in Register A.
531A
GOSUB to the helper at 5342H, which loads 02H and writes it, emitting the transfer record type byte 02H to the file.
531D
GOSUB to the helper at 5342H again to write 02H as the transfer record length (two address bytes follow).
5320
LD HL,402DH 21 2D 40
Self-Modifying Code
Point Register Pair HL at the transfer address. The operand at 5321H holds the TRA value (default 402DH, the resident @EXIT return-to-DOS entry) set by the TRA/T keyword.
5323
LD A,L 7D
Copy the low byte of the transfer address (Register L) into Register A.
5324
GOSUB to the output helper at 5344H to write the transfer-address low byte (Register A) to the file.
5327
LD A,H 7C
Copy the high byte of the transfer address (Register H) into Register A. For an ASCII dump this row is not reached; the ETX character is written instead at 5328H.
5328
GOSUB to the output helper at 5344H to write Register A to the file: the transfer-address high byte for a load module, or the ETX character for an ASCII dump.
532B
GOSUB to the resident SYS0 service @CLOSE (4428H) to flush the last sector and close the file described by the FCB at DE (542CH). Returns the NZ FLAG and a DOS error code in Register A on failure.
532E
If the NZ FLAG is set (close failed), JUMP to 534BH to report the DOS error code in Register A.
5330
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H, the success return code (a non-error exit), for the shared exit logic that follows.
5333
LD SP,0000H 31 00 00
Self-Modifying Code
Restore the caller's stack pointer. The operand at 5334H was set at entry by the LD (5334H),SP instruction at 5200H, so this reloads the exact stack the command was entered with.
5336
LD A,H 7C
Copy the high byte of the return code (Register H) into Register A to test for the zero (success) code.
5337
OR L B5
OR the low byte of the return code (Register L) into Register A. The Z FLAG is set only when Register Pair HL is 0000H, meaning success.
5338
RET Z C8
If the Z FLAG is set (successful completion), RETURN to the resident command handler and thence to DOS Ready.
5339
LD A,(430FH) 3A 0F 43
Fetch the resident system flag SFLAG$ from 430FH into Register A to learn whether the command was invoked below command level (for example from within a JCL job).
533C
BIT 5,A CB 6F
Test bit 5 of SFLAG$ (Register A). When set, execution is not at command level, so an error must abort the job rather than return quietly.
533E
RET Z C8
If bit 5 was clear (the Z FLAG is set), RETURN to the caller carrying the error indication in Register Pair HL.
533F
Not at command level and an error occurred, so JUMP to the resident SYS0 service @ABORT (4030H) to abort the executing job.

5342H - Output-Byte Helper and Error Handlers

Every byte written to the dump file passes through the helper at 5344H, which calls the ROM @PUT driver at 001BH and returns on success. A write failure falls through into the error handler, which shares three overlapping entry points: 5348H keeps the disk error already in Register A, 5349H forces parameter error 2CH, and 534BH reports a DOS error code left by a failed @INIT, @FNAME or @CLOSE. The message paths at 5352H and 5355H display a fixed string and exit.

5342
LD A,02H 3E 02
Load Register A with 02H, the load-module record type used for a transfer record. Execution falls straight into the output helper at 5344H, so this doubles as "write a 02H byte".
5344
GOSUB to the ROM output driver @PUT (001BH) to write the byte in Register A to the device/file whose control block is in Register Pair DE (the open dump file). On return the Z FLAG is set if the byte was accepted.
5347
RET Z C8
If the Z FLAG is set (the byte was written successfully), RETURN to the caller to continue dumping.
5348
LD BC,2C3EH 01 3E 2C
Self-Modifying Code
Reached only on a write failure. This inert LD BC,2C3EH exists so its second and third bytes (3E 2C) are the instruction LD A,2CH when entered one byte later at 5349H. Falling through here leaves Register A holding the disk error code returned by @PUT.
5349
LD A,2CH 3E 2C
Load Register A with error code 2CH (parameter error). This entry point is taken by the option-validation jumps for a bad START/END/LRL value.
534B
OR 0C0H F6 C0
Set the two high bits of the error code (Register A), the @ERROR convention that requests both a text display and a return of the code. This entry point is used directly when Register A already holds a DOS error code from a failed @INIT, @FNAME or @CLOSE.
534D
GOSUB to the resident SYS0 service @ERROR (4409H) to display the error message for the code in Register A.
5350
JUMP to 5358H to load the error return code and exit.
5352
LD HL,538AH 21 8A 53
Point Register Pair HL at 538AH, the "File spec required!" message, for the two entry jumps taken when no valid file name was given.
5355
GOSUB to the resident SYS0 service @LOGOT (447BH) to display the message addressed by Register Pair HL (either "START or END error!", "Start less than X'5500'!", or "File spec required!").
5358
LD HL,0FFFFH 21 FF FF
Load Register Pair HL with 0FFFFH, the non-zero error return code read by the shared exit logic.
535B
JUMP to 5333H to restore the caller's stack pointer and exit, aborting the job if this command is running below command level.

535DH - Message Strings

The three error messages, each terminated by a carriage return (0DH) for @LOGOT. This region is data, not code; the disassembler that produced the working listing decoded part of it as instructions.

535D-5370
DEFM 'START or END error!' 53 54 41 52 54 20 6F 72 20 45 4E 44 20 65 72 72 6F 72 21 0D
Displayed when the ending address is below the starting address (reached from 5229H). The final byte at 5370H is the 0DH terminator.
5371-5389
DEFM "Start less than X'5500'!" 53 74 61 72 74 20 6C 65 73 73 20 74 68 61 6E 20 58 27 35 35 30 30 27 21 0D
Displayed on the low-memory rejection path (reached from 523FH). The final byte at 5389H is the 0DH terminator.
538A-539D
DEFM 'File spec required!' 46 69 6C 65 20 73 70 65 63 20 72 65 71 75 69 72 65 64 21 0D
Displayed when no file name (or a device name) was given (reached from 520AH, 5210H and 5352H). The final byte at 539DH is the 0DH terminator.

539EH - Default Extensions and Parameter Keyword Table

The two three-character default file extensions, followed by the @PARAM keyword table. Each table entry is eight bytes: a six-character space-padded keyword and a two-byte little-endian pointer to the operand cell that receives the parsed value. Six full keywords (START, END, TRA, ASCII, LRL, ETX) are followed by five single-letter abbreviations (S, E, T, A, L); a 00H byte ends the table.

539E-53A0
DEFM 'CIM' 43 49 4D
Default file extension for a load-module (non-ASCII) dump, applied by @FEXT at 527AH.
53A1-53A3
DEFM 'TXT' 54 58 54
Default file extension for an ASCII dump, applied by @FEXT at 527AH.
53A4-53AB
DEFM 'START ', DEFW 52D3H 53 54 41 52 54 20 D3 52
START keyword. The pointer 52D3H is the operand of the LD HL,nnnn at 52D2H, the starting address of the dump (default 5500H).
53AC-53B3
DEFM 'END ', DEFW 52D9H 45 4E 44 20 20 20 D9 52
END keyword. The pointer 52D9H is the operand of the LD HL,nnnn at 52D8H, the ending address of the dump (default 54FFH).
53B4-53BB
DEFM 'TRA ', DEFW 5321H 54 52 41 20 20 20 21 53
TRA keyword. The pointer 5321H is the operand of the LD HL,nnnn at 5320H, the transfer (execution) address written into the load module (default 402DH, @EXIT).
53BC-53C3
DEFM 'ASCII ', DEFW 5243H 41 53 43 49 49 20 43 52
ASCII keyword. The pointer 5243H is the operand of the LD BC,nnnn at 5242H, the flag that selects a pure ASCII dump instead of a load module (default 0000H).
53C4-53CB
DEFM 'LRL ', DEFW 527EH 4C 52 4C 20 20 20 7E 52
LRL keyword (logical record length of the created file). The pointer 527EH is the operand of the LD BC,nnnn at 527DH; the validated value is passed to @INIT (default 0000H, meaning 256).
53CC-53D3
DEFM 'ETX ', DEFW 5315H 45 54 58 20 20 20 15 53
ETX keyword. The pointer 5315H is the operand of the LD BC,nnnn at 5314H, the End-of-Text character appended to an ASCII dump (default 03H).
53D4-53DB
DEFM 'S ', DEFW 52D3H 53 20 20 20 20 20 D3 52
Single-letter abbreviation for START, pointing at the same operand cell 52D3H.
53DC-53E3
DEFM 'E ', DEFW 52D9H 45 20 20 20 20 20 D9 52
Single-letter abbreviation for END, pointing at the same operand cell 52D9H.
53E4-53EB
DEFM 'T ', DEFW 5321H 54 20 20 20 20 20 21 53
Single-letter abbreviation for TRA, pointing at the same operand cell 5321H.
53EC-53F3
DEFM 'A ', DEFW 5243H 41 20 20 20 20 20 43 52
Single-letter abbreviation for ASCII, pointing at the same operand cell 5243H.
53F4-53FB
DEFM 'L ', DEFW 527EH 4C 20 20 20 20 20 7E 52
Single-letter abbreviation for LRL, pointing at the same operand cell 527EH. (ETX has no single-letter form, since E is taken by END.)
53FC
DEFB 00H 00
Zero byte terminating the @PARAM keyword table.

53FDH - Dump Announcement Literal

The screen prompt printed before the dump begins. It carries no carriage return of its own: the reconstructed file specification that @FNAME builds into the scratch buffer at 5406H sits immediately after it in memory, so one @LOGOT call from 53FDH prints "Dumping: " and the file name together. 5405H is the last byte of the loaded overlay image; 5406H onward is uninitialized RAM used as scratch.

53FD-5405
DEFM 'Dumping: ' 44 75 6D 70 69 6E 67 3A 20
Displayed by @LOGOT at 52B2H, immediately followed by the file specification built at 5406H and terminated there by a carriage return.

Disassembly - Overlay 11 - PURGE

5200H - PURGE Command (RST 28H Code 89H, Command 72H)

Parse the PURGE command line and options. The command form is an optional leading minus (invert the selection), an optional partspec filename and /extension mask with the wildcard $, a mandatory :drive, and the option list (INV, SYS, MPW, QUERY, DATE). The filename mask is built at 5705H and the extension mask at 570DH; the drive number is validated with @CKDRV and stored at 54ADH, and two BIT drive,A instructions are self-modified so later code can test this drive's entry in the resident dated-directory bitmap at 475DH. Options are parsed by @PARAM against the keyword table at 5734H.

5200
LD (52DEH),SP ED 73 DE 52
Self-Modifying Code
Save the caller's stack pointer into 52DEH, the operand of the LD SP,nnnn at 52DDH, so the original stack is restored on exit.
5204
LD A,(4423H) 3A 23 44
Fetch the keyboard flag KFLAG$ from 4423H into Register A to clear its type-ahead and pause bits while the purge runs.
5207
AND 0FCH E6 FC
Mask Register A with 0FCH, clearing the low two bits of KFLAG$ (type-ahead and BREAK-pending) so stray keystrokes do not disturb the purge.
5209
LD (4423H),A 32 23 44
Store the cleared flags (Register A) back into KFLAG$ at 4423H.
520C
LD A,(HL) 7E
Loop Start
Fetch the current command-line character (addressed by HL) into Register A to skip leading blanks.
520D
INC HL 23
Advance the command-line pointer (Register Pair HL) to the next character.
520E
CP 20H FE 20
Compare Register A against 20H (space). If equal the Z FLAG is set.
5210
If the Z FLAG is set (a blank), LOOP BACK to 520CH to skip it.
5212
LD DE,5705H 11 05 57
Point Register Pair DE at 5705H, the eight-byte filename-mask buffer that the partspec name characters are copied into.
5215
LD B,08H 06 08
Load Register B with 8, the width of the filename field in the mask.
5217
CP 2DH FE 2D
Compare the first non-blank character (Register A) against 2DH (ASCII -), the leading minus that inverts the selection (purge everything EXCEPT the matching files).
5219
If the NZ FLAG is set (no leading minus), JUMP to 5220H to copy the partspec name.
521B
LD (5352H),A 32 52 53
Self-Modifying Code
Store the minus (Register A, non-zero) into 5352H, the exclude flag; a later test at 5348H inverts the mask match when this cell is non-zero.
521E
LD A,(HL) 7E
Fetch the character after the minus (addressed by HL) into Register A.
521F
INC HL 23
Advance the command-line pointer (Register Pair HL) past it.
5220
GOSUB to the mask-copy helper at 5558H to copy up to Register B name characters (from HL) into the mask at DE (5705H), folding case and passing the wildcard $. Returns the delimiter in Register A.
5223
CP 2FH FE 2F
Compare the delimiter (Register A) against 2FH (ASCII /), the extension separator.
5225
If the NZ FLAG is set (no extension given), JUMP to 5231H to look for the drivespec.
5227
LD DE,570DH 11 0D 57
Point Register Pair DE at 570DH, the three-byte extension-mask buffer.
522A
LD B,03H 06 03
Load Register B with 3, the width of the extension field.
522C
LD A,(HL) 7E
Fetch the first extension character (addressed by HL) into Register A.
522D
INC HL 23
Advance the command-line pointer (Register Pair HL).
522E
GOSUB to the mask-copy helper at 5558H to copy up to Register B extension characters (from HL) into the mask at DE (570DH). Returns the delimiter in Register A.
5231
CP 3AH FE 3A
Compare the delimiter (Register A) against 3AH (ASCII :), the start of the mandatory drivespec.
5233
If the NZ FLAG is set (no colon), JUMP to 5260H where the not-Zero flag forces the "parameter error" report, since the drivespec is required.
5235
LD A,(HL) 7E
Fetch the drive digit (addressed by HL) into Register A.
5236
INC HL 23
Advance the command-line pointer (Register Pair HL).
5237
SUB 30H D6 30
Subtract 30H from Register A to convert the ASCII drive digit to its binary value.
5239
CP 08H FE 08
Compare the binary drive number (Register A) against 8. If it is 8 or greater the NO CARRY FLAG is set.
523B
If the NO CARRY FLAG is set (drive number out of range 0-7), JUMP to 55D3H to report parameter error 2CH.
523E
LD C,A 4F
Copy the drive number (Register A) into Register C for @CKDRV.
523F
LD (54ADH),A 32 AD 54
Store the drive number (Register A) into 54ADH, the working drive cell used throughout the overlay.
5242
RLCA 07
Rotate Register A left circularly (first of three), beginning to multiply the drive number by 8 to build a BIT-opcode operand.
5243
RLCA 07
Rotate Register A left circularly (second of three).
5244
RLCA 07
Rotate Register A left circularly (third of three); Register A now holds the drive number times 8.
5245
OR 47H F6 47
OR Register A with 47H, forming the Z80 opcode byte for BIT drive,A (47H is BIT 0,A; adding 8 per drive selects the bit).
5247
LD (558CH),A 32 8C 55
Self-Modifying Code
Store the assembled opcode (Register A) into 558CH, the operand of the BIT 0,A at 558BH, so the date helper tests this drive's bit in the dated-directory bitmap.
524A
LD (5423H),A 32 23 54
Self-Modifying Code
Store the same opcode (Register A) into 5423H, the operand of the BIT 0,A at 5422H, so the mod-flag extractor tests this drive's dated-directory bit.
524D
GOSUB to the resident SYS0 service @CKDRV (44B8H) to validate the drive number in Register C. Returns the NZ FLAG or the CARRY FLAG for a missing or not-ready drive.
5250
LD A,20H 3E 20
Load Register A with error code 20H (device not available) in case the drive is absent.
5252
If the NZ FLAG is set (drive not in the drive table), JUMP to 55D5H to report the device-not-available error.
5255
LD A,0FH 3E 0F
Load Register A with error code 0FH (drive not ready) in case the drive is not ready.
5257
If the CARRY FLAG is set (drive not ready), JUMP to 55D5H to report the drive-not-ready error.
525A
LD DE,5734H 11 34 57
Point Register Pair DE at 5734H, the @PARAM keyword table (I/INV, S/SYS, MPW, Q/QUERY, D/DATE).
525D
GOSUB to the resident SYS0 service @PARAM (4476H) to scan the options (from HL) against the table at DE. Each option stores its value into the operand cell named by the table. Returns the NZ FLAG on error.
5260
If the NZ FLAG is set (a bad option, or no colon was found earlier), JUMP to 55D3H to report parameter error 2CH.

5263H - Parse the Date Filter

When the DATE option is present its pointer sits in the operand of the LD HL at 5263H. The value accepts four forms - "M/D/Y", "M/D/Y-M/D/Y", "-M/D/Y" and "M/D/Y-" - handled by parsing an optional lower date (packed into 5711H) and an optional upper date (packed into 5713H). A flag byte at 5710H records which bounds are present (bit 7 = lower, bit 0 = upper). Each date is packed by the helper at 55F4H.

5263
LD HL,0000H 21 00 00
Self-Modifying Code
Load Register Pair HL with the DATE option value. The operand at 5264H holds a pointer to the date string (set by the DATE/D keyword), or 0000H when no date filter was given.
5266
LD A,H 7C
Copy the high byte of the date pointer (Register H) into Register A to test whether a date filter is present.
5267
OR L B5
OR the low byte (Register L) into Register A. The Z FLAG is set only when the pointer is 0000H (no DATE option).
5268
If the Z FLAG is set (no date filter), JUMP to 5299H to skip date parsing.
526A
LD A,(HL) 7E
Fetch the first character of the date string (addressed by HL) into Register A.
526B
CP 2DH FE 2D
Compare Register A against 2DH (ASCII -). A leading minus means "on or before" (only an upper bound).
526D
If the Z FLAG is set (leading minus), JUMP to 5284H to parse only the upper date.
526F
LD A,80H 3E 80
Load Register A with 80H to set the "date filter active" flag.
5271
LD (5710H),A 32 10 57
Store 80H into 5710H, the date-flag byte, marking that a lower date bound is present.
5274
GOSUB to the date-parse helper at 55F4H to convert the first "M/D/Y" string (at HL) into a packed 16-bit date in Register Pair BC.
5277
LD (5711H),BC ED 43 11 57
Store the packed lower date (Register Pair BC) into 5711H-5712H.
527B
LD A,(HL) 7E
Fetch the next date-string character (addressed by HL) into Register A to look for a range.
527C
CP 22H FE 22
Compare Register A against 22H (ASCII "), the closing quote (a single date, no range).
527E
If the Z FLAG is set (end of the date string), JUMP to 528DH to finish with only a lower bound.
5280
CP 2DH FE 2D
Compare Register A against 2DH (ASCII -), the range separator.
5282
If the NZ FLAG is set (neither quote nor minus), JUMP to 5299H leaving only the single date.
5284
INC HL 23
Loop target
Advance the date-string pointer (Register Pair HL) past the minus.
5285
LD A,(HL) 7E
Fetch the character after the minus (addressed by HL) into Register A.
5286
CP 22H FE 22
Compare Register A against 22H (ASCII "). A quote here means "on or after" (open-ended upper bound).
5288
If the Z FLAG is set (no upper date), JUMP to 5299H keeping only the lower bound.
528A
GOSUB to the date-parse helper at 55F4H to convert the upper "M/D/Y" string (at HL) into a packed date in Register Pair BC.
528D
LD A,(5710H) 3A 10 57
Loop target
Fetch the date-flag byte from 5710H into Register A.
5290
OR 01H F6 01
OR Register A with 01H to set the "upper bound present" flag.
5292
LD (5710H),A 32 10 57
Store the updated flag byte (Register A) into 5710H.
5295
LD (5713H),BC ED 43 13 57
Store the packed upper date (Register Pair BC) into 5713H-5714H.

5299H - Guard the Query Context and Read the Directory

If interactive querying is on (the default) the command is refused inside a JCL/DO job, since it would need keyboard responses. The disk's GAT sector is read and the master password verified (54ACH), the directory cylinder is located with DIRCYL, and the first directory sector is read into 5A00H with RDSSEC before the entry scan begins.

5299
LD A,(53C0H) 3A C0 53
Fetch the QUERY flag from 53C0H into Register A. It is FFH by default (query each file) or 00H when Q=OFF/N was given.
529C
OR A B7
Test Register A (the QUERY flag). The Z FLAG is set when querying is off.
529D
If the Z FLAG is set (Q=OFF, unattended purge), JUMP to 52A5H, skipping the command-level check.
529F
GOSUB to 5552H to read SFLAG$; it returns the NZ FLAG when the purge is running below LDOS command level (inside a JCL/DO job).
52A2
If the NZ FLAG is set (interactive query requested while inside a DO job), JUMP to 55E4H to report "Invalid command during <DO> processing".
52A5
GOSUB to 54ACH to read the disk's GAT sector and verify the master password before any file is removed.
52A8
LD A,(54ADH) 3A AD 54
Fetch the working drive number from 54ADH into Register A.
52AB
LD C,A 4F
Copy the drive number (Register A) into Register C for the directory read.
52AC
GOSUB to the resident SYS0 service DIRCYL (4B65H) to seek the directory cylinder of the drive in Register C.
52AF
LD E,01H 1E 01
Load Register E with 1, the sector number of the first directory (HIT) sector on the directory cylinder.
52B1
LD HL,5A00H 21 00 5A
Point Register Pair HL at 5A00H, the buffer that receives the directory sector.
52B4
GOSUB to the resident SYS0 service RDSSEC (4B45H) to read directory sector Register E into the buffer at HL (5A00H). Returns the NZ FLAG on a read error.
52B7
LD A,16H 3E 16
Load Register A with error code 16H (directory read error) in case the read failed.
52B9
If the NZ FLAG is set (directory sector unreadable), JUMP to 55D5H to report the error.
52BC
JUMP to 52ECH to begin walking the directory entries.

52BEH - Directory Entry Iteration and BREAK Check

The loop walks the directory slots in 32-byte steps, skipping the two HIT bytes at the head of the sector and any empty positions, and honours a BREAK keypress (KFLAG$ bit 0) by aborting with "Purge aborted". When the whole directory has been scanned it prints a closing carriage return, restores the stack and returns, aborting the job at @ABORT if it was running below command level.

52BE
POP HL E1
Loop Start
Restore the directory pointer (Register Pair HL) saved before an entry was processed.
52BF
POP BC C1
Restore the saved entry index (Register Pair BC); Register B holds the low byte of the current directory slot.
52C0
LD A,(4423H) 3A 23 44
Fetch KFLAG$ from 4423H into Register A to test whether the user pressed BREAK to abort the purge.
52C3
RRCA 0F
Rotate Register A right circularly, moving KFLAG$ bit 0 (BREAK pending) into the CARRY FLAG.
52C4
If the CARRY FLAG is set (BREAK was pressed), JUMP to 55DCH to report "Purge aborted".
52C7
LD H,5AH 26 5A
Load Register H with 5AH, fixing the high byte of the directory-sector buffer at 5A00H.
52C9
LD L,B 68
Copy the saved slot index (Register B) into Register L, so Register Pair HL again addresses the current directory entry.
52CA
LD A,L 7D
Loop target
Copy the slot offset (Register L) into Register A.
52CB
ADD A,20H C6 20
Add 20H (32 bytes) to Register A to step to the next directory entry within the sector.
52CD
LD L,A 6F
Copy the advanced offset (Register A) back into Register L.
52CE
If the NO CARRY FLAG is set (still within the sector), JUMP to 52ECH to test the next entry.
52D0
INC L 2C
The offset wrapped past the sector end, so increment Register L to align the multi-sector directory scan.
52D1
CP 1FH FE 1F
Compare Register A against 1FH, the marker that the whole directory has been scanned.
52D3
If the NZ FLAG is set (more directory sectors remain), JUMP to 52ECH to continue.
52D5
LD A,0DH 3E 0D
The entire directory has been processed. Load Register A with 0DH (carriage return) to end the display line.
52D7
GOSUB to the ROM display driver at 0033H to print the carriage return in Register A.
52DA
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H, the success return code, for the shared exit.
52DD
LD SP,0000H 31 00 00
Self-Modifying Code
Restore the caller's stack pointer; the operand at 52DEH was set at entry by the LD (52DEH),SP at 5200H.
52E0
LD A,H 7C
Copy the high byte of the return code (Register H) into Register A.
52E1
OR L B5
OR the low byte (Register L) into Register A. The Z FLAG is set only when Register Pair HL is 0000H (success).
52E2
RET Z C8
If the Z FLAG is set (successful purge), RETURN to the RST 28H dispatcher.
52E3
LD A,(430FH) 3A 0F 43
Fetch SFLAG$ from 430FH into Register A to test the command-level bit for the error exit.
52E6
BIT 5,A CB 6F
Test bit 5 of SFLAG$ (Register A); when set the purge is not at command level.
52E8
RET Z C8
If bit 5 was clear (the Z FLAG is set), RETURN to the caller carrying the error code in Register Pair HL.
52E9
Not at command level and an error occurred, so JUMP to the resident SYS0 service @ABORT (4030H) to abort the job.
52EC
LD A,L 7D
Loop target
Copy the current slot offset (Register L) into Register A.
52ED
AND 0FEH E6 FE
Mask Register A with 0FEH; the result is zero only for slot offsets 00H and 01H, which are the HIT bytes rather than a file entry.
52EF
If the Z FLAG is set (a HIT byte, not an entry), JUMP back to 52CAH to step to the next slot.
52F1
LD A,(HL) 7E
Fetch the first byte of the directory slot (addressed by HL) into Register A to test whether it is an allocated entry.
52F2
OR A B7
Test Register A. The Z FLAG is set when the slot byte is zero (an unused directory position).
52F3
If the Z FLAG is set (empty slot), JUMP back to 52CAH to step to the next slot.

52F5H - Read the Entry and Apply the Attribute and Name Filters

The directory record is brought into SBUFF$ (4200H) with DIRRD if not already buffered, and the entry's attribute byte is tested: bit 4 must be set (allocated), bit 7 must be clear (BOOT/SYS, DIR/SYS and directory housekeeping entries are never purged), a set bit 6 (system) requires the SYS switch, and a set bit 3 (invisible) requires the INV switch. Surviving entries are matched against the eleven-character name+extension mask at 5705H, with $ matching any character and a blank matching a don't-care position. The leading-minus exclude flag at 5352H inverts the sense of a match, and is read both explicitly at 5348H and as the self-modified operand of the LD A at 5351H.

52F5
LD B,L 45
Copy the current slot offset (Register L) into Register B to preserve the entry index across the read.
52F6
PUSH BC C5
Save the entry index (Register Pair BC) on the stack while the entry is read and tested.
52F7
LD A,L 7D
Copy the slot offset (Register L) into Register A to compute which 256-byte directory record holds this entry.
52F8
AND 0E0H E6 E0
Mask Register A with 0E0H, rounding down to the directory-record boundary that DIRRD expects.
52FA
LD L,A 6F
Copy the rounded record base (Register A) back into Register L.
52FB
XOR B A8
XOR Register B (the true offset) into Register A to see whether the wanted record is already the one in the buffer.
52FC
CP 0FFH FE FF
Compare Register A against 0FFH, the marker meaning the record is already resident.
52FE
If the Z FLAG is set (record already in SBUFF$), JUMP to 5309H, skipping the re-read.
5300
LD (52FDH),A 32 FD 52
Self-Modifying Code
Store the computed record marker (Register A) into 52FDH, the operand of the LD A,nn at 52FCH, caching which record is buffered.
5303
GOSUB to the resident SYS0 service DIRRD (4B10H) to read the directory record into the resident sector buffer SBUFF$ at 4200H. Returns the NZ FLAG on a read error.
5306
If the NZ FLAG is set (directory record unreadable), JUMP to 55D5H to report the error.
5309
LD H,42H 26 42
Loop target
Load Register H with 42H, pointing Register Pair HL into the resident sector buffer SBUFF$ (4200H) where the directory entry now lives.
530B
LD A,(HL) 7E
Fetch the entry's attribute byte (addressed by HL, entry offset 0) into Register A.
530C
BIT 4,A CB 67
Test bit 4 of the attribute byte (Register A); a set bit marks an allocated (in-use) directory entry.
530E
If the Z FLAG is set (bit 4 clear, slot not in use), JUMP to 52BFH to skip to the next entry.
5310
BIT 7,A CB 7F
Test bit 7 of the attribute byte (Register A); a set bit marks a protected entry that may never be purged (BOOT/SYS, DIR/SYS and the directory's own housekeeping entries).
5312
If the NZ FLAG is set (bit 7 set, protected entry), JUMP to 52BFH to skip it.
5314
BIT 6,A CB 77
Test bit 6 of the attribute byte (Register A); a set bit marks a system file.
5316
If the Z FLAG is set (not a system file), JUMP to 5322H to test the invisible attribute.
5318
LD DE,0000H 11 00 00
Self-Modifying Code
Load Register Pair DE with the SYS option flag; the operand at 5319H is non-zero only when the SYS switch was given.
531B
LD A,D 7A
Copy the high byte of the SYS flag (Register D) into Register A.
531C
OR E B3
OR the low byte (Register E) into Register A. The Z FLAG is set when the SYS switch was not given.
531D
If the Z FLAG is set (SYS not requested), JUMP to 52BFH to skip this system file.
5320
A system file was requested, so JUMP to 532EH to test it against the name mask.
5322
BIT 3,A CB 5F
Loop target
Test bit 3 of the attribute byte (Register A); a set bit marks an invisible file.
5324
If the Z FLAG is set (a visible file), JUMP to 532EH to test the name mask.
5326
LD DE,0000H 11 00 00
Self-Modifying Code
Load Register Pair DE with the INV option flag; the operand at 5327H is non-zero only when the INV switch was given.
5329
LD A,D 7A
Copy the high byte of the INV flag (Register D) into Register A.
532A
OR E B3
OR the low byte (Register E) into Register A. The Z FLAG is set when the INV switch was not given.
532B
If the Z FLAG is set (INV not requested), JUMP to 52BFH to skip this invisible file.
532E
PUSH HL E5
Loop target
Save the entry pointer (Register Pair HL) while the name and extension are matched against the mask.
532F
LD A,L 7D
Copy the entry offset (Register L) into Register A.
5330
ADD A,05H C6 05
Add 5 to Register A to reach entry offset 5, the start of the eight-character file name in the directory entry.
5332
LD L,A 6F
Copy the advanced offset (Register A) back into Register L, so Register Pair HL points at the file name.
5333
LD DE,5705H 11 05 57
Point Register Pair DE at 5705H, the eleven-byte name+extension mask built during command parsing.
5336
LD B,0BH 06 0B
Load Register B with 11 (0BH), the eight name plus three extension positions to compare.
5338
LD A,(DE) 1A
Loop Start
Fetch the current mask character (addressed by DE at 5705H onward) into Register A.
5339
CP 24H FE 24
Compare Register A against 24H (ASCII $), the wildcard that matches any character.
533B
If the Z FLAG is set (wildcard), JUMP to 5344H accepting this position unconditionally.
533D
CP (HL) BE
Compare the mask character (Register A) against the entry character (addressed by HL). If equal the Z FLAG is set.
533E
If the Z FLAG is set (characters match), JUMP to 5344H to advance to the next position.
5340
CP 20H FE 20
Compare the mask character (Register A) against 20H (space), an unused (don't-care) mask position.
5342
If the NZ FLAG is set (a real mismatch), JUMP to 5351H to record that this file does not match.
5344
INC HL 23
Loop target
Advance the entry-name pointer (Register Pair HL) to the next character.
5345
INC DE 13
Advance the mask pointer (Register Pair DE) to the next mask character.
5346
DECrement Register B and LOOP BACK to 5338H until all eleven name and extension positions have been compared.
5348
LD A,(5352H) 3A 52 53
The whole mask matched. Fetch the exclude flag from 5352H into Register A (non-zero when a leading minus inverted the selection).
534B
OR A B7
Test Register A (the exclude flag). The NZ FLAG is set when the selection was inverted.
534C
If the NZ FLAG is set (invert mode and the file matched), JUMP to 52BEH to skip it, since matching files are excluded.
534F
A normal match with no inversion, so JUMP to 5357H to purge (or query) this file.
5351
LD A,00H 3E 00
Self-Modifying Code
A mask mismatch. This LD A,nn reads its own operand at 5352H, which is the exclude flag: 2DH in invert mode, 00H otherwise.
5353
OR A B7
Test Register A. The Z FLAG is set in normal mode (operand 00H) and clear in invert mode (operand 2DH).
5354
If the Z FLAG is set (normal mode, file did not match), JUMP to 52BEH to skip it; in invert mode execution falls through to purge the non-matching file.

5357H - Build the File-Description Line

A matched file is checked against the date filter using the packed modification date unpacked at 5577H (RST 18H performs the 16-bit compares; undated files are dropped when a date filter is active). The overlay then assembles the display line at 5719H: the file name, optional /extension, :drive, a space, a + when the file has been modified since backup, and the modification date inside braces as MM-Mon-YY, using the three-letter month table at 56E1H and the resident dated-directory bitmap at 475DH to decide between the standard and extended year formats.

5357
POP HL E1
Loop target
Restore the entry pointer (Register Pair HL) saved before the mask test.
5358
PUSH HL E5
Save the entry pointer (Register Pair HL) again while the modification date is examined.
5359
INC HL 23
Advance Register Pair HL to entry offset 1, the first of the packed date bytes.
535A
GOSUB to 5577H to unpack the file's modification date from the entry into Register Pair DE as a comparable 16-bit value.
535D
LD A,(5710H) 3A 10 57
Fetch the date-flag byte from 5710H into Register A to test whether a lower date bound is active.
5360
RLCA 07
Rotate Register A left circularly, moving bit 7 (lower bound present) into the CARRY FLAG.
5361
If the NO CARRY FLAG is set (no lower bound), JUMP to 5371H to test the upper bound.
5363
LD A,D 7A
Copy the high byte of the file date (Register D) into Register A.
5364
OR E B3
OR the low byte (Register E) into Register A. The Z FLAG is set when the file has no modification date.
5365
If the Z FLAG is set (undated file), JUMP to 52BEH to skip it, since date-filtered purges never show undated files.
5368
LD HL,(5711H) 2A 11 57
Load Register Pair HL with the packed lower date bound from 5711H.
536B
EX DE,HL EB
Exchange Register Pairs DE and HL so HL holds the file date and DE the lower bound for the comparison.
536C
RST 18 DF
RST 18H compares Register Pair HL (file date) against Register Pair DE (lower bound), setting the CARRY FLAG when the file date is the smaller.
536D
EX DE,HL EB
Exchange DE and HL back to their roles.
536E
If the CARRY FLAG is set (file date before the lower bound), JUMP to 52BEH to skip the file.
5371
LD A,(5710H) 3A 10 57
Loop target
Fetch the date-flag byte from 5710H into Register A to test the upper bound.
5374
RRCA 0F
Rotate Register A right circularly, moving bit 0 (upper bound present) into the CARRY FLAG.
5375
If the NO CARRY FLAG is set (no upper bound), JUMP to 5383H to build the display line.
5377
LD A,D 7A
Copy the high byte of the file date (Register D) into Register A.
5378
OR E B3
OR the low byte (Register E) into Register A. The Z FLAG is set for an undated file.
5379
If the Z FLAG is set (undated file), JUMP to 52BEH to skip it.
537C
LD HL,(5713H) 2A 13 57
Load Register Pair HL with the packed upper date bound from 5713H.
537F
RST 18 DF
RST 18H compares Register Pair HL (upper bound) against Register Pair DE (file date), setting the CARRY FLAG when the file date is the larger (past the upper bound).
5380
If the CARRY FLAG is set (file date after the upper bound), JUMP to 52BEH to skip the file.
5383
POP HL E1
Loop target
Restore the entry pointer (Register Pair HL).
5384
PUSH HL E5
Save the entry pointer (Register Pair HL) once more while the display line is assembled.
5385
LD A,L 7D
Copy the entry offset (Register L) into Register A.
5386
ADD A,05H C6 05
Add 5 to Register A to reach the file-name field at entry offset 5.
5388
LD L,A 6F
Copy the advanced offset (Register A) back into Register L.
5389
LD DE,5719H 11 19 57
Point Register Pair DE at 5719H, the buffer that holds the human-readable "name/ext:d + {date}" line.
538C
LD B,08H 06 08
Load Register B with 8, the file-name field width.
538E
LD A,(HL) 7E
Loop Start
Fetch a file-name character (addressed by HL) into Register A.
538F
CP 20H FE 20
Compare Register A against 20H (space), the padding that ends the name.
5391
If the Z FLAG is set (trailing blank), JUMP to 5398H to append the extension.
5393
LD (DE),A 12
Store the name character (Register A) into the display buffer (addressed by DE).
5394
INC HL 23
Advance the entry-name pointer (Register Pair HL).
5395
INC DE 13
Advance the display-buffer pointer (Register Pair DE).
5396
DECrement Register B and LOOP BACK to 538EH until the name is copied or a blank is met.
5398
LD A,L 7D
Loop target
Copy the name offset (Register L) into Register A.
5399
ADD A,B 80
Add the remaining count (Register B) to Register A to skip any unused name positions and land on the extension field.
539A
LD L,A 6F
Copy the adjusted offset (Register A) back into Register L, so Register Pair HL points at the extension.
539B
LD A,(HL) 7E
Fetch the first extension character (addressed by HL) into Register A.
539C
CP 20H FE 20
Compare Register A against 20H (space); a blank means there is no extension.
539E
If the Z FLAG is set (no extension), JUMP to 53B0H to append the drivespec.
53A0
LD A,2FH 3E 2F
Load Register A with 2FH (ASCII /), the extension separator.
53A2
LD (DE),A 12
Store the slash (Register A) into the display buffer (addressed by DE).
53A3
INC DE 13
Advance the display-buffer pointer (Register Pair DE).
53A4
LD B,03H 06 03
Load Register B with 3, the extension field width.
53A6
LD A,(HL) 7E
Loop Start
Fetch an extension character (addressed by HL) into Register A.
53A7
CP 20H FE 20
Compare Register A against 20H (space), which ends the extension.
53A9
If the Z FLAG is set (trailing blank), JUMP to 53B0H to append the drivespec.
53AB
LD (DE),A 12
Store the extension character (Register A) into the display buffer (addressed by DE).
53AC
INC HL 23
Advance the entry pointer (Register Pair HL).
53AD
INC DE 13
Advance the display-buffer pointer (Register Pair DE).
53AE
DECrement Register B and LOOP BACK to 53A6H until the extension is copied or a blank is met.
53B0
LD A,3AH 3E 3A
Loop target
Load Register A with 3AH (ASCII :), the drivespec separator.
53B2
LD (DE),A 12
Store the colon (Register A) into the display buffer (addressed by DE).
53B3
INC DE 13
Advance the display-buffer pointer (Register Pair DE).
53B4
LD A,(54ADH) 3A AD 54
Fetch the working drive number from 54ADH into Register A.
53B7
OR 30H F6 30
OR Register A with 30H to convert the drive number to its ASCII digit.
53B9
LD (DE),A 12
Store the drive digit (Register A) into the display buffer (addressed by DE).
53BA
INC DE 13
Advance the display-buffer pointer (Register Pair DE).
53BB
LD A,03H 3E 03
Load Register A with 03H, a temporary End-of-Text terminator for the line so far.
53BD
LD (DE),A 12
Store the terminator (Register A) into the display buffer (addressed by DE).
53BE
PUSH DE D5
Save the display-buffer position (Register Pair DE) at the end of the file spec.
53BF
LD DE,0FFFFH 11 FF FF
Self-Modifying Code
Load Register Pair DE with the QUERY flag; the operand at 53C0H is FFFFH when querying is on (the default) and 0000H when Q=OFF was given.
53C2
LD A,E 7B
Copy the low byte of the QUERY flag (Register E) into Register A.
53C3
OR D B2
OR the high byte (Register D) into Register A. The Z FLAG is set when querying is off.
53C4
If the Z FLAG is set (Q=OFF, unattended), JUMP to 546EH to purge the file without prompting.
53C7
LD HL,56C4H 21 C4 56
Point Register Pair HL at 56C4H, the "Purge file: " prompt.
53CA
GOSUB to the resident SYS0 service @DSPLY (4467H) to display the "Purge file: " prompt (from HL).
53CD
POP DE D1
Restore the end-of-filespec buffer position (Register Pair DE).
53CE
POP HL E1
Restore the entry pointer (Register Pair HL) so the modification flag and date can be appended.
53CF
PUSH DE D5
Save the buffer position (Register Pair DE) again.
53D0
INC HL 23
Advance Register Pair HL to entry offset 1, which carries the modified-since-backup flag.
53D1
BIT 6,(HL) CB 76
Test bit 6 of the byte at entry offset 1 (addressed by HL); a set bit means the file has been modified since its last backup.
53D3
If the Z FLAG is set (not modified), JUMP to 53DDH to append the date field opener.
53D5
LD A,20H 3E 20
Load Register A with 20H (space) preceding the modified marker.
53D7
LD (DE),A 12
Store the space (Register A) into the display buffer (addressed by DE).
53D8
INC DE 13
Advance the display-buffer pointer (Register Pair DE).
53D9
LD A,2BH 3E 2B
Load Register A with 2BH (ASCII +), the "modified" indicator.
53DB
LD (DE),A 12
Store the plus sign (Register A) into the display buffer (addressed by DE).
53DC
INC DE 13
Advance the display-buffer pointer (Register Pair DE).
53DD
LD A,20H 3E 20
Loop target
Load Register A with 20H (space) separating the flag from the date.
53DF
LD (DE),A 12
Store the space (Register A) into the display buffer (addressed by DE).
53E0
INC DE 13
Advance the display-buffer pointer (Register Pair DE).
53E1
INC HL 23
Advance Register Pair HL to entry offset 2, the first packed date byte.
53E2
EX DE,HL EB
Exchange Register Pairs DE and HL so HL addresses the display buffer.
53E3
LD (HL),7BH 36 7B
Store 7BH (ASCII {) into the display buffer (addressed by HL), opening the date field.
53E5
INC HL 23
Advance the display-buffer pointer (Register Pair HL).
53E6
EX DE,HL EB
Exchange DE and HL back, so HL again addresses the entry date bytes and DE the buffer.
53E7
LD A,(HL) 7E
Fetch the packed date byte (addressed by HL) into Register A.
53E8
OR A B7
Test Register A. The Z FLAG is set when the file has no modification date.
53E9
If the Z FLAG is set (undated), JUMP to 544AH to close the line without a date.
53EB
RRCA 0F
Rotate Register A right circularly (first of three) to align the packed month field.
53EC
RRCA 0F
Rotate Register A right circularly (second of three).
53ED
RRCA 0F
Rotate Register A right circularly (third of three).
53EE
AND 1FH E6 1F
Mask Register A with 1FH to isolate the five-bit month number.
53F0
LD B,2FH 06 2F
Load Register B with 2FH, one below ASCII 0, as the tens-digit accumulator.
53F2
INC B 04
Loop Start
Increment Register B, counting the tens of the month value.
53F3
SUB 0AH D6 0A
Subtract 10 (0AH) from Register A.
53F5
If the NO CARRY FLAG is set (still 10 or more), LOOP BACK to 53F2H to count another ten.
53F7
ADD A,3AH C6 3A
Add 3AH to Register A, converting the leftover units back to an ASCII digit.
53F9
PUSH AF F5
Save the units digit (Register AF) on the stack.
53FA
LD A,B 78
Copy the tens digit (Register B, now an ASCII 0-1) into Register A.
53FB
LD (DE),A 12
Store the month tens digit (Register A) into the display buffer (addressed by DE).
53FC
INC DE 13
Advance the display-buffer pointer (Register Pair DE).
53FD
POP AF F1
Restore the units digit (Register AF).
53FE
LD (DE),A 12
Store the month units digit (Register A) into the display buffer (addressed by DE).
53FF
INC DE 13
Advance the display-buffer pointer (Register Pair DE).
5400
LD A,2DH 3E 2D
Load Register A with 2DH (ASCII -) separating month from month name.
5402
LD (DE),A 12
Store the hyphen (Register A) into the display buffer (addressed by DE).
5403
INC DE 13
Advance the display-buffer pointer (Register Pair DE).
5404
PUSH HL E5
Save the entry pointer (Register Pair HL).
5405
DEC HL 2B
Step Register Pair HL back to entry offset 1 to read the month index again for the name table.
5406
LD A,(HL) 7E
Fetch that byte (addressed by HL) into Register A.
5407
AND 0FH E6 0F
Mask Register A with 0FH to isolate the low four bits of the month index.
5409
DEC A 3D
Decrement Register A so month 1 maps to table index 0.
540A
LD C,A 4F
Copy the month index (Register A) into Register C.
540B
RLCA 07
Rotate Register A left circularly, doubling the index.
540C
ADD A,C 81
Add Register C, giving three times the month index (each name is three characters).
540D
LD C,A 4F
Copy the scaled index (Register A) into Register C.
540E
LD B,00H 06 00
Load Register B with 0 so Register Pair BC is the 16-bit table offset.
5410
LD HL,56E1H 21 E1 56
Point Register Pair HL at 56E1H, the three-letter month-name table.
5413
ADD HL,BC 09
Add the offset (Register Pair BC) to Register Pair HL, addressing this month's abbreviation.
5414
LD C,03H 0E 03
Load Register C with 3, the length of the month abbreviation.
5416
LDIR ED B0
Block-copy the three month-name characters from (HL) to the display buffer (DE), advancing both pointers (LDIR).
5418
LD A,2DH 3E 2D
Load Register A with 2DH (ASCII -) separating month name from year.
541A
LD (DE),A 12
Store the hyphen (Register A) into the display buffer (addressed by DE).
541B
INC DE 13
Advance the display-buffer pointer (Register Pair DE).
541C
POP HL E1
Restore the entry pointer (Register Pair HL).
541D
LD C,38H 0E 38
Load Register C with 38H (ASCII 8), the tens digit used for years in the 1980s by default.
541F
LD A,(475DH) 3A 5D 47
Fetch the resident dated-directory bitmap from 475DH into Register A.
5422
BIT 0,A CB 47
Self-Modifying Code
Test this drive's bit in the bitmap (Register A). The opcode was patched at 524AH to BIT drive,A; a set bit means the directory carries a full extended date.
5424
If the NZ FLAG is set (extended date format), JUMP to 542BH to read the full year.
5426
LD A,(HL) 7E
Standard format: fetch the packed year (addressed by HL) into Register A.
5427
AND 07H E6 07
Mask Register A with 07H to isolate the three-bit year-within-decade value.
5429
JUMP to 5441H to emit the year digits (tens fixed at 8, i.e. 198x).
542B
LD A,L 7D
Loop target
Copy the entry offset (Register L) into Register A for the extended-date field.
542C
ADD A,11H C6 11
Add 11H to Register A to reach the extended date field elsewhere in the entry.
542E
LD L,A 6F
Copy the advanced offset (Register A) back into Register L.
542F
LD A,(HL) 7E
Fetch the extended year byte (addressed by HL) into Register A.
5430
AND 1FH E6 1F
Mask Register A with 1FH to isolate the five-bit year value.
5432
CP 14H FE 14
Compare Register A against 14H (20). Years of 20 or more belong to the 2000s decade.
5434
If the CARRY FLAG is set (year under 20), JUMP to 543AH keeping the 1980-1999 tens base.
5436
SUB 14H D6 14
Subtract 20 (14H) from Register A to fold a 2000s year into a 0-9 range.
5438
LD C,30H 0E 30
Load Register C with 30H (ASCII 0), the tens digit for the 2000s.
543A
CP 0AH FE 0A
Loop target
Compare Register A against 10 (0AH) to split the year into tens and units.
543C
If the CARRY FLAG is set (under 10), JUMP to 5441H with the tens digit already correct.
543E
INC C 0C
Increment Register C to advance the tens digit by one decade.
543F
SUB 0AH D6 0A
Subtract 10 (0AH) from Register A.
5441
LD B,A 47
Loop target
Copy the year units (Register A) into Register B.
5442
LD A,C 79
Copy the year tens digit (Register C, an ASCII character) into Register A.
5443
LD (DE),A 12
Store the year tens digit (Register A) into the display buffer (addressed by DE).
5444
INC DE 13
Advance the display-buffer pointer (Register Pair DE).
5445
LD A,B 78
Copy the year units (Register B) into Register A.
5446
ADD A,30H C6 30
Add 30H to Register A to make it an ASCII digit.
5448
LD (DE),A 12
Store the year units digit (Register A) into the display buffer (addressed by DE).
5449
INC DE 13
Advance the display-buffer pointer (Register Pair DE).
544A
LD A,03H 3E 03
Loop target
Load Register A with 03H, the End-of-Text terminator for the display line.
544C
LD (DE),A 12
Store the terminator (Register A) into the display buffer (addressed by DE), completing the "name/ext:d + {MM-Mon-YY}" text.

544DH - Prompt, Read the Response, and Delete the File

With querying on, the file description is shown followed by the "} ? " prompt and a keyboard reply is read; only Y proceeds, and BREAK aborts. When querying is off the code enters at 546EH and deletes unconditionally. "Purging: " and the file description are logged, a temporary FCB is filled at 577DH with the file's directory record number and drive, and @KILL removes it. The record cache marker at 52FDH is invalidated so the next entry is re-read from the just-modified directory.

544D
LD HL,5719H 21 19 57
Point Register Pair HL at 5719H, the assembled file-description line.
5450
GOSUB to the resident SYS0 service @DSPLY (4467H) to display the file description (from HL).
5453
LD HL,56D1H 21 D1 56
Point Register Pair HL at 56D1H, the "} ? " suffix that closes the date brace and asks the question.
5456
GOSUB to the resident SYS0 service @DSPLY (4467H) to display the query suffix (from HL).
5459
LD HL,5715H 21 15 57
Point Register Pair HL at 5715H, the small buffer that receives the keyboard response.
545C
LD B,03H 06 03
Load Register B with 3, the maximum response length.
545E
GOSUB to the ROM keyboard-line driver @KEYIN (0040H) to read the reply into the buffer at HL. Returns the CARRY FLAG if BREAK was pressed.
5461
If the CARRY FLAG is set (BREAK during the query), JUMP to 55DCH to report "Purge aborted".
5464
LD A,(HL) 7E
Fetch the first response character (addressed by HL) into Register A.
5465
RES 5,A CB AF
Clear bit 5 of Register A, folding a lowercase reply to uppercase.
5467
CP 59H FE 59
Compare Register A against 59H (ASCII Y).
5469
If the NZ FLAG is set (any answer other than Y, including ENTER or N), JUMP to 52BEH to skip this file.
546C
EX (SP),HL E3
Exchange the top of the stack with Register Pair HL, swapping the saved entry pointer into place for the delete.
546D
PUSH HL E5
Save Register Pair HL back on the stack for the delete sequence.
546E
LD A,(4423H) 3A 23 44
Loop target
Fetch KFLAG$ from 4423H into Register A. The unattended (Q=OFF) path enters here, skipping the prompt.
5471
RRCA 0F
Rotate Register A right circularly, moving the BREAK-pending bit into the CARRY FLAG.
5472
If the CARRY FLAG is set (BREAK pressed), JUMP to 55DCH to report "Purge aborted".
5475
LD HL,56D7H 21 D7 56
Point Register Pair HL at 56D7H, the "Purging: " message.
5478
GOSUB to the resident SYS0 service @LOGOT (447BH) to display "Purging: " (from HL).
547B
POP HL E1
Restore the display-buffer end pointer (Register Pair HL).
547C
LD (HL),0DH 36 0D
Store 0DH (carriage return) at the end of the file-description line (addressed by HL), terminating it for @LOGOT.
547E
LD HL,5719H 21 19 57
Point Register Pair HL at 5719H, the file-description line.
5481
GOSUB to the resident SYS0 service @LOGOT (447BH) to echo which file is being purged (from HL).
5484
POP HL E1
Restore the entry pointer (Register Pair HL).
5485
POP BC C1
Restore the saved entry index (Register Pair BC).
5486
PUSH BC C5
Save the entry index (Register Pair BC) again for the loop continuation.
5487
LD A,B 78
Copy the entry index (Register B) into Register A, the directory record number of the file to delete.
5488
LD (5784H),A 32 84 57
Store the directory record number (Register A) into 5784H, part of the temporary FCB used by @KILL.
548B
LD A,(54ADH) 3A AD 54
Fetch the working drive number from 54ADH into Register A.
548E
LD (5783H),A 32 83 57
Store the drive number (Register A) into 5783H of the temporary FCB.
5491
LD A,01H 3E 01
Load Register A with 01H.
5493
LD (577EH),A 32 7E 57
Store 01H into 577EH of the temporary FCB (an internal open-code field).
5496
LD A,80H 3E 80
Load Register A with 80H.
5498
LD (577DH),A 32 7D 57
Store 80H into 577DH, the leading flag byte of the temporary FCB that marks it as a directory-referenced delete.
549B
LD DE,577DH 11 7D 57
Point Register Pair DE at 577DH, the temporary FCB for the file to delete.
549E
GOSUB to the resident SYS0 service @KILL (442CH) to remove the file described by the FCB at DE and free its space. Returns the NZ FLAG and an error code on failure.
54A1
If the NZ FLAG is set (the delete failed), JUMP to 55D5H to report the error.
54A4
LD A,0FFH 3E FF
Load Register A with 0FFH.
54A6
LD (52FDH),A 32 FD 52
Self-Modifying Code
Store 0FFH into 52FDH, the record-cache marker, forcing the next iteration to re-read the directory record since @KILL has just changed it.
54A9
JUMP to 52BFH to continue the directory scan with the entry index restored.

54ACH - Read the GAT and Verify the Master Password

The disk's Granule Allocation Table sector is read into 5900H and its master-password hash (at 59CEH) is compared with the hash of the default password "PASSWORD" (42E0H). If the disk uses the default the purge proceeds with no prompt; otherwise a candidate password is taken from the MPW option or requested from the keyboard, hashed, and compared with the empty-password hash (113DH) and the disk hash. A mismatch reports "Invalid master password".

54AC
LD C,00H 0E 00
Load Register C with 0, selecting sector 0 (the GAT) of the directory cylinder.
54AE
GOSUB to 553FH to read the drive's GAT sector into the buffer at 5900H.
54B1
If the NZ FLAG is set (GAT read failed), JUMP to 55D5H to report the error.
54B4
LD HL,(59CEH) 2A CE 59
Load Register Pair HL with the disk's master-password hash from 59CEH within the GAT buffer.
54B7
LD DE,42E0H 11 E0 42
Load Register Pair DE with 42E0H, the hash of the default master password "PASSWORD".
54BA
XOR A AF
Set Register A to zero, clearing the CARRY FLAG for the compare.
54BB
SBC HL,DE ED 52
Subtract the default hash (Register Pair DE) from the disk hash (Register Pair HL). The Z FLAG is set when they are equal.
54BD
RET Z C8
If the Z FLAG is set (the disk uses the default password), RETURN accepting the purge with no password prompt.
54BE
LD DE,0000H 11 00 00
Self-Modifying Code
Load Register Pair DE with the MPW option value; the operand at 54BFH points at the supplied master password, or is 0000H if none was given.
54C1
LD HL,5678H 21 78 56
Point Register Pair HL at 5678H, the "Master password ?" prompt used if the password must be requested.
54C4
GOSUB to 54DAH to obtain the candidate password (from the MPW option or the keyboard) and return its hash in Register Pair DE.
54C7
RET NZ C0
If the NZ FLAG is set (no password could be obtained), RETURN carrying the error.
54C8
EX DE,HL EB
Exchange Register Pairs DE and HL so HL holds the candidate hash.
54C9
LD HL,113DH 21 3D 11
Load Register Pair HL with 113DH, the hash of an empty password.
54CC
XOR A AF
Set Register A to zero, clearing the CARRY FLAG.
54CD
SBC HL,DE ED 52
Subtract the candidate hash (Register Pair DE) from 113DH (Register Pair HL). The Z FLAG is set for an empty password.
54CF
RET Z C8
If the Z FLAG is set (empty candidate), RETURN accepting it.
54D0
LD HL,(59CEH) 2A CE 59
Load Register Pair HL with the disk's master-password hash from 59CEH in the GAT buffer.
54D3
XOR A AF
Set Register A to zero, clearing the CARRY FLAG.
54D4
SBC HL,DE ED 52
Subtract the candidate hash (Register Pair DE) from the disk hash (Register Pair HL). The Z FLAG is set when they match.
54D6
RET Z C8
If the Z FLAG is set (correct master password), RETURN accepting the purge.
54D7
The password did not match, so JUMP to 55E0H to report "Invalid master password".

54DAH - Obtain and Hash the Candidate Password

The candidate master password is taken from the MPW option string or, when none was given, requested with the "Master password ?" prompt (refused inside a DO job). Up to eight characters are copied to 5800H, blank-padded and upcased, and then hashed by the resident directory/attribute/password service through RST 28H request code 0E4H - the same service the ATTRIB overlay uses - returning the 16-bit hash for comparison.

54DA
GOSUB to 54E6H to build the candidate password into the buffer at 5800H, from the MPW option or by prompting.
54DD
RET NZ C0
If the NZ FLAG is set (no password available, e.g. inside a DO job), RETURN carrying the failure.
54DE
GOSUB to 54E3H to hash the candidate password through the resident directory/password service.
54E1
CP A BF
Compare Register A with itself, forcing the Z FLAG to indicate success.
54E2
RET C9
RETURN with the password hash in Register Pair DE.
54E3
LD A,0E4H 3E E4
Loop target
Load Register A with request code 0E4H to select the resident directory/attribute/password service.
54E5
RST 28 EF
RST 28H invokes the resident SYS0 supervisor at that request code, hashing the eight-character password at 5800H and returning the 16-bit hash in Register Pair DE (the same E4H service the ATTRIB overlay uses).
54E6
LD A,D 7A
Loop target
Copy the high byte of the MPW option pointer (Register D) into Register A.
54E7
OR E B3
OR the low byte (Register E) into Register A. The Z FLAG is set when no MPW option was given.
54E8
If the Z FLAG is set (no MPW option), JUMP to 5507H to prompt for the password.
54EA
INC A 3C
Increment Register A to test for an FFFFH pointer.
54EB
If the Z FLAG is set (FFFFH, empty option), JUMP to 5507H to prompt.
54ED
LD HL,5800H 21 00 58
Point Register Pair HL at 5800H, the eight-byte password buffer.
54F0
PUSH HL E5
Save the buffer pointer (Register Pair HL) for the later padding and upcasing.
54F1
LD B,08H 06 08
Load Register B with 8, the password field width.
54F3
LD A,(DE) 1A
Loop Start
Fetch a character of the supplied password (addressed by DE) into Register A.
54F4
CP 0DH FE 0D
Compare Register A against 0DH (carriage return), which ends the option.
54F6
If the Z FLAG is set (end of password), JUMP to 5525H to blank-fill the rest.
54F8
CP 2CH FE 2C
Compare Register A against 2CH (ASCII ,), the option separator.
54FA
If the Z FLAG is set (next option), JUMP to 5525H to blank-fill the rest.
54FC
CP 22H FE 22
Compare Register A against 22H (ASCII "), the closing quote.
54FE
If the Z FLAG is set (closing quote), JUMP to 5525H to blank-fill the rest.
5500
INC DE 13
Advance the source pointer (Register Pair DE).
5501
LD (HL),A 77
Store the password character (Register A) into the buffer (addressed by HL).
5502
INC HL 23
Advance the buffer pointer (Register Pair HL).
5503
DECrement Register B and LOOP BACK to 54F3H until eight characters are copied or a delimiter is met.
5505
The full eight characters were copied, so JUMP to 552AH to upcase the buffer.
5507
Loop target
GOSUB to 5552H to read SFLAG$; it returns the NZ FLAG when running below command level.
550A
RET NZ C0
If the NZ FLAG is set (inside a DO job, cannot prompt), RETURN carrying the failure.
550B
GOSUB to the resident SYS0 service @DSPLY (4467H) to display the "Master password ?" prompt still addressed by Register Pair HL.
550E
LD B,08H 06 08
Load Register B with 8, the maximum password length.
5510
LD HL,5800H 21 00 58
Point Register Pair HL at 5800H, the password buffer.
5513
PUSH HL E5
Save the buffer pointer (Register Pair HL).
5514
GOSUB to the ROM keyboard-line driver @KEYIN (0040H) to read the password into the buffer at HL. Returns the CARRY FLAG on BREAK.
5517
If the CARRY FLAG is set (BREAK pressed), JUMP to 55DCH to report "Purge aborted".
551A
EX DE,HL EB
Exchange Register Pairs DE and HL to compute the pad count.
551B
LD H,00H 26 00
Load Register H with 0.
551D
LD L,B 68
Copy the entered length (Register B) into Register L, so Register Pair HL is the count.
551E
ADD HL,DE 19
Add Register Pair DE (the buffer base) to Register Pair HL, addressing the first unused byte.
551F
LD A,08H 3E 08
Load Register A with 8, the full field width.
5521
SUB B 90
Subtract the entered length (Register B) from Register A, giving the number of pad bytes.
5522
If the Z FLAG is set (a full eight characters entered), JUMP to 552AH to upcase.
5524
LD B,A 47
Copy the pad count (Register A) into Register B.
5525
LD (HL),20H 36 20
Loop Start
Store 20H (space) into the buffer (addressed by HL) to pad the password field.
5527
INC HL 23
Advance the buffer pointer (Register Pair HL).
5528
DECrement Register B and LOOP BACK to 5525H until the eight-byte field is space-filled.
552A
POP HL E1
Loop target
Restore the buffer pointer (Register Pair HL) to the start of the password.
552B
PUSH HL E5
Save the buffer pointer (Register Pair HL) again.
552C
LD B,08H 06 08
Load Register B with 8, the field width, for the upcase pass.
552E
LD A,(HL) 7E
Loop Start
Fetch a password character (addressed by HL) into Register A.
552F
CP 61H FE 61
Compare Register A against 61H (ASCII a). If below, the CARRY FLAG is set (already uppercase or punctuation).
5531
If the CARRY FLAG is set (not lowercase), JUMP to 5539H leaving the character unchanged.
5533
CP 7BH FE 7B
Compare Register A against 7BH (one past ASCII z). If Register A is 7BH or more the NO CARRY FLAG is set.
5535
If the NO CARRY FLAG is set (beyond lowercase), JUMP to 5539H unchanged.
5537
RES 5,(HL) CB AE
Clear bit 5 of the character in the buffer (addressed by HL), folding it to uppercase.
5539
INC HL 23
Loop target
Advance the buffer pointer (Register Pair HL).
553A
DECrement Register B and LOOP BACK to 552EH until all eight characters are upcased.
553C
POP DE D1
Restore the buffer base into Register Pair DE for the caller.
553D
XOR A AF
Set Register A to zero, forcing the Z FLAG to signal success.
553E
RET C9
RETURN with the completed password in the buffer at 5800H.

553FH - Sector-Read, Command-Level and Mask-Copy Helpers

Three shared subroutines: 553FH reads sector 0 (the GAT) of the drive's directory cylinder into 5900H; 5552H reports whether the command is running below LDOS command level (SFLAG$ bit 5); and 5558H copies a partspec field into a mask buffer, passing the $ wildcard, folding letters to uppercase, and stopping at the first delimiter, which it returns in Register A.

553F
PUSH DE D5
Save Register Pair DE across the read.
5540
PUSH HL E5
Save Register Pair HL across the read.
5541
GOSUB to the resident SYS0 service DIRCYL (4B65H) to seek the directory cylinder of the drive in Register C.
5544
LD E,00H 1E 00
Load Register E with 0, selecting sector 0 (the GAT) of the directory cylinder.
5546
LD HL,5900H 21 00 59
Point Register Pair HL at 5900H, the GAT buffer.
5549
GOSUB to the resident SYS0 service RDSSEC (4B45H) to read sector Register E into the buffer at HL (5900H). Returns the NZ FLAG on error.
554C
POP HL E1
Restore Register Pair HL.
554D
POP DE D1
Restore Register Pair DE.
554E
RET Z C8
If the Z FLAG is set (the read succeeded), RETURN to the caller.
554F
LD A,14H 3E 14
Load Register A with error code 14H (directory read error).
5551
RET C9
RETURN carrying the error code.
5552
LD A,(430FH) 3A 0F 43
Loop target
Fetch SFLAG$ from 430FH into Register A.
5555
BIT 5,A CB 6F
Test bit 5 of SFLAG$ (Register A); a set bit means execution is below LDOS command level.
5557
RET C9
RETURN with the NZ FLAG reflecting the not-command-level state.
5558
CP 24H FE 24
Loop Start
Compare the current source character (Register A) against 24H (ASCII $), the wildcard which is copied into the mask verbatim.
555A
If the Z FLAG is set (wildcard), JUMP to 5570H to store it.
555C
CP 41H FE 41
Compare Register A against 41H (ASCII A). If Register A is 41H or more the NO CARRY FLAG is set.
555E
If the NO CARRY FLAG is set (letter or higher), JUMP to 5566H to fold its case.
5560
CP 3AH FE 3A
Compare Register A against 3AH (one past ASCII 9). If Register A is 3AH or more the NO CARRY FLAG is set (a non-digit below the letters).
5562
RET NC D0
If the NO CARRY FLAG is set (a delimiter between digits and letters), RETURN, ending the copy.
5563
CP 30H FE 30
Compare Register A against 30H (ASCII 0). If below, the CARRY FLAG is set.
5565
RET C D8
If the CARRY FLAG is set (below 0, a delimiter), RETURN, ending the copy.
5566
CP 61H FE 61
Loop target
Compare Register A against 61H (ASCII a). If below, the CARRY FLAG is set (already uppercase).
5568
If the CARRY FLAG is set (not lowercase), JUMP to 5570H to store it unchanged.
556A
CP 7BH FE 7B
Compare Register A against 7BH (one past ASCII z). If 7BH or more the NO CARRY FLAG is set.
556C
If the NO CARRY FLAG is set (beyond lowercase), JUMP to 5570H unchanged.
556E
RES 5,A CB AF
Clear bit 5 of Register A, folding a lowercase letter to uppercase.
5570
LD (DE),A 12
Loop target
Store the mask character (Register A) into the mask buffer (addressed by DE).
5571
INC DE 13
Advance the mask pointer (Register Pair DE).
5572
LD A,(HL) 7E
Fetch the next command-line character (addressed by HL) into Register A.
5573
INC HL 23
Advance the command-line pointer (Register Pair HL).
5574
DECrement Register B and LOOP BACK to 5558H until the field width is filled or a delimiter ends it.
5576
RET C9
RETURN with the delimiter character in Register A.

5577H - Unpack the Modification Date

Reads the two packed date bytes at entry offsets 1 and 2 and, depending on this drive's bit in the dated-directory bitmap at 475DH, either the standard three-bit year or the extended year field. The month, day and year are shifted and merged into a single 16-bit value in Register Pair DE that can be compared directly against the packed date bounds.

5577
LD A,(HL) 7E
Fetch entry offset 1 (addressed by HL) into Register A, the byte carrying the high bits of the packed date.
5578
AND 0FH E6 0F
Mask Register A with 0FH to isolate the low four bits.
557A
LD E,00H 1E 00
Load Register E with 0, clearing the low half of the packed date being assembled in Register Pair DE.
557C
SRL A CB 3F
Shift Register A right, moving its low bit toward the carry as the packed value is built.
557E
RR E CB 1B
Rotate the carry into the top of Register E, assembling the packed date.
5580
LD D,A 57
Copy the shifted high part (Register A) into Register D.
5581
INC HL 23
Advance Register Pair HL to entry offset 2, the next packed date byte.
5582
LD A,(HL) 7E
Fetch entry offset 2 (addressed by HL) into Register A.
5583
AND 0F8H E6 F8
Mask Register A with 0F8H to isolate the day bits.
5585
RRCA 0F
Rotate Register A right circularly to align the day field.
5586
OR E B3
OR the low date bits already in Register E into Register A.
5587
LD E,A 5F
Copy the combined low byte (Register A) into Register E.
5588
LD A,(475DH) 3A 5D 47
Fetch the resident dated-directory bitmap from 475DH into Register A.
558B
BIT 0,A CB 47
Self-Modifying Code
Test this drive's bit in the bitmap (Register A). The opcode was patched at 5247H to BIT drive,A; a set bit selects the extended date format.
558D
If the NZ FLAG is set (extended date format), JUMP to 5598H to read the year from the extended field.
558F
LD A,(HL) 7E
Standard format: fetch entry offset 2 again (addressed by HL) into Register A.
5590
AND 07H E6 07
Mask Register A with 07H to isolate the three-bit year value.
5592
RLCA 07
Loop target
Rotate Register A left circularly (first of three) to align the year into the packed date high byte.
5593
RLCA 07
Rotate Register A left circularly (second of three).
5594
RLCA 07
Rotate Register A left circularly (third of three).
5595
OR D B2
OR the month bits already in Register D into Register A.
5596
LD D,A 57
Copy the completed high byte (Register A) into Register D, finishing the packed date in Register Pair DE.
5597
RET C9
RETURN with the packed modification date in Register Pair DE.
5598
LD A,L 7D
Loop target
Copy the entry offset (Register L) into Register A for the extended date field.
5599
ADD A,11H C6 11
Add 11H to Register A to reach the extended date field within the entry.
559B
LD L,A 6F
Copy the advanced offset (Register A) back into Register L.
559C
LD A,(HL) 7E
Fetch the extended year byte (addressed by HL) into Register A.
559D
AND 1FH E6 1F
Mask Register A with 1FH to isolate the five-bit extended year value.
559F
JUMP to 5592H to fold the year into the packed date.

55A1H - Date-String Number Parsers

Helpers used by the date packer. 55A1H reads the three slash-separated month/day/year fields into the scratch area at 5717H; 55B6H parses one one- or two-digit decimal number; and 55CCH fetches and validates a single ASCII digit. A malformed field returns the NZ FLAG so the caller can report "Bad date format".

55A1
LD DE,5717H 11 17 57
Point Register Pair DE at 5717H, the top of the three-byte scratch area that receives the parsed month, day and year.
55A4
LD B,03H 06 03
Load Register B with 3, the number of date fields to read.
55A6
PUSH DE D5
Loop Start
Save the field pointer (Register Pair DE).
55A7
GOSUB to 55B6H to read a one- or two-digit number from the string (at HL) into Register A. Returns the NZ FLAG on a non-numeric field.
55AA
POP DE D1
Restore the field pointer (Register Pair DE).
55AB
RET NZ C0
If the NZ FLAG is set (not a valid number), RETURN reporting the bad date.
55AC
LD (DE),A 12
Store the parsed field value (Register A) into the scratch area (addressed by DE).
55AD
DEC B 05
Decrement Register B, the count of remaining fields.
55AE
RET Z C8
If the Z FLAG is set (all three fields read), RETURN successfully.
55AF
DEC DE 1B
Step Register Pair DE down to the next scratch byte.
55B0
LD A,(HL) 7E
Fetch the next string character (addressed by HL) into Register A.
55B1
INC HL 23
Advance the string pointer (Register Pair HL).
55B2
CP C B9
Compare Register A against Register C (the separator 2FH, ASCII /).
55B3
If the Z FLAG is set (a slash), LOOP BACK to 55A6H to read the next field.
55B5
RET C9
RETURN when the separator is missing (end of the date).
55B6
Loop target
GOSUB to 55CCH to fetch and test one digit; returns it in Register A with the CARRY FLAG set for a valid digit.
55B9
If the NO CARRY FLAG is set (not a digit), JUMP to 55CAH to report a non-numeric field.
55BB
LD E,A 5F
Copy the first digit (Register A) into Register E.
55BC
RLCA 07
Rotate Register A left circularly (times 2).
55BD
RLCA 07
Rotate Register A left circularly again (times 4).
55BE
ADD A,E 83
Add Register E, giving five times the digit.
55BF
RLCA 07
Rotate Register A left circularly, giving ten times the digit.
55C0
LD E,A 5F
Copy the tens value (Register A) into Register E.
55C1
GOSUB to 55CCH to fetch the next digit into Register A, CARRY FLAG set if it is a digit.
55C4
If the NO CARRY FLAG is set (only one digit), JUMP to 55CAH to accept the single-digit value.
55C6
ADD A,E 83
Add the tens value (Register E) to the units digit (Register A), forming the two-digit number.
55C7
LD E,A 5F
Copy the result (Register A) into Register E.
55C8
CP A BF
Compare Register A with itself, forcing the Z FLAG to signal a valid number.
55C9
RET C9
RETURN with the parsed value in Register A.
55CA
OR A B7
Loop target
OR Register A with itself to set the NZ FLAG (a single-digit or empty field), leaving the value in Register A.
55CB
RET C9
RETURN.
55CC
LD A,(HL) 7E
Loop target
Fetch a date-string character (addressed by HL) into Register A.
55CD
INC HL 23
Advance the string pointer (Register Pair HL).
55CE
SUB 30H D6 30
Subtract 30H from Register A, converting an ASCII digit to its binary value.
55D0
CP 0AH FE 0A
Compare Register A against 10 (0AH). A valid digit leaves the CARRY FLAG set.
55D2
RET C9
RETURN with the digit in Register A and the CARRY FLAG indicating validity.

55D3H - Error Reporters and the Four-Way Message Dispatcher

Parameter and DOS errors are reported through @ERROR at 55D5H (55D3H first forces code 2CH). The block at 55DCH is a compact four-way message dispatcher: four different entry points each load a different message address into Register Pair HL, and the intervening DD prefix bytes turn the following LD HL,nnnn into an inert LD IX,nnnn when execution falls through, so one shared @LOGOT call prints whichever message was selected. All paths exit through 55EEH.

55D3
LD A,2CH 3E 2C
Loop target
Load Register A with error code 2CH (parameter error).
55D5
OR 0C0H F6 C0
Loop target
Set the two high bits of the error code (Register A), the @ERROR convention requesting a display and a return of the code. Entered directly when Register A already holds a DOS error code.
55D7
GOSUB to the resident SYS0 service @ERROR (4409H) to display the error for the code in Register A.
55DA
JUMP to 55EEH to load the error return code and exit.
55DC
LD HL,5642H 21 42 56
Entry point that points Register Pair HL at 5642H, the "Purge aborted" message, when BREAK was pressed. Falling through, the following DD byte turns the next entry's load into an inert LD IX.
55DF
DEFB 0DDH DD
The DD prefix. On fall-through it combines with the bytes at 55E0H to form LD IX,5690H (inert), hiding the 55E0H entry point.
55E0
LD HL,5690H 21 90 56
Entry point that points Register Pair HL at 5690H, the "Invalid master password" message. Reached by the jump at 54D7H.
55E3
DEFB 0DDH DD
The DD prefix that turns the bytes at 55E4H into an inert LD IX,5651H on fall-through, hiding the 55E4H entry point.
55E4
LD HL,5651H 21 51 56
Entry point that points Register Pair HL at 5651H, the "Invalid command during <DO> processing" message. Reached by the jump at 52A2H.
55E7
DEFB 0DDH DD
The DD prefix that turns the bytes at 55E8H into an inert LD IX,56B4H on fall-through, hiding the 55E8H entry point.
55E8
LD HL,56B4H 21 B4 56
Entry point that points Register Pair HL at 56B4H, the "Bad date format" message. Reached by the several date-parsing jumps to 55E8H.
55EB
GOSUB to the resident SYS0 service @LOGOT (447BH) to display whichever message Register Pair HL was set to by the entry point taken.
55EE
LD HL,0FFFFH 21 FF FF
Loop target
Load Register Pair HL with 0FFFFH, the non-zero error return code.
55F1
JUMP to 52DDH to restore the stack and exit, aborting the job if the purge was running below command level.

55F4H - Pack a Date String into a Comparable Value

Parses an "M/D/Y" date, expands a two-digit year (under 12 becomes a 2000s year, rebased on 1980), validates the month (1-12) and the day against the month-length table at 56A8H with a leap-year adjustment to February, and folds the month, day and year into the same packed 16-bit format used for the directory dates, returned in Register Pair BC. Any malformed field reports "Bad date format".

55F4
LD A,(HL) 7E
Fetch the first date-string character (addressed by HL) into Register A.
55F5
LD C,2FH 0E 2F
Load Register C with 2FH (ASCII /), the field separator, for the field parser.
55F7
GOSUB to 55A1H to read the three month/day/year fields into the scratch area at 5715H-5717H. Returns the NZ FLAG on a malformed date.
55FA
If the NZ FLAG is set (bad date), JUMP to 55E8H to report "Bad date format".
55FC
LD A,(DE) 1A
Fetch the parsed year field (addressed by DE) into Register A.
55FD
CP 0CH FE 0C
Compare Register A against 12 (0CH); a two-digit year under 12 is treated as a 2000s year.
55FF
If the NO CARRY FLAG is set (year 12 or more, a 19xx year), JUMP to 5604H.
5601
ADD A,64H C6 64
Add 100 (64H) to Register A, mapping years 00-11 into the 2000-2011 range.
5603
LD (DE),A 12
Store the adjusted year (Register A) back into the scratch area (addressed by DE).
5604
EX DE,HL EB
Loop target
Exchange Register Pairs DE and HL so HL addresses the year for the leap-year test.
5605
AND 03H E6 03
Mask Register A with 03H to compute the year modulo 4 for the leap-year test.
5607
LD HL,56A9H 21 A9 56
Point Register Pair HL at 56A9H, February's entry in the month-length table.
560A
If the NZ FLAG is set (not a leap year), JUMP to 560DH.
560C
INC (HL) 34
Increment February's length in the table (addressed by HL) from 28 to 29 for a leap year.
560D
LD A,(5717H) 3A 17 57
Loop target
Fetch the parsed month (from 5717H) into Register A.
5610
DEC A 3D
Decrement Register A so month 1 maps to table index 0.
5611
CP 0CH FE 0C
Compare Register A against 12 (0CH). A value of 12 or more is an illegal month.
5613
If the NO CARRY FLAG is set (month out of range), JUMP to 55E8H to report "Bad date format".
5615
DEC HL 2B
Step Register Pair HL back to 56A8H, the base of the month-length table.
5616
ADD A,L 85
Add the month index (Register A) to the table-base low byte (Register L).
5617
LD L,A 6F
Copy the sum (Register A) back into Register L, addressing this month's length.
5618
If the NO CARRY FLAG is set (no page crossing), JUMP to 561BH.
561A
INC H 24
Increment Register H to carry into the high byte of the table pointer.
561B
LD A,(5716H) 3A 16 57
Loop target
Fetch the parsed day (from 5716H) into Register A.
561E
DEC A 3D
Decrement Register A so day 1 maps to 0 for the range test.
561F
CP (HL) BE
Compare Register A against the month length (addressed by HL). A day past the month length sets the NO CARRY FLAG.
5620
If the NO CARRY FLAG is set (day out of range for the month), JUMP to 55E8H to report "Bad date format".
5622
LD HL,5717H 21 17 57
Point Register Pair HL at 5717H, the parsed month field, to begin packing.
5625
LD B,(HL) 46
Fetch the month (addressed by HL) into Register B.
5626
LD C,00H 0E 00
Load Register C with 0 to build the packed low byte.
5628
SRL B CB 38
Shift Register B right, moving its low bit toward the day field.
562A
RR C CB 19
Rotate the carry into the top of Register C, packing the month bit.
562C
DEC HL 2B
Step Register Pair HL down to the parsed day field.
562D
LD A,(HL) 7E
Fetch the day (addressed by HL) into Register A.
562E
DEC HL 2B
Step Register Pair HL down to the parsed year field.
562F
RLCA 07
Rotate Register A left circularly (first of two) to align the day bits.
5630
RLCA 07
Rotate Register A left circularly (second of two).
5631
OR C B1
OR the month bit already in Register C into Register A.
5632
LD C,A 4F
Copy the packed low byte (Register A) into Register C.
5633
LD A,(HL) 7E
Fetch the year (addressed by HL) into Register A.
5634
SUB 50H D6 50
Subtract 50H (80) from Register A, rebasing the year on 1980.
5636
CP 70H FE 70
Compare Register A against 70H; a value at or above it is outside the supported year span.
5638
If the CARRY FLAG is set (year within range), JUMP to 563BH.
563A
XOR A AF
Zero Register A for an out-of-range year.
563B
RLCA 07
Loop target
Rotate Register A left circularly (first of three) to align the year bits.
563C
RLCA 07
Rotate Register A left circularly (second of three).
563D
RLCA 07
Rotate Register A left circularly (third of three).
563E
OR B B0
OR the day bits already in Register B into Register A.
563F
LD B,A 47
Copy the packed high byte (Register A) into Register B.
5640
EX DE,HL EB
Exchange Register Pairs DE and HL to leave the caller's string pointer in HL.
5641
RET C9
RETURN with the packed 16-bit date in Register Pair BC.

5642H - Messages and Tables

The overlay's message strings (terminated by 0DH for @LOGOT or 03H for @DSPLY), the twelve-byte month-length table at 56A8H (February is incremented in place for leap years), the three-letter month-name table at 56E1H, and the date-flag byte at 5710H. This region is data; the working listing's disassembler decoded parts of it as instructions. The RAM work area 5711H-5733H that follows is not part of the loaded overlay image and holds the filename/extension masks (5705H region), the packed date bounds and the display line at run time.

5642-5650
DEFM 0AH, 'Purge aborted', 0DH 0A 50 75 72 67 65 20 61 62 6F 72 74 65 64 0D
Shown when BREAK is pressed during a purge (reached at 55DCH). Begins with a line feed and ends with a carriage return.
5651-5677
DEFM 'Invalid command during <DO> processing', 0DH 49 6E 76 61 6C 69 64 20 63 6F 6D 6D 61 6E 64 20 64 75 72 69 6E 67 20 3C 44 4F 3E 20 70 72 6F 63 65 73 73 69 6E 67 0D
Shown when a querying purge is attempted inside a JCL/DO job (reached at 55E4H). Terminated by 0DH.
5678-568F
DEFM 'Master password ? ', 03H 4D 61 73 74 65 72 20 70 61 73 73 77 6F 72 64 20 3F 20 20 20 20 20 20 03
The prompt requesting the disk master password, with a trailing input field. Terminated by 03H for @DSPLY.
5690-56A6
DEFM 'Invalid master password' 49 6E 76 61 6C 69 64 20 6D 61 73 74 65 72 20 70 61 73 73 77 6F 72 64
Shown when the supplied master password does not match (reached at 55E0H). Terminated by the 0DH at 56A7H.
56A7
DEFB 0DH 0D
Carriage-return terminator for the preceding message, immediately preceding the month-length table.
56A8-56B3
DEFB 1FH, 1CH, 1FH, 1EH, 1FH, 1EH, 1FH, 1FH, 1EH, 1FH, 1EH, 1FH 1F 1C 1F 1E 1F 1E 1F 1F 1E 1F 1E 1F
Days per month, January through December (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31). February's entry at 56A9H is incremented to 29 in a leap year during date validation.
56B4-56C3
DEFM 'Bad date format', 0DH 42 61 64 20 64 61 74 65 20 66 6F 72 6D 61 74 0D
Shown when a DATE option string cannot be parsed (reached at 55E8H). Terminated by 0DH.
56C4-56D0
DEFM 'Purge file: ', 03H 50 75 72 67 65 20 66 69 6C 65 3A 20 03
The per-file query prefix displayed by @DSPLY at 53CAH. Terminated by 03H.
56D1-56D5
DEFM '} ? ' 7D 20 3F 20 20
The query suffix displayed at 5456H: the closing brace of the "{MM-Mon-YY}" date field followed by " ? ", prompting for a Y/N answer. Terminated by the 03H at 56D6H.
56D6-56E0
DEFM 03H, 'Purging: ', 03H 03 50 75 72 67 69 6E 67 3A 20 03
The message logged before a file is removed (from 56D7H at 5478H). The leading 03H terminates the preceding query suffix; the trailing 03H terminates this string.
56E1-570F
DEFM 'JanFebMarAprMayJunJulAugSepOctNovDec ' 4A 61 6E 46 65 62 4D 61 72 41 70 72 4D 61 79 4A 75 6E 4A 75 6C 41 75 67 53 65 70 4F 63 74 4E 6F 76 44 65 63 20 20 20 20 20 20 20 20 20 20 20
The three-letter month-name table indexed at 5410H to build the displayed date, followed by trailing spaces that pad the record.
5710
DEFB 00H 00
The date-filter flag byte: bit 7 set means a lower date bound is present, bit 0 set means an upper bound is present.

5734H - Parameter Keyword Table

The @PARAM keyword table scanned at 525DH. Each entry is eight bytes: a six-character space-padded keyword and a two-byte little-endian pointer to the operand cell that receives the parsed value. The five options INV, SYS, MPW, QUERY and DATE appear with their single-letter abbreviations I, S, Q and D; a 00H byte ends the table.

5734-573B
DEFM 'I ', DEFW 5327H 49 20 20 20 20 20 27 53
The I abbreviation for INV. The pointer 5327H is the operand of the LD DE at 5326H, the "include invisible files" flag.
573C-5743
DEFM 'INV ', DEFW 5327H 49 4E 56 20 20 20 27 53
INV keyword: include invisible files. Points at the same flag cell 5327H.
5744-574B
DEFM 'S ', DEFW 5319H 53 20 20 20 20 20 19 53
The S abbreviation for SYS. The pointer 5319H is the operand of the LD DE at 5318H, the "include system files" flag.
574C-5753
DEFM 'SYS ', DEFW 5319H 53 59 53 20 20 20 19 53
SYS keyword: include system files. Points at the same flag cell 5319H.
5754-575B
DEFM 'MPW ', DEFW 54BFH 4D 50 57 20 20 20 BF 54
MPW keyword: the disk master password. The pointer 54BFH is the operand of the LD DE at 54BEH, which receives a pointer to the supplied password string.
575C-5763
DEFM 'QUERY ', DEFW 53C0H 51 55 45 52 59 20 C0 53
QUERY keyword. The pointer 53C0H is the operand of the LD DE at 53BFH, the ON/OFF query flag (FFFFH = ask before each file, 0000H = purge unattended).
5764-576B
DEFM 'Q ', DEFW 53C0H 51 20 20 20 20 20 C0 53
The Q abbreviation for QUERY. Points at the same flag cell 53C0H.
576C-5773
DEFM 'DATE ', DEFW 5264H 44 41 54 45 20 20 64 52
DATE keyword: restrict the purge to a range of modification dates. The pointer 5264H is the operand of the LD HL at 5263H, which receives a pointer to the date string.
5774-577B
DEFM 'D ', DEFW 5264H 44 20 20 20 20 20 64 52
The D abbreviation for DATE. Points at the same date-string pointer cell 5264H.
577C
DEFB 00H 00
Zero byte terminating the @PARAM keyword table and the loaded overlay image.

Disassembly - Overlay 12 - FORMS

5200H - FORMS Command Entry, Exit and Error Paths

The FORMS command changes the operating parameters of the resident printer Forms filter. Its entry saves the caller stack pointer with a self-modifying LD (nnnnH),SP, calls the worker at 522DH, then returns to the RST 28H dispatcher with a completion code in Register Pair HL (0000H success, 0FFFFH error). On an error while running under DO/JCL it aborts to @ABORT at 4030H. The two error tails display a parameter-error message through @ERROR or the "Forms Filter not Resident" message through @LOGOT.

5200
LD (520BH),SP ED 73 0B 52
Self-Modifying Code
Save the caller's stack pointer into 520BH, the operand of the LD SP,nnnn at 520AH, so the original stack can be restored when the command finishes.
5204
GOSUB to 522DH, the routine that locates the resident Forms filter, parses the command line and updates the filter (or displays its current settings). It returns with Register Pair HL holding the completion code (0000H success, 0FFFFH error) through the exit tail below.
5207
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H, the success completion code, for the case where the work routine falls straight through to here. The work routine at 52F5H jumps back to this point on success.
520A
LD SP,0000H 31 00 00
Self-Modifying Code
Restore the caller's stack pointer from the operand at 520BH (written at entry by 5200H). Register Pair HL still holds the completion code (0000H success, 0FFFFH error).
520D
LD A,H 7C
Copy the high byte of the completion code (Register H) into Register A to test whether Register Pair HL is zero.
520E
OR L B5
OR the low byte of the completion code (Register L) into Register A. The Z FLAG is set only when the whole completion code in Register Pair HL is 0000H, meaning success.
520F
RET Z C8
If the Z FLAG is set (completion code 0000H, success), RETurn to the resident RST 28H dispatcher.
5210
LD A,(430FH) 3A 0F 43
Fetch the resident system flag SFLAG$ from 430FH into Register A. Reached only on an error completion code; bit 5 of this byte is set when execution is not at the LDOS command level (running under DO/JCL).
5213
BIT 5,A CB 6F
Test bit 5 of SFLAG$ (Register A). If bit 5 is set, the command is running under DO/JCL rather than at the command level.
5215
RET Z C8
If the Z FLAG is set (SFLAG$ bit 5 clear, so at the LDOS command level), RETurn to the RST 28H dispatcher, letting the caller see the error code in Register Pair HL.
5216
Not at the command level, so JUMP to the resident @ABORT vector (4030H) to abort the running DO/JCL job on the error.
5219
LD A,2CH 3E 2C
Load Register A with 2CH (44 decimal), the LDOS parameter-error code, for the bad-keyword error path (entered from 5268H).
521B
OR 0C0H F6 C0
OR 0C0H into Register A, setting bit 7 (return to caller rather than abort) and bit 6 (message-only) on the parameter-error code before calling @ERROR.
521D
GOSUB to the resident SYS0 service @ERROR (4409H) to display the parameter-error message for the code in Register A.
5220
JUMP to 5228H to load the error completion code and return through the exit tail.
5222
LD HL,548AH 21 8A 54
Filter Not Resident Path
Point Register Pair HL at 548AH, the "Forms Filter not Resident" message, reached from 5234H when the module lookup finds no resident Forms filter.
5225
GOSUB to the resident SYS0 service @LOGOT (447BH) to display the carriage-return-terminated message addressed by Register Pair HL (548AH).
5228
LD HL,0FFFFH 21 FF FF
Load Register Pair HL with 0FFFFH, the error completion code, so the exit tail takes the error path.
522B
JUMP back to 520AH to restore the stack pointer and return the error code in Register Pair HL.

522DH - Locate the Forms Filter and Edit or Display the Parameters

The worker asks the resident dispatcher (RST 28H code 0BCH) to locate the "$FF" Forms-filter control block. It copies the filter's ten live setting bytes into a local working copy addressed by Register IY (base 552BH), then either parses the parenthesized options with @PARAM and writes the edited settings back, or - when no options are given - falls through to the display routine. PAGE and LINES are held in the filter with an internal +1 bias whenever the XLATE-active flag (IY+7 bit 3) is set.

522D
PUSH HL E5
Locate the Filter and Parse the Command
Save the command-line pointer (Register Pair HL, positioned by the dispatcher just past the command name) on the stack while the resident Forms filter is located.
522E
LD DE,5480H 11 80 54
Point Register Pair DE at 5480H, the module-name string "$FF" (03H-terminated), the name under which the resident Forms filter installs its control block.
5231
GOSUB to 53B8H, which issues RST 28H request 0BCH to ask the resident dispatcher to locate the "$FF" module control block. On return the NZ FLAG is set if no such module is resident.
5234
If the NZ FLAG is set (no resident Forms filter was found), JUMP to 5222H to report "Forms Filter not Resident".
5236
EX DE,HL EB
Exchange Register Pairs DE and HL so Register Pair HL now holds the address of the located Forms-filter control block returned by the lookup.
5237
LD BC,0008H 01 08 00
Load Register Pair BC with 0008H, the offset of the parameter-pointer word within the filter control block.
523A
ADD HL,BC 09
Add 0008H (Register Pair BC) to the control-block base (Register Pair HL) so Register Pair HL points at control-block offset 8, the two-byte pointer to the filter's parameter storage.
523B
LD E,(HL) 5E
Fetch the low byte of the parameter-storage pointer (addressed by Register Pair HL at control-block offset 8) into Register E.
523C
INC HL 23
Advance Register Pair HL to control-block offset 9, the high byte of the parameter-storage pointer.
523D
LD D,(HL) 56
Fetch the high byte of the parameter-storage pointer (addressed by Register Pair HL) into Register D, so Register Pair DE now points at the filter's parameter storage.
523E
INC HL 23
Advance Register Pair HL to control-block offset 0AH, the start of the seven-byte flag/geometry area held directly in the control block.
523F
PUSH HL E5
Save the control-block+0AH pointer (Register Pair HL) on the stack for the second copy below.
5240
EX DE,HL EB
Exchange Register Pairs DE and HL so Register Pair HL now points at the filter's parameter storage (the pointer read from control-block offset 8).
5241
LD C,03H 0E 03
Load Register C with 03H (Register B is already zero here), the offset of the first live parameter byte within the parameter storage.
5243
ADD HL,BC 09
Add 0003H (Register Pair BC) to the parameter-storage base (Register Pair HL), so Register Pair HL points at parameter-storage offset 3, the first of the three low parameter bytes.
5244
LD (52E7H),HL 22 E7 52
Self-Modifying Code
Store the parameter-storage+3 pointer (Register Pair HL) into 52E7H, the operand of the LD DE,nnnn at 52E6H, so the write-back at 52ECH sends the edited bytes to the same place.
5247
LD DE,552BH 11 2B 55
Point Register Pair DE at 552BH, the ten-byte local working copy of the filter's settings that the display and edit code accesses through Register IY.
524A
PUSH DE D5
Push the working-copy address (Register Pair DE, 552BH) so it can be pulled into Register IY.
524B
POP IY FD E1
Pull the working-copy address into Register IY, establishing IY = 552BH as the base of the local settings structure (IY+0 through IY+9).
524D
LD C,03H 0E 03
Load Register C with 03H, the count of low parameter bytes to copy from parameter-storage offset 3.
524F
LDIR ED B0
Block-copy three bytes: Source Register Pair HL (parameter-storage+3), Destination Register Pair DE (552BH = IY+0), count Register Pair BC (3). This loads IY+0 through IY+2 (CHARS-index, INDENT and one flag byte) from the filter's parameter storage.
5251
POP HL E1
Pull the saved control-block+0AH pointer into Register Pair HL as the source for the second copy.
5252
LD (52EFH),HL 22 EF 52
Self-Modifying Code
Store the control-block+0AH pointer (Register Pair HL) into 52EFH, the operand of the LD DE,nnnn at 52EEH, so the seven-byte write-back at 52F3H returns the edited bytes to the control block.
5255
LD C,07H 0E 07
Load Register C with 07H, the count of bytes to copy from control-block offset 0AH (Register Pair DE currently points at 552EH = IY+3, just past the three bytes copied above).
5257
LDIR ED B0
Block-copy seven bytes: Source Register Pair HL (control-block+0AH), Destination Register Pair DE (552EH = IY+3), count Register Pair BC (7). IY+3 through IY+9 now mirror the filter's flag byte, PAGE/LINES counters, XLATE characters, CHARS and MARGIN.
5259
POP HL E1
Pull the saved command-line pointer into Register Pair HL to examine the first character after the command name.
525A
LD A,(HL) 7E
Fetch the first command-line character (addressed by Register Pair HL) into Register A.
525B
CP 0EH FE 0E
Compare Register A (the first command-line character) against 0EH. Command bytes below 0EH are treated as end-of-line, so no parameters were supplied.
525D
If the NO CARRY FLAG is set (character 0EH or above, a real parameter follows), JUMP to 5262H to parse the parameter list.
525F
No parameters were given, so JUMP to 52F8H to display the filter's current settings.
5262
LD DE,53BBH 11 BB 53
Point Register Pair DE at 53BBH, the base of the @PARAM keyword descriptor table (LINES, PAGE, CHARS, INDENT, ADDLF, FFHARD, TAB, XLATE, MARGIN, DEFAULT and their abbreviations).
5265
GOSUB to the resident SYS0 service @PARAM (4476H) to match the parenthesized options on the command line (Register Pair HL) against the keyword table at Register Pair DE. Each recognized option stores its value into the operand cell named by the table entry. Returns the NZ FLAG on a bad or unknown keyword.
5268
If the NZ FLAG is set (a bad or unknown parameter), JUMP to 5219H to report parameter error 2CH.
526B
LD BC,0000H 01 00 00
Self-Modifying Code
Load Register Pair BC with the DEFAULT-option flag. The operand at 526CH is set non-zero by the DEFAULT/D keyword through @PARAM; it defaults to 0000H (DEFAULT not requested).
526E
LD A,B 78
Copy the high byte of the DEFAULT flag (Register B) into Register A to test whether DEFAULT was given.
526F
OR C B1
OR the low byte of the DEFAULT flag (Register C) into Register A. The Z FLAG is set only when the whole flag is zero, meaning DEFAULT was not requested.
5270
If the Z FLAG is set (DEFAULT not requested), JUMP to 527DH to apply the individually parsed options.
5272
LD HL,546EH 21 6E 54
Point Register Pair HL at 546EH, the twenty-byte block of factory-default parameter values.
5275
LD DE,545CH 11 5C 54
Point Register Pair DE at 545CH, the block of parameter value cells (LINES through MARGIN) that the parsed options and the code below read.
5278
LD BC,0014H 01 14 00
Load Register Pair BC with 0014H (20), the length of the default parameter block.
527B
LDIR ED B0
Block-copy twenty bytes: Source Register Pair HL (546EH default block), Destination Register Pair DE (545CH value cells), count Register Pair BC (20). This resets all Forms parameters to their factory defaults before any explicit options are applied.
527D
LD A,(5460H) 3A 60 54
Fetch the CHARS value (the low byte of the CHARS cell at 5460H, maximum characters per printed line) into Register A.
5280
LD (IY+08H),A FD 77 08
Store the CHARS value (Register A) into IY+8 of the working settings copy (5533H), the filter's characters-per-line field.
5283
LD A,(546CH) 3A 6C 54
Fetch the MARGIN value (the low byte of the MARGIN cell at 546CH, the left-margin width) into Register A.
5286
LD (IY+09H),A FD 77 09
Store the MARGIN value (Register A) into IY+9 of the working copy (5534H), the filter's left-margin field.
5289
LD A,(5462H) 3A 62 54
Fetch the INDENT value (the low byte of the INDENT cell at 5462H, the wrap-indent count) into Register A.
528C
LD (IY+06H),A FD 77 06
Store the INDENT value (Register A) into IY+6 of the working copy (5531H), the filter's wrapped-line indent field.
528F
XOR A AF
Set Register A to zero to begin assembling the filter's flag byte from the switch options.
5290
BIT 3,(IY+07H) FD CB 07 5E
Test bit 3 of the current flag byte IY+7 (5532H), the filter's existing XLATE-active bit, which is preserved across this edit.
5294
If the Z FLAG is set (the existing XLATE-active bit was clear), JUMP to 5297H, leaving Register A bit 0 clear.
5296
INC A 3C
The existing XLATE-active bit was set, so INCrement Register A to 1, carrying that bit forward into the rebuilt flag byte.
5297
LD HL,(5468H) 2A 68 54
Fetch the TAB option cell (5468H) into Register Pair HL; @PARAM leaves the low byte 0FFH when the TAB switch was given, 00H otherwise.
529A
RLC L CB 05
Rotate Register L left circularly, moving the TAB switch's high bit into the CARRY FLAG (CARRY set when TAB was given).
529C
RLA 17
Rotate Register A left through the CARRY FLAG, shifting the assembling flag byte and bringing the TAB switch into bit 0.
529D
LD HL,(5466H) 2A 66 54
Fetch the FFHARD option cell (5466H) into Register Pair HL (low byte 0FFH when the FFHARD switch was given).
52A0
RLC L CB 05
Rotate Register L left circularly, moving the FFHARD switch bit into the CARRY FLAG.
52A2
RLA 17
Rotate Register A left through the CARRY FLAG, advancing the flag byte and bringing FFHARD into bit 0 (TAB moves to bit 1).
52A3
LD HL,(5464H) 2A 64 54
Fetch the ADDLF option cell (5464H) into Register Pair HL (low byte 0FFH when the ADDLF switch was given).
52A6
RLC L CB 05
Rotate Register L left circularly, moving the ADDLF switch bit into the CARRY FLAG.
52A8
RLA 17
Rotate Register A left through the CARRY FLAG, bringing ADDLF into bit 0. Register A now holds bit0=ADDLF, bit1=FFHARD, bit2=TAB, bit3=preserved XLATE-active.
52A9
LD (IY+07H),A FD 77 07
Store the assembled flag byte (Register A) into IY+7 of the working copy (5532H), the filter's switch/flag field.
52AC
LD HL,(546AH) 2A 6A 54
Fetch the XLATE value word (546AH) into Register Pair HL: Register H is the "from" character and Register L the "to" character of X'aabb'.
52AF
LD (IY+04H),H FD 74 04
Store the XLATE "from" character (Register H) into IY+4 of the working copy (552FH), the character the filter translates from.
52B2
LD (IY+05H),L FD 75 05
Store the XLATE "to" character (Register L) into IY+5 of the working copy (5530H), the character the filter translates to.
52B5
LD A,(545EH) 3A 5E 54
Fetch the PAGE value (the low byte of the PAGE cell at 545EH, the physical page length in lines) into Register A.
52B8
INC A 3C
INCrement Register A, applying the filter's internal off-by-one bias to the PAGE count before it is stored.
52B9
LD (IY+00H),A FD 77 00
Store the biased PAGE value (Register A) into IY+0 of the working copy (552BH), the filter's page-length counter.
52BC
LD (IY+01H),01H FD 36 01 01
Store 01H into IY+1 of the working copy (552CH), the filter's running line-within-page counter, initialised to one.
52C0
LD (IY+03H),00H FD 36 03 00
Store 00H into IY+3 of the working copy (552EH), clearing a filter state byte.
52C4
LD A,(545CH) 3A 5C 54
Fetch the LINES value (the low byte of the LINES cell at 545CH, the number of lines printed per page) into Register A. The default is 0FFH (not specified).
52C7
INC A 3C
INCrement Register A. When LINES was left unspecified (0FFH) the result is zero.
52C8
AND A A7
Test Register A. The Z FLAG is set only when LINES was unspecified.
52C9
If the NZ FLAG is set (LINES was specified), JUMP to 52CEH to store the requested value.
52CB
LD A,(IY+00H) FD 7E 00
LINES was unspecified, so fetch the biased PAGE value from IY+0 (552BH) into Register A, defaulting LINES to the page length so no blank lines are added.
52CE
LD (IY+02H),A FD 77 02
Store the LINES value (Register A) into IY+2 of the working copy (552DH), the filter's lines-per-page field.
52D1
BIT 3,(IY+07H) FD CB 07 5E
Test bit 3 of the flag byte IY+7 (5532H), the XLATE-active bit just rebuilt above.
52D5
If the NZ FLAG is set (XLATE active), JUMP to 52E0H, leaving PAGE and LINES stored with the internal +1 bias.
52D7
DEC (IY+00H) FD 35 00
XLATE is not active, so DECrement IY+0 (552BH), removing the +1 bias from the stored PAGE count.
52DA
DEC (IY+01H) FD 35 01
DECrement IY+1 (552CH), clearing the line-within-page counter back to zero for the non-XLATE representation.
52DD
DEC (IY+02H) FD 35 02
DECrement IY+2 (552DH), removing the +1 bias from the stored LINES count.
52E0
GOSUB to 52F8H to format and display the settings just written into the working copy.
52E3
LD HL,552BH 21 2B 55
Point Register Pair HL at 552BH (IY+0), the first of the three low bytes to write back into the filter's parameter storage.
52E6
LD DE,0000H 11 00 00
Self-Modifying Code
Point Register Pair DE at the filter's parameter-storage+3 address; the operand at 52E7H was patched at 5244H with that address.
52E9
LD BC,0003H 01 03 00
Load Register Pair BC with 0003H, the count of low parameter bytes to write back.
52EC
LDIR ED B0
Block-copy three bytes: Source Register Pair HL (552BH working copy), Destination Register Pair DE (parameter storage+3), count Register Pair BC (3). This commits CHARS-index, INDENT and the flag byte to the filter.
52EE
LD DE,0000H 11 00 00
Self-Modifying Code
Point Register Pair DE at the filter control-block+0AH address; the operand at 52EFH was patched at 5252H with that address.
52F1
LD C,07H 0E 07
Load Register C with 07H, the count of bytes to write back into the control block (Register Pair HL now points at 552EH = IY+3).
52F3
LDIR ED B0
Block-copy seven bytes: Source Register Pair HL (552EH working copy), Destination Register Pair DE (control-block+0AH), count Register Pair BC (7). This commits the page/line counters, XLATE characters, CHARS and MARGIN to the filter.
52F5
JUMP back to 5207H to load the success completion code and return through the exit tail.

52F8H - Format and Display the Current Settings

This routine fills the on-screen template at 54A4H from the working copy: the switch fields ADDLF, FFHARD and TAB show " ON" or "OFF"; CHARS, INDENT, LINES, MARGIN and PAGE are formatted as three-digit decimals (PAGE and LINES have the internal +1 bias removed when XLATE is active); and the "Xlate" line is enabled only when a translation is defined, showing the from/to characters in hexadecimal. The whole block is sent with @DSPLY.

52F8
BIT 0,(IY+07H) FD CB 07 46
Display the Current Settings
Test bit 0 of the working-copy flag byte IY+7 (5532H), the ADDLF switch state.
52FC
LD DE,54EEH 11 EE 54
Point Register Pair DE at 54EEH, the "OFF" value field of the "Addlf" line in the display template, ready to be overwritten if ADDLF is on.
52FF
If the NZ FLAG is set (ADDLF on), GOSUB to 537BH to overwrite the field at Register Pair DE with " ON".
5302
LD A,(IY+08H) FD 7E 08
Fetch the CHARS field from IY+8 (5533H), the characters-per-line value, into Register A.
5305
OR A B7
Test Register A. The Z FLAG is set when CHARS is zero (meaning no character limit, shown as OFF).
5306
LD DE,54C7H 11 C7 54
Point Register Pair DE at 54C7H, the value field of the "Chars" line in the display template.
5309
If the NZ FLAG is set (CHARS non-zero), GOSUB to 5384H to format the CHARS value in Register A as a right-justified three-digit number into the field at Register Pair DE.
530C
If the NZ FLAG is set (CHARS was non-zero and already formatted), JUMP to 5314H to continue with FFHARD.
530E
LD HL,5487H 21 87 54
CHARS is zero, so point Register Pair HL at 5487H, the "OFF" string, to show that no character limit is set.
5311
GOSUB to 537EH to copy the three-byte "OFF" string (Register Pair HL) into the "Chars" value field at Register Pair DE.
5314
BIT 1,(IY+07H) FD CB 07 4E
Test bit 1 of the flag byte IY+7 (5532H), the FFHARD switch state.
5318
LD DE,54FBH 11 FB 54
Point Register Pair DE at 54FBH, the "OFF" value field of the "Ffhard" line in the display template.
531B
If the NZ FLAG is set (FFHARD on), GOSUB to 537BH to overwrite the field at Register Pair DE with " ON".
531E
LD A,(IY+06H) FD 7E 06
Fetch the INDENT field from IY+6 (5531H), the wrapped-line indent count, into Register A.
5321
LD DE,54E1H 11 E1 54
Point Register Pair DE at 54E1H, the value field of the "Indent" line in the display template.
5324
GOSUB to 5384H to format the INDENT value in Register A as a three-digit number into the field at Register Pair DE.
5327
LD A,(IY+02H) FD 7E 02
Fetch the LINES field from IY+2 (552DH), the lines-per-page count, into Register A.
532A
BIT 3,(IY+07H) FD CB 07 5E
Test bit 3 of the flag byte IY+7 (5532H), the XLATE-active bit that governs the +1 bias.
532E
If the Z FLAG is set (XLATE inactive, value stored without bias), JUMP to 5331H to display LINES as-is.
5330
DEC A 3D
XLATE is active, so DECrement Register A to remove the internal +1 bias from the LINES count before display.
5331
LD DE,54BAH 11 BA 54
Point Register Pair DE at 54BAH, the value field of the "Lines" line in the display template.
5334
GOSUB to 5384H to format the LINES value in Register A as a three-digit number into the field at Register Pair DE.
5337
LD A,(IY+09H) FD 7E 09
Fetch the MARGIN field from IY+9 (5534H), the left-margin width, into Register A.
533A
LD DE,54D4H 11 D4 54
Point Register Pair DE at 54D4H, the value field of the "Margin" line in the display template.
533D
GOSUB to 5384H to format the MARGIN value in Register A as a three-digit number into the field at Register Pair DE.
5340
LD A,(IY+00H) FD 7E 00
Fetch the PAGE field from IY+0 (552BH), the page-length counter, into Register A.
5343
BIT 3,(IY+07H) FD CB 07 5E
Test bit 3 of the flag byte IY+7 (5532H), the XLATE-active bit that governs the +1 bias.
5347
If the Z FLAG is set (XLATE inactive, value stored without bias), JUMP to 534AH to display PAGE as-is.
5349
DEC A 3D
XLATE is active, so DECrement Register A to remove the internal +1 bias from the PAGE count before display.
534A
LD DE,54ADH 11 AD 54
Point Register Pair DE at 54ADH, the value field of the "Page" line in the display template.
534D
GOSUB to 5384H to format the PAGE value in Register A as a three-digit number into the field at Register Pair DE.
5350
BIT 2,(IY+07H) FD CB 07 56
Test bit 2 of the flag byte IY+7 (5532H), the TAB switch state.
5354
LD DE,5508H 11 08 55
Point Register Pair DE at 5508H, the "OFF" value field of the "Tab" line in the display template.
5357
If the NZ FLAG is set (TAB on), GOSUB to 537BH to overwrite the field at Register Pair DE with " ON".
535A
LD A,(IY+04H) FD 7E 04
Fetch the XLATE "from" character from IY+4 (552FH) into Register A.
535D
LD B,(IY+05H) FD 46 05
Fetch the XLATE "to" character from IY+5 (5530H) into Register B.
5360
CP B B8
Compare the "from" character (Register A) against the "to" character (Register B). Equal characters mean no translation is defined.
5361
If the Z FLAG is set (from equals to, so XLATE is inactive), JUMP to 5375H to skip building the Xlate line and display what is assembled.
5363
LD HL,550CH 21 0C 55
A translation is defined, so point Register Pair HL at 550CH, the byte immediately before the "Xlate" line in the template.
5366
LD (HL),0AH 36 0A
Store 0AH (line feed) at 550CH, changing the byte that precedes the "Xlate" line from a carriage return to a line feed so the Xlate line is displayed as part of the block.
5368
LD HL,5518H 21 18 55
Point Register Pair HL at 5518H, the two-character hex field for the XLATE "from" character in the "Xlate" line.
536B
GOSUB to the resident SYS0 number formatter (4D7BH) to write the "from" character in Register A as two hexadecimal digits at Register Pair HL.
536E
LD A,B 78
Copy the XLATE "to" character (Register B) into Register A for formatting.
536F
LD HL,5521H 21 21 55
Point Register Pair HL at 5521H, the two-character hex field for the XLATE "to" character in the "Xlate" line.
5372
GOSUB to the resident SYS0 number formatter (4D7BH) to write the "to" character in Register A as two hexadecimal digits at Register Pair HL.
5375
LD HL,54A4H 21 A4 54
Point Register Pair HL at 54A4H, the start of the assembled settings-display block ("Page ... Xlate ...").
5378
JUMP to the resident SYS0 service @DSPLY (4467H) to display the whole settings block at Register Pair HL; @DSPLY returns to the caller of this routine.

537BH - Field-Copy, Decimal-Format and Module-Lookup Helpers

Three shared helpers: a three-byte field copier (used to stamp " ON" or "OFF" into a template field), a byte-to-three-decimal-digit formatter that uses @DIV and a five-byte scratch buffer at 5526H, and the RST 28H code 0BCH module-lookup trampoline that returns the "$FF" filter control block.

537B
LD HL,5484H 21 84 54
Switch and Field Helpers
Point Register Pair HL at 5484H, the three-byte " ON" string, then fall into the copy helper. Entered when a switch (ADDLF/FFHARD/TAB) is on to overwrite its "OFF" field.
537E
LD BC,0003H 01 03 00
Load Register Pair BC with 0003H, the length of the three-character value field to copy.
5381
LDIR ED B0
Block-copy three bytes: Source Register Pair HL (a three-character string such as " ON" or "OFF"), Destination Register Pair DE (a template value field), count Register Pair BC (3).
5383
RET C9
RETurn to the display routine.
5384
PUSH BC C5
Format a Byte as Three Decimal Digits
Save Register Pair BC on the stack; entry Register A holds the value to format and Register Pair DE points at the destination field.
5385
PUSH HL E5
Save Register Pair HL on the stack across the conversion.
5386
PUSH AF F5
Save Register AF (the value in Register A) on the stack.
5387
PUSH DE D5
Save Register Pair DE (the destination field pointer) on the stack for the copy below.
5388
LD DE,5526H 11 26 55
Point Register Pair DE at 5526H, the five-byte scratch buffer where the decimal conversion is built.
538B
LD H,00H 26 00
Load Register H with 00H, clearing the high byte so Register Pair HL will hold the value 0 to 255.
538D
LD L,A 6F
Copy the value (Register A) into Register L, giving Register Pair HL the number to convert.
538E
GOSUB to 539FH to convert Register Pair HL to a right-justified, space-padded five-digit decimal string at the scratch buffer (Register Pair DE).
5391
DEC DE 1B
DECrement Register Pair DE, backing up over the scratch buffer toward its last three digits.
5392
DEC DE 1B
DECrement Register Pair DE again.
5393
DEC DE 1B
DECrement Register Pair DE a third time so Register Pair DE points at the low three decimal digits of the converted value.
5394
POP HL E1
Pull the saved destination field pointer into Register Pair HL.
5395
EX DE,HL EB
Exchange Register Pairs DE and HL so Register Pair DE is the destination field and Register Pair HL is the three-digit source in the scratch buffer.
5396
LD BC,0003H 01 03 00
Load Register Pair BC with 0003H, the number of digits to copy.
5399
LDIR ED B0
Block-copy three bytes: Source Register Pair HL (low three digits in the scratch buffer), Destination Register Pair DE (the template value field), count Register Pair BC (3).
539B
POP AF F1
Restore Register AF from the stack.
539C
POP HL E1
Restore Register Pair HL from the stack.
539D
POP BC C1
Restore Register Pair BC from the stack.
539E
RET C9
RETurn to the display routine with the value written into the field.
539F
LD B,05H 06 05
Convert HL to Five Decimal Digits
Load Register B with 05H, the field width in digits, to space-fill the scratch buffer first.
53A1
LD A,20H 3E 20
Load Register A with 20H (ASCII space) to blank the scratch buffer.
53A3
LD (DE),A 12
Store the space (Register A) into the scratch buffer (addressed by Register Pair DE).
53A4
INC DE 13
Advance Register Pair DE to the next scratch-buffer byte.
53A5
DECrement Register B and LOOP BACK to 53A3H until all five scratch bytes are blanked. Register Pair DE now points just past the buffer.
53A7
PUSH DE D5
Save the end-of-buffer pointer (Register Pair DE) on the stack; digits are written backward from here.
53A8
DEC DE 1B
DECrement Register Pair DE to point at the last (units) digit position.
53A9
LD A,0AH 3E 0A
Loop Start
Load Register A with 0AH (10), the divisor for extracting the next decimal digit.
53AB
GOSUB to the resident SYS0 service @DIV (44C4H) to divide Register Pair HL by 10; the quotient returns in Register Pair HL and the remainder (the next digit) in Register A.
53AE
ADD A,30H C6 30
Add 30H to the remainder digit (Register A) to convert it to its ASCII character.
53B0
LD (DE),A 12
Store the ASCII digit (Register A) into the current buffer position (addressed by Register Pair DE).
53B1
DEC DE 1B
DECrement Register Pair DE to the next-higher digit position.
53B2
LD A,H 7C
Copy the quotient high byte (Register H) into Register A to test whether the value is exhausted.
53B3
OR L B5
OR the quotient low byte (Register L) into Register A. The Z FLAG is set when the quotient in Register Pair HL has reached zero.
53B4
If the NZ FLAG is set (more digits remain), LOOP BACK to 53A9H to extract the next digit.
53B6
POP DE D1
Restore the end-of-buffer pointer into Register Pair DE.
53B7
RET C9
RETurn to the formatter with the decimal string in the scratch buffer.
53B8
LD A,0BCH 3E BC
Module-Lookup Trampoline
Load Register A with 0BCH, the resident supervisor request that locates a named module control block; Register Pair DE points at the module name.
53BA
RST 28H EF
Execute the supervisor call: the resident dispatcher runs request 0BCH and returns the "$FF" Forms-filter control block in Register Pair HL, or the NZ FLAG if no such module is resident. Control returns to 5234H.

53BBH - Parameter Keyword Table (@PARAM)

The keyword descriptor table @PARAM scans (loaded into Register Pair DE at 5262H). Each entry is a six-character space-padded keyword followed by the two-byte (low, high) address of the value cell that receives the parsed value. Every keyword has a single-letter abbreviation pointing at the same cell. A 00H byte terminates the table.

53BB-53C2
DEFM 'LINES ' + DEFW 545CH 4C 49 4E 45 53 20 5C 54
Keyword LINES value pointer to 545CH. LINES - the number of lines printed per page.
53C3-53CA
DEFM 'L ' + DEFW 545CH 4C 20 20 20 20 20 5C 54
Abbreviation L value pointer to 545CH. LINES - the number of lines printed per page.
53CB-53D2
DEFM 'PAGE ' + DEFW 545EH 50 41 47 45 20 20 5E 54
Keyword PAGE value pointer to 545EH. PAGE - the physical page length in lines (default 66).
53D3-53DA
DEFM 'P ' + DEFW 545EH 50 20 20 20 20 20 5E 54
Abbreviation P value pointer to 545EH. PAGE - the physical page length in lines (default 66).
53DB-53E2
DEFM 'CHARS ' + DEFW 5460H 43 48 41 52 53 20 60 54
Keyword CHARS value pointer to 5460H. CHARS - the maximum characters per printed line.
53E3-53EA
DEFM 'C ' + DEFW 5460H 43 20 20 20 20 20 60 54
Abbreviation C value pointer to 5460H. CHARS - the maximum characters per printed line.
53EB-53F2
DEFM 'INDENT' + DEFW 5462H 49 4E 44 45 4E 54 62 54
Keyword INDENT value pointer to 5462H. INDENT - spaces to indent a wrapped line.
53F3-53FA
DEFM 'I ' + DEFW 5462H 49 20 20 20 20 20 62 54
Abbreviation I value pointer to 5462H. INDENT - spaces to indent a wrapped line.
53FB-5402
DEFM 'ADDLF ' + DEFW 5464H 41 44 44 4C 46 20 64 54
Keyword ADDLF value pointer to 5464H. ADDLF - switch: send a line feed after every carriage return.
5403-540A
DEFM 'A ' + DEFW 5464H 41 20 20 20 20 20 64 54
Abbreviation A value pointer to 5464H. ADDLF - switch: send a line feed after every carriage return.
540B-5412
DEFM 'FFHARD' + DEFW 5466H 46 46 48 41 52 44 66 54
Keyword FFHARD value pointer to 5466H. FFHARD - switch: send X'0C' as a form feed instead of line feeds.
5413-541A
DEFM 'F ' + DEFW 5466H 46 20 20 20 20 20 66 54
Abbreviation F value pointer to 5466H. FFHARD - switch: send X'0C' as a form feed instead of line feeds.
541B-5422
DEFM 'TAB ' + DEFW 5468H 54 41 42 20 20 20 68 54
Keyword TAB value pointer to 5468H. TAB - switch: expand X'09' to eight-column tab stops.
5423-542A
DEFM 'T ' + DEFW 5468H 54 20 20 20 20 20 68 54
Abbreviation T value pointer to 5468H. TAB - switch: expand X'09' to eight-column tab stops.
542B-5432
DEFM 'XLATE ' + DEFW 546AH 58 4C 41 54 45 20 6A 54
Keyword XLATE value pointer to 546AH. XLATE - the X'aabb' translate pair (from/to characters).
5433-543A
DEFM 'X ' + DEFW 546AH 58 20 20 20 20 20 6A 54
Abbreviation X value pointer to 546AH. XLATE - the X'aabb' translate pair (from/to characters).
543B-5442
DEFM 'MARGIN' + DEFW 546CH 4D 41 52 47 49 4E 6C 54
Keyword MARGIN value pointer to 546CH. MARGIN - the left-margin width.
5443-544A
DEFM 'M ' + DEFW 546CH 4D 20 20 20 20 20 6C 54
Abbreviation M value pointer to 546CH. MARGIN - the left-margin width.
544B-5452
DEFM 'DEFAUL' + DEFW 526CH 44 45 46 41 55 4C 6C 52
Keyword DEFAUL value pointer to 526CH. DEFAULT - flag cell (operand of the LD BC at 526BH); requests a reset of all parameters to their factory defaults.
5453-545A
DEFM 'D ' + DEFW 526CH 44 20 20 20 20 20 6C 52
Abbreviation D value pointer to 526CH. DEFAULT - flag cell (operand of the LD BC at 526BH); requests a reset of all parameters to their factory defaults.
545B
DEFB 00H 00
Table terminator.

545CH - Parameter Value Cells, Defaults and Switch Literals

The nine value cells @PARAM fills, pre-initialized to their unspecified/default values, followed by the twenty-byte factory-default block the DEFAULT option copies over them, the "$FF" filter module-name string, and the three-character " ON"/"OFF" switch literals.

545C-545D
DEFW FFFFH FF FF
LINES value cell, initial value 0FFFFH (unspecified).
545E-545F
DEFW 0042H 42 00
PAGE value cell, initial value 0042H (66 lines).
5460-5461
DEFW 0000H 00 00
CHARS value cell, initial value 0000H (no limit).
5462-5463
DEFW 0000H 00 00
INDENT value cell, initial value 0000H.
5464-5465
DEFW 0000H 00 00
ADDLF value cell, initial value 0000H (off).
5466-5467
DEFW 0000H 00 00
FFHARD value cell, initial value 0000H (off).
5468-5469
DEFW 0000H 00 00
TAB value cell, initial value 0000H (off).
546A-546B
DEFW 0000H 00 00
XLATE value cell, initial value 0000H (none).
546C-546D
DEFW 0000H 00 00
MARGIN value cell, initial value 0000H.
546E-546F
DEFW FFFFH FF FF
Default LINES value copied to 545CH by the DEFAULT option.
5470-5471
DEFW 0042H 42 00
Default PAGE value copied to 545EH by the DEFAULT option.
5472-5473
DEFW 0000H 00 00
Default CHARS value copied to 5460H by the DEFAULT option.
5474-5475
DEFW 0000H 00 00
Default INDENT value copied to 5462H by the DEFAULT option.
5476-5477
DEFW 0000H 00 00
Default ADDLF value copied to 5464H by the DEFAULT option.
5478-5479
DEFW 0000H 00 00
Default FFHARD value copied to 5466H by the DEFAULT option.
547A-547B
DEFW 0000H 00 00
Default TAB value copied to 5468H by the DEFAULT option.
547C-547D
DEFW 0000H 00 00
Default XLATE value copied to 546AH by the DEFAULT option.
547E-547F
DEFW 0000H 00 00
Default MARGIN value copied to 546CH by the DEFAULT option.
5480-5483
DEFM '$FF' + DEFB 03H 24 46 46 03
Module-name string used at 522EH for the RST 28H code 0BCH lookup of the resident Forms filter. (The DEFAULT copy above is twenty bytes and reads its final two bytes harmlessly from the start of this string.)
5484-5486
DEFM ' ON' 20 4F 4E
The three-character "on" literal stamped over a switch field by the helper at 537BH.
5487-5489
DEFM 'OFF' 4F 46 46
The three-character "off" literal written into the CHARS field at 5311H when no character limit is set.

548AH - Message and Settings Display Template

The "Forms Filter not Resident" message and the multi-line settings template. Each template line carries a value field that the display routine overwrites: PAGE at 54ADH, LINES at 54BAH, CHARS at 54C7H, MARGIN at 54D4H, INDENT at 54E1H, ADDLF at 54EEH, FFHARD at 54FBH, TAB at 5508H, and the two XLATE hex fields at 5518H and 5521H. The byte at 550CH is a carriage return that the display routine changes to a line feed to append the "Xlate" line when a translation is active.

548A-54A3
DEFM 'Forms Filter not Resident' + 0DH 46 6F 72 6D 73 20 46 69 6C 74 65 72 20 6E 6F 74 20 52 65 73 69 64 65 6E 74 0D
Displayed via @LOGOT at 5225H when no resident "$FF" Forms filter is installed. Terminated by 0DH at 54A3H.
54A4-54B0
DEFM 'Page = 66' + 0AH 50 61 67 65 20 20 20 3D 20 20 36 36 0A
PAGE line; the value field at 54ADH is overwritten with the current page length.
54B1-54BD
DEFM 'Lines = 66' + 0AH 4C 69 6E 65 73 20 20 3D 20 20 36 36 0A
LINES line; value field at 54BAH.
54BE-54CA
DEFM 'Chars = OFF' + 0AH 43 68 61 72 73 20 20 3D 20 4F 46 46 0A
CHARS line; value field at 54C7H (shows OFF when no limit).
54CB-54D7
DEFM 'Margin = 0' + 0AH 4D 61 72 67 69 6E 20 3D 20 20 20 30 0A
MARGIN line; value field at 54D4H.
54D8-54E4
DEFM 'Indent = 0' + 0AH 49 6E 64 65 6E 74 20 3D 20 20 20 30 0A
INDENT line; value field at 54E1H.
54E5-54F1
DEFM 'Addlf = OFF' + 0AH 41 64 64 6C 66 20 20 3D 20 4F 46 46 0A
ADDLF line; value field at 54EEH (OFF or " ON").
54F2-54FE
DEFM 'Ffhard = OFF' + 0AH 46 66 68 61 72 64 20 3D 20 4F 46 46 0A
FFHARD line; value field at 54FBH (OFF or " ON").
54FF-550B
DEFM 'Tab = OFF' + 0AH 54 61 62 20 20 20 20 3D 20 4F 46 46 0A
TAB line; value field at 5508H (OFF or " ON").
550C
DEFB 0DH 0D
Carriage return ending the block; patched to 0AH (line feed) at 5366H when a translation is active so the "Xlate" line below is appended.
550D-5525
DEFM 'Xlate = X''00'' => X''00''' + 0AH + 0DH 58 6C 61 74 65 20 20 3D 20 58 27 30 30 27 20 3D 3E 20 58 27 30 30 27 0A 0D
XLATE line, appended only when a translation is defined; the "from" hex field at 5518H and "to" hex field at 5521H are filled by the resident number formatter at 4D7BH. Terminated by 0AH,0DH; 5525H is the last byte of the overlay image.

Disassembly - Overlay 13 - SETCOM

5200H - SETCOM Command Entry, Exit and Error Paths

The SETCOM command changes or displays the parameters of the resident RS-232 serial driver. Its entry saves the caller stack pointer, calls the worker at 522DH, and returns to the RST 28H dispatcher with a completion code in Register Pair HL (0000H success, 0FFFFH error), aborting to @ABORT at 4030H on an error while running under DO/JCL. The two error tails display a parameter-error message through @ERROR or the "RS232/DVR not installed" message through @LOGOT.

5200
LD (520BH),SP ED 73 0B 52
Self-Modifying Code
Save the caller's stack pointer into 520BH, the operand of the LD SP,nnnn at 520AH, so the original stack can be restored when the command finishes.
5204
GOSUB to 522DH, the routine that locates the resident RS-232 driver, parses the command line, applies any changed parameters and reprograms the driver (or displays the current settings). Control reaches the exit tail below with a completion code in Register Pair HL.
5207
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H, the success completion code, reached when the driver's activation routine returns here.
520A
LD SP,0000H 31 00 00
Self-Modifying Code
Restore the caller's stack pointer from the operand at 520BH (written at entry by 5200H). Register Pair HL holds the completion code (0000H success, 0FFFFH error).
520D
LD A,H 7C
Copy the high byte of the completion code (Register H) into Register A to test whether Register Pair HL is zero.
520E
OR L B5
OR the low byte of the completion code (Register L) into Register A. The Z FLAG is set only when the completion code in Register Pair HL is 0000H (success).
520F
RET Z C8
If the Z FLAG is set (success), RETurn to the resident RST 28H dispatcher.
5210
LD A,(430FH) 3A 0F 43
Fetch the resident system flag SFLAG$ from 430FH into Register A; bit 5 is set when execution is not at the LDOS command level (running under DO/JCL).
5213
BIT 5,A CB 6F
Test bit 5 of SFLAG$ (Register A) to see whether the command is running under DO/JCL.
5215
RET Z C8
If the Z FLAG is set (SFLAG$ bit 5 clear, at command level), RETurn to the dispatcher with the error code in Register Pair HL.
5216
Not at command level, so JUMP to the resident @ABORT vector (4030H) to abort the running DO/JCL job on the error.
5219
LD A,2CH 3E 2C
Parameter Error Path
Load Register A with 2CH (44 decimal), the LDOS parameter-error code. This entry is reached by the applier's error returns (through the address pushed at 5394H) and from a bad @PARAM keyword at 524EH.
521B
OR 0C0H F6 C0
OR 0C0H into Register A, setting bit 7 (return to caller) and bit 6 (message-only) on the parameter-error code.
521D
GOSUB to the resident SYS0 service @ERROR (4409H) to display the parameter-error message for the code in Register A.
5220
LD HL,0FFFFH 21 FF FF
Load Register Pair HL with 0FFFFH, the error completion code.
5223
JUMP back to 520AH to restore the stack pointer and return the error code in Register Pair HL.
5225
LD HL,5504H 21 04 55
Driver Not Installed Path
Point Register Pair HL at 5504H, the "RS232/DVR not installed" message, reached from 5238H when no resident RS-232 driver is found.
5228
GOSUB to the resident SYS0 service @LOGOT (447BH) to display the carriage-return-terminated message addressed by Register Pair HL (5504H).
522B
JUMP to 5220H to load the error completion code and return through the exit tail.

522DH - Locate the RS-232 Driver, Parse and Dispatch

The worker asks the resident dispatcher (RST 28H code 0BCH) to locate the "$CL" RS-232 driver control block, addressed through Register IX. With no parenthesized parameters it displays the current settings; otherwise it parses the options with @PARAM, optionally resets the block to defaults, applies every parsed value at 5394H, then jumps to the driver's own activation routine (address at IX+04/+05) to reprogram the UART.

522D
PUSH HL E5
Locate the Driver, Parse and Dispatch
Save the command-line pointer (Register Pair HL, positioned by the dispatcher just past the command name) on the stack while the RS-232 driver is located.
522E
LD DE,5500H 11 00 55
Point Register Pair DE at 5500H, the module-name string "$CL" (03H-terminated), the name under which the resident RS-232 driver installs its control block.
5231
GOSUB to 54FDH, which issues RST 28H request 0BCH to locate the "$CL" driver control block. On return Register Pair DE holds the control-block address and the NZ FLAG is set if the driver is not resident.
5234
PUSH DE D5
Save the returned control-block address (Register Pair DE) on the stack to transfer it into Register IX.
5235
POP IX DD E1
Pull the control-block address into Register IX, so the RS-232 driver control block is addressed as IX+00 through IX+05 throughout the overlay.
5237
POP HL E1
Pull the saved command-line pointer back into Register Pair HL.
5238
If the NZ FLAG is set (the RS-232 driver is not resident), JUMP to 5225H to report "RS232/DVR not installed".
523A
DEC HL 2B
DECrement Register Pair HL so the following INC re-reads the same first character; this pairs with the blank-skip loop.
523B
INC HL 23
Loop Start
Advance Register Pair HL to the next command-line character.
523C
LD A,(HL) 7E
Fetch the current command-line character (addressed by Register Pair HL) into Register A.
523D
CP 20H FE 20
Compare Register A against 20H (ASCII space).
523F
If the Z FLAG is set (the character is a space), LOOP BACK to 523BH to skip it.
5241
CP 28H FE 28
Compare Register A (the first non-blank character) against 28H (ASCII left parenthesis), which introduces a parameter list.
5243
LD BC,54E1H 01 E1 54
Load Register Pair BC with 54E1H, the address of the "display current settings" trampoline, as a return address for the no-parameter case.
5246
PUSH BC C5
Push the display-trampoline address (Register Pair BC) so a following RET can branch to it.
5247
RET NZ C0
If the NZ FLAG is set (no opening parenthesis, so no parameters were supplied), RETurn to 54E1H to display the current settings.
5248
LD DE,55FCH 11 FC 55
Point Register Pair DE at 55FCH, the base of the @PARAM keyword descriptor table (BAUD, WORD, STOP, PARITY, EVEN, ODD, BREAK, DTR, RTS, RI, CD, DSR, CTS, DEFAULT and abbreviations).
524B
GOSUB to the resident SYS0 service @PARAM (4476H) to match the parenthesized options on the command line (Register Pair HL) against the keyword table at Register Pair DE. Each recognized option stores its value into the operand cell named by the table entry. Returns the NZ FLAG on a bad or unknown keyword.
524E
If the NZ FLAG is set (a bad or unknown parameter), JUMP to 5219H to report parameter error 2CH.
5251
LD DE,0000H 11 00 00
Self-Modifying Code
Load Register Pair DE with the DEFAULT-option flag; the operand at 5252H is set non-zero by the DEFAULT/D keyword through @PARAM, defaulting to 0000H (DEFAULT not requested).
5254
LD A,D 7A
Copy the high byte of the DEFAULT flag (Register D) into Register A to test whether DEFAULT was given.
5255
OR E B3
OR the low byte of the DEFAULT flag (Register E) into Register A. The Z FLAG is set only when the flag is zero.
5256
If the NZ FLAG is set (DEFAULT requested), GOSUB to 5383H to reset the control block to its factory defaults before other options are applied.
5259
GOSUB to 5394H to apply every parsed parameter to the driver control block (IX+00 through IX+03).
525C
LD L,(IX+04H) DD 6E 04
Fetch the low byte of the driver's activation-routine address from control-block offset 4 (IX+04H) into Register L.
525F
LD H,(IX+05H) DD 66 05
Fetch the high byte of the activation-routine address from control-block offset 5 (IX+05H) into Register H, so Register Pair HL points at the driver routine that reloads the UART from the control block.
5262
JP (HL) E9
JUMP to the driver's activation routine (Register Pair HL) to reprogram the RS-232 hardware from the edited control block; that routine returns to 5207H, the success path.

5263H - Status Display Field Routines

One small routine per displayed field. The status-display driver at 5364H calls them in the order given by the address list at 553CH, interleaving the ", " separator (535EH) between fields. Baud is shown as a decimal number from the baud table; word length, stop bits and parity are decoded from the configuration byte IX+01H; the break character is shown in hexadecimal; and the modem-control signals are read from the two-bit fields of IX+00H as IGNORE, ON or OFF.

5263
LD HL,556CH 21 6C 55
Status Display Field Routines
Point Register Pair HL at 556CH, the "RS232: " heading string, then display it. This routine and those below are invoked in turn by the display driver at 5364H.
5266
GOSUB to the resident SYS0 service @DSPLY (4467H) to display the "RS232: " heading at Register Pair HL.
5269
LD (HL),0AH 36 0A
Store 0AH into the byte @DSPLY left Register Pair HL pointing at (the heading's 03H terminator), converting it to a line feed.
526B
RET C9
RETurn to the display driver.
526C
LD HL,5575H 21 75 55
Baud Field
Point Register Pair HL at 5575H, the "Baud=" label, and display it.
526F
GOSUB to @DSPLY (4467H) to display the "Baud=" label at Register Pair HL.
5272
LD A,(IX+02H) DD 7E 02
Fetch the baud-rate byte from control-block offset 2 (IX+02H) into Register A.
5275
AND 0FH E6 0F
Mask Register A to its low nibble (AND 0FH), the baud-rate table index (0 to 15).
5277
ADD A,A 87
Add Register A to itself (multiply by two), since each baud-table entry is a two-byte value.
5278
LD HL,551CH 21 1C 55
Point Register Pair HL at 551CH, the base of the sixteen-entry baud-rate value table.
527B
ADD A,L 85
Add the doubled index (Register A) to the table-base low byte (Register L).
527C
LD L,A 6F
Move the sum (Register A) into Register L, forming the low byte of the table-entry address.
527D
If the NO CARRY FLAG is set (no carry out of the low byte), JUMP to 5280H.
527F
INC H 24
A carry occurred, so INCrement Register H to complete the sixteen-bit table-entry address in Register Pair HL.
5280
LD A,(HL) 7E
Fetch the low byte of the baud-rate value (addressed by Register Pair HL) into Register A.
5281
INC HL 23
Advance Register Pair HL to the high byte of the baud-rate value.
5282
LD H,(HL) 66
Fetch the high byte of the baud-rate value (addressed by Register Pair HL) into Register H.
5283
LD L,A 6F
Move the low byte (Register A) into Register L, so Register Pair HL now holds the decimal baud rate (for example 300 or 9600).
5284
LD DE,55ECH 11 EC 55
Point Register Pair DE at 55ECH, the five-byte scratch buffer for the decimal conversion.
5287
GOSUB to 54E4H to convert the baud rate in Register Pair HL to a right-justified, space-padded five-digit decimal string at Register Pair DE.
528A
LD A,03H 3E 03
Load Register A with 03H, the @DSPLY string terminator.
528C
LD (DE),A 12
Store the terminator (Register A) after the converted digits (addressed by Register Pair DE).
528D
LD HL,55ECH 21 EC 55
Point Register Pair HL at 55ECH, the start of the converted baud string.
5290
LD A,20H 3E 20
Loop Start
Load Register A with 20H (ASCII space) to skip the leading blanks of the right-justified number.
5292
CP (HL) BE
Compare the space (Register A) against the current digit (addressed by Register Pair HL).
5293
INC HL 23
Advance Register Pair HL to the next character.
5294
If the Z FLAG is set (the character was a leading space), LOOP BACK to 5292H to keep skipping.
5296
DEC HL 2B
DECrement Register Pair HL to point at the first significant digit of the baud value.
5297
JUMP to @DSPLY (4467H) to display the baud digits at Register Pair HL; @DSPLY returns to the display driver.
529A
LD HL,557BH 21 7B 55
Word Field
Point Register Pair HL at 557BH, the "Word=" label, and display it.
529D
GOSUB to @DSPLY (4467H) to display the "Word=" label.
52A0
LD A,(IX+01H) DD 7E 01
Fetch the configuration byte from control-block offset 1 (IX+01H) into Register A.
52A3
RLCA 07
Rotate Register A left circularly to bring the word-length bits (bits 5 and 6) toward the low end.
52A4
RLCA 07
Rotate Register A left circularly again.
52A5
RLCA 07
Rotate Register A left circularly a third time, so the two word-length bits now sit in bits 0 and 1.
52A6
AND 03H E6 03
Mask Register A to those two bits (AND 03H), giving the word-length code 0 to 3.
52A8
If the parity of the two-bit code is even (codes 00 or 11), JUMP to 52ADH, leaving the code unchanged.
52AB
XOR 03H EE 03
The code has odd parity (01 or 10), so XOR it with 03H to map it to the correct word-length ordering.
52AD
ADD A,35H C6 35
Add 35H (ASCII "5") to the decoded code (Register A), yielding the character "5", "6", "7" or "8".
52AF
JUMP to the ROM character-output routine @DSP (0033H) to print the word-length digit in Register A; @DSP returns to the display driver.
52B2
LD HL,5581H 21 81 55
Stop Field
Point Register Pair HL at 5581H, the "Stop=" label, and display it.
52B5
GOSUB to @DSPLY (4467H) to display the "Stop=" label.
52B8
LD A,31H 3E 31
Load Register A with 31H (ASCII "1"), assuming one stop bit.
52BA
BIT 4,(IX+01H) DD CB 01 66
Test bit 4 of the configuration byte IX+01H, the stop-bit selector.
52BE
If the Z FLAG is set (bit 4 clear, one stop bit), JUMP to 52C1H to print "1".
52C0
INC A 3C
Bit 4 was set (two stop bits), so INCrement Register A to 32H (ASCII "2").
52C1
JUMP to the ROM character-output routine @DSP (0033H) to print the stop-bit digit in Register A; @DSP returns to the display driver.
52C4
LD HL,5587H 21 87 55
Parity Field
Point Register Pair HL at 5587H, the "Parity=" label, and display it.
52C7
GOSUB to @DSPLY (4467H) to display the "Parity=" label.
52CA
LD HL,55D8H 21 D8 55
Point Register Pair HL at 55D8H, the "OFF" string.
52CD
BIT 3,(IX+01H) DD CB 01 5E
Test bit 3 of the configuration byte IX+01H, the parity-disable bit.
52D1
If the NZ FLAG is set (bit 3 set, parity disabled), JUMP to @DSPLY (4467H) to display "OFF"; @DSPLY returns to the display driver.
52D4
LD HL,55DCH 21 DC 55
Parity is enabled, so point Register Pair HL at 55DCH, the "ODD" string.
52D7
BIT 7,(IX+01H) DD CB 01 7E
Test bit 7 of the configuration byte IX+01H, the even/odd selector.
52DB
If the Z FLAG is set (bit 7 clear, odd parity), JUMP to 52E0H to display "ODD".
52DD
LD HL,55E0H 21 E0 55
Bit 7 was set (even parity), so point Register Pair HL at 55E0H, the "EVEN" string.
52E0
JUMP to @DSPLY (4467H) to display the parity string ("ODD" or "EVEN") at Register Pair HL; @DSPLY returns to the display driver.
52E3
LD HL,558FH 21 8F 55
Break Field
Point Register Pair HL at 558FH, the "Break=" label, and display it.
52E6
GOSUB to @DSPLY (4467H) to display the "Break=" label.
52E9
LD A,(IX+03H) DD 7E 03
Fetch the logical-break character from control-block offset 3 (IX+03H) into Register A.
52EC
LD HL,55F4H 21 F4 55
Point Register Pair HL at 55F4H, the two-digit hex field inside the "X'00'" template.
52EF
GOSUB to the resident SYS0 number formatter (4D7BH) to write the break character in Register A as two hexadecimal digits at Register Pair HL.
52F2
LD HL,55F2H 21 F2 55
Point Register Pair HL at 55F2H, the start of the "X'nn'" break-character display.
52F5
JUMP to @DSPLY (4467H) to display the break character as X'nn' at Register Pair HL; @DSPLY returns to the display driver.
52F8
LD HL,5596H 21 96 55
Output Control Heading
Point Register Pair HL at 5596H, the newline plus "Output control: " heading.
52FB
JUMP to @DSPLY (4467H) to display the "Output control:" heading at Register Pair HL; @DSPLY returns to the display driver.
52FE
LD HL,55A8H 21 A8 55
DTR Field
Point Register Pair HL at 55A8H, the "DTR=" label.
5301
GOSUB to @DSPLY (4467H) to display the "DTR=" label.
5304
BIT 1,(IX+01H) DD CB 01 4E
Test bit 1 of the configuration byte IX+01H, the DTR state.
5308
JUMP to the shared ON/OFF display at 5314H.
530A
LD HL,55ADH 21 AD 55
RTS Field
Point Register Pair HL at 55ADH, the "RTS=" label.
530D
GOSUB to @DSPLY (4467H) to display the "RTS=" label.
5310
BIT 0,(IX+01H) DD CB 01 46
Test bit 0 of the configuration byte IX+01H, the RTS state, then fall into the shared display below.
5314
LD HL,55D5H 21 D5 55
Point Register Pair HL at 55D5H, the "ON" string (the shared handler for DTR and RTS).
5317
If the Z FLAG is set (the tested control bit is clear, meaning the signal is asserted), JUMP to 531CH to display "ON".
5319
LD HL,55D8H 21 D8 55
The tested bit was set, so point Register Pair HL at 55D8H, the "OFF" string.
531C
JUMP to @DSPLY (4467H) to display the ON/OFF string at Register Pair HL; @DSPLY returns to the display driver.
531F
LD HL,55B2H 21 B2 55
Input Control Heading
Point Register Pair HL at 55B2H, the newline plus "Input control: " heading.
5322
JUMP to @DSPLY (4467H) to display the "Input control:" heading at Register Pair HL; @DSPLY returns to the display driver.
5325
LD HL,55C3H 21 C3 55
RI Field
Point Register Pair HL at 55C3H, the "RI=" label.
5328
LD A,11H 3E 11
Load Register A with 11H, the two-bit field mask for the Ring Indicator signal in IX+00H (bits 0 and 4).
532A
JUMP to the shared input-signal display at 533FH.
532C
LD HL,55C7H 21 C7 55
DSR Field
Point Register Pair HL at 55C7H, the "DSR=" label.
532F
LD A,44H 3E 44
Load Register A with 44H, the two-bit field mask for the Data Set Ready signal in IX+00H (bits 2 and 6).
5331
JUMP to the shared input-signal display at 533FH.
5333
LD HL,55CCH 21 CC 55
CD Field
Point Register Pair HL at 55CCH, the "CD=" label.
5336
LD A,22H 3E 22
Load Register A with 22H, the two-bit field mask for the Carrier Detect signal in IX+00H (bits 1 and 5).
5338
JUMP to the shared input-signal display at 533FH.
533A
LD HL,55D0H 21 D0 55
CTS Field
Point Register Pair HL at 55D0H, the "CTS=" label.
533D
LD A,88H 3E 88
Load Register A with 88H, the two-bit field mask for the Clear To Send signal in IX+00H (bits 3 and 7), then fall into the shared display.
533F
PUSH AF F5
Shared Input-Signal Display
Save the signal mask (Register AF) on the stack across the label display.
5340
GOSUB to @DSPLY (4467H) to display the signal label (for example "RI=") at Register Pair HL.
5343
POP AF F1
Restore the signal mask into Register A.
5344
AND (IX+00H) DD A6 00
AND the mask with the modem-control byte IX+00H, isolating this signal's two status bits.
5347
LD HL,55E5H 21 E5 55
Point Register Pair HL at 55E5H, the "IGNORE" string, the default when both bits are clear.
534A
If the Z FLAG is set (both bits clear), JUMP to 5355H to display "IGNORE".
534C
LD HL,55D5H 21 D5 55
Point Register Pair HL at 55D5H, the "ON" string.
534F
If the parity is odd (exactly one of the two bits is set), JUMP to 5355H to display "ON".
5352
LD HL,55D8H 21 D8 55
Both bits were set, so point Register Pair HL at 55D8H, the "OFF" string.
5355
JUMP to @DSPLY (4467H) to display the signal state ("IGNORE", "ON" or "OFF") at Register Pair HL; @DSPLY returns to the display driver.
5358
LD HL,55F8H 21 F8 55
Line Terminator
Point Register Pair HL at 55F8H, the carriage-return string.
535B
JUMP to @DSPLY (4467H) to send the carriage return at Register Pair HL, ending the display line; @DSPLY returns to the display driver.
535E
LD HL,55F9H 21 F9 55
Field Separator
Point Register Pair HL at 55F9H, the ", " separator string, and JUMP to @DSPLY (4467H) to display it between fields; @DSPLY returns to the display driver.
5361
This entry point (the tail of the separator routine) is unused; it re-displays the string at 55F9H via @DSPLY.

5364H - Status Display Driver

Walks the two-byte address list at 553CH, calling each field routine in turn through a small trampoline that returns to 537AH to advance to the next entry, and stops at the 0000H end marker. It returns to the success path so the command finishes cleanly.

5364
PUSH IY FD E5
Status Display Driver
Save Register IY (the driver control-block work register is Register IX, so IY is free) on the stack.
5366
LD IY,553CH FD 21 3C 55
Point Register IY at 553CH, the ordered list of two-byte field-routine addresses that make up the status display.
536A
LD L,(IY+00H) FD 6E 00
Loop Start
Fetch the low byte of the next field-routine address (IY+00H) into Register L.
536D
LD H,(IY+01H) FD 66 01
Fetch the high byte of the next field-routine address (IY+01H) into Register H, forming the routine address in Register Pair HL.
5370
LD A,H 7C
Copy the high byte (Register H) into Register A to test for the end-of-list marker.
5371
OR L B5
OR the low byte (Register L) into Register A. The Z FLAG is set when the address is 0000H, ending the list.
5372
If the Z FLAG is set (end of list), JUMP to 5380H to finish.
5374
PUSH HL E5
Save the field-routine address (Register Pair HL) on the stack.
5375
LD HL,537AH 21 7A 53
Point Register Pair HL at 537AH, the return address that advances to the next list entry.
5378
EX (SP),HL E3
Exchange the top of stack with Register Pair HL, so the field-routine address is on top and Register Pair HL holds 537AH.
5379
JP (HL) E9
JUMP to the field routine (whose address is now on top of the stack); when it RETurns it lands at 537AH.
537A
INC IY FD 23
Advance Register IY past the low byte of the just-called list entry.
537C
INC IY FD 23
Advance Register IY past the high byte, so Register IY points at the next list entry.
537E
LOOP BACK to 536AH to call the next field routine.
5380
POP IY FD E1
Restore Register IY from the stack.
5382
RET C9
RETurn (to 5207H via the display trampoline, giving the success completion code).

5383H - Reset the Control Block to Defaults

The DEFAULT option handler. It writes the factory-default four-byte control block 00H A5H 55H 00H: all input signals IGNORE, RTS off, DTR on, seven-bit word, one stop bit, even parity enabled, 300 baud and no break character.

5383
LD (IX+00H),00H DD 36 00 00
Reset the Control Block to Defaults
Store 00H into control-block offset 0 (IX+00H), clearing every modem-control field so all input signals default to IGNORE.
5387
LD (IX+01H),0A5H DD 36 01 A5
Store 0A5H into control-block offset 1 (IX+01H), the default configuration: RTS off, DTR on, seven-bit word, one stop bit, even parity enabled.
538B
LD (IX+02H),55H DD 36 02 55
Store 55H into control-block offset 2 (IX+02H), the default baud-rate index selecting 300 baud.
538F
LD (IX+03H),00H DD 36 03 00
Store 00H into control-block offset 3 (IX+03H), clearing the logical-break character.
5393
RET C9
RETurn to the dispatcher at 5259H.

5394H - Apply the Parsed Parameters to the Control Block

Applies each parsed option to the driver control block. It pushes the parameter-error handler (5219H) as a return address so any out-of-range value returns straight to the error path. Baud is validated against the baud table; word length (5-8), stop bits (1-2) and parity (ODD/EVEN/OFF) are merged bit by bit into the configuration byte; the break character and the DTR/RTS bits are set; and the four input-control signals are set through the shared helper at 5498H. Two small helpers merge a bit field (54B3H) and fold a character to upper case (54BCH), and the baud lookup lives at 54C5H.

5394
LD HL,5219H 21 19 52
Apply the Parsed Parameters
Point Register Pair HL at 5219H, the parameter-error handler.
5397
PUSH HL E5
Push the error-handler address (Register Pair HL) so that any RET NZ below on an out-of-range value branches straight to the parameter-error path.
5398
LD DE,0000H 11 00 00
Self-Modifying Code
Load Register Pair DE with the BAUD option value; the operand at 5399H is written by the BAUD/B keyword through @PARAM, defaulting to 0000H (not specified).
539B
LD A,D 7A
Copy the high byte of the BAUD value (Register D) into Register A.
539C
OR E B3
OR the low byte (Register E) into Register A. The Z FLAG is set when BAUD was not specified.
539D
If the Z FLAG is set (BAUD not given), JUMP to 53A6H to leave the baud rate unchanged.
539F
GOSUB to 54C5H to look the requested baud value (Register Pair DE) up in the baud-rate table; it returns the encoded index in Register A, or the NZ FLAG if the value is not a supported rate.
53A2
RET NZ C0
If the NZ FLAG is set (unsupported baud rate), RETurn to the pushed parameter-error handler at 5219H.
53A3
LD (IX+02H),A DD 77 02
Store the baud-rate index (Register A) into control-block offset 2 (IX+02H).
53A6
LD C,(IX+01H) DD 4E 01
Fetch the current configuration byte from control-block offset 1 (IX+01H) into Register C, to be edited field by field.
53A9
LD DE,0000H 11 00 00
Self-Modifying Code
Load Register Pair DE with the WORD option value; the operand at 53AAH is written by the WORD/W keyword, defaulting to 0000H (not specified).
53AC
LD A,D 7A
Copy the high byte of the WORD value (Register D) into Register A.
53AD
OR E B3
OR the low byte (Register E) into Register A. The Z FLAG is set when WORD was not specified.
53AE
If the Z FLAG is set (WORD not given), JUMP to 53C8H to leave the word length unchanged.
53B0
INC D 14
INCrement Register D.
53B1
DEC D 15
DECrement Register D to test it: the flags reflect whether the WORD value exceeds 255.
53B2
RET NZ C0
If the NZ FLAG is set (WORD value above 255), RETurn to the parameter-error handler at 5219H.
53B3
LD A,E 7B
Copy the WORD value low byte (Register E) into Register A.
53B4
SUB 05H D6 05
SUBtract 05H from Register A, so a legal word length of 5 to 8 becomes 0 to 3.
53B6
RET C D8
If the CARRY FLAG is set (word length below 5), RETurn to the parameter-error handler at 5219H.
53B7
CP 04H FE 04
Compare Register A against 04H (word length 9 relative to the base of 5).
53B9
RET NC D0
If the NO CARRY FLAG is set (word length 9 or more), RETurn to the parameter-error handler at 5219H.
53BA
OR A B7
Test Register A (the 0-to-3 word-length code) to set the parity flag for the mapping below.
53BB
If the parity of the code is even, JUMP to 53C0H, leaving the code unchanged.
53BE
XOR 03H EE 03
The code has odd parity, so XOR it with 03H to match the UART's word-length bit ordering.
53C0
RRCA 0F
Rotate Register A right circularly to position the word-length bits.
53C1
RRCA 0F
Rotate Register A right circularly again.
53C2
RRCA 0F
Rotate Register A right circularly a third time, so the word-length bits align with bits 5 and 6.
53C3
LD B,60H 06 60
Load Register B with 60H, the bit mask for the word-length field (bits 5 and 6).
53C5
GOSUB to 54B3H to merge the word-length bits (Register A, masked by Register B) into the configuration byte held in Register C.
53C8
LD DE,0000H 11 00 00
Self-Modifying Code
Load Register Pair DE with the STOP option value; the operand at 53C9H is written by the STOP/S keyword, defaulting to 0000H (not specified).
53CB
LD A,E 7B
Copy the low byte of the STOP value (Register E) into Register A.
53CC
OR D B2
OR the high byte (Register D) into Register A. The Z FLAG is set when STOP was not specified.
53CD
If the Z FLAG is set (STOP not given), JUMP to 53E2H to leave the stop bits unchanged.
53CF
INC D 14
INCrement Register D.
53D0
DEC D 15
DECrement Register D to test whether the STOP value exceeds 255.
53D1
RET NZ C0
If the NZ FLAG is set (STOP value above 255), RETurn to the parameter-error handler at 5219H.
53D2
LD A,E 7B
Copy the STOP value low byte (Register E) into Register A.
53D3
OR A B7
Test Register A.
53D4
RET Z C8
If the Z FLAG is set (STOP of zero), RETurn to the parameter-error handler at 5219H.
53D5
CP 03H FE 03
Compare Register A against 03H.
53D7
RET NC D0
If the NO CARRY FLAG is set (STOP of 3 or more, only 1 and 2 are valid), RETurn to the parameter-error handler at 5219H.
53D8
DEC A 3D
DECrement Register A, mapping stop bits 1 to 0 and 2 to 1.
53D9
RLCA 07
Rotate Register A left circularly to position the stop-bit selector.
53DA
RLCA 07
Rotate Register A left circularly again.
53DB
RLCA 07
Rotate Register A left circularly a third time.
53DC
RLCA 07
Rotate Register A left circularly a fourth time, aligning the stop-bit value with bit 4.
53DD
LD B,10H 06 10
Load Register B with 10H, the bit mask for the stop-bit field (bit 4).
53DF
GOSUB to 54B3H to merge the stop-bit selector (Register A, masked by Register B) into the configuration byte in Register C.
53E2
LD DE,0001H 11 01 00
Self-Modifying Code
Load Register Pair DE with the PARITY option value; the operand at 53E3H is written by the PARITY/P keyword, defaulting to 0001H (not specified).
53E5
LD A,E 7B
Copy the low byte of the PARITY value (Register E) into Register A.
53E6
DEC A 3D
DECrement Register A.
53E7
OR D B2
OR the high byte (Register D) into Register A. The Z FLAG is set when the value is the 0001H default (PARITY not given).
53E8
If the Z FLAG is set (PARITY keyword not used), JUMP to 5410H to check for the separate ODD keyword.
53EA
LD A,D 7A
Copy the high byte (Register D) into Register A.
53EB
OR E B3
OR the low byte (Register E) into Register A. The Z FLAG is set when the value is 0000H (PARITY used as a bare OFF switch).
53EC
If the Z FLAG is set (PARITY given without a value), JUMP to 5408H to turn parity off.
53EE
LD A,D 7A
Copy the high byte (Register D) into Register A.
53EF
AND E A3
AND it with the low byte (Register E).
53F0
INC A 3C
INCrement Register A. The Z FLAG is set when the value was 0FFFFH (PARITY used as a bare ON switch).
53F1
If the Z FLAG is set (PARITY given as a bare switch), JUMP to 5408H to enable parity.
53F3
LD A,(DE) 1A
PARITY was given a text value; fetch the first character of that value (addressed by Register Pair DE) into Register A.
53F4
GOSUB to 54BCH to fold the character in Register A to upper case.
53F7
CP 4FH FE 4F
Compare Register A against 4FH (ASCII "O", for ODD).
53F9
If the Z FLAG is set (the value is "ODD"), JUMP to 5402H to select odd parity.
53FB
CP 45H FE 45
Compare Register A against 45H (ASCII "E", for EVEN).
53FD
RET NZ C0
If the NZ FLAG is set (the value is neither ODD nor EVEN), RETurn to the parameter-error handler at 5219H.
53FE
SET 7,C CB F9
The value is "EVEN", so SET bit 7 of the configuration byte in Register C (even parity).
5400
JUMP to 5404H to enable parity.
5402
RES 7,C CB B9
The value is "ODD", so RESet bit 7 of the configuration byte in Register C (odd parity).
5404
RES 3,C CB 99
RESet bit 3 of the configuration byte in Register C, enabling parity generation and checking.
5406
JUMP to 5430H to continue with the BREAK option.
5408
LD A,D 7A
Parity Switch Path
Copy the high byte of the PARITY value (Register D) into Register A.
5409
OR E B3
OR the low byte (Register E) into Register A. The Z FLAG is set when the value was 0000H (OFF).
540A
SET 3,C CB D9
SET bit 3 of the configuration byte in Register C, disabling parity.
540C
If the Z FLAG is set (PARITY OFF), JUMP to 5430H, leaving parity disabled.
540E
RES 3,C CB 99
The switch was ON (0FFFFH), so RESet bit 3 of the configuration byte in Register C, enabling parity.
5410
LD DE,0001H 11 01 00
Self-Modifying Code
Load Register Pair DE with the ODD option value; the operand at 5411H is written by the ODD/O keyword, defaulting to 0001H (not specified).
5413
LD A,E 7B
Copy the low byte (Register E) into Register A.
5414
DEC A 3D
DECrement Register A.
5415
OR D B2
OR the high byte (Register D) into Register A. The Z FLAG is set when the value is the 0001H default (ODD not given).
5416
If the Z FLAG is set (ODD not given), JUMP to 5420H to check for EVEN.
5418
LD A,D 7A
Copy the high byte (Register D) into Register A.
5419
OR E B3
OR the low byte (Register E) into Register A to test the switch value.
541A
SET 7,C CB F9
SET bit 7 of the configuration byte in Register C (odd parity is coded by bit 7 clear, so this presets it before the conditional clear below).
541C
If the Z FLAG is set (ODD value 0000H), JUMP to 5420H.
541E
RES 7,C CB B9
RESet bit 7 of the configuration byte in Register C, selecting odd parity.
5420
LD DE,0001H 11 01 00
Self-Modifying Code
Load Register Pair DE with the EVEN option value; the operand at 5421H is written by the EVEN/E keyword, defaulting to 0001H (not specified).
5423
LD A,E 7B
Copy the low byte (Register E) into Register A.
5424
DEC A 3D
DECrement Register A.
5425
OR D B2
OR the high byte (Register D) into Register A. The Z FLAG is set when the value is the 0001H default (EVEN not given).
5426
If the Z FLAG is set (EVEN not given), JUMP to 5430H to continue with BREAK.
5428
LD A,D 7A
Copy the high byte (Register D) into Register A.
5429
OR E B3
OR the low byte (Register E) into Register A to test the switch value.
542A
RES 7,C CB B9
RESet bit 7 of the configuration byte in Register C, selecting even parity.
542C
If the Z FLAG is set (EVEN value 0000H), JUMP to 5430H.
542E
SET 7,C CB F9
SET bit 7 of the configuration byte in Register C.
5430
LD DE,0100H 11 00 01
Self-Modifying Code
Load Register Pair DE with the BREAK option value; the operand at 5431H is written by the BREAK keyword, defaulting to 0100H (not specified).
5433
LD A,D 7A
Copy the high byte (Register D) into Register A.
5434
DEC A 3D
DECrement Register A.
5435
OR E B3
OR the low byte (Register E) into Register A. The Z FLAG is set when the value is the 0100H default (BREAK not given).
5436
If the Z FLAG is set (BREAK not given), JUMP to 5451H to leave the break character unchanged.
5438
LD A,D 7A
Copy the high byte (Register D) into Register A.
5439
OR E B3
OR the low byte (Register E) into Register A. The Z FLAG is set when the value is 0000H (BREAK used as a bare OFF switch).
543A
If the Z FLAG is set, JUMP to 5446H to select the switch break character.
543C
LD A,D 7A
Copy the high byte (Register D) into Register A.
543D
AND E A3
AND it with the low byte (Register E).
543E
INC A 3C
INCrement Register A. The Z FLAG is set when the value is 0FFFFH (BREAK used as a bare ON switch).
543F
If the Z FLAG is set, JUMP to 5446H to select the switch break character.
5441
INC D 14
INCrement Register D.
5442
DEC D 15
DECrement Register D to test whether the BREAK value exceeds 255.
5443
RET NZ C0
If the NZ FLAG is set (BREAK value above 255), RETurn to the parameter-error handler at 5219H.
5444
JUMP to 544EH to store the requested break character (Register E).
5446
LD A,D 7A
Break Switch Path
Copy the high byte (Register D) into Register A.
5447
OR E B3
OR the low byte (Register E) into Register A. The Z FLAG is set when the switch value was 0000H (OFF).
5448
LD E,01H 1E 01
Load Register E with 01H, the break character for the OFF form (Control-A).
544A
If the Z FLAG is set (OFF), JUMP to 544EH to store 01H.
544C
LD E,03H 1E 03
Load Register E with 03H, the break character for the ON form (Control-C, the version 6 default).
544E
LD (IX+03H),E DD 73 03
Store the break character (Register E) into control-block offset 3 (IX+03H).
5451
LD DE,0001H 11 01 00
Self-Modifying Code
Load Register Pair DE with the DTR option value; the operand at 5452H is written by the DTR keyword, defaulting to 0001H (not specified).
5454
LD A,E 7B
Copy the low byte (Register E) into Register A.
5455
DEC A 3D
DECrement Register A.
5456
OR D B2
OR the high byte (Register D) into Register A. The Z FLAG is set when the value is the 0001H default (DTR not given).
5457
If the Z FLAG is set (DTR not given), JUMP to 5461H to leave DTR unchanged.
5459
LD A,D 7A
Copy the high byte (Register D) into Register A.
545A
OR E B3
OR the low byte (Register E) into Register A to test the DTR value.
545B
SET 1,C CB C9
SET bit 1 of the configuration byte in Register C (DTR is asserted when bit 1 is clear, so this presets it before the conditional clear).
545D
If the Z FLAG is set (DTR value 0000H, OFF), JUMP to 5461H, leaving bit 1 set.
545F
RES 1,C CB 89
RESet bit 1 of the configuration byte in Register C, asserting DTR (ON).
5461
LD DE,0001H 11 01 00
Self-Modifying Code
Load Register Pair DE with the RTS option value; the operand at 5462H is written by the RTS keyword, defaulting to 0001H (not specified).
5464
LD A,E 7B
Copy the low byte (Register E) into Register A.
5465
DEC A 3D
DECrement Register A.
5466
OR D B2
OR the high byte (Register D) into Register A. The Z FLAG is set when the value is the 0001H default (RTS not given).
5467
If the Z FLAG is set (RTS not given), JUMP to 5471H to leave RTS unchanged.
5469
LD A,D 7A
Copy the high byte (Register D) into Register A.
546A
OR E B3
OR the low byte (Register E) into Register A to test the RTS value.
546B
SET 0,C CB C1
SET bit 0 of the configuration byte in Register C (RTS is asserted when bit 0 is clear, so this presets it before the conditional clear).
546D
If the Z FLAG is set (RTS value 0000H, OFF), JUMP to 5471H, leaving bit 0 set.
546F
RES 0,C CB 81
RESet bit 0 of the configuration byte in Register C, asserting RTS (ON).
5471
SET 2,C CB D1
SET bit 2 of the configuration byte in Register C, a fixed bit the driver always requires set.
5473
LD (IX+01H),C DD 71 01
Store the fully assembled configuration byte (Register C) back into control-block offset 1 (IX+01H).
5476
LD HL,0001H 21 01 00
Self-Modifying Code / RI Signal
Load Register Pair HL with the RI option value; the operand at 5477H is written by the RI keyword, defaulting to 0001H (not specified).
5479
LD C,01H 0E 01
Load Register C with 01H, the low bit of the Ring Indicator two-bit field in IX+00H.
547B
GOSUB to 5498H to set the RI signal to ON, OFF or leave it unchanged according to the value in Register Pair HL.
547E
LD HL,0001H 21 01 00
Self-Modifying Code / DSR Signal
Load Register Pair HL with the DSR option value; the operand at 547FH is written by the DSR keyword, defaulting to 0001H (not specified).
5481
LD C,04H 0E 04
Load Register C with 04H, the low bit of the Data Set Ready two-bit field in IX+00H.
5483
GOSUB to 5498H to apply the DSR signal state from Register Pair HL.
5486
LD HL,0001H 21 01 00
Self-Modifying Code / CD Signal
Load Register Pair HL with the CD option value; the operand at 5487H is written by the CD keyword, defaulting to 0001H (not specified).
5489
LD C,02H 0E 02
Load Register C with 02H, the low bit of the Carrier Detect two-bit field in IX+00H.
548B
GOSUB to 5498H to apply the CD signal state from Register Pair HL.
548E
LD HL,0001H 21 01 00
Self-Modifying Code / CTS Signal
Load Register Pair HL with the CTS option value; the operand at 548FH is written by the CTS keyword, defaulting to 0001H (not specified).
5491
LD C,08H 0E 08
Load Register C with 08H, the low bit of the Clear To Send two-bit field in IX+00H.
5493
GOSUB to 5498H to apply the CTS signal state from Register Pair HL.
5496
POP AF F1
Pull the pushed parameter-error-handler address (5219H) off the stack and discard it, since no error occurred.
5497
RET C9
RETurn to the dispatcher at 525CH.
5498
LD A,L 7D
Apply One Input-Control Signal
Copy the option value low byte (Register L) into Register A.
5499
DEC A 3D
DECrement Register A.
549A
OR H B4
OR the value high byte (Register H) into Register A. The Z FLAG is set when the value is the 0001H default (this signal was not specified).
549B
RET Z C8
If the Z FLAG is set (signal not specified), RETurn, leaving this signal's field unchanged.
549C
LD A,C 79
Copy the signal's low mask bit (Register C) into Register A.
549D
RLCA 07
Rotate Register A left circularly.
549E
RLCA 07
Rotate Register A left circularly again.
549F
RLCA 07
Rotate Register A left circularly a third time.
54A0
RLCA 07
Rotate Register A left circularly a fourth time, moving the low mask bit into the field's high bit position.
54A1
OR C B1
OR the original low mask bit (Register C) into Register A, so Register A now has both bits of this signal's two-bit field set.
54A2
LD B,A 47
Copy the two-bit field mask (Register A) into Register B.
54A3
CPL 2F
Complement Register A to form the inverse mask (all bits except this field).
54A4
AND (IX+00H) DD A6 00
AND the inverse mask with the modem-control byte IX+00H, clearing this signal's two bits while preserving the others.
54A7
LD E,A 5F
Copy the cleared byte (Register A) into Register E to hold it.
54A8
LD A,H 7C
Copy the option value high byte (Register H) into Register A.
54A9
OR L B5
OR the value low byte (Register L) into Register A. The Z FLAG is set when the value is 0000H (OFF).
54AA
LD A,B 78
Load Register A with the full two-bit mask (Register B), the OFF encoding (both bits set).
54AB
If the Z FLAG is set (value 0000H, OFF), JUMP to 54AEH to store the OFF encoding.
54AD
LD A,C 79
The value was non-zero (ON), so load Register A with only the low mask bit (Register C), the ON encoding (one bit set).
54AE
OR E B3
OR the preserved other bits (Register E) into Register A, combining this signal's new state with the rest of the byte.
54AF
LD (IX+00H),A DD 77 00
Store the updated modem-control byte (Register A) into control-block offset 0 (IX+00H).
54B2
RET C9
RETurn to the applier.
54B3
AND B A0
Merge a Bit Field
AND the value bits (Register A) with the field mask (Register B), keeping only the bits inside the field.
54B4
PUSH AF F5
Save the masked value (Register AF) on the stack.
54B5
LD A,B 78
Copy the field mask (Register B) into Register A.
54B6
CPL 2F
Complement Register A to form the inverse field mask.
54B7
AND C A1
AND the inverse mask with the configuration byte (Register C), clearing the field bits while preserving the rest.
54B8
POP BC C1
Pull the masked value back (into Register B; Register C receives the pushed flags and is overwritten next).
54B9
OR B B0
OR the masked value (Register B) into the cleared configuration byte (Register A).
54BA
LD C,A 4F
Copy the merged configuration byte (Register A) into Register C.
54BB
RET C9
RETurn to the applier.
54BC
CP 61H FE 61
Fold to Upper Case
Compare the character (Register A) against 61H (ASCII "a").
54BE
RET C D8
If the CARRY FLAG is set (character below "a"), RETurn unchanged.
54BF
CP 7BH FE 7B
Compare the character (Register A) against 7BH (one past ASCII "z").
54C1
RET NC D0
If the NO CARRY FLAG is set (character above "z"), RETurn unchanged.
54C2
AND 5FH E6 5F
AND the character (Register A) with 5FH, clearing bit 5 to convert the lower-case letter to upper case.
54C4
RET C9
RETurn with the upper-cased character in Register A.
54C5
LD HL,551CH 21 1C 55
Look Up a Baud Rate
Point Register Pair HL at 551CH, the base of the sixteen-entry baud-rate table.
54C8
LD BC,1000H 01 00 10
Load Register Pair BC with 1000H: Register B is 16 (the entry count) and Register C is 0 (the running index).
54CB
LD A,(HL) 7E
Loop Start
Fetch the low byte of the current table entry (addressed by Register Pair HL) into Register A.
54CC
INC HL 23
Advance Register Pair HL to the high byte of the entry.
54CD
CP E BB
Compare the entry low byte (Register A) against the requested value low byte (Register E).
54CE
If the NZ FLAG is set (low bytes differ), JUMP to 54D4H to try the next entry.
54D0
LD A,(HL) 7E
The low bytes match; fetch the entry high byte (addressed by Register Pair HL) into Register A.
54D1
CP D BA
Compare the entry high byte (Register A) against the requested value high byte (Register D).
54D2
If the Z FLAG is set (both bytes match), JUMP to 54D9H, the match found.
54D4
INC HL 23
Advance Register Pair HL to the next table entry.
54D5
INC C 0C
INCrement the running index (Register C).
54D6
DECrement Register B and LOOP BACK to 54CBH until all sixteen entries have been checked.
54D8
RET C9
No entry matched; RETurn with the NZ FLAG set (the last comparison left it set) to signal an unsupported rate.
54D9
LD A,C 79
Match Found
Copy the matching index (Register C) into Register A.
54DA
RLCA 07
Rotate Register A left circularly.
54DB
RLCA 07
Rotate Register A left circularly again.
54DC
RLCA 07
Rotate Register A left circularly a third time.
54DD
RLCA 07
Rotate Register A left circularly a fourth time, moving the index into the high nibble.
54DE
OR C B1
OR the original index (Register C) into Register A, so both nibbles hold the baud index (the form the driver stores at IX+02H).
54DF
CP A BF
Compare Register A with itself to set the Z FLAG, signalling a successful lookup.
54E0
RET C9
RETurn with the encoded baud index in Register A and the Z FLAG set.

54E1H - Display Trampoline, Decimal Formatter and Module Lookup

The trampoline that enters the status display when no parameters are given, the byte-to-five-decimal-digit formatter used for the baud display (via @DIV), and the RST 28H code 0BCH module-lookup trampoline that returns the "$CL" driver control block in Register Pair DE.

54E1
Display Trampoline
JUMP to the status display driver at 5364H; entered (via the RET at 5247H) when no parameter list was supplied.
54E4
LD B,05H 06 05
Convert HL to Five Decimal Digits
Load Register B with 05H, the field width, to space-fill the scratch buffer.
54E6
LD A,20H 3E 20
Load Register A with 20H (ASCII space).
54E8
LD (DE),A 12
Store the space (Register A) into the scratch buffer (addressed by Register Pair DE).
54E9
INC DE 13
Advance Register Pair DE to the next scratch byte.
54EA
DECrement Register B and LOOP BACK to 54E8H until five spaces have been written.
54EC
PUSH DE D5
Save the end-of-buffer pointer (Register Pair DE) on the stack.
54ED
DEC DE 1B
DECrement Register Pair DE to the units digit position.
54EE
LD A,0AH 3E 0A
Loop Start
Load Register A with 0AH (10), the divisor for the next decimal digit.
54F0
GOSUB to the resident SYS0 service @DIV (44C4H) to divide Register Pair HL by 10; the quotient returns in Register Pair HL and the remainder (the next digit) in Register A.
54F3
ADD A,30H C6 30
Add 30H to the remainder (Register A) to form its ASCII digit.
54F5
LD (DE),A 12
Store the ASCII digit (Register A) into the current buffer position (addressed by Register Pair DE).
54F6
DEC DE 1B
DECrement Register Pair DE to the next-higher digit position.
54F7
LD A,H 7C
Copy the quotient high byte (Register H) into Register A.
54F8
OR L B5
OR the quotient low byte (Register L) into Register A. The Z FLAG is set when the quotient has reached zero.
54F9
If the NZ FLAG is set (more digits remain), LOOP BACK to 54EEH.
54FB
POP DE D1
Restore the end-of-buffer pointer into Register Pair DE.
54FC
RET C9
RETurn with the decimal string in the scratch buffer.
54FD
LD A,0BCH 3E BC
Module-Lookup Trampoline
Load Register A with 0BCH, the resident supervisor request that locates a named module control block; Register Pair DE points at the module name.
54FF
RST 28H EF
Execute the supervisor call: the resident dispatcher runs request 0BCH and returns the "$CL" RS-232 driver control block in Register Pair DE, or the NZ FLAG if the driver is not resident. Control returns to 5234H.

5500H - Driver Name, Message, Baud Table and Display List

The "$CL" driver module name, the not-installed message, the sixteen-entry baud-rate value table indexed by IX+02H, and the ordered list of field-routine addresses the display driver walks (terminated by 0000H).

5500-5503
DEFM '$CL' + DEFB 03H 24 43 4C 03
Module-name string used at 522EH for the RST 28H code 0BCH lookup of the resident RS-232 driver.
5504-551B
DEFM 'RS232/DVR not installed' + 0DH 52 53 32 33 32 2F 44 56 52 20 6E 6F 74 20 69 6E 73 74 61 6C 6C 65 64 0D
Displayed via @LOGOT at 5228H when no resident "$CL" driver is found. Terminated by 0DH at 551BH.
551C-551D
DEFW 0032H 32 00
Baud-rate value 50 (index 0).
551E-551F
DEFW 004BH 4B 00
Baud-rate value 75 (index 1).
5520-5521
DEFW 006EH 6E 00
Baud-rate value 110 (index 2).
5522-5523
DEFW 0087H 87 00
Baud-rate value 134.5 (index 3).
5524-5525
DEFW 0096H 96 00
Baud-rate value 150 (index 4).
5526-5527
DEFW 012CH 2C 01
Baud-rate value 300 (index 5).
5528-5529
DEFW 0258H 58 02
Baud-rate value 600 (index 6).
552A-552B
DEFW 04B0H B0 04
Baud-rate value 1200 (index 7).
552C-552D
DEFW 0708H 08 07
Baud-rate value 1800 (index 8).
552E-552F
DEFW 07D0H D0 07
Baud-rate value 2000 (index 9).
5530-5531
DEFW 0960H 60 09
Baud-rate value 2400 (index 10).
5532-5533
DEFW 0E10H 10 0E
Baud-rate value 3600 (index 11).
5534-5535
DEFW 12C0H C0 12
Baud-rate value 4800 (index 12).
5536-5537
DEFW 1C20H 20 1C
Baud-rate value 7200 (index 13).
5538-5539
DEFW 2580H 80 25
Baud-rate value 9600 (index 14).
553A-553B
DEFW 4B00H 00 4B
Baud-rate value 19200 (index 15).
553C-553D
DEFW 5263H 63 52
Field routine 5263H (RS232: header).
553E-553F
DEFW 526CH 6C 52
Field routine 526CH (Baud).
5540-5541
DEFW 535EH 5E 53
Field routine 535EH (separator).
5542-5543
DEFW 529AH 9A 52
Field routine 529AH (Word).
5544-5545
DEFW 535EH 5E 53
Field routine 535EH (separator).
5546-5547
DEFW 52B2H B2 52
Field routine 52B2H (Stop).
5548-5549
DEFW 535EH 5E 53
Field routine 535EH (separator).
554A-554B
DEFW 52C4H C4 52
Field routine 52C4H (Parity).
554C-554D
DEFW 535EH 5E 53
Field routine 535EH (separator).
554E-554F
DEFW 52E3H E3 52
Field routine 52E3H (Break).
5550-5551
DEFW 52F8H F8 52
Field routine 52F8H (Output control heading).
5552-5553
DEFW 52FEH FE 52
Field routine 52FEH (DTR).
5554-5555
DEFW 535EH 5E 53
Field routine 535EH (separator).
5556-5557
DEFW 530AH 0A 53
Field routine 530AH (RTS).
5558-5559
DEFW 531FH 1F 53
Field routine 531FH (Input control heading).
555A-555B
DEFW 5325H 25 53
Field routine 5325H (RI).
555C-555D
DEFW 535EH 5E 53
Field routine 535EH (separator).
555E-555F
DEFW 532CH 2C 53
Field routine 532CH (DSR).
5560-5561
DEFW 535EH 5E 53
Field routine 535EH (separator).
5562-5563
DEFW 5333H 33 53
Field routine 5333H (CD).
5564-5565
DEFW 535EH 5E 53
Field routine 535EH (separator).
5566-5567
DEFW 533AH 3A 53
Field routine 533AH (CTS).
5568-5569
DEFW 5358H 58 53
Field routine 5358H (CR).
556A-556B
DEFW 0000H 00 00
End-of-list marker for the display driver.

556CH - Labels and Value Strings

The field labels (each 03H-terminated for @DSPLY), the ON/OFF/ODD/EVEN/IGNORE value words, the baud-number scratch buffer, the break-character template, the carriage-return string and the ", " separator.

556C-5574
DEFM 'RS232: ' + 03H 00 52 53 32 33 32 3A 20 03
Status-line heading (displayed at 5263H).
5575-557A
DEFM 'Baud=' + 03H 42 61 75 64 3D 03
Baud field label.
557B-5580
DEFM 'Word=' + 03H 57 6F 72 64 3D 03
Word-length field label.
5581-5586
DEFM 'Stop=' + 03H 53 74 6F 70 3D 03
Stop-bit field label.
5587-558E
DEFM 'Parity=' + 03H 50 61 72 69 74 79 3D 03
Parity field label.
558F-5595
DEFM 'Break=' + 03H 42 72 65 61 6B 3D 03
Break-character field label.
5596-55A7
DEFM 0AH + 'Output control: ' + 03H 0A 4F 75 74 70 75 74 20 63 6F 6E 74 72 6F 6C 3A 20 03
Output-control section heading (line feed then text).
55A8-55AC
DEFM 'DTR=' + 03H 44 54 52 3D 03
DTR field label.
55AD-55B1
DEFM 'RTS=' + 03H 52 54 53 3D 03
RTS field label.
55B2-55C2
DEFM 0AH + 'Input control: ' + 03H 0A 49 6E 70 75 74 20 63 6F 6E 74 72 6F 6C 3A 20 03
Input-control section heading (line feed then text).
55C3-55C6
DEFM 'RI=' + 03H 52 49 3D 03
Ring Indicator field label.
55C7-55CB
DEFM 'DSR=' + 03H 44 53 52 3D 03
Data Set Ready field label.
55CC-55CF
DEFM 'CD=' + 03H 43 44 3D 03
Carrier Detect field label.
55D0-55D4
DEFM 'CTS=' + 03H 43 54 53 3D 03
Clear To Send field label.
55D5-55D7
DEFM 'ON' + 03H 4F 4E 03
The "ON" value word.
55D8-55DB
DEFM 'OFF' + 03H 4F 46 46 03
The "OFF" value word.
55DC-55DF
DEFM 'ODD' + 03H 4F 44 44 03
The "ODD" parity word.
55E0-55E4
DEFM 'EVEN' + 03H 45 56 45 4E 03
The "EVEN" parity word.
55E5-55EB
DEFM 'IGNORE' + 03H 49 47 4E 4F 52 45 03
The "IGNORE" value word for input signals.
55EC-55F1
DEFM '00000' + 03H 30 30 30 30 30 03
Five-byte scratch buffer where the baud rate is formatted for display (filled at 5287H).
55F2-55F7
DEFM "X'00'" + 03H 58 27 30 30 27 03
Break-character display template; the two hex digits at 55F4H are filled by the number formatter at 4D7BH.
55F8
DEFB 0DH 0D
Carriage-return string ending each display line (displayed at 5358H).
55F9-55FB
DEFM ', ' + 03H 2C 20 03
Field separator displayed between fields at 535EH.

55FCH - Parameter Keyword Table (@PARAM)

The keyword descriptor table @PARAM scans (loaded into Register Pair DE at 5248H). Each entry is a six-character space-padded keyword followed by the two-byte (low, high) address of the operand cell in the applier that receives the parsed value. A 00H byte terminates the table.

55FC-5603
DEFM 'BREAK ' + DEFW 5431H 42 52 45 41 4B 20 31 54
Value pointer to 5431H. BREAK - the logical-break character.
5604-560B
DEFM 'BAUD ' + DEFW 5399H 42 41 55 44 20 20 99 53
Value pointer to 5399H. BAUD - the serial baud rate.
560C-5613
DEFM 'B ' + DEFW 5399H 42 20 20 20 20 20 99 53
Value pointer to 5399H. Abbreviated BAUD.
5614-561B
DEFM 'WORD ' + DEFW 53AAH 57 4F 52 44 20 20 AA 53
Value pointer to 53AAH. WORD - the data word length (5-8).
561C-5623
DEFM 'W ' + DEFW 53AAH 57 20 20 20 20 20 AA 53
Value pointer to 53AAH. Abbreviated WORD.
5624-562B
DEFM 'STOP ' + DEFW 53C9H 53 54 4F 50 20 20 C9 53
Value pointer to 53C9H. STOP - the number of stop bits (1-2).
562C-5633
DEFM 'S ' + DEFW 53C9H 53 20 20 20 20 20 C9 53
Value pointer to 53C9H. Abbreviated STOP.
5634-563B
DEFM 'PARITY' + DEFW 53E3H 50 41 52 49 54 59 E3 53
Value pointer to 53E3H. PARITY - ODD, EVEN or OFF.
563C-5643
DEFM 'P ' + DEFW 53E3H 50 20 20 20 20 20 E3 53
Value pointer to 53E3H. Abbreviated PARITY.
5644-564B
DEFM 'EVEN ' + DEFW 5421H 45 56 45 4E 20 20 21 54
Value pointer to 5421H. EVEN - switch selecting even parity.
564C-5653
DEFM 'E ' + DEFW 5421H 45 20 20 20 20 20 21 54
Value pointer to 5421H. Abbreviated EVEN.
5654-565B
DEFM 'ODD ' + DEFW 5411H 4F 44 44 20 20 20 11 54
Value pointer to 5411H. ODD - switch selecting odd parity.
565C-5663
DEFM 'O ' + DEFW 5411H 4F 20 20 20 20 20 11 54
Value pointer to 5411H. Abbreviated ODD.
5664-566B
DEFM 'DTR ' + DEFW 5452H 44 54 52 20 20 20 52 54
Value pointer to 5452H. DTR - Data Terminal Ready control.
566C-5673
DEFM 'RTS ' + DEFW 5462H 52 54 53 20 20 20 62 54
Value pointer to 5462H. RTS - Request To Send control.
5674-567B
DEFM 'RI ' + DEFW 5477H 52 49 20 20 20 20 77 54
Value pointer to 5477H. RI - Ring Indicator input control.
567C-5683
DEFM 'CD ' + DEFW 5487H 43 44 20 20 20 20 87 54
Value pointer to 5487H. CD - Carrier Detect input control.
5684-568B
DEFM 'DSR ' + DEFW 547FH 44 53 52 20 20 20 7F 54
Value pointer to 547FH. DSR - Data Set Ready input control.
568C-5693
DEFM 'CTS ' + DEFW 548FH 43 54 53 20 20 20 8F 54
Value pointer to 548FH. CTS - Clear To Send input control.
5694-569B
DEFM 'DEFAUL' + DEFW 5252H 44 45 46 41 55 4C 52 52
Value pointer to 5252H. DEFAULT - flag cell (operand at 5252H); resets all parameters to their factory defaults.
569C
DEFB 00H 00
Table terminator; also the last byte of the overlay image.