TRS-80 DOS - LDOS 5.3.1 for the Model I - SYS7/SYS Disassembled
Page Customization
Page Index
SYS7/SYS
Overlays in SYS7
Other Navigation
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 Code | Load Range | Bytes | Command / Function |
|---|---|---|---|
| 11H | 5200-5351H | 338 | AUTO Set, display, or clear the diskette's auto-execute command line (stored in the GAT sector at offset E0H). Documented below. |
| 15H / 16H | 5200-548DH | 654 | DATE / 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. |
| 13H | 5200-53D2H | 467 | CREATE 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 / 1BH | 5200-5349H | 330 | DEBUG / 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. |
| 1CH | 5200-552FH | 816 | SYSGEN Build or delete the stored system configuration file CONFIG/SYS.CCC:0; messages "User configuration built/deleted", "*** CONFIGURING ***". |
| 22H | 5200-55A3H | 932 | FREE Display drive free-space and diskette information ("Drive :d packname packdate cyldh Free=sssss.s/sssss.s Fi=nnn/nnn"). |
| A1H | 5200-5EE6H | 3303 | SYSTEM 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. |
| 33H | 5200-5402H | 515 | BUILD Build or append a keystroke/JCL file ("Building: ", "Appending: *KI to "), with HEX and APPEND options; "Odd # of hex digits!". |
| 51H | 5200-56D5H | 1238 | ATTRIB Set file/diskette attributes and passwords (PW/LOCK/UNLOCK/NAME/MPW); "New Master password ?", "Invalid master password!", "ATTRIB aborted!". |
| 71H | 5200-5405H | 518 | DUMP 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'!". |
| 72H | 5200-577CH | 1405 | PURGE Selectively delete files with INV/SYS/MPW/QUERY options and date filtering; "Purge file: ", "Purging: ", "Master password ?". |
| B1H | 5200-5525H | 806 | FORMS Set the Forms printer-filter parameters (LINES/PAGE/CHARS/INDENT/ADDLF/FFHARD/TAB/XLATE/MARGIN); "Forms Filter not Resident". |
| B2H | 5200-569CH | 1181 | SETCOM 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 Range | Purpose |
|---|---|
| 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
| Address | Name / Purpose |
|---|---|
| 5200H | AUTO 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. |
| 52A1H | Validate 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. |
| 52B4H | Parse 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. |
| 52D0H | Read 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. |
| 52E3H | Write 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.
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.
Advance HL to the next command-line character. HL is the running command-line pointer.
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.
Restore the caller's stack pointer from 5220H, where it was saved at 5200H, before transferring to the resident command executor.
Load Register A with the drive-valid flag. The operand at 5268H was patched by 52A1H to 00H (drive valid) or FFH (drive invalid).
Fetch the next source character of the new command from the command line (addressed by HL) into Register A.
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.
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.
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.
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).
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.
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.
Advance the command-line pointer HL past the drive digit (and past any trailing blanks on subsequent iterations).
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.
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.
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.
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.
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.
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".
Increment the February entry of the days-per-month table at 5241H to 29 for the leap year.
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.
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.
Fetch the current command-line character (addressed by HL) into Register A.
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.
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.
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.
Increment the February entry at 5241H to 29 for the leap year.
Fetch the next month's day count (addressed by DE) into Register A.
Increment Register B, the running count of tens in the day value.
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.
Fetch the next name character (addressed by HL) into Register A.
Save the current field-cell pointer (Register Pair DE) across the number parse.
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.
Load Register A with 20H (ASCII space) to blank a field position.
Move DE back one position to the next digit slot (digits are written least-significant first, right to left).
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.
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.
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.
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).
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).
Store the computed record count (HL) into the record-count cell at 5241H, the same cell REC would have set.
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).
Save the logical record length (Register A) into 5344H for the attribute-setting helper at 5333H to store into the directory.
Store the SHRINK word (HL) into 5302H so the later fill/close logic can consult it.
Store the SHRINK flag (Register A) into 5308H for the same later use.
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.
Decrement the remaining record count (BC).
Restore the caller's stack pointer. The operand at 5325H was overwritten at 5200H with the caller's SP.
Store BEH into 533FH, adjusting the offset the update helper at 5338H writes to in the directory record.
Load Register A with the logical record length. The operand at 5344H was set at 526BH to the file's LRL.
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.
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.
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).
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.
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).
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.
Restore the caller's stack pointer. The operand at 5283H was overwritten at 529AH with the caller's SP.
Save the caller's stack pointer into 5283H, the operand of the LD SP,nnnn at 5282H, for the common exit.
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).
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.
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.
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.
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.
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.
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.
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.
Store the ASCII drive digit (Register A) into 543CH, the drive position of the "Attrib CONFIG/SYS.CCC:0 (I,P=RE)" message string.
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".
Fetch the next name character from the address in Register Pair HL (walking "CONFIG" from 542DH) into Register A.
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.
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.
Read the byte at the address in Register Pair HL (the current test address) into Register A, preserving the original contents.
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.
Load Register C with the low byte of the region byte count from the table entry at Register Pair HL.
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.
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.
Save the current source/reload address (Register Pair HL) on the stack.
Fetch the next data byte from the source address in Register Pair HL into Register A.
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).
Fetch the next data byte from the source address in Register Pair HL into Register A.
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".
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.
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.
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.
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.
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".
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.
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.
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.
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.
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.
Load Register A with the SFLAG$ value saved at entry. The 00H operand at 53D7H was overwritten at 53A7H with the original SFLAG$ byte.
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.
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.
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.
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.
5520H - Data: Module Pad
The remaining bytes of the overlay slot are zero fill.
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.
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.
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.
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.
Save the current drive number (Register Pair BC) across the display call.
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.
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.
INCrement Register C to the current cylinder number.
Load Register A with the granules-per-cylinder count. The 00H operand at 527DH is patched at 534BH with the computed granules per cylinder.
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.
Single-drive header entry: load Register C with the drive number. The 0FFH operand at 52C6H was patched at 5218H with the requested drive.
Store the drive digit (Register A) into 5519H, the "Drive :d" field of the header template at 5512H.
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.
Fetch this cylinder's GAT byte from Register Pair HL into Register A; a set bit marks an allocated granule.
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.
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.
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.
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.
Add the sectors per granule (Register C) to Register A.
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.
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.
DECrement Register Pair DE, adjusting the running count as each HIT slot is examined.
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.
Store the decremented line counter (Register A) back into 53C7H, the counter operand read at 53C6H.
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.
Store the fill character (Register A) into the buffer position addressed by Register Pair HL.
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.
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.
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.
Load Register A with the sectors-per-granule count. The 00H operand at 540EH was patched at 52E5H with that value.
Load Register Pair DE with the destination field pointer saved at 5409H (the 0000H operand at 541EH holds that address).
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.
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.
INCrement Register D, counting how many times the place value divides into the number.
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.
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).
Test bit 3 of the drive-spec byte (IY+03H). Set means a hard disk, which has no floppy lock-out marking.
54A9H - Helper: Plot a Directory Cylinder
Fills the current cylinder's granule positions with 'D' to mark the directory track.
Store 44H ('D') into the line buffer at Register Pair IX, marking a directory granule.
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.
INCrement Register C toward the end cylinder of this line.
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.)
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.
Restore the entry Stack Pointer. The 0000H operand at 5504H was overwritten at entry (5200H) with the saved SP.
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.
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.
559AH - Data: @PARAM Option Table and Pad
The keyword descriptor table passed to @PARAM, defining the single P option.
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.
| Address | Keyword / 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.
| Address | Name / Purpose |
|---|---|
| 5A61H | Read 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. |
| 5A6EH | Write 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. |
| 5AE7H | Locate 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. |
| 5AF7H | High-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.
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.
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.
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.
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.
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.
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.
Store 00H (Register A) at the address in DE, zeroing one byte of the communications region.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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).
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.
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).
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.
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.
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.
Load BC from the SMALL value cell at 541AH to test whether BLINK,SMALL was specified.
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).
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).
Patch the cursor character into the blink-task body at 54ABH (the operand of the second CP nn used while scanning for the cursor).
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.
Store the current HIGH$ (HL) into the template's saved-ceiling field at 546BH so a later BLINK=OFF can restore it.
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.
LARGE value cell, read at 540FH. @PARAM sets it FFFFH when BLINK,LARGE is specified; the default 0000H means LARGE was not requested. Data.
Module link / saved-ceiling word, written at 543FH (new allocation) or 5435H (already resident). Data.
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.
Cursor routine entry (runs relocated in high memory). GOSUB to the resident @RPTSK (4416H) to obtain this task's control block address into IX.
Load Register A with the chosen cursor character (the operand at 548DH was patched at 5421H; shown here as the assembled 8FH).
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.
Copy the low byte of the search address (C) into Register A to step the search back through video memory one screen row.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Store the lookup's returned ceiling (DE) into the template's link field at 557BH.
Store the current HIGH$ (HL) into the template's saved-ceiling field at 557BH so a later ALIVE=OFF can restore it.
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.
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.
Module link / saved-ceiling word, written at 5544H (already resident) or 5550H (new allocation). Data.
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.
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).
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.
Store the current HIGH$ (HL) into the "$SVCKLI" template's saved-ceiling field at 55E2H so the module records the memory it reserved.
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.
Patch the "$SVCKLI" template word at 56EBH with the relocated address (HL), fixing up the module's second self-reference.
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).
Saved-ceiling field, written at 55A9H with the HIGH$ value in effect before this module was reserved. 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.
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).
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.
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.
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.
Store the current HIGH$ (HL) into the "$Sn" header's link field at 574AH.
Patch the name character (Register A) into the header so the resident module is named "$Sn" for overlay n.
Store the current HIGH$ (HL) into the "$SR" template's saved-ceiling field at 57C1H.
Patch the hook's LD HL,57C8H operand at 57F3H with the relocated slot-table address before the module is copied.
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.
Point HL at the slot table (the operand at 57F3H was relocated at 57A7H to the table's high-memory address).
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.
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).
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.
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.
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.
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.
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.
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.
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.
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.
Read the next character of the driver filespec from the command line (addressed by DE) into Register A.
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.
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.
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.
Store 0000H into the DRIVE value cell at 582DH, so the swap below uses drive 0 as the second drive.
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.
Store the swap drive number (Register A) into 5A04H, the operand of the LD C,nn at 5A03H that selects this drive's DCT.
Patch the ASCII drive digit (Register A) into the ":S" position of the "Drives :S and :D now swapped" message at 5D44H.
Store the destination drive number (Register A) into 5A0BH, the operand of the LD C,nn at 5A0AH that selects the second DCT.
Patch the ASCII drive digit (Register A) into the ":D" position of the swap message at 5D4BH.
Load C with the swap drive number (the operand at 5A04H was patched at 59D3H) to fetch its DCT.
Load C with the destination drive number (the operand at 5A0BH was patched at 59E3H) to fetch its DCT.
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).
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.
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.
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.
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.
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).
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.)
Patch the ASCII drive digit (Register A) into the "Insert SYSTEM diskette in drive X!" prompt at 5CD9H.
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.
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.
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).
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.
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!".
Fall-through LD IX,5CDCH. Entered at 5B15H (the BREAK-abort path), decodes as LD HL,5CDCH -> "Manual <BREAK> abort!".
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!".
Fall-through LD IX,5D1BH. Entered at 5B1DH (the drive-number error path), decodes as LD HL,5D1BH -> "Drive specification error <0-7>!".
Fall-through LD IX,5D59H. Entered at 5B21H (the same-drive error path), decodes as LD HL,5D59H -> "Source & Destination are the same drive!".
Fall-through LD IX,5BBAH. Entered at 5B25H (the active-spooler path), decodes as LD HL,5BBAH -> "Can't SYSGEN with active SPOOLER!".
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.
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.
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.
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.
Fetch the next file-specification character (addressed by HL) into Register A.
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.
Store 3FH (Register A) into 52BEH, the operand of the LD B,0FFH at 52BDH, limiting JCL input lines to 63 characters.
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).
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.
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.
Load Register A with the current keystroke-label letter. The operand at 52A2H starts at 40H ('@') and is incremented for each KSM line.
Store the incremented label letter (Register A) back into 52A2H so the next line advances to the following letter.
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.
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.
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.
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.
Store the end-of-input pointer (HL) into 52F3H, the operand of the LD DE,nnnn at 52F2H, marking where the collected data ends.
Load Register Pair DE with the end-of-input pointer saved at 52F3H, to compare against the running pointer.
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.
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).
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.
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.
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.
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.
Restore the caller's stack pointer. The operand at 535CH was overwritten at 5200H with the caller's SP.
536AH - Messages, Parameter Table, and Default Extension
The message strings, the @PARAM keyword table, and the default extension. These are data, not code.
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.
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.
Rotate Register A right circularly, walking the extended-dating bitmap so bit (drive) lands in the carry after B rotations.
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).
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.
Fetch the current command-line character (addressed by HL) into Register A.
Fetch the current command-line character (addressed by HL) into Register A to search 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.
Advance the command-line pointer (Register Pair HL) past the parenthesis or comma to the next option letter.
Fetch the current table entry's first letter (addressed by HL) into Register A.
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.
Fetch the next command-line character (addressed by HL) into Register A after an option has been processed.
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.
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.
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.
Fetch the next source character (addressed by HL) into Register A.
Advance the command-line pointer (Register Pair HL) to the next character while scanning for the "=" sign.
Store a space (Register A) into the value buffer (addressed by DE).
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.
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).
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).
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).
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.
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.
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.
Load Register Pair DE from the operand at 53F6H, the NAME pointer cell written by @PARAM (0000H if NAME was not given).
Load Register Pair DE from the operand at 540EH, the PW pointer cell written by @PARAM (0000H if no new master password was given).
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).
Load Register A from the operand at 54CCH, the target drive number saved at 53D4H.
Load Register Pair BC from the operand at 5431H, the LOCK flag (non-zero when LOCK was given).
Load Register Pair BC from the operand at 543BH, the UNLOCK flag (non-zero when UNLOCK was given).
Store the password to apply (Register Pair HL) into 5495H, the operand of the LD DE,nnnn at 5494H used inside the scan.
Store the password to match (Register Pair DE) into 548CH, the operand of the LD HL,nnnn at 548BH used inside the scan.
Copy the HIT-slot low address (Register L) into Register A to test the slot position.
Store the derived directory record number (Register A) into 546DH, the operand used by the following DIRRD call and the write-back test.
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).
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).
Load Register A from 546DH, the last directory record number processed, to decide whether the current directory sector was modified.
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.
Restore the caller's stack pointer. The operand at 54BDH was set at 5200H to the entry SP.
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.
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).
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.
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.
Fetch the next source character from the supplied value (addressed by DE) into Register A.
Store a space (20H) into the output buffer (addressed by HL) to blank-fill the field.
Fetch the next field character (addressed by HL) into Register A.
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.
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.
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.
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.
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.
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.
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.
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.
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.
560AH - Prompts and Diskette Messages
The interactive prompts (terminated with 03H for @KEYIN) and the remaining diskette-form messages (terminated with 0DH for @LOGOT).
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.
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.
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.
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.
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.
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).
Fetch the current name character (addressed by HL in the FCB) into Register A for validation.
Load Register A with 20H (ASCII space) to pad the rest of the module name.
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.
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.
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.
Advance the scan pointer (Register Pair HL) to the next character of the built file specification.
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.
Fetch the current module-name character (addressed by HL at 5426H onward) into Register A.
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.
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.
Save the current source pointer (Register Pair HL) so it can be reloaded after the remaining-byte count is computed.
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.
Fetch the current memory byte to be dumped (addressed by the source pointer HL) into Register A.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Fetch the current command-line character (addressed by HL) into Register A to skip leading blanks.
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.
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.
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.
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.
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.
Advance the date-string pointer (Register Pair HL) past the minus.
Fetch the date-flag byte from 5710H into Register A.
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.
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.
Restore the directory pointer (Register Pair HL) saved before an entry was processed.
Copy the slot offset (Register L) into Register A.
Restore the caller's stack pointer; the operand at 52DEH was set at entry by the LD (52DEH),SP at 5200H.
Copy the current slot offset (Register L) into Register A.
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.
Store the computed record marker (Register A) into 52FDH, the operand of the LD A,nn at 52FCH, caching which record is buffered.
Load Register H with 42H, pointing Register Pair HL into the resident sector buffer SBUFF$ (4200H) where the directory entry now lives.
Load Register Pair DE with the SYS option flag; the operand at 5319H is non-zero only when the SYS switch was given.
Test bit 3 of the attribute byte (Register A); a set bit marks an invisible file.
Load Register Pair DE with the INV option flag; the operand at 5327H is non-zero only when the INV switch was given.
Save the entry pointer (Register Pair HL) while the name and extension are matched against the mask.
Fetch the current mask character (addressed by DE at 5705H onward) into Register A.
Advance the entry-name pointer (Register Pair HL) to the next character.
A mask mismatch. This LD A,nn reads its own operand at 5352H, which is the exclude flag: 2DH in invert mode, 00H otherwise.
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.
Restore the entry pointer (Register Pair HL) saved before the mask test.
Fetch the date-flag byte from 5710H into Register A to test the upper bound.
Restore the entry pointer (Register Pair HL).
Fetch a file-name character (addressed by HL) into Register A.
Copy the name offset (Register L) into Register A.
Fetch an extension character (addressed by HL) into Register A.
Load Register A with 3AH (ASCII :), the drivespec separator.
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.
Load Register A with 20H (space) separating the flag from the date.
Increment Register B, counting the tens of the month value.
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.
Copy the entry offset (Register L) into Register A for the extended-date field.
Compare Register A against 10 (0AH) to split the year into tens and units.
Copy the year units (Register A) into Register B.
Load Register A with 03H, the End-of-Text terminator for the display line.
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.
Fetch KFLAG$ from 4423H into Register A. The unattended (Q=OFF) path enters here, skipping the prompt.
Store 0FFH into 52FDH, the record-cache marker, forcing the next iteration to re-read the directory record since @KILL has just changed it.
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".
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.
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.
Load Register A with request code 0E4H to select the resident directory/attribute/password service.
Copy the high byte of the MPW option pointer (Register D) into Register A.
Fetch a character of the supplied password (addressed by DE) into Register A.
GOSUB to 5552H to read SFLAG$; it returns the NZ FLAG when running below command level.
Store 20H (space) into the buffer (addressed by HL) to pad the password field.
Restore the buffer pointer (Register Pair HL) to the start of the password.
Fetch a password character (addressed by HL) into Register A.
Advance the buffer pointer (Register Pair HL).
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.
Fetch SFLAG$ from 430FH into Register A.
Compare the current source character (Register A) against 24H (ASCII $), the wildcard which is copied into the mask verbatim.
Compare Register A against 61H (ASCII a). If below, the CARRY FLAG is set (already uppercase).
Store the mask character (Register A) into the mask buffer (addressed by DE).
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.
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.
Rotate Register A left circularly (first of three) to align the year into the packed date high byte.
Copy the entry offset (Register L) into Register A for the extended date field.
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".
Save the field pointer (Register Pair DE).
GOSUB to 55CCH to fetch and test one digit; returns it in Register A with the CARRY FLAG set for a valid digit.
OR Register A with itself to set the NZ FLAG (a single-digit or empty field), leaving the value in Register A.
Fetch a date-string character (addressed by HL) into Register A.
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.
Load Register A with error code 2CH (parameter error).
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.
Load Register Pair HL with 0FFFFH, the non-zero error return code.
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".
Exchange Register Pairs DE and HL so HL addresses the year for the leap-year test.
Fetch the parsed month (from 5717H) into Register A.
Fetch the parsed day (from 5716H) into Register A.
Rotate Register A left circularly (first of three) to align the year bits.
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.
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.
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.
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.
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).
Point Register Pair HL at 548AH, the "Forms Filter not Resident" message, reached from 5234H when the module lookup finds no resident Forms filter.
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.
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.
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.
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.
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).
Point Register Pair DE at the filter's parameter-storage+3 address; the operand at 52E7H was patched at 5244H with that address.
Point Register Pair DE at the filter control-block+0AH address; the operand at 52EFH was patched at 5252H with that address.
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.
Test bit 0 of the working-copy flag byte IY+7 (5532H), the ADDLF switch state.
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.
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.
Save Register Pair BC on the stack; entry Register A holds the value to format and Register Pair DE points at the destination field.
Load Register B with 05H, the field width in digits, to space-fill the scratch buffer first.
Load Register A with 0AH (10), the divisor for extracting the next decimal digit.
Load Register A with 0BCH, the resident supervisor request that locates a named module control block; Register Pair DE points at the module name.
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.
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.
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.
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.
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.
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).
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.
Point Register Pair HL at 5504H, the "RS232/DVR not installed" message, reached from 5238H when no resident RS-232 driver is found.
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.
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.
Advance Register Pair HL to the next command-line character.
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).
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.
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.
Point Register Pair HL at 5575H, the "Baud=" label, and display it.
Load Register A with 20H (ASCII space) to skip the leading blanks of the right-justified number.
Point Register Pair HL at 557BH, the "Word=" label, and display it.
Point Register Pair HL at 5581H, the "Stop=" label, and display it.
Point Register Pair HL at 5587H, the "Parity=" label, and display it.
Point Register Pair HL at 558FH, the "Break=" label, and display it.
Point Register Pair HL at 5596H, the newline plus "Output control: " heading.
Point Register Pair HL at 55A8H, the "DTR=" label.
Point Register Pair HL at 55ADH, the "RTS=" label.
Point Register Pair HL at 55B2H, the newline plus "Input control: " heading.
Point Register Pair HL at 55C3H, the "RI=" label.
Point Register Pair HL at 55C7H, the "DSR=" label.
Point Register Pair HL at 55CCH, the "CD=" label.
Point Register Pair HL at 55D0H, the "CTS=" label.
Save the signal mask (Register AF) on the stack across the label display.
Point Register Pair HL at 55F8H, the carriage-return string.
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.
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.
Save Register IY (the driver control-block work register is Register IX, so IY is free) on the stack.
Fetch the low byte of the next field-routine address (IY+00H) into Register L.
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.
Store 00H into control-block offset 0 (IX+00H), clearing every modem-control field so all input signals default to IGNORE.
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.
Point Register Pair HL at 5219H, the parameter-error handler.
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).
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).
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).
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).
Copy the high byte of the PARITY value (Register D) into Register A.
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).
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).
Load Register Pair DE with the BREAK option value; the operand at 5431H is written by the BREAK keyword, defaulting to 0100H (not specified).
Copy the high byte (Register D) into Register A.
Load Register Pair DE with the DTR option value; the operand at 5452H is written by the DTR keyword, defaulting to 0001H (not specified).
Load Register Pair DE with the RTS option value; the operand at 5462H is written by the RTS keyword, defaulting to 0001H (not specified).
Load Register Pair HL with the RI option value; the operand at 5477H is written by the RI keyword, defaulting to 0001H (not specified).
Load Register Pair HL with the DSR option value; the operand at 547FH is written by the DSR keyword, defaulting to 0001H (not specified).
Load Register Pair HL with the CD option value; the operand at 5487H is written by the CD keyword, defaulting to 0001H (not specified).
Load Register Pair HL with the CTS option value; the operand at 548FH is written by the CTS keyword, defaulting to 0001H (not specified).
Copy the option value low byte (Register L) into Register A.
AND the value bits (Register A) with the field mask (Register B), keeping only the bits inside the field.
Compare the character (Register A) against 61H (ASCII "a").
Point Register Pair HL at 551CH, the base of the sixteen-entry baud-rate table.
Fetch the low byte of the current table entry (addressed by Register Pair HL) into Register A.
Copy the matching index (Register C) into Register A.
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.
JUMP to the status display driver at 5364H; entered (via the RET at 5247H) when no parameter list was supplied.
Load Register B with 05H, the field width, to space-fill the scratch buffer.
Load Register A with 0AH (10), the divisor for the next decimal digit.
Load Register A with 0BCH, the resident supervisor request that locates a named module control block; Register Pair DE points at the module name.
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).
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.
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.