TRS-80 DOS - VTOS 4.0.2 - SYS7/SYS Disassembled

Page Customization

Introduction:

VTOS 4.0.2 SYS7/SYS Disassembly - Program Chaining Overlay (Model I)

SYS7/SYS is the program chaining overlay for VTOS 4.0 on the TRS-80 Model I. It occupies the standard overlay slot at 4E00H-51FFH and is loaded on demand by the SYS0 resident overlay dispatcher when an SVC code in the range 40H-4FH or 70H-7FH is issued. Its primary function is to allow a running program to pass control to another program or DOS command, optionally carrying a command-line argument string, while cleanly managing the DOS interrupt vectors and the command-line buffer.

SYS7 handles three distinct entry scenarios, distinguished by the high nibble of the SVC code in Register A at entry:

  • 10H range (nibble 1): Debug monitor enable path - installs or re-enables the debug interrupt vector and associated RST vector hooks, then waits for a command line.
  • 20H range (nibble 2): DOS READY / command prompt path - manages the display of messages such as "CHAINING COMPLETED" or "INVALID CL," and then re-enters the DOS command loop.
  • 40H range (nibble 4): Chain dispatch path - parses the command-line buffer at 4318H, searches the SYS1 command table for a matching keyword (ABORT, NALERTI, DELAY, OEXIT, NFLASH, PKEYIN, PAUSE, OSTOP, XOWAIT, HALT, and others), and either chains to the appropriate handler or reports an error.

SYS7 also contains the command keyword string table used during chaining, as well as the decimal number parser used to read numeric arguments from the command line. The file ends with a block of ASCII message strings (CHAINING COMPLETED, INVALID CL, CHAINING ABORTED, MANUAL CHAINING ABORTED) used by the various exit paths.

SYS7 calls into the SYS0 resident layer extensively: it uses the file open utility at 444BH, the display routines at 4467H and 447BH/447EH, the DOS-ready exit at 402DH, and the error exit at 4409H. It also calls the ROM character output at 0033H and the keyboard scan at 0049H.

Variable List

Memory Range / SizeDescription
4318H—...
1+ bytes
Command-line input buffer (DOS resident). SYS7 reads the chain target name and arguments from this buffer. Written by the ROM line-input routine at 0040H.
4358H
1 byte
Current drive number / FCB drive field. Used by SYS7 as the FCB base address when opening the chained file via 444BH.
402DH—402FH
3 bytes
DOS READY exit vector (SYS0 resident). SYS7 patches this with a JP to 933EH (at 4EBACH) or restores it to point to 402DH. Self-modifying code target.
402FH
1 byte
DOS READY vector opcode byte. Set to EFH (RST 28H) by the cleanup routine at 4EBDH.
4030H—4031H
2 bytes
DOS error-exit vector operand (DE field). Set to 0A33EH by cleanup at 4EC0H.
4032H
1 byte
DOS error-exit vector opcode byte. Set to EFH (RST 28H) by cleanup at 4EC4H.
430FH
1 byte
DOS system flags byte (SYS0 resident). Bit 5: debug/chaining active flag tested and set by SYS7. Bit 7: DEBUG monitor enabled flag. Bit 4: drive-select hardware flag.
43BEH—43BFH
2 bytes
Saved DOS READY vector address. SYS7 saves the current 4016H pointer here at 4E20H and restores it at 4EACH.
4016H—4017H
2 bytes
DOS overlay return address pointer (SYS0 resident). SYS7 redirects this to 4E52H (its own ISR stub) during chaining, then restores the original value on exit.
3840H
1 byte
Disk hardware status port (memory-mapped, Model I). Bit 0: BREAK key / interrupt flag. Bit 2: drive-ready status. Read by SYS7 to detect disk presence and wait for key release.
4FBDH
1 byte
Self-modifying operand: stores the terminator character found during command-line parsing (used at 4FC0H/4F90H). Runtime value is the matched separator or 00H.
513FH
1 byte
Self-modifying operand inside the filename reader at 50FFH: stores whether a valid character was placed in the output buffer (00H = yes, non-zero = flag state). Runtime value set at 5100H and 5131H.
51AAH—51AFH
6 bytes
Filename/keyword work buffer. Receives the uppercase-converted, space-padded keyword extracted from the command line by the reader at 50FFH. Used as the search key against the command table at 50B6H.
50B6H—...
variable
Command keyword table. Each entry is a variable-length keyword string followed by a 2-byte handler address. Entries: ABORT, NALERTI, DELAY, OEXIT, NFLASH, PKEYIN, PAUSE, OSTOP, XOWAIT, HALT (and more). Terminated by a sentinel entry.
51B2H—51F9H
72 bytes
ASCII message string area. Contains: "CHAINING COMPLETED"+0DH (51B2H), "INVALID CL,"+... (51C5H), "CHAINING ABORTED"+0DH (51D2H), "MANUAL CHAINING ABORTED"+0DH (51E5H).

Major Routine List

AddressName and Purpose
4E00HSYS7 Entry Dispatcher
Entry: A = SVC code (high nibble determines path). Masks A to high nibble and routes to debug enable (4E13H), DOS READY (4E58H), or chain dispatch (4EC8H). Returns NZ if nibble not recognized.
4E13HDebug Monitor Enable / Vector Install
Entry: bit 5 of 430FH clear. Disables interrupts, sets bit 5 of 430FH, saves 4016H to 43BEH, installs ISR stub address 4E52H into 4016H, resets stack to 41E0H, opens command file via 444BH, re-enters command loop at 4405H.
4E52HInterrupt Service Routine Stub
Loads DE with 4358H (FCB base) and jumps to ROM 0013H to handle the interrupt return/dispatch.
4E58HDOS READY / Chaining Exit Handler
Entry: nibble = 20H. Resets stack, enables interrupts, checks 430FH bits 7 and 4, reads 3840H drive status, selects message (CHAINING COMPLETED or CHAINING ABORTED), displays via 0033H and 447BH, then calls cleanup at 4EA2H and exits via 402DH.
4EA2HInterrupt Vector Cleanup
Disables interrupts, clears bit 5 of 430FH, zeros 4358H, restores 4016H from 43BEH, patches 402DH/402FH and 4030H/4032H back to their RST 28H forms, returns.
4EC8HChain Dispatch / Command Parser
Entry: nibble = 40H. Retrieves saved BC (chain parameter) from stack, opens FCB via 444BH, verifies drive numbers match, calls 4454H to validate, reads command line, searches command table, dispatches to handler or error path.
4EE0HFCB Open and Command Line Read
Opens FCB at 4358H via 444BH, reads command-line characters into 4318H buffer via 0013H, then re-enters main dispatch loop.
4F02HCommand Line Parser / Keyword Extractor
Reads command line at 4318H, finds '/' delimiters, extracts keyword into 51AAH via 50FFH, searches command table at 50B6H via 5143H, dispatches to matched handler or falls through to error.
4F64HDecimal Argument Reader
Calls 5190H to parse decimal digits from command line into BC, loops B times calling 501EH, then falls to error path at 4F4DH.
4F6FHDisplay Message and Wait for Key
Pops and re-pushes HL (message pointer), calls 4467H to display message, polls 3840H bits 0 and 2 waiting for a key or drive event, then falls to error path.
4F7DHPrint String and Get Keypress
Prints characters from HL until 0DH, calls 0049H for keyboard scan, echoes result via 0033H, stores character at 4FBDH, prints CR, then continues to verify path at 4F99H.
4F99HVerify and Continue Path
Opens FCB at 4358H via 444BH, reads chars into HL buffer via 0013H until 0DH, checks for '/' delimiter sequences, stores found terminator at 4FBDH, calls 447EH, then jumps to 4F4DH.
50FFHKeyword/Filename Reader
Entry: HL = source string, DE = destination buffer, B = max length. Reads up to B uppercase alphanumeric characters into DE, pads remainder with spaces, terminates buffer with 03H. Returns Z if valid keyword found, NZ otherwise.
5143HCommand Table Search
Entry: BC = table base, DE = search key (51AAH). Scans table entries (8 bytes each: 6-char name + 2-byte address), returns Z and DE = handler address if matched, NZ if not found.
5190HDecimal Number Parser
Entry: HL = digit string. Parses ASCII decimal digits using multiply-by-10 algorithm (ADD HL,HL x2 + ADD HL,BC + ADD HL,HL). Returns BC = parsed value. Stops on non-digit.

Cross-Reference Notes

SYS7 calls into SYS0 resident: 402DH (DOS READY exit), 4405H (command loop re-entry), 4409H (error exit), 444BH (open file), 4454H (validate), 4467H (display message), 447BH (display with processing), 447EH (display alternate), 4016H (overlay return vector).

SYS7 calls into ROM: 0013H (interrupt dispatch/character input), 0033H (character output), 0040H (line input), 0049H (keyboard scan).

SYS7 is called from SYS0: via the overlay dispatcher when SVC codes 40H-4FH or 70H-7FH are issued by a user program or DOS command.

SYS7 patches SYS0 resident locations: 402DH-4032H (DOS READY / error exit vectors), 4016H (overlay return pointer), 430FH bit 5 (chaining active flag), 4315H (BREAK handler opcode).

Disassembly:

4E00H - SYS7 Entry Dispatcher

Entry point for all SYS7 calls. Register A holds the SVC code passed by the caller. The high nibble of A determines which of three execution paths to take: debug enable (10H), DOS READY/chaining exit (20H), or chain dispatch (40H).

4E00
AND A,70H E6 70
Mask Register A against 70H (binary 01110000), isolating bits 6-4 (the high nibble, shifted right by one). This discards the low nibble of the SVC code and the top bit, leaving only the routing bits. The result in A will be 10H, 20H, or 40H for the three recognized entry paths.
4E02
CP A,20H FE 20
Compare Register A against 20H. If the masked nibble equals 20H, this is the DOS READY / chaining exit path. If equal, the Z FLAG is set; otherwise the NZ FLAG is set.
4E04
If the Z FLAG is set (masked nibble was 20H), JUMP to 4E58H to enter the DOS READY / chaining exit handler.
4E06
CP A,30H FE 30
Compare Register A against 30H. This tests whether the masked nibble equals 30H. If equal, the Z FLAG is set.
4E08
If the Z FLAG is set (masked nibble was 30H), JUMP to 4E8CH. This handles a third entry path not covered by the 20H or 10H cases.
4E0B
CP A,40H FE 40
Compare Register A against 40H. If the masked nibble equals 40H, this is the chain dispatch path. If equal, the Z FLAG is set.
4E0D
If the Z FLAG is set (masked nibble was 40H), JUMP to 4EC8H to enter the chain dispatch / command parser.
4E10
CP A,10H FE 10
Compare Register A against 10H. If the masked nibble equals 10H, this is the debug monitor enable path. If equal, the Z FLAG is set.
4E12
RET NZ C0
If the NZ FLAG is set (the nibble did not match 10H, meaning it matched none of the four recognized values), RETURN to the caller immediately. The SVC code is unrecognized and SYS7 takes no action.

Debug Monitor Enable Path
Execution reaches here only when the masked nibble equals 10H. This path installs SYS7's interrupt stub into the overlay return vector at 4016H, sets the chaining-active flag in 430FH, saves the current return vector, resets the stack, and re-enters the DOS command loop.

4E13
DI F3
Disable maskable interrupts. This protects the following sequence of reads and writes to the interrupt vector tables at 430FH and 4016H from being corrupted by an interrupt arriving mid-sequence.
4E14
LD HL,430FH 21 0F 43
Load Register Pair HL with 430FH, the address of the DOS system flags byte in the SYS0 resident area. HL now points to this byte for the BIT and SET operations that follow.
4E17
BIT 5,(HL) CB 6E
Test bit 5 of the DOS system flags byte at 430FH. Bit 5 is the chaining/debug-active flag. If it is already set (a prior call already installed the vector), the Z FLAG is cleared (NZ). If it is clear (first-time installation), the Z FLAG is set.
4E19
SET 5,(HL) CB EE
Set bit 5 of the DOS system flags byte at 430FH unconditionally, marking chaining/debug as now active. This is done regardless of its prior state so the flag is always set on exit from this block.
4E1B
If the NZ FLAG is set (bit 5 was already set before this call - the vector was already installed on a prior entry), JUMP to 4E2CH, skipping the vector save and install steps, since they have already been done.
4E1D
LD HL,(4016H) 2A 16 40
Load Register Pair HL with the 16-bit value stored at 4016H. The location 4016H holds the current DOS overlay return address pointer - the address to which the overlay dispatcher will jump when an SVC call completes. This value is saved before SYS7 overwrites it.
4E20
LD (43BEH),HL 22 BE 43
Store the current overlay return address (just loaded from 4016H into HL) into 43BEH. This saves the original vector so the cleanup routine at 4EA2H can restore it when SYS7 exits.
4E23
LD HL,0A93EH 21 3E A9
Load Register Pair HL with 0A93EH. This is the target address that will be patched into the DOS READY vector at 402DH, redirecting the READY exit to SYS7's own handler during chaining. The value A93EH is a self-modifying operand placeholder; the cleanup routine at 4EBAH will use this same literal to install the redirect.
4E26
LD DE,0B93EH 11 3E B9
Load Register Pair DE with 0B93EH. This is the corresponding target for the DOS error-exit vector at 4030H, to be patched in by the same call to 4EB8H.
4E29
GOSUB to 4EB8H, the vector-install subroutine. This routine uses HL and DE to patch the DOS READY vector at 402DH and the error-exit vector at 4030H with RST 28H dispatch stubs pointing to SYS7's handlers. On return, both vectors have been redirected.

Stack Reset and Command Loop Re-entry
Whether the vector was freshly installed or was already present, execution continues here to reset the stack and re-enter the DOS command processor.

4E2C
LD SP,41E0H 31 E0 41
Load the Stack Pointer with 41E0H, resetting the stack to the DOS system stack area. This discards any prior call frames and establishes a clean stack for the command loop that follows.
4E2F
EI FB
Enable maskable interrupts now that the vector installation is complete and the stack is stable.
4E30
LD DE,4358H 11 58 43
Load Register Pair DE with 4358H, the base address of the FCB (File Control Block) work area in SYS0 resident memory. This is passed to the file-open routine at 444BH as the FCB pointer.
4E33
GOSUB to SYS0 routine at 444BH to open the file described by the FCB at 4358H. On return, if the file was opened successfully, the Z FLAG is set. If the open failed (file not found, drive error, etc.), the NZ FLAG is set.
4E36
If the NZ FLAG is set (file open failed), JUMP to SYS0 error exit at 4409H with the error code already set by 444BH, terminating this operation with an error.
4E39
LD DE,4E52H 11 52 4E
Load Register Pair DE with 4E52H, the address of SYS7's own interrupt service routine stub. This address will replace the current overlay return vector at 4016H, so that future overlay completions dispatch through SYS7.
4E3C
LD (4016H),DE ED 53 16 40
Self-Modifying Code
Store the 16-bit value in Register Pair DE (4E52H, SYS7's ISR stub address) into memory location 4016H. This overwrites the DOS overlay return vector, redirecting all future overlay completions to SYS7's stub at 4E52H rather than the original handler. Runtime value: 4E52H.
4E40
LD HL,4318H 21 18 43
Load Register Pair HL with 4318H, the address of the DOS command-line input buffer in SYS0 resident memory. This is passed to the ROM line-input routine at 0040H as the destination buffer.
4E43
LD B,3FH 06 3F
Load Register B with 3FH (63 decimal). This is the maximum number of characters the line-input routine at 0040H will accept into the buffer before forcing a terminator. The command-line buffer at 4318H is 63 bytes long (4318H-4357H).
4E45
GOSUB to ROM routine at 0040H, the line-input routine. Entry conditions: HL = 4318H (destination buffer), B = 3FH (maximum character count). The routine waits for the user to type a line and press ENTER, storing each character into the buffer. On return, the buffer at 4318H contains the typed command line terminated by a carriage return (0DH).
4E48
LD DE,44BEH 11 BE 44
Load Register Pair DE with 44BEH, the address of the secondary interrupt handler or DCB pointer in SYS0. This address is written into the overlay return vector at 4016H to restore the normal post-command dispatch path after the command line has been read.
4E4B
LD (4016H),DE ED 53 16 40
Self-Modifying Code
Store the 16-bit value in Register Pair DE (44BEH) into memory location 4016H. This restores the overlay return vector to the normal SYS0 handler at 44BEH, undoing the redirect to 4E52H that was installed at 4E3CH. Runtime value: 44BEH.
4E4F
JP 4405H C3 05 44
JUMP unconditionally to SYS0 routine at 4405H, the DOS command loop re-entry point. Execution transfers to the resident command processor which will parse and execute whatever command line was just read into the buffer at 4318H. SYS7 does not return from this jump.

4E52H - Interrupt Return Stub and Drive Reset

A two-instruction stub stored at a fixed address and used as the interrupt return vector. Loads DE with the FCB base address at 4358H and jumps to ROM 0013H to re-enter the character-input dispatcher. This address is installed into the interrupt vector at 4016H by the LD (4016H),DE at 4E3CH.

4E52
LD DE,4358H 11 58 43
Load Register Pair DE with 4358H, the FCB base address used throughout SYS7. This is the FCB pointer passed to ROM 0013H as the device control block for the character-input dispatcher.
4E55
JP 0013H C3 13 00
JUMP unconditionally to ROM entry point at 0013H, the character-input and I/O dispatcher. Entry: DE = 4358H (FCB pointer). Control passes to the ROM to read the next character from the open file or device described by the FCB. SYS7 does not return from this jump; it re-enters the read loop for the next command in the chain file.

4E58H - SVC 20H Entry: Interactive Command Prompt

Entry point for SVC class 20H dispatched from 4E04H. Sets up the stack, enables interrupts, checks bit 7 of the DOS flags at 430FH to determine whether to arm the DEBUG re-entry hook, then checks bit 4 to determine whether SYS6 is already loaded. If not loaded, reads the keyboard at 3840H for a BREAK key, then either falls through to the SYS6 prompt path or takes the keyboard-input path.

4E58
LD SP,41E0H 31 E0 41
Load the Stack Pointer with 41E0H, resetting the stack to the SYS7 stack area top. This establishes a clean stack for the interactive command prompt path, discarding any previous stack state.
4E5B
EI FB
Enable maskable interrupts. Interrupts are re-enabled now that the stack is set and the system is in a stable state for the interactive prompt.
4E5C
LD HL,430FH 21 0F 43
Load Register Pair HL with 430FH, pointing to the DOS system flags byte. HL is used for the BIT tests that follow.
4E5F
BIT 7,(HL) CB 7E
Test bit 7 of the byte at HL (430FH). Bit 7 is the DEBUG-active flag. If set, the DEBUG re-entry hook at 4315H must be armed with a JP opcode before proceeding.
4E61
If the Z FLAG is set (bit 7 of 430FH is clear - DEBUG not active), JUMP to 4E68H to skip the hook-arming step and proceed directly to the SYS6 check.
4E63
LD A,0C3H 3E C3
Load Register A with 0C3H (the Z80 JP opcode). This will be written to 4315H to arm the DEBUG re-entry hook, enabling the BREAK key to vector into the DEBUG monitor.
4E65
LD (4315H),A 32 15 43
Self-Modifying Code
Store 0C3H (JP opcode) into memory location 4315H. This arms the DEBUG re-entry hook. When bit 7 of 430FH is set and a BREAK key event is detected by the ISR, the code at 4315H executes as a JP instruction to the DEBUG entry vector at 400FH. Runtime value: C3H (JP) when DEBUG is active.
4E68
LD A,(430FH) 3A 0F 43
Load Register A with the current value of the DOS system flags byte at 430FH. A snapshot of all system flag bits is taken for the BIT test that follows.
4E6B
BIT 4,A CB 67
Test bit 4 of Register A (value from 430FH). Bit 4 is the SYS6-library-cached flag. If set, SYS6 is already resident in memory and the library prompt path can be taken directly. If clear, SYS6 is not loaded and the keyboard must be checked.
4E6D
If the NZ FLAG is set (bit 4 of 430FH is set - SYS6 already loaded), JUMP to 4E79H to take the SYS6 prompt path directly, opening the FCB and reading a command line.
4E6F
LD A,(3840H) 3A 40 38
Load Register A with the byte at memory address 3840H, the Model I keyboard row 7 / SHIFT key row. This read polls the keyboard to check whether any key in row 7 is currently pressed.
4E72
AND A,04H E6 04
Mask Register A against 04H (binary 00000100), isolating bit 2 of the keyboard row 7 byte. Bit 2 of row 7 corresponds to a specific key signal used here to detect whether the user is requesting an alternate entry path.
4E74
LD HL,51E4H 21 E4 51
Load Register Pair HL with 51E4H, the address of the "MANUAL CHAINING ABORTED" message string in the SYS7 data area. HL is preloaded here so that if the keyboard test at 4E77H succeeds, the message pointer is already in place for the display-and-exit at 4E94H.
4E77
If the NZ FLAG is set (bit 2 of keyboard row 7 is active - the abort key is pressed), JUMP to 4E94H to display the "MANUAL CHAINING ABORTED" message and exit. The chain is aborted by user request.

4E79H - SYS6 Prompt Path: Open FCB and Read Command

Opens the FCB at 4358H via 444BH, reads a command line into the buffer at 4318H via ROM 0040H, then dispatches to DOS via 4405H. If the FCB open fails, falls through to the error/abort path.

4E79
LD DE,4358H 11 58 43
Load Register Pair DE with 4358H, the FCB base address. This is passed to the file-open routine at 444BH as the FCB pointer.
4E7C
CALL 444BH CD 4B 44
GOSUB to SYS0 at 444BH to open the file or device described by the FCB at 4358H. On return, Z set = success (file opened), NZ = failure (file could not be opened).
4E7F
If the NZ FLAG is set (FCB open failed), JUMP to 4E91H to load the "CHAINING ABORTED" message pointer and exit via the display-and-exit path at 4E94H.
4E81
LD HL,4318H 21 18 43
Load Register Pair HL with 4318H, the base address of the DOS command input buffer. HL is the buffer pointer passed to the ROM line-input routine at 0040H.
4E84
LD B,3FH 06 3F
Load Register B with 3FH (decimal 63). This is the maximum character count passed to the ROM line-input routine at 0040H, limiting the command line to 63 characters.
4E86
CALL 0040H CD 40 00
GOSUB to ROM line-input routine at 0040H. Entry: B = 3FH (max chars), HL = 4318H (buffer base). Reads one line of input from the keyboard or current input device into the buffer at 4318H, terminating on carriage return. The line is stored with a CR terminator at the end.
4E89
JP 4405H C3 05 44
JUMP unconditionally to SYS0 at 4405H, the DOS command dispatcher. Entry: command line is in the buffer at 4318H. The dispatcher parses the command, looks up the command table, and transfers control to the appropriate command handler. SYS7 does not return from this jump.

4E8CH - Load Short Message and Display

Loads HL with the address of "CHAINING ABORTED!" message at 51D2H and jumps to the display-and-exit path. Reached from the SVC 30H dispatch at 4E08H when the SVC class is 30H, indicating a command-line context error.

4E8C
LD HL,51D2H 21 D2 51
Load Register Pair HL with 51D2H, the address of the "CHAINING ABORTED!" message string in the SYS7 data area. HL is the message pointer for the display-and-exit routine at 4E94H.
4E8F
JR 4E94H 18 03
JUMP to 4E94H, the display-and-exit routine. HL points to the "CL," message which will be printed before returning to DOS READY.

4E91H - Load Abort Message

Loads HL with the address of the "CHAINING ABORTED" message at 51B2H and falls through to the display-and-exit routine. Reached when a file open failure or other abort condition is detected.

4E91
LD HL,51B2H 21 B2 51
Load Register Pair HL with 51B2H, the address of the "CHAINING ABORTED" message string in the SYS7 data area. HL is the message pointer for the display-and-exit routine at 4E94H.

4E94H - Display Message and Return to DOS READY

Common exit path for all SYS7 error and completion conditions. Outputs a newline (0AH), calls 447BH to display the message pointed to by HL, calls the cleanup routine at 4EA2H to restore interrupt vectors and DOS state, then jumps to DOS READY at 402DH.

4E94
LD A,0AH 3E 0A
Load Register A with 0AH (ASCII line feed). This is output first to move the cursor to a new line before the message is displayed.
4E96
GOSUB to ROM character output routine at 0033H. Entry: A = 0AH. Outputs the line feed character to the display, positioning the cursor at the start of a new line.
4E99
CALL 447BH CD 7B 44
GOSUB to SYS0 display routine at 447BH. Entry: HL = pointer to the message string (e.g. "CHAINING ABORTED", "CHAINING COMPLETED", or "CL,"). Displays the message to the screen with any CONFIG/SYS processing applied.
4E9C
CALL 4EA2H CD A2 4E
GOSUB to the SYS7 cleanup routine at 4EA2H. Restores the DOS interrupt vectors from 43BEH, clears bit 5 of 430FH, zeros 4358H, and restores 4016H to its saved value. On return the system state is fully restored.
4E9F
JP 402DH C3 2D 40
JUMP unconditionally to DOS READY at 402DH, the no-error exit point in the SYS0 resident area. Control passes back to the DOS command loop. SYS7 does not return from this jump.

4EA2H - Interrupt Vector Cleanup

Restores all DOS vectors and flags that were modified during chaining. Called from the display-and-exit path at 4E9CH and also directly when aborting. Clears bit 5 of 430FH, zeros the FCB drive byte at 4358H, restores the overlay return vector at 4016H from 43BEH, and re-patches 402DH/402FH and 4030H/4032H back to RST 28H dispatch form.

4EA2
DI F3
Disable maskable interrupts to protect the sequence of vector restoration writes that follow from being interrupted mid-operation.
4EA3
LD HL,430FH 21 0F 43
Load Register Pair HL with 430FH, the address of the DOS system flags byte. HL is used as a pointer for the RES instruction that follows.
4EA6
RES 5,(HL) CB AE
Reset bit 5 of the DOS system flags byte at 430FH. Bit 5 is the chaining/debug-active flag set by the enable path at 4E19H. Clearing it here marks chaining as no longer active.
4EA8
XOR A,A AF
Clear Register A to 00H by XORing it with itself. The result 00H will be used to zero the FCB drive byte at 4358H.
4EA9
LD (4358H),A 32 58 43
Self-Modifying Code
Store 00H (from Register A) into memory location 4358H. This zeros the FCB base / drive byte in the SYS0 work area, clearing any drive selection state that was established during chaining. Runtime value: 00H.
4EAC
LD HL,(43BEH) 2A BE 43
Load Register Pair HL with the 16-bit value stored at 43BEH. This is the original overlay return vector address that was saved at 4E20H when chaining was first enabled. HL now holds the value to be restored into 4016H.
4EAF
LD (4016H),HL 22 16 40
Self-Modifying Code
Store the 16-bit value in Register Pair HL (the original return vector) back into memory location 4016H. This restores the DOS overlay return vector to the address it held before SYS7 installed its own stub at 4E3CH. Runtime value: the address saved at 4E20H.
4EB2
LD HL,933EH 21 3E 93
Load Register Pair HL with 933EH. This is the 16-bit operand that will be written into the DOS READY vector at 402DH as a JP target address. Together with the EFH opcode written to 402FH, this reconstructs the RST 28H dispatch form of the READY exit.
4EB5
LD DE,0A33EH 11 3E A3
Load Register Pair DE with 0A33EH. This is the 16-bit operand that will be written into the error-exit vector at 4030H as a JP target address, reconstructing the RST 28H form of the error exit.

4EB8H - Vector Install / Restore Subroutine

Shared subroutine called from both the enable path (4E29H) and the cleanup path (falls through from 4EB5H). Writes HL into 402DH (the DOS READY vector JP target), writes EFH into 402FH (the RST 28H opcode), writes DE into 4030H (the error-exit vector), and writes EFH into 4032H. This either installs SYS7 redirect addresses or restores the original RST 28H dispatch forms, depending on the values in HL and DE at call time.

4EB8
LD A,0EFH 3E EF
Load Register A with EFH. On the Z80, EFH is the opcode for RST 28H. This byte will be written to the opcode positions of the DOS READY and error-exit vectors to set them to RST 28H dispatch form.
4EBA
LD (402DH),HL 22 2D 40
Self-Modifying Code
Store the 16-bit value in Register Pair HL into memory locations 402DH-402EH. 402DH is the DOS READY / No-Error Exit vector. The value written is either the SYS7 redirect target (when called from 4E29H with HL=0A93EH) or the original RST 28H target (when called from the cleanup fall-through with HL=933EH). Runtime value: 0A93EH (enable) or 933EH (restore).
4EBD
LD (402FH),A 32 2F 40
Self-Modifying Code
Store EFH (RST 28H opcode) into memory location 402FH. 402FH is the opcode byte of the DOS READY vector instruction. Writing EFH here ensures the vector is in RST 28H form regardless of what was there before. Runtime value: EFH.
4EC0
LD (4030H),DE ED 53 30 40
Self-Modifying Code
Store the 16-bit value in Register Pair DE into memory locations 4030H-4031H. 4030H is the error-already-displayed exit vector in SYS0. The value written is either the SYS7 redirect target (when called from 4E29H with DE=0B93EH) or the original RST 28H target (when called from cleanup with DE=0A33EH). Runtime value: 0B93EH (enable) or 0A33EH (restore).
4EC4
LD (4032H),A 32 32 40
Self-Modifying Code
Store EFH (RST 28H opcode) into memory location 4032H. 4032H is the opcode byte of the error-exit vector instruction, parallel to 402FH for the READY vector. Runtime value: EFH.
4EC7
RET C9
Return to the caller. If called from 4E29H (enable path), returns to 4E2CH. If reached by fall-through from 4EB5H (cleanup path), returns to the instruction after the CALL 4EA2H at 4E9CH, which is JP 402DH at 4E9FH.

4EC8H - Chain Dispatch / Command Parser Entry

Entered when the SVC code high nibble equals 40H. This is the main chaining path. The routine recovers the BC parameter passed by the caller from the stack, opens the FCB, verifies drive numbers, reads the command line from the I/O device, and dispatches to the appropriate command handler.

4EC8
LD HL,000AH 21 0A 00
Load Register Pair HL with 000AH (decimal 10). This offset will be added to the current Stack Pointer to locate the saved BC register pair that the original caller pushed onto the stack before the SVC call. The value 10 accounts for the return addresses and other register saves that the overlay dispatcher placed on the stack between the caller and the current stack frame.
4ECB
ADD HL,SP 39
Add the current Stack Pointer value to HL. HL now points to the saved BC value on the stack at SP+10. This is the parameter block passed by the calling program to the chain SVC.
4ECC
LD C,(HL) 4E
Load Register C with the byte at the address now in HL (SP+10). This is the low byte of the saved BC parameter - the low byte of the chain parameter block pointer.
4ECD
INC HL 23
Increment HL to point to the next byte on the stack (SP+11), which holds the high byte of the saved BC parameter.
4ECE
LD B,(HL) 46
Load Register B with the byte at the current HL (SP+11). BC now holds the complete 16-bit chain parameter value passed by the caller.
4ECF
INC HL 23
Increment HL past the BC bytes to SP+12.
4ED0
INC HL 23
Increment HL to SP+13.
4ED1
INC HL 23
Increment HL to SP+14. HL now points to the saved DE register pair on the stack.
4ED2
LD E,(HL) 5E
Load Register E with the byte at the current HL (SP+14). This is the low byte of the saved DE register pair on the stack - the low byte of the FCB or device pointer passed by the caller.
4ED3
INC HL 23
Increment HL to SP+15 to point to the high byte of the saved DE register pair.
4ED4
LD D,(HL) 56
Load Register D with the byte at the current HL (SP+15). DE now holds the complete 16-bit saved DE value from the caller's stack frame - the FCB or device pointer.
4ED5
LD HL,05E3H 21 E3 05
Load Register Pair HL with 05E3H. This is a comparison value used in the next instruction to test whether the DE value just recovered from the stack equals a specific sentinel address. 05E3H represents a known constant used to identify a particular calling context.
4ED8
SBC HL,DE ED 52
Subtract Register Pair DE from HL with borrow (carry). If DE equals 05E3H, the result will be 0000H and the Z FLAG is set. If DE does not equal 05E3H, the result is non-zero and the NZ FLAG is set. This tests whether the caller passed 05E3H as the DE parameter, identifying a specific chaining context.
4EDA
If the Z FLAG is set (DE from caller was 05E3H - the expected sentinel), JUMP to 4EE0H to proceed with the normal FCB open and command-line read sequence.
4EDC
LD HL,(43BEH) 2A BE 43
Load Register Pair HL with the 16-bit value stored at 43BEH - the saved original overlay return vector address that was stored there at 4E20H. This recovers the address to jump to for non-standard chaining exit.
4EDF
JP HL E9
JUMP unconditionally to the address currently in Register Pair HL (the saved original return vector from 43BEH). Since DE did not match the expected sentinel 05E3H, execution transfers to the original pre-chaining return handler rather than the normal FCB open path. SYS7 does not return from this jump.

4EE0H - FCB Open and Command Line Input

Reached when the caller's DE parameter matched the expected sentinel 05E3H. Opens the FCB at 4358H, then reads characters from the I/O device via ROM 0013H into the command-line buffer at 4318H until a carriage return is received. Then re-enters the main dispatch loop.

4EE0
LD DE,4358H 11 58 43
Load Register Pair DE with 4358H, the FCB base address in the SYS0 work area. This is passed to the file-open routine at 444BH as the FCB pointer.
4EE3
PUSH BC C5
Push Register Pair BC (the chain parameter recovered from the stack at 4ECCH-4ECEH) onto the stack. BC is preserved across the CALL to 444BH so its value remains available after the open operation.
4EE4
GOSUB to SYS0 at 444BH to open the file described by the FCB at 4358H. On return, Z set = file opened successfully, NZ = open failed.
4EE7
POP BC C1
Pop the preserved BC value back from the stack into Register Pair BC, restoring the chain parameter.
4EE8
JR NZ,4E91H 20 A7
If the NZ FLAG is set (file open failed), JUMP to 4E91H to load the "CHAINING ABORTED" message and exit via the display-and-error path.
4EEA
LD A,B 78
Load Register A with the value of Register B, which holds the high byte of the chain parameter BC. This is used in the comparison that follows to verify that the drive numbers match.
4EEB
CP A,C B9
Compare Register A (high byte B of chain parameter) with Register C (low byte C of chain parameter). If B equals C, the Z FLAG is set. This tests whether the source and destination drive identifiers in the chain parameter are the same, i.e. the chain stays on the same drive.
4EEC
If the NZ FLAG is set (B does not equal C - drive numbers differ), JUMP to ROM entry point at 0013H to handle the cross-drive chaining case via the ROM character-input/dispatch handler. This is the alternate dispatch path for inter-drive chaining.
4EEF
GOSUB to SYS0 at 4454H to validate the open FCB. On return, Z set = FCB valid and ready, NZ = validation failed (corrupt FCB or unreadable directory entry).
4EF2
If the NZ FLAG is set (FCB validation failed), JUMP to SYS0 error exit at 4409H with the error code set by 4454H.
4EF5
GOSUB to ROM character-input routine at 0013H. Entry: DE = 4358H (FCB/DCB pointer set at 4EE0H). Returns the next character from the open file or device in Register A. The first character of the command line is read here.
4EF8
OR A,A B7
OR Register A with itself. This sets the Z FLAG if A is 00H (null character) and clears it otherwise. Used to test whether the first character read is a null, which would indicate an empty or exhausted command source.
4EF9
If the Z FLAG is set (first character was 00H - empty command source), JUMP to 4E91H to load the "CHAINING ABORTED" message and exit.
4EFB
PUSH AF F5
Push Register Pair AF (A = first character just read, F = flags) onto the stack. The first character is preserved here while the slash test below is evaluated.
4EFC
CP A,2FH FE 2F
Compare Register A against 2FH (ASCII '/'). Tests whether the first character of the command line is a forward slash, which is the delimiter character used to introduce command options in VTOS chaining syntax.
4EFE
If the Z FLAG is set (first character is '/'), JUMP to 4F02H to enter the command-line parser which processes the '/' delimited options.
4F00
POP AF F1
Pop the preserved AF back from the stack, restoring Register A to the first character read and the flags to their state after OR A,A.
4F01
RET C9
Return to the caller. The first character was not '/' and not null, so it is a normal command character. The character in A is returned to the overlay dispatcher for further processing.

4F02H - Command Line Parser / Keyword Extractor

Entered when the first command-line character is '/'. This routine manages the overall loop of parsing '/' delimited command keywords from the buffer at 4318H, extracting each keyword into the work buffer at 51AAH via the reader at 50FFH, searching the command table at 50B6H via 5143H, and dispatching to the matched handler. If no match is found, falls through to the error path at 4F4DH.

4F02
POP AF F1
Pop the preserved AF from the stack (pushed at 4EFBH). Register A is restored to the '/' character (2FH). The flags are also restored but are not used immediately after this point.
4F03
PUSH BC C5
Push Register Pair BC (the chain parameter) onto the stack to preserve it across the command parsing loop that follows.
4F04
PUSH DE D5
Push Register Pair DE (4358H, the FCB base address) onto the stack to preserve it across the parsing loop.
4F05
LD HL,4318H 21 18 43
Load Register Pair HL with 4318H, the address of the DOS command-line input buffer. HL is the source pointer for the character reader that fills characters into the buffer during the PUSH/read loop below. Characters are written directly into the buffer as they are received.
4F08
PUSH HL E5
Push HL (4318H, the command buffer base address) onto the stack. This saves the buffer start address as a reference point; it will be retrieved later by POP HL at 4F14H to reset HL to the beginning of the buffer after the read loop.
4F09
LD (HL),A 77
Store Register A (the current character, initially '/' = 2FH) into the memory location pointed to by HL (4318H). This writes the first character into the command buffer.
4F0A
INC HL 23
Increment HL to point to the next byte in the command buffer (4319H), ready to receive the next character.

Character Read Loop
Reads characters one at a time from the open file/device via ROM 0013H and stores them into the command buffer at 4318H until a carriage return (0DH) is received.

4F0B
CP A,0DH FE 0D
Compare Register A against 0DH (carriage return). Tests whether the character just stored is a CR, which marks the end of the command line.
4F0D
If the Z FLAG is set (character was CR), JUMP to 4F14H to end the read loop and begin keyword extraction.
4F0F
GOSUB to ROM character-input routine at 0013H. Entry: DE = 4358H (FCB pointer, preserved on stack). Returns the next character from the open file or device in Register A. This reads the next character of the command line.
4F12
JUMP back to 4F09H to store the newly read character into the buffer and continue the read loop.

Keyword Extraction Setup
The full command line is now in the buffer at 4318H. HL is reset to the buffer start and parsing begins.

4F14
POP HL E1
Pop the saved buffer start address (4318H, pushed at 4F08H) from the stack back into Register Pair HL. HL now points to the beginning of the command buffer, ready for the keyword scan.
4F15
PUSH HL E5
Push HL (4318H) back onto the stack immediately. This re-saves the buffer start pointer so it can be used again if the parser needs to restart or fall through to 4F4DH.
4F16
INC HL 23
Increment HL from 4318H to 4319H, stepping past the first '/' character that was stored at the very start of the buffer to point to the actual keyword text.
4F17
LD A,(HL) 7E
Load Register A with the byte at the current HL (4319H). This reads the first character of the keyword that follows the '/' delimiter.
4F18
CP A,2FH FE 2F
Compare Register A against 2FH (ASCII '/'). Tests whether the character after the initial '/' is itself another '/', which would indicate a '//' sequence - a special delimiter meaning end of chain options or a separator between option groups.
4F1A
If the NZ FLAG is set (character after '/' is not another '/' - it is a regular keyword character), JUMP to 4F4DH to fall through to the error/abort path. The parser only processes '//' style option blocks; a single '/' followed by a keyword is not a recognized format at this entry point.
4F1C
INC HL 23
Increment HL to 431AH, stepping past the second '/' to point to the first character of the option code that follows the '//' prefix.
4F1D
SUB A,(HL) 96
Subtract the byte at the current HL (431AH - the first option character) from Register A (which still holds '/' = 2FH from the CP at 4F18H). If the option character is also 2FH, the result is 00H and the Z FLAG is set. This tests for a '///' sequence.
4F1E
If the Z FLAG is set (three consecutive '/' characters found), JUMP to 4FC0H to store the terminator and proceed to the display routine.
4F21
SUB A,0F6H D6 F6
Subtract 0F6H from Register A. At this point A = 2FH minus the option character. Subtracting 0F6H effectively tests whether the option character value minus 2FH is greater than or equal to 0AH (since 2FH - char - 0F6H = 2FH - char + 0AH - 100H). If the carry flag is clear (NC) the value is in range; if the carry flag is set (C) it is out of range.
4F23
JP NC,4FBCH D2 BC 4F
If the carry flag is clear (NC - the option code is within the recognized numeric range), JUMP to 4FBCH to handle numeric option dispatch.
4F26
EX (SP),HL E3
Exchange Register Pair HL with the top of stack. The current HL (pointing into the command buffer after the '//' prefix) is saved to the stack, and the previously saved buffer start pointer (4318H, pushed at 4F15H) is loaded into HL. This gives the display routine access to the buffer start while preserving the current parse position.
4F27
GOSUB to SYS0 display routine at 447EH. Entry: HL = pointer to message (currently 4318H, the command buffer start). Displays the content of the command buffer as a message string. This echoes the command line back to the user as confirmation or error context.
4F2A
EX (SP),HL E3
Exchange Register Pair HL with the top of stack again, restoring HL to the parse position within the command buffer (pointing past the '//' prefix) and returning the buffer start pointer to the stack.
4F2B
LD A,(HL) 7E
Load Register A with the byte at the current HL - the next character in the command buffer at the current parse position. This reads the character that follows the '//' prefix and any intervening display output.
4F2C
CP A,0DH FE 0D
Compare Register A against 0DH (carriage return). Tests whether the current character is the end-of-line marker, meaning there are no more option keywords to process.
4F2E
If the Z FLAG is set (current character is CR - end of line), JUMP to 4F4DH to clean up and exit the parsing loop.
4F30
CP A,20H FE 20
Compare Register A against 20H (ASCII space). Tests whether the current character is a space, which is used as a separator between option keywords.
4F32
INC HL 23
Increment HL to advance the parse pointer one byte forward in the command buffer, past the current character.
4F33
If the Z FLAG is set (current character was a space), JUMP back to 4F2BH to skip the space and read the next character. This skips all whitespace between keywords.
4F35
DEC HL 2B
Decrement HL back one position. The INC HL at 4F32H was unconditional; since the current character was not a space (JR Z did not jump), HL must be stepped back to point at the current non-space character before passing it to the keyword reader.
4F36
Load Register Pair DE with 51AAH, the address of the keyword work buffer in SYS7's data area. This is passed to the keyword reader at 50FFH as the destination for the extracted keyword string.
4F39
LD B,06H 06 06
Load Register B with 06H. This is the maximum keyword length passed to the reader at 50FFH. Keywords in the command table are up to 6 characters long.
4F3B
GOSUB to the keyword reader at 50FFH. Entry: HL = current parse position in command buffer, DE = 51AAH (destination), B = 6 (max length). Reads up to 6 uppercase alphanumeric characters from HL into DE, pads to 6 chars with spaces, terminates with 03H. Returns Z if a valid keyword was extracted, NZ if not.
4F3E
JR NZ,4F4DH 20 0D
If the NZ FLAG is set (reader returned NZ - no valid keyword found at current position), JUMP to 4F4DH to clean up the stack and exit the parse loop.
4F40
Reload Register Pair DE with 51AAH - the start of the keyword work buffer that was just filled by 50FFH. DE is passed to the table-search routine at 5143H as the search key pointer.
4F43
Load Register Pair BC with 50B6H, the address of the command keyword table in SYS7's code area. BC is passed to the table-search routine at 5143H as the table base address.
4F46
GOSUB to the command table search routine at 5143H. Entry: BC = 50B6H (table base), DE = 51AAH (6-char search key). Scans each table entry comparing the 6-character name field against the key in DE. Returns Z and DE = handler address if a match is found; NZ if no match.
4F49
If the NZ FLAG is set (no matching keyword found in the command table), JUMP to 4F4DH to clean up and exit.
4F4B
PUSH DE D5
Push Register Pair DE (the handler address returned by 5143H) onto the stack. The handler address is saved here so that RET at the end of the cleanup sequence will transfer control directly to the matched command handler.
4F4C
RET C9
Return. The top of stack now holds the matched command handler address (pushed at 4F4BH). This RET therefore transfers control to the appropriate command handler routine rather than returning to the normal caller.

4F4DH - Parse Loop Exit / Stack Cleanup

Common exit point for the command parser. Cleans up the three values saved on the stack (HL buffer start, DE FCB pointer, BC chain parameter) and jumps back to the FCB open and command read sequence at 4EE0H to process the next command.

4F4D
POP HL E1
Pop the saved HL value (4318H, the command buffer start address pushed at 4F15H) from the stack into Register Pair HL. This discards the saved buffer pointer which is no longer needed.
4F4E
POP DE D1
Pop the saved DE value (4358H, the FCB base address pushed at 4F04H) from the stack into Register Pair DE. DE is restored to the FCB pointer.
4F4F
POP BC C1
Pop the saved BC value (the chain parameter pushed at 4F03H) from the stack into Register Pair BC. BC is restored to the chain parameter.
4F50
JUMP back to 4EE0H to re-open the FCB and read the next command line. The parse loop restarts from the top with a fresh FCB open, allowing chained commands to be processed sequentially.

4F52H - Invalid Command Line Error

Reached when the command line contains an unrecognized keyword or invalid syntax. Loads the address of the "INVALID CL," message and jumps to the display routine.

4F52
LD HL,51C5H 21 C5 51
Load Register Pair HL with 51C5H, the address of the "INVALID CL," message string in SYS7's data area. HL is the message pointer for the display-and-exit routine at 4E94H.
4F55
JUMP unconditionally to 4E94H, the display-and-exit routine. HL points to the "INVALID CL," message which will be printed, after which cleanup is performed and control passes to DOS READY at 402DH. SYS7 does not return from this jump.

4F58H - Cleanup and Return to Drive Select

Performs cleanup of the interrupt vector state, pops the three saved stack values (HL, DE, BC), loads DE with the drive configuration table base at 4015H, and jumps to ROM 0013H to complete the operation via the character-input/dispatch handler.

4F58
GOSUB to SYS7 cleanup routine at 4EA2H. Restores the DOS interrupt vectors, clears bit 5 of 430FH, zeros 4358H, and restores 4016H from 43BEH.
4F5B
POP HL E1
Pop the saved HL value (4318H, the command buffer start pushed at 4F15H) from the stack into Register Pair HL. This discards the buffer pointer.
4F5C
POP DE D1
Pop the saved DE value (4358H, the FCB base address pushed at 4F04H) from the stack into Register Pair DE.
4F5D
POP BC C1
Pop the saved BC value (the chain parameter pushed at 4F03H) from the stack into Register Pair BC.
4F5E
LD DE,4015H 11 15 40
Load Register Pair DE with 4015H, the base address of drive configuration table #1 in the SYS0 resident area. This is passed to the ROM handler at 0013H as the DCB/device pointer for the final dispatch.
4F61
JUMP unconditionally to ROM entry point at 0013H, the character-input/dispatch handler. Entry: DE = 4015H (drive configuration table base). This completes the cleanup and exits SYS7 by handing control back to the ROM I/O dispatcher with the drive table pointer. SYS7 does not return from this jump.

4F64H - Decimal Argument Reader and Loop

This routine reads a decimal numeric argument from the current parse position in the command buffer, then calls a sub-handler B times (the parsed count), and falls through to the parse loop exit at 4F4DH. It is reached as a dispatch target from the command table for commands that take a repeat count.

4F64
GOSUB to the decimal number parser at 5190H. Entry: HL = current parse position in the command buffer. Parses ASCII decimal digits from HL using the multiply-by-10 algorithm and returns BC = the parsed numeric value. HL is advanced past the digits consumed.
4F67
LD B,C 41
Load Register B with the value of Register C, the low byte of the parsed decimal count returned in BC by 5190H. B now holds the repeat count for the loop below. The high byte of BC (Register B from 5190H) is discarded; only counts up to 255 are supported.

4F68H - Repeat Call Loop

Calls the sub-handler at 501EH exactly B times, then falls to the parse loop exit.

4F68
GOSUB to the sub-handler routine at 501EH. This routine performs the action associated with the current command (e.g. a delay step or a single iteration of a repeating operation). The specific action depends on the command that dispatched to 4F64H.
4F6B
Decrement Register B and JUMP back to 4F68H if B is not zero. This repeats the CALL 501EH exactly the number of times specified by the parsed decimal count. When B reaches zero, execution falls through to 4F6DH.
4F6D
JUMP to 4F4DH, the parse loop exit, to clean up the stack and re-enter the FCB open and command read sequence for the next command in the chain.

4F6FH - Display Message and Wait for Key or Drive Event

Pops and re-pushes HL to get the message pointer, calls 4467H to display the message, then polls the hardware status port at 3840H waiting for either bit 0 (BREAK/key signal) or bit 2 (drive-ready signal) to become active. On detection, falls through to the parse loop exit.

4F6F
POP HL E1
Pop the top-of-stack value into Register Pair HL. The top of stack at this point holds the message pointer that was saved before the dispatch to this routine. HL now points to the message string to display.
4F70
PUSH HL E5
Push HL (the message pointer) back onto the stack immediately. The pointer is re-saved so the stack frame remains consistent for the parse loop exit at 4F4DH which expects three saved values.
4F71
GOSUB to SYS0 display routine at 4467H. Entry: HL = pointer to message string. Displays the message to the screen.
4F74
LD A,(3840H) 3A 40 38
Load Register A with the byte at memory address 3840H, the Model I keyboard row 6 / hardware status port. Bit 0 reflects the BREAK key or interrupt signal; bit 2 reflects the drive-ready signal. This read polls the hardware to check for an event.
4F77
AND A,05H E6 05
Mask Register A against 05H (binary 00000101), isolating bits 0 and 2. If either bit 0 or bit 2 is set, A will be non-zero (NZ - event detected). If both are clear, A will be zero (Z - no event yet).
4F79
If the Z FLAG is set (neither bit 0 nor bit 2 active - no event yet), JUMP back to 4F74H to poll again. This is a busy-wait loop that spins until a key press or drive event is detected.
4F7B
JUMP to 4F4DH, the parse loop exit. An event was detected; the routine exits cleanly by cleaning up the stack and re-entering the FCB open and command read sequence.

4F7DH - Print String and Get Keypress

Pops and re-pushes HL to get the message pointer, prints the message character by character via ROM 0033H until a carriage return is found, then calls ROM 0049H for a keyboard scan, echoes the key via 0033H, stores it at 4FBDH, prints a CR, and falls through to the verify-and-continue path at 4F99H.

4F7D
POP HL E1
Pop the top-of-stack value into Register Pair HL. The top of stack holds the message pointer saved before dispatch to this routine. HL now points to the message string to print.
4F7E
PUSH HL E5
Push HL (the message pointer) back onto the stack to re-save it and keep the stack frame consistent.

Character Print Loop
Prints each character of the message pointed to by HL until a carriage return (0DH) is found.

4F7F
LD A,(HL) 7E
Load Register A with the byte at the current HL - the next character of the message string.
4F80
INC HL 23
Increment HL to point to the next character in the message string, ready for the next iteration.
4F81
CP A,0DH FE 0D
Compare Register A against 0DH (carriage return). Tests whether the current character is the end-of-string terminator.
4F83
If the Z FLAG is set (character is CR - end of message), JUMP to 4F8AH to end the print loop and get a keypress.
4F85
GOSUB to ROM character output routine at 0033H. Entry: A = current message character. Outputs the character to the video display.
4F88
JUMP back to 4F7FH to load and print the next character. This loops until the CR terminator is found.

Keypress Capture
The full message has been printed. Now wait for and capture a keypress.

4F8A
GOSUB to ROM keyboard scan routine at 0049H. This is a non-blocking scan that returns the currently pressed key in Register A, or 00H if no key is pressed. The routine waits until a key is detected.
4F8D
GOSUB to ROM character output at 0033H. Entry: A = key character returned by 0049H. Echoes the pressed key to the video display so the user can see what was typed.
4F90
LD (4FBDH),A 32 BD 4F
Self-Modifying Code
Store the key character (in Register A) into memory location 4FBDH. This location is used as a runtime variable to hold the most recently captured keypress or terminator character. It is read back later by the verify path at 4FC0H. Runtime value: the ASCII code of the key pressed by the user.
4F93
LD A,0DH 3E 0D
Load Register A with 0DH (carriage return). This will be output to move the cursor to the start of the next line after echoing the keypress.
4F95
GOSUB to ROM character output at 0033H. Entry: A = 0DH. Outputs a carriage return to the display, ending the line after the echoed keypress.
4F98
POP HL E1
Pop the saved message pointer (pushed at 4F7EH) from the stack into Register Pair HL. HL is restored to the message base address. This discards the saved pointer from the stack frame since the print-and-key operation is complete.

4F99H - Verify and Continue Path

Opens the FCB at 4358H, reads characters from the open file into the command buffer at 4318H via HL until a carriage return, then scans for '/' delimiter sequences. If a '//NUL' or specific terminator pattern is found, stores the result at 4FBDH and calls 447EH before jumping to the parse loop exit.

4F99
PUSH HL E5
Push Register Pair HL (the command buffer pointer restored from the stack at 4F98H, or the current HL at entry to this path) onto the stack. The buffer pointer is re-saved for use by the parse loop exit at 4F4DH.
4F9A
LD DE,4358H 11 58 43
Load Register Pair DE with 4358H, the FCB base address. This is passed to the file-open routine at 444BH.
4F9D
GOSUB to SYS0 at 444BH to open the file described by the FCB at 4358H. On return, Z set = success, NZ = failure.
4FA0
If the NZ FLAG is set (file open failed), JUMP to 4E91H to load the "CHAINING ABORTED" message and exit via the error path.
4FA3
GOSUB to ROM character-input routine at 0013H. Entry: DE = 4358H (FCB pointer). Returns the next character from the open file in Register A.
4FA6
LD (HL),A 77
Store Register A (the character just read) into the memory location pointed to by HL (current position in the command buffer). This writes the character into the buffer.
4FA7
INC HL 23
Increment HL to advance the buffer write pointer to the next position.
4FA8
CP A,0DH FE 0D
Compare Register A against 0DH (carriage return). Tests whether the character just stored is the end-of-line terminator.
4FAA
If the NZ FLAG is set (character was not CR), JUMP back to 4FA3H to read the next character. This loops until a CR is stored in the buffer.
4FAC
POP HL E1
Pop the saved buffer pointer (pushed at 4F99H) from the stack into Register Pair HL. HL is now reset to the beginning of the command buffer at 4318H for the delimiter scan that follows.
4FAD
PUSH HL E5
Push HL (the buffer start pointer) back onto the stack immediately to re-save it for the parse loop exit.
4FAE
LD A,(HL) 7E
Load Register A with the byte at the current HL - the first character of the command buffer (which should be '/' if the buffer starts with a delimiter sequence).
4FAF
CP A,2FH FE 2F
Compare Register A against 2FH (ASCII '/'). Tests whether the first character of the buffer is a '/' delimiter.
4FB1
If the NZ FLAG is set (first character is not '/'), JUMP back to 4F98H to pop HL and re-enter the verify path from the top, retrying with the next buffer state.
4FB3
INC HL 23
Increment HL to point to the second character in the buffer, past the first '/'.
4FB4
CP A,(HL) BE
Compare Register A (still holding 2FH = '/') against the byte at the current HL (the second character of the buffer). Tests whether the second character is also '/', forming a '//' sequence.
4FB5
If the NZ FLAG is set (second character is not '/' - no '//' sequence), JUMP back to 4F98H to retry.
4FB7
INC HL 23
Increment HL to point to the third character in the buffer, past the second '/'.
4FB8
SUB A,(HL) 96
Subtract the byte at the current HL (the third character) from Register A (2FH). If the third character is also '/' (2FH), the result is 00H and the Z FLAG is set - a '///' sequence detected. If not, the result is non-zero.
4FB9
If the Z FLAG is set ('///' sequence found), JUMP to 4FC0H to store the terminator and proceed to the display step.
4FBB
LD A,(HL) 7E
Load Register A with the byte at the current HL (the third character, which is not '/'). This is the option code character following the '//' prefix.
4FBC
CP A,00H FE 00
Compare Register A against 00H. Tests whether the option code character is a null byte, which would indicate a null-terminated or empty option field.
4FBE
If the NZ FLAG is set (option code is not null), JUMP back to 4F98H to retry the verify loop with the next buffer state.

4FC0H - Store Terminator and Call Display

Stores the current Register A value (the terminator character found - either 00H from a null option or 00H from a '///' sequence) into 4FBDH, then calls 447EH to display the buffer content, and jumps to the parse loop exit.

4FC0
LD (4FBDH),A 32 BD 4F
Self-Modifying Code
Store Register A (the terminator character - 00H for '///' or null option) into memory location 4FBDH. This location holds the most recently found command delimiter or terminator character, read back by subsequent parsing logic to determine how to handle the end of the option sequence. Runtime value: 00H in these cases.
4FC3
POP HL E1
Pop the saved buffer pointer (pushed at 4FADH) from the stack into Register Pair HL. HL is restored to the command buffer start at 4318H.
4FC4
PUSH HL E5
Push HL (4318H) back onto the stack immediately to re-save it for the parse loop exit at 4F4DH.
4FC5
GOSUB to SYS0 display routine at 447EH. Entry: HL = 4318H (command buffer start). Displays the content of the command buffer as a message. This echoes the parsed command line back to the user.
4FC8
JUMP unconditionally to 4F4DH, the parse loop exit. Cleans up the stack and re-enters the FCB open and command read sequence for the next command.

4FCBH - Skip Spaces and Commas

Advances HL through the command buffer skipping space (20H) and comma (2CH) separator characters, stopping on the first non-separator character or carriage return. Used to position HL at the start of the next token after a delimiter.

4FCB
LD A,(HL) 7E
Load Register A with the byte at the current HL - the next character in the command buffer at the current parse position.
4FCC
INC HL 23
Increment HL to advance the parse pointer past the current character.
4FCD
CP A,20H FE 20
Compare Register A against 20H (ASCII space). Tests whether the current character is a space separator.
4FCF
If the Z FLAG is set (character was a space), JUMP back to 4FCBH to skip it and read the next character.
4FD1
CP A,2CH FE 2C
Compare Register A against 2CH (ASCII ','). Tests whether the current character is a comma separator.
4FD3
If the Z FLAG is set (character was a comma), JUMP back to 4FCBH to skip it and read the next character.
4FD5
CP A,0DH FE 0D
Compare Register A against 0DH (carriage return). Tests whether the current character is the end-of-line terminator.
4FD7
If the Z FLAG is set (character was CR - end of line), JUMP to 4F4DH, the parse loop exit, to clean up the stack and re-enter the FCB open sequence.
4FDA
CP A,29H FE 29
Compare Register A against 29H (ASCII ')'). Tests whether the current character is a closing parenthesis, which marks the end of a parenthesised option group.
4FDC
If the Z FLAG is set (character was ')'), JUMP to 4FE7H to handle end-of-group processing.
4FDE
CP A,28H FE 28
Compare Register A against 28H (ASCII '('). Tests whether the current character is an opening parenthesis, which marks the start of a parenthesised option group.
4FE0
If the NZ FLAG is set (character was not '(' - it is some other non-separator character), JUMP to 4FF1H to process it as a regular option token.
4FE2
LD (4FE8H),HL 22 E8 4F
Self-Modifying Code
Store Register Pair HL (the current parse position, just past the '(' character) into memory locations 4FE8H-4FE9H. This saves the position of the start of the parenthesised group so that the closing ')' handler at 4FE7H can verify the group boundaries. Runtime value: the address in HL at the time '(' is encountered.
4FE5
JUMP back to 4FCBH to continue scanning, now inside the parenthesised group. The opening '(' has been recorded; parsing continues with the characters inside the group.

4FE7H - Closing Parenthesis Handler

Handles a ')' character found during parsing. Loads HL with 0000H (null pointer) and tests whether it is non-zero. Since it is always zero here, jumps to the skip-separator loop at 4FCBH to continue parsing after the closing parenthesis.

4FE7
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H. This clears HL to a null pointer value. The immediate OR test that follows uses this to determine whether a saved group-start pointer is present.
4FEA
LD A,H 7C
Load Register A with the high byte of HL (00H). Used together with the OR below to test whether HL is zero.
4FEB
OR A,L B5
OR Register A (H byte = 00H) with Register L (00H). Result is 00H, setting the Z FLAG. This tests whether HL is zero - since HL was just loaded with 0000H it is always zero here, so Z is always set.
4FEC
If the NZ FLAG is set (HL was non-zero - a saved group pointer exists), JUMP to 4FCBH to continue parsing inside the group. Since HL is always 0000H here, this branch is never taken; execution always falls through.
4FEE
JUMP unconditionally to 4F52H, the invalid command line error handler. Since HL was zero (no open group was recorded when ')' was encountered), the closing parenthesis is unmatched and the command line is invalid.

4FF1H - Option Token Processor

Reached when a non-separator, non-parenthesis character is found. Steps HL back one position to point at the character, calls 5190H to parse a decimal count, stores the XOR-inverted count as a self-modifying operand, then enters a loop that alternately calls 5014H (when bit 0 of the count is set) and 501EH (when bit 0 is clear), polls the hardware status port for a terminating event, and repeats via DJNZ.

4FF1
DEC HL 2B
Decrement HL by one to step back to the current non-separator character. The INC HL at 4FCCH advanced past it; this restores HL to point at the token character so the decimal parser at 5190H can read it.
4FF2
GOSUB to the decimal number parser at 5190H. Entry: HL = current parse position. Parses ASCII decimal digits into BC using the multiply-by-10 algorithm. Returns BC = parsed value, HL advanced past the digits.
4FF5
LD B,C 41
Load Register B with the value of Register C (the low byte of the parsed decimal count returned in BC by 5190H). B will serve as the DJNZ loop counter. Only the low byte is used; counts above 255 are not supported.
4FF6
LD A,00H 3E 00
Load Register A with 00H. This is the base value that will be XOR-inverted with FFH at the next instruction to produce FFH. Used to initialise the self-modifying counter byte.
4FF8
XOR A,0FFH EE FF
XOR Register A (00H) with FFH, producing FFH in A. This inverted value is stored as a self-modifying operand at 4FF7H that controls which of the two sub-handlers (5014H or 501EH) is called on each loop iteration.
4FFA
LD (4FF7H),A 32 F7 4F
Self-Modifying Code
Store Register A (FFH) into memory location 4FF7H. Location 4FF7H is the operand byte of the LD A,00H instruction at 4FF6H. By writing FFH here, the next time through the loop this instruction will load A with FFH instead of 00H, toggling the handler selection. Runtime value: alternates between 00H and FFH on successive iterations.
4FFD
LD C,A 4F
Load Register C with Register A (FFH on first entry). C holds the current handler-selection value. The BIT tests below use bit 0 of C to decide which sub-handler to call.
4FFE
BIT 0,C CB 41
Test bit 0 of Register C. If bit 0 is set (C = FFH, odd), the Z FLAG is clear (NZ). If bit 0 is clear (C = 00H, even), the Z FLAG is set.
5000
If the NZ FLAG is set (bit 0 of C is 1 - odd iteration), CALL 5014H. This sub-handler performs one phase of the option action (e.g. asserting a signal or writing to a port).
5003
BIT 0,C CB 41
Test bit 0 of Register C again. This second test selects the complementary handler for the even iteration.
5005
If the Z FLAG is set (bit 0 of C is 0 - even iteration), CALL 501EH. This sub-handler performs the complementary phase of the option action.
5008
LD A,(3840H) 3A 40 38
Load Register A with the byte at memory address 3840H, the Model I keyboard row 6 / hardware status port. Bits 0 and 2 are checked to detect a terminating event.
500B
AND A,05H E6 05
Mask Register A against 05H (binary 00000101), isolating bits 0 and 2. If either is set, a key or drive event has occurred and A is non-zero (NZ).
500D
If the NZ FLAG is set (event detected), JUMP to 4F4DH, the parse loop exit. The option action is terminated by the hardware event.
5010
Decrement Register B and JUMP back to 4FFEH if B is not zero. This repeats the handler-call and status-poll sequence for the full parsed count. When B reaches zero, execution falls through.
5012
JUMP back to 4FCBH to continue scanning the command buffer for the next separator or token. The option token has been fully processed.

5014H - Sub-handler A: Six Iterations of 502FH

Preserves BC, calls 502FH six times via DJNZ, then restores BC and returns. Called from the option token processor at 5000H when bit 0 of the handler-selection byte is set.

5014
PUSH BC C5
Save Register Pair BC (the loop counter and chain parameter) onto the stack. BC must be preserved across the six calls to 502FH.
5015
LD B,06H 06 06
Load Register B with 06H. B is the DJNZ counter that will call 502FH exactly six times.
5017
GOSUB to 502FH, which asserts the output port at 37E4H and optionally delays. One of the six iterations.
501A
Decrement Register B and JUMP back to 5017H if B is not zero. Calls 502FH six times in total.
501C
POP BC C1
Restore Register Pair BC from the stack, recovering the loop counter and chain parameter saved at 5014H.
501D
RET C9
Return to the caller at 5002H in the option token processor.

501EH - Sub-handler B: Conditional Delay

Reads bit 3 of the DOS system flags byte at 430FH. If set, calls the delay routine at 5026H. Returns to the caller. Called from the option token processor at 5005H when bit 0 of the handler-selection byte is clear, and from the repeat loop at 4F68H.

501E
LD A,(430FH) 3A 0F 43
Load Register A with the current value of the DOS system flags byte at 430FH. A snapshot of all system flag bits is taken for the BIT test that follows.
5021
BIT 3,A CB 5F
Test bit 3 of Register A (the value just read from 430FH). Bit 3 is a flag indicating whether the extended delay mode is active. If set (NZ), the delay routine is called; if clear (Z), it is skipped.
5023
If the NZ FLAG is set (bit 3 of 430FH is set - extended delay active), CALL 5026H to perform the delay. If bit 3 is clear, this call is skipped and execution falls through to RET.

5026H - Delay Routine

Preserves BC, loads BC with 199BH (the delay count), calls ROM 0060H to perform a busy-wait delay loop, then restores BC and returns.

5026
PUSH BC C5
Save Register Pair BC onto the stack. BC holds the loop counter and chain parameter that must be preserved across the ROM delay call.
5027
LD BC,199BH 01 9B 19
Load Register Pair BC with 199BH (decimal 6555). This is the delay count passed to the ROM delay routine at 0060H. The value 199BH produces a delay of approximately 6555 iterations of the ROM busy-wait loop, corresponding to a specific timing interval used by the chaining option processor.
502A
GOSUB to ROM delay routine at 0060H. Entry: BC = 199BH (loop count). Performs a busy-wait delay by decrementing BC to zero. On return the delay period has elapsed.
502D
POP BC C1
Restore Register Pair BC from the stack, recovering the loop counter and chain parameter saved at 5026H.
502E
RET C9
Return to the caller. If called from 5023H (CALL NZ), returns to 5025H which falls through to RET at 5025H and then back to the option token processor. If called from 502FH, returns to 5038H.

502FH - Port Assert and Optional Delay

Writes 01H to the output port at 37E4H (asserting a signal), then calls 503CH which writes 00H to the same port (deasserting it) and optionally delays. Used by sub-handler A at 5017H to toggle the port six times per call.

502F
LD A,01H 3E 01
Load Register A with 01H. This is the value to be written to the hardware output port at 37E4H to assert the signal (set bit 0 high).
5031
GOSUB to 5036H to write Register A (01H) to port 37E4H and optionally delay. On return the port has been written.
5034
LD A,00H 3E 00
Load Register A with 00H. This is the value to write to port 37E4H to deassert the signal (set bit 0 low).

5036H - Write to Port 37E4H and Optional Delay

Writes Register A to memory-mapped I/O port 37E4H, reads bit 3 of the DOS flags at 430FH, and if set calls the delay routine at 5041H. Returns to the caller. This is the low-level port write used by both the assert (01H) and deassert (00H) steps of the option token processor.

5036
LD (37E4H),A 32 E4 37
Store Register A into memory address 37E4H. On the TRS-80 Model I, address 37E4H is a memory-mapped I/O register used to control an external hardware signal - in the VTOS chaining context this is the port used to assert or deassert a hardware handshake or control line associated with the chaining mechanism. Writing 01H asserts the line; writing 00H deasserts it.
5039
LD A,(430FH) 3A 0F 43
Load Register A with the current value of the DOS system flags byte at 430FH. Bit 3 is checked to determine whether the extended delay is required after the port write.
503C
BIT 3,A CB 5F
Test bit 3 of Register A (value from 430FH). If bit 3 is set (NZ), the extended delay routine at 5041H is called. If clear (Z), the delay is skipped.
503E
If the NZ FLAG is set (bit 3 of 430FH active), CALL 5041H to perform a short busy-wait delay after the port write, allowing the hardware time to respond to the signal change.
5041
LD DE,0240H 11 40 02
Load Register Pair DE with 0240H (decimal 576). This is the iteration count for the inline busy-wait delay loop that follows.
5044
DEC DE 1B
Decrement Register Pair DE by 1. Each iteration reduces the count by one.
5045
LD A,D 7A
Load Register A with the high byte of DE (Register D). Used together with the OR below to test whether DE has reached zero.
5046
OR A,E B3
OR Register A (D byte) with Register E. If DE is 0000H, both D and E are 00H and the result is 00H, setting the Z FLAG. If DE is non-zero, the result is non-zero, clearing Z.
5047
If the NZ FLAG is set (DE not yet zero), JUMP back to 5044H to continue the delay loop. When DE reaches zero, execution falls through.
5049
RET C9
Return to the caller. The port write and optional delay are complete. If reached via CALL NZ at 503EH, returns to 5040H which is the instruction after the CALL, falling through to 5041H - however since 5041H is the delay entry itself, a direct fall-through from RET at 5049H returns to 5040H and then to the caller of 5036H.

504AH - Read Count and Timed Loop

Parses a decimal count from the command buffer via 5190H, then loops B times calling 505EH per iteration, polling 3840H for a terminating event after each call. On event detection or loop completion, jumps to the parse loop exit.

504A
CALL 5190H CD 90 51
GOSUB to the decimal number parser at 5190H. Entry: HL = current parse position in the command buffer. Returns BC = parsed decimal count. HL is advanced past the digits consumed.
504D
LD B,C 41
Load Register B with Register C, the low byte of the decimal count returned in BC by 5190H. B becomes the DJNZ loop counter for the timed repetition loop below.
504E
CALL 505EH CD 5E 50
GOSUB to 505EH to perform one iteration of the timed action: calls 501EH (conditional delay) then 5064H (video invert). This is one pass of the timed loop.
5051
LD A,(3840H) 3A 40 38
Load Register A with the byte at memory address 3840H, the Model I hardware status port. Bits 0 and 2 are checked for a terminating event (key or drive activity).
5054
AND A,05H E6 05
Mask Register A against 05H (binary 00000101), isolating bits 0 and 2. If either bit is set, A is non-zero (NZ) indicating an event has occurred.
5056
JP NZ,4F4DH C2 4D 4F
If the NZ FLAG is set (event detected), JUMP to 4F4DH, the parse loop exit, to clean up the stack and re-enter the FCB open sequence.
5059
Decrement Register B and JUMP back to 504EH if B is not zero. Repeats the timed action and event poll for the full parsed count. When B reaches zero, execution falls through.
505B
JP 4F4DH C3 4D 4F
JUMP unconditionally to 4F4DH, the parse loop exit. The timed loop completed without a terminating event; clean up the stack and continue.

505EH - Timed Action: Delay then Video Invert

Calls the conditional delay at 501EH, then falls through to 5064H to invert the video RAM. Used as the body of the timed loop at 504EH.

505E
CALL 501EH CD 1E 50
GOSUB to 501EH, the conditional delay sub-handler. Reads bit 3 of 430FH; if set, calls the delay routine at 5026H. On return the optional delay has been performed.
5061
CALL 5064H CD 64 50
GOSUB to 5064H, the video RAM invert routine. Inverts every byte in the video RAM at 3C00H-3FFFH by XORing each byte with DFH, producing a flashing or inverse-video effect. On return all video RAM bytes have been toggled.

5064H - Video RAM Invert

Inverts every byte in the Model I video RAM (3C00H-3FFFH, 1024 bytes) by XORing each byte with DFH. This toggles bit 5 of each character code, switching between normal and inverse video for every character on screen. Used to produce a flash effect by the timed action loop.

5064
LD HL,3C00H 21 00 3C
Load Register Pair HL with 3C00H, the base address of the Model I video RAM. The 1024-byte video buffer occupies 3C00H-3FFFH (64 columns x 16 rows). HL is the read/write pointer for the XOR loop.
5067
LD A,(HL) 7E
Load Register A with the byte at the current HL - the current video RAM character code at the screen position pointed to by HL.
5068
XOR A,0DFH EE DF
XOR Register A with DFH (binary 11011111). This toggles bit 5 of the character code. On the Model I, bit 5 of a character code distinguishes between normal characters (bit 5 set) and graphic/inverse characters (bit 5 clear), so this XOR inverts the display appearance of every character.
506A
LD (HL),A 77
Store the XOR-inverted character code back into the video RAM at the current HL position, updating the display.
506B
INC L 2C
Increment Register L (the low byte of HL) to advance the pointer to the next video RAM byte. Only L is incremented here rather than the full HL pair, exploiting the fact that the video RAM is aligned to a 256-byte boundary: incrementing L wraps within each 256-byte page.
506C
If the NZ FLAG is set (L has not wrapped to 00H - still within the current 256-byte page), JUMP back to 5067H to process the next video RAM byte. When L wraps from FFH to 00H, the Z FLAG is set and execution falls through.
506E
INC H 24
Increment Register H (the high byte of HL) to advance to the next 256-byte page of video RAM. After processing the first page (3C00H-3CFFH), H advances from 3CH to 3DH, and so on.
506F
LD A,H 7C
Load Register A with the current high byte of HL (Register H). This value is compared against 40H to detect when HL has advanced past the end of video RAM at 3FFFH.
5070
CP A,40H FE 40
Compare Register A against 40H. The video RAM ends at 3FFFH, so when H reaches 40H, all four 256-byte pages (3C00H, 3D00H, 3E00H, 3F00H) have been processed. If H equals 40H, the Z FLAG is set indicating completion.
5072
If the NZ FLAG is set (H has not reached 40H - more video RAM pages remain), JUMP back to 5067H to continue inverting the next page. When H equals 40H, execution falls through.
5074
JR 501EH 18 A8
JUMP to 501EH, the conditional delay sub-handler. After inverting the entire video RAM, a delay is performed if bit 3 of 430FH is set, creating a visible pause between flash states. On return from 501EH, execution returns to the caller of 5064H.

5076H - Display Message from Stack and Read Decimal

Exchanges HL with the top of stack to retrieve a message pointer, calls 4467H to display the message, restores HL, then calls 5190H to read a decimal number from the command buffer. Used to prompt the user and read a response count.

5076
EX (SP),HL E3
Exchange Register Pair HL with the value at the top of the stack. The current HL is saved to the stack, and the message pointer that was on top of the stack is loaded into HL. HL now points to the message string to display.
5077
CALL 4467H CD 67 44
GOSUB to SYS0 display routine at 4467H. Entry: HL = message pointer. Displays the message string to the screen.
507A
EX (SP),HL E3
Exchange Register Pair HL with the top of stack again, restoring HL to its previous value (the parse position) and returning the message pointer to the stack.
507B
CALL 5190H CD 90 51
GOSUB to the decimal number parser at 5190H. Entry: HL = current parse position. Returns BC = parsed decimal value. HL is advanced past the digits.
507E
LD A,(HL) 7E
Load Register A with the byte at the current HL - the character immediately following the parsed decimal digits in the command buffer. This is examined to verify the expected ':' separator.
507F
CP A,3AH FE 3A
Compare Register A against 3AH (ASCII ':'). Tests whether the character following the decimal number is a colon, which is the expected field separator in this command syntax.
5081
JP NZ,4F52H C2 52 4F
If the NZ FLAG is set (character after the decimal is not ':'), JUMP to 4F52H, the invalid command line error handler. The expected syntax requires a ':' separator after the count.
5084
LD A,C 79
Load Register A with Register C, the low byte of the parsed decimal count returned in BC. This value is stored as a self-modifying operand in the next instruction.
5085
LD (50A2H),A 32 A2 50
Self-Modifying Code
Store Register A (the low byte of the first parsed decimal field) into memory location 50A2H. Location 50A2H is the operand byte of the CP A,00H instruction at 50A1H in the XWAIT command handler. This patches the comparison value so that the wait loop at 509EH terminates when the clock value reaches the stored count. Runtime value: the first decimal field parsed from the command line.
5088
INC HL 23
Increment HL to advance the parse pointer past the ':' separator character, positioning HL at the start of the second numeric field.
5089
CALL 5190H CD 90 51
GOSUB to the decimal number parser at 5190H again to read the second numeric field. Entry: HL = position after ':'. Returns BC = second parsed value. HL is advanced past those digits.
508C
LD A,(HL) 7E
Load Register A with the character following the second decimal field - the expected second ':' separator.
508D
CP A,3AH FE 3A
Compare Register A against 3AH (ASCII ':'). Tests whether the second separator is also a colon as required by the three-field command syntax.
508F
JP NZ,4F52H C2 52 4F
If the NZ FLAG is set (second separator is not ':'), JUMP to 4F52H, the invalid command line error handler.
5092
LD A,C 79
Load Register A with Register C, the low byte of the second parsed decimal field returned by the second call to 5190H.
5093
LD (50A9H),A 32 A9 50
Self-Modifying Code
Store Register A (the second decimal field) into memory location 50A9H. Location 50A9H is the operand byte of the CP A,00H instruction at 50A8H in the wait loop. This patches the comparison threshold for the second clock field (minutes). Runtime value: the second decimal field from the command line.
5096
INC HL 23
Increment HL to advance past the second ':' separator to the start of the third numeric field.
5097
CALL 5190H CD 90 51
GOSUB to 5190H to read the third and final numeric field from the command line. Returns BC = third parsed value. HL is advanced past those digits.
509A
LD A,C 79
Load Register A with Register C, the low byte of the third parsed decimal field.
509B
LD (50B0H),A 32 B0 50
Self-Modifying Code
Store Register A (the third decimal field) into memory location 50B0H. Location 50B0H is the operand byte of the CP A,00H instruction at 50AFH in the wait loop. This patches the comparison threshold for the third clock field (seconds). Runtime value: the third decimal field from the command line.

509EH - Clock Wait Loop

Waits until the real-time clock values at 4041H (seconds), 4042H (minutes), and 4043H (hours) reach the threshold values patched into the comparison instructions at 50A2H, 50A9H, and 50B0H respectively. Loops continuously reading the clock bytes and comparing against the stored thresholds until all three match, then jumps to the parse loop exit.

509E
LD A,(4043H) 3A 43 40
Load Register A with the current hours value from the real-time clock byte at 4043H in the SYS0 resident work area. The clock is maintained by the interrupt service routine which increments these bytes at regular intervals.
50A1
CP A,00H FE 00
Self-Modifying Code
Compare Register A (current hours) against the threshold value at the operand byte 50A2H. The 00H shown here is the initial value; the operand at 50A2H was patched with the first decimal field by the instruction at 5085H. If A equals the patched threshold, Z is set. Runtime comparison value: the first decimal field from the command line.
50A3
If the NZ FLAG is set (hours value does not yet match the threshold), JUMP back to 509EH to re-read the hours clock byte and try again. This loops until the hours threshold is met.
50A5
LD A,(4042H) 3A 42 40
Load Register A with the current minutes value from the real-time clock byte at 4042H. This is checked only after the hours threshold has been met.
50A8
CP A,00H FE 00
Self-Modifying Code
Compare Register A (current minutes) against the threshold at operand byte 50A9H, patched at 5093H with the second decimal field. Runtime comparison value: the second decimal field.
50AA
If the NZ FLAG is set (minutes value does not match), JUMP back to 509EH to restart the clock comparison from the hours byte. The loop restarts from the top to ensure all three fields are checked together.
50AC
LD A,(4041H) 3A 41 40
Load Register A with the current seconds value from the real-time clock byte at 4041H. This is checked last, only after both hours and minutes thresholds have been met.
50AF
CP A,00H FE 00
Self-Modifying Code
Compare Register A (current seconds) against the threshold at operand byte 50B0H, patched at 509BH with the third decimal field. Runtime comparison value: the third decimal field.
50B1
If the NZ FLAG is set (seconds value does not match), JUMP back to 509EH to restart from the hours check. All three clock fields must simultaneously match their thresholds before the loop exits.
50B3
JP 4F4DH C3 4D 4F
JUMP unconditionally to 4F4DH, the parse loop exit. All three clock thresholds have been met; the wait is complete. Stack cleanup and re-entry to the FCB open sequence follows.

50B6H - Command Keyword Table

The command keyword table searched by the routine at 5143H. Each entry consists of a 6-character keyword (space-padded, uppercase, terminated by 03H at position 6) followed by a 2-byte little-endian handler address. The search key from the keyword reader at 50FFH is compared against the 6-character name field of each entry. A null entry (first byte 00H or sentinel) terminates the table.

50B6
"ABORT " + 03H 41 42 4F 52 54 20 03
Keyword entry: "ABORT " (6 chars, space-padded) followed by 03H terminator.
50BC
DEFW 4E8CH 8C 4E
The table search returns DE=4E8CH.
50BE
"ALERT " + 03H 41 4C 45 52 54 20 03
Keyword entry: "ALERT "
50C4
DEFW 4FCBH CB 4F
The table search returns DE=4FCBH.
50C6
"DELAY "+ 03H 44 45 4C 41 59 20 03
Keyword entry: "DELAY " (space-padded to 6 chars). The DELAY command reads a decimal repeat count and calls the sub-handler that many times, implementing a timed delay in the chain sequence.
50CC
DEFW 4F64H 64 4F
Subhandler for "DELAY" = 4F64H.
50CE
"EXIT " + 03H 45 58 49 54 20 20 03
Keyword entry: "EXIT " (space-padded). Handler address follows. The EXIT command performs a conditional exit from the chain sequence based on an option condition.
50D4
DEFW 4E91H91 4E
Subhandler for "EXIT" = 4E91H.
50D6
"FLASH " + 03H 46 4C 41 53 20 48 03
Keyword entry: "FLASH " with handler at 504AH. The NFLASH command reads a decimal count and repeatedly inverts the video RAM (flashing the screen) for the specified number of iterations.
50D4
DEFW 504AH 4A 50
Subhandler for "FLASH" = 504AH.
50DE
"KEYIN " + 03H 50 4B 45 59 49 4E 20 03
Keyword entry: "KEYIN " with handler at 4F7DH. The KEYIN command prints a message and waits for a keypress, capturing the key character for use in subsequent processing.
50D4
DEFW 4F7DH 7D 4F
Subhandler for "KEYIN" = 4F7DH.
50E6
"PAUSE " + 03H 50 41 55 53 45 20 03
Keyword entry: "PAUSE " (space-padded) with handler at 4F6FH. The PAUSE command displays a message and waits for either a key press or a drive event before continuing the chain.
50EC
DEFW 4F6FH 6F 4F
Subhandler for "PAUSE" = 4F6FH.
50EE
"STOP " + 03H 53 54 4F 50 20 20 03
Keyword entry: "STOP " (space-padded). Handler address follows. The STOP command performs a conditional stop in the chain sequence.
50F4
DEFW 4F58H 58 4F
Subhandler for "STOP" = 4F58H.
50F6
"WAIT " + 03H 57 41 49 54 20 20003
Keyword entry: "WAIT " (space-padded). Handler address follows.
50FC
DEFW 5076H 76 50
Subhandler for "WAIT" = 5076H.
50FE
DEFB 00H00
A 00H byte marks the end of the command keyword table. The search routine at 5143H tests the first byte of each entry; when 00H is found the search terminates with NZ (no match).

50FFH - Keyword / Filename Reader

Reads up to B characters from the source string at HL into the destination buffer at DE. Accepts uppercase letters (41H-5AH), digits (30H-39H), and lowercase letters (61H-7AH converted to uppercase by subtracting 20H). Any other character terminates the read. The destination buffer is written with valid characters and closed with a 03H terminator. Returns Z if at least one valid character was written, NZ if none were found.

50FF
LD A,B 78
Load Register A with Register B, the maximum character count (06H when called from 4F39H). This value is stored at 513FH as the no-valid-character sentinel: if it remains non-zero at return time, no valid character was found.
5100
LD (513FH),A 32 3F 51
Self-Modifying Code
Store Register A (initial count, 06H) into memory location 513FH. Location 513FH is used as a flag: it holds the original count while no valid character has been placed in the output buffer, and is zeroed at 5131H the first time a valid character is stored. On return, if 513FH is non-zero the routine returns NZ (no valid characters found); if zero it returns Z (at least one character stored). Runtime value: 06H at entry, 00H after first valid character is stored.
5103
INC B 04
Increment Register B by 1, pre-compensating the character count. The character read loop at 5104H fetches a character and then tests B via DEC B / JR Z at 512CH-512DH. The extra increment ensures the first valid character does not prematurely trigger the buffer-full exit.
5104
LD A,(HL) 7E
Load Register A with the byte at the current HL - the next character from the source string in the command buffer at the current parse position.
5105
CP A,03H FE 03
Compare Register A against 03H (ETX end-of-text terminator). Tests whether the source character is the keyword-list terminator used in the chaining option format.
5107
If the Z FLAG is set (character is 03H terminator), JUMP to 513AH to close the output buffer with a 03H byte and return.
5109
CP A,0DH FE 0D
Compare Register A against 0DH (carriage return). Tests whether the source character is the end-of-line terminator.
510B
If the Z FLAG is set (character is CR), JUMP to 513AH to close the output buffer and return.
510D
CP A,28H FE 28
Compare Register A against 28H (ASCII '('). Tests whether the current character is an opening parenthesis, which terminates a keyword token in the chaining command syntax.
510F
If the Z FLAG is set (character is '('), JUMP to 513AH to close the output buffer and return.
5111
INC HL 23
Increment HL to advance the source pointer past the current character. HL now points to the next character in the command buffer. The advance is done before the range checks so that on any valid character path HL is already positioned correctly for the next iteration.
5112
CP A,30H FE 30
Compare Register A against 30H (ASCII '0'). If A is less than 30H the character is below the digit range and is not a valid alphanumeric. The CARRY FLAG is set when A is below 30H.
5114
If the CARRY FLAG is set (A is below 30H - not a valid character), JUMP to 513AH to close the output buffer and return.
5116
CP A,3AH FE 3A
Compare Register A against 3AH (one past ASCII '9'). If A is less than 3AH the character is a valid decimal digit in the range 30H-39H.
5118
If the CARRY FLAG is set (A is in 30H-39H - valid digit), JUMP to 512CH to store the character into the output buffer at DE.
511A
CP A,41H FE 41
Compare Register A against 41H (ASCII 'A'). If A is less than 41H the character falls in the gap between digits and uppercase letters (3AH-40H) and is not a valid keyword character.
511C
If the CARRY FLAG is set (A is in 3AH-40H - non-alphanumeric gap), JUMP to 513AH to close the output buffer and return.
511E
CP A,5BH FE 5B
Compare Register A against 5BH (one past ASCII 'Z'). If A is less than 5BH the character is a valid uppercase letter in the range 41H-5AH.
5120
If the CARRY FLAG is set (A is in 41H-5AH - valid uppercase letter), JUMP to 512CH to store the character into the output buffer.
5122
CP A,61H FE 61
Compare Register A against 61H (ASCII 'a'). If A is less than 61H the character falls in the gap between uppercase and lowercase letters (5BH-60H) and is not valid.
5124
If the CARRY FLAG is set (A is in 5BH-60H - non-alphanumeric gap), JUMP to 513AH to close the output buffer and return.
5126
CP A,7BH FE 7B
Compare Register A against 7BH (one past ASCII 'z'). If A is less than 7BH the character is a valid lowercase letter in the range 61H-7AH.
5128
If the CARRY FLAG is clear (A is 7BH or above - above the lowercase range), JUMP to 513AH to close the output buffer and return.
512A
SUB A,20H D6 20
Subtract 20H from Register A. Converts a lowercase letter (61H-7AH) to its uppercase equivalent (41H-5AH) by removing the bit 5 difference between the two ASCII ranges. Execution falls through to 512CH to store the now-uppercased character.

512CH - Store Valid Character into Output Buffer

Common entry point reached after a character in Register A has been validated as alphanumeric (and uppercased if necessary). Decrements the remaining-space counter B, stores the character to DE if space remains, clears the no-valid-character flag at 513FH, advances DE, and loops back to 5104H to read the next character. If the buffer is full, increments B back to 1 and loops to discard further source characters.

512C
DEC B 05
Decrement Register B, the remaining output buffer space counter. B was set to the maximum count + 1 at 5103H. Each valid character stored reduces B by one. When B reaches zero the output buffer is full.
512D
If the Z FLAG is set (B has reached zero - output buffer full), JUMP to 5137H to restore B to 1 and continue consuming source characters without storing them, discarding overflow input.
512F
LD (DE),A 12
Store Register A (the valid uppercase character) into the output keyword buffer at the address in Register Pair DE. One character is written to the work buffer at 51AAH.
5130
XOR A,A AF
Clear Register A to 00H by XORing it with itself. The value 00H will be written to 513FH to clear the no-valid-character sentinel flag.
5131
LD (513FH),A 32 3F 51
Self-Modifying Code
Store 00H into memory location 513FH. This clears the no-valid-character flag that was initialised at 5100H with the original count. Once zeroed here, the flag stays at 00H for the remainder of this call, ensuring the routine returns Z on exit regardless of subsequent characters. Runtime value: 00H after the first valid character is stored.
5134
INC DE 13
Increment Register Pair DE to advance the output buffer pointer to the next available position in the keyword work buffer at 51AAH.
5135
JR 5104H 18 CD
JUMP back to 5104H to load the next character from the source string and repeat the validation and store sequence.
5137
INC B 04
Increment Register B back to 1. B had decremented to zero indicating the buffer is full. Restoring it to 1 allows the loop to continue consuming and discarding source characters without attempting further stores.
5138
JR 5104H 18 CA
JUMP back to 5104H to read and discard the next source character. The loop continues until a terminating character (03H, 0DH, '(', or out-of-range byte) is encountered.

513AH - Pad Buffer and Return

Reached when a terminating character is found during the keyword read. Saves the terminating character in C, writes a 03H terminator into the output buffer at DE, then tests the flag byte at 513FH via OR to set the Z or NZ return condition. Returns Z if at least one valid character was stored (513FH was zeroed at 5131H), NZ if the buffer is entirely empty (513FH still holds the original count). Register A on return holds the terminating character.

513A
LD C,A 4F
Load Register C with Register A, preserving the terminating character that caused the exit from the read loop. C holds the terminator (03H, 0DH, 28H, or an out-of-range byte) so it can be restored into A before return.
513B
LD A,03H 3E 03
Load Register A with 03H (ETX). This is the keyword terminator byte written into the output buffer to mark the end of the extracted keyword string.
513D
LD (DE),A 12
Store 03H into the output buffer at the current DE position, terminating the keyword string in the work buffer at 51AAH. Any positions between the last stored character and this 03H are implicitly undefined; the 03H marks the logical end of valid keyword data.
513E
LD A,00H 3E 00
Load Register A with 00H in preparation for the OR test that determines the return condition.
5140
OR A,(HL) B6
OR Register A (00H) with the byte at memory address HL. At this point HL still holds the source parse position; however the byte that matters for the return condition is at 513FH. The OR effectively reads the flag byte: if 513FH is 00H (was cleared at 5131H - at least one valid character stored) the result is 00H and Z is set. If 513FH still holds the original count (no valid characters were stored) the result is non-zero and NZ is set. Note: the OR reads from HL which points into the source buffer, not directly from 513FH; the source byte at this position coincidentally reflects the flag state because HL has not been advanced past the terminator.
5141
LD A,C 79
Load Register A with Register C, restoring the terminating character that was saved at 513AH. Register A on return holds the character that ended the keyword read, allowing the caller at 4F3DH to inspect the terminator and determine whether a '(' group follows.
5142
RET C9
Return to the caller. Z FLAG reflects whether a valid keyword was found (Z = yes, NZ = no). Register A holds the terminating character. DE points one past the 03H terminator in the keyword work buffer at 51AAH.

5143H - Command Table Search

Searches the command keyword table pointed to by BC for an entry whose 6-character name field matches the search key at DE. Each table entry is 9 bytes: 6-char name + 03H terminator + 2-byte handler address. Advances through the table in 8-byte steps (add 0008H to HL) until a match is found or a null sentinel terminates the scan. Returns Z and DE = handler address on match; NZ on no match.

5143
PUSH HL E5
Save Register Pair HL (the current parse position pointer) onto the stack. HL is preserved across the table search so the caller's parse position is not disturbed.
5144
LD H,B 60
Load Register H with Register B (the high byte of the table base address BC). HL is being constructed to point to the start of the command keyword table.
5145
LD L,C 69
Load Register L with Register C (the low byte of the table base address BC). HL now equals BC and points to the first entry in the command keyword table at 50B6H.
5146
LD A,(DE) 1A
Load Register A with the byte at the address in Register Pair DE - the first character of the search key in the keyword work buffer at 51AAH. This is the first character to compare against the current table entry.
5147
CP A,(HL) BE
Compare Register A (first character of search key) against the byte at the current HL (first character of the current table entry name). If they match, Z is set; if not, NZ is set.
5148
If the Z FLAG is set (first characters match), JUMP to 5157H to perform the full 5-character comparison of the remaining keyword bytes.
514A
PUSH BC C5
Save Register Pair BC (the table base address) onto the stack. BC must be preserved while HL is advanced to the next table entry.
514B
LD BC,0008H 01 08 00
Load Register Pair BC with 0008H. Each command table entry is 8 bytes (6-char name + 03H + 1 byte of the 2-byte handler address that straddles the boundary). Adding 8 to HL advances to the first byte of the next entry.
514E
ADD HL,BC 09
Add BC (0008H) to HL, advancing HL to the start of the next command keyword table entry.
514F
POP BC C1
Restore Register Pair BC (the table base address) from the stack.
5150
LD A,(HL) 7E
Load Register A with the first byte of the next table entry at the new HL. This is used by the sentinel test below to detect the end of the table.
5151
OR A,A B7
OR Register A with itself. Sets the Z FLAG if A is 00H (null sentinel - end of table). Clears Z if A is non-zero (valid entry name byte).
5152
If the NZ FLAG is set (current entry is not the null sentinel - more entries remain), JUMP back to 5146H to compare the first character of this entry against the search key.
5154
POP HL E1
Pop the saved HL (the caller's parse position) from the stack, restoring it before returning.
5155
INC A 3C
Increment Register A (currently 00H from the null sentinel). The result is 01H, which is non-zero, ensuring the NZ FLAG is set on return to signal no match was found.
5156
RET C9
Return to the caller with NZ set, indicating the search key was not found in the command keyword table.

5157H - Full Keyword Match

Reached when the first character of the search key matched the current table entry. Compares the remaining 5 characters of the keyword one by one. If all 5 match, loads DE with the handler address from the table entry and returns Z. If any character mismatches, steps to the next table entry and resumes the outer scan.

5157
LD B,05H 06 05
Load Register B with 05H. This is the count of remaining characters to compare (positions 2 through 6 of the 6-character keyword). The first character was already matched at 5147H.
5159
PUSH HL E5
Save Register Pair HL (current table entry pointer) onto the stack. HL is preserved so that if the full match fails, it can be restored to step to the next entry via the outer scan loop.
515A
PUSH DE D5
Save Register Pair DE (the search key pointer into 51AAH) onto the stack. DE must be restored if the match fails so the outer loop can retry from the same search key.
515B
INC DE 13
Increment DE to advance the search key pointer past the first character (already matched), pointing to the second character of the search key.
515C
INC HL 23
Increment HL to advance the table entry pointer past the first character (already matched), pointing to the second character of the current table entry name.
515D
LD A,(DE) 1A
Load Register A with the next character of the search key from the buffer at DE.
515E
CP A,03H FE 03
Compare Register A against 03H (ETX terminator). Tests whether the search key has ended before all 5 remaining characters have been compared. A 03H in the search key means the keyword is shorter than 6 characters.
5160
If the Z FLAG is set (search key character is 03H - end of key), JUMP to 5187H to check whether the table entry character at the same position is a space (20H), which would indicate a match on a shorter keyword.
5162
CP A,0DH FE 0D
Compare Register A against 0DH (carriage return). Tests whether the search key ends with a CR instead of a 03H terminator.
5164
If the Z FLAG is set (search key character is CR - end of key), JUMP to 5187H to perform the trailing-space match check.
5166
CP A,(HL) BE
Compare Register A (current search key character) against the byte at the current HL (corresponding character of the table entry name). Tests whether this character position matches.
5167
If the NZ FLAG is set (characters do not match at this position), JUMP to 5177H to abandon this entry and resume the outer scan.
5169
Decrement Register B and JUMP back to 515BH if B is not zero. Repeats the character comparison for each of the 5 remaining positions. When B reaches zero all 5 remaining characters matched.
516B
POP DE D1
Pop the saved DE (search key pointer) from the stack. DE is restored but its value is no longer needed since the match succeeded.
516C
POP BC C1
Pop the saved HL (table entry pointer at start of this entry) from the stack into Register Pair BC. BC now points to the start of the matched table entry.
516D
LD HL,0006H 21 06 00
Load Register Pair HL with 0006H. Adding this offset to BC (the matched entry base) advances the pointer 6 bytes past the name field to reach the handler address bytes at positions +6 and +7 of the table entry.
5170
ADD HL,BC 09
Add BC (matched entry base address) to HL (offset 0006H). HL now points to the low byte of the 2-byte little-endian handler address stored at offset +6 of the matched table entry.
5171
LD E,(HL) 5E
Load Register E with the byte at the current HL - the low byte of the handler address stored in the table entry.
5172
INC HL 23
Increment HL to point to the high byte of the handler address.
5173
LD D,(HL) 56
Load Register D with the byte at the current HL - the high byte of the handler address. DE now holds the complete 16-bit handler address for the matched keyword command.
5174
POP HL E1
Pop the saved HL (the caller's parse position, pushed at 5143H) from the stack, restoring it before return.
5175
XOR A,A AF
Clear Register A to 00H, setting the Z FLAG. This ensures the routine returns with Z set to signal a successful match to the caller at 4F46H.
5176
RET C9
Return to the caller with Z set and DE = handler address. The matched command's handler address is in DE ready for the dispatch at 4F4BH.

5177H - Mismatch: Resume Outer Scan

Reached when a character comparison failed during the full keyword match at 5166H. Restores DE and HL from the stack, then re-enters the outer scan loop to advance to the next table entry and retry.

5177
CP A,30H FE 30
Compare Register A (the mismatched search key character) against 30H (ASCII '0'). This and the following range checks determine whether the mismatched character is still a valid alphanumeric, which affects whether the outer scan should continue or abort entirely.
5179
If the CARRY FLAG is set (A < 30H - character is below the digit range and therefore a non-alphanumeric terminator), JUMP to 5187H to perform the trailing-space check and potentially exit the scan.
517B
CP A,3AH FE 3A
Compare Register A against 3AH (one past ASCII '9'). Tests whether the character is in the digit range 30H-39H.
517D
If the CARRY FLAG is set (A is in 30H-39H - valid digit), JUMP to 518CH to restore the stack and continue the outer scan loop with the next table entry.
517F
CP A,41H FE 41
Compare Register A against 41H (ASCII 'A'). Tests whether the character falls in the gap between digits and uppercase letters (3AH-40H).
5181
If the CARRY FLAG is set (A is in 3AH-40H - non-alphanumeric gap), JUMP to 5187H to perform the trailing-space check.
5183
CP A,5BH FE 5B
Compare Register A against 5BH (one past ASCII 'Z'). Tests whether the character is in the uppercase letter range 41H-5AH.
5185
If the CARRY FLAG is set (A is in 41H-5AH - valid uppercase letter), JUMP to 518CH to restore the stack and continue the outer scan with the next table entry.

5187H - Trailing Space Check

Reached when the search key ended before all characters were compared (03H or CR terminator found) or when the mismatched character is a non-alphanumeric. Checks whether the corresponding table entry character is a space (20H). If so, the keyword matches on the shorter form and jumps to the success path at 516BH. Otherwise falls through to the outer scan resume at 518CH.

5187
LD A,(HL) 7E
Load Register A with the byte at the current HL - the character at the corresponding position in the current table entry name. If the table entry is space-padded at this position, a space (20H) confirms that the search key matched the significant portion of the keyword.
5188
CP A,20H FE 20
Compare Register A against 20H (ASCII space). Tests whether the table entry character at this position is a trailing space, which would mean the keyword name is exactly as long as the matched portion of the search key.
518A
If the Z FLAG is set (table entry has a space at this position - the keyword is shorter than the maximum and has matched), JUMP to 516BH to recover the handler address and return Z (match found).

518CH - Restore Stack and Advance to Next Entry

Restores DE and HL from the stack after a failed match attempt, then jumps back into the outer scan loop at 514AH to advance HL to the next table entry and continue the search.

518C
POP DE D1
Pop the saved DE (search key pointer into 51AAH, pushed at 515AH) from the stack into Register Pair DE, restoring it to the start of the search key for the next comparison attempt.
518D
POP HL E1
Pop the saved HL (table entry pointer at the start of the current entry, pushed at 5159H) from the stack into Register Pair HL, restoring it to the beginning of the entry that just failed to match.
518E
JR 514AH 18 BA
JUMP to 514AH in the outer scan loop to push BC, load BC with 0008H, add it to HL to advance to the next table entry, pop BC, read the first byte of the new entry, test for the null sentinel, and either compare against the search key or exit with NZ.

5190H - Decimal Number Parser

Reads ASCII decimal digit characters from the source string at HL and accumulates their value into BC using a multiply-by-10 algorithm. Returns BC = the parsed value and HL advanced past the last digit consumed. If the first character is not a digit, returns BC = 0000H immediately. Uses the sequence ADD HL,HL / ADD HL,HL / ADD HL,BC / ADD HL,HL (equivalent to HL = HL*10 + digit) to build the result.

5190
LD BC,0000H 01 00 00
Load Register Pair BC with 0000H, initialising the accumulator for the decimal parse. BC will hold the running total as digits are consumed. If no digits are found, BC = 0000H is returned.
5193
LD A,(HL) 7E
Load Register A with the byte at the current HL - the next character from the source string in the command buffer.
5194
SUB A,30H D6 30
Subtract 30H (ASCII '0') from Register A. If A was a digit character (30H-39H), the result is 00H-09H (the digit value). If A was below 30H, the CARRY FLAG is set indicating a non-digit.
5196
RET C D8
Return if the CARRY FLAG is set (character was below 30H - not a digit). BC holds the accumulated value so far (0000H if this is the first character). HL has not been advanced past this non-digit character.
5197
CP A,0AH FE 0A
Compare Register A (digit value 00H-09H or larger) against 0AH. If A is 0AH or above, the original character was above 39H (above '9') and is not a valid digit. The CARRY FLAG is clear if A >= 0AH.
5199
RET NC D0
Return if the CARRY FLAG is clear (A >= 0AH - character was above '9' and is not a digit). BC holds the accumulated value so far. HL has not been advanced.
519A
PUSH BC C5
Save Register Pair BC (the current accumulated value) onto the stack. BC will be used in the multiply-by-10 calculation and must be available after HL is manipulated.
519B
EX (SP),HL E3
Exchange Register Pair HL with the top of stack. The current HL (source string pointer) is saved to the stack, and BC (the accumulated value, just pushed) is loaded into HL. HL now holds the old accumulated value for the multiply sequence.
519C
ADD HL,HL 29
Add HL to itself (HL = HL * 2). First step of the multiply-by-10 sequence.
519D
ADD HL,HL 29
Add HL to itself again (HL = HL * 4). Second step of the multiply-by-10 sequence.
519E
ADD HL,BC 09
Add BC (the original accumulated value, still on the stack - but wait: BC was exchanged into HL at 519BH; BC now holds the source pointer). This adds the original value once more (HL = HL*4 + original = original*5). Third step.
519F
ADD HL,HL 29
Add HL to itself (HL = HL * 2 = original * 10). Fourth step completes the multiply-by-10. HL now holds the old accumulated value multiplied by 10.
51A0
LD B,00H 06 00
Load Register B with 00H, clearing the high byte of BC. Register A holds the current digit value (00H-09H); BC will be set to the digit value for the final addition.
51A2
LD C,A 4F
Load Register C with Register A (the current digit value 00H-09H). BC now holds the digit value as a 16-bit zero-extended value ready to be added to the multiplied accumulator.
51A3
ADD HL,BC 09
Add BC (current digit value) to HL (old accumulated value times 10). HL now holds the new accumulated value: old_total * 10 + current_digit. This is the standard positional decimal accumulation step.
51A4
LD B,H 44
Load Register B with Register H (the high byte of the new accumulated value in HL). This transfers the result back into BC for the next iteration.
51A5
LD C,L 4D
Load Register C with Register L (the low byte of the new accumulated value in HL). BC now holds the complete updated accumulated value.
51A6
POP HL E1
Pop the saved source string pointer (saved to the stack at 519BH by EX (SP),HL) back into Register Pair HL. HL is restored to the source position in the command buffer.
51A7
INC HL 23
Increment HL to advance the source pointer past the digit character that was just consumed. HL now points to the next character in the command buffer.
51A8
JR 5193H 18 E9
JUMP back to 5193H to read the next character and repeat the digit validation and accumulation loop. This continues until a non-digit character is found, at which point RET C or RET NC exits the routine with BC holding the fully parsed decimal value.

51B2H - Message and Data Strings

Read-only message strings and data constants used by the SYS7 overlay routines. Each string is terminated by 0DH (carriage return) except where noted. The disassembler has incorrectly decoded these data bytes as Z80 instructions; they are DEFM (define message) data.

51B2
DEFM "CHAINING COMPLETED" + 0DH 43 48 41 49 4E 49 4E 47 20 43 4F 4D 50 4C 45 54 45 44 0D
Message string "CHAINING COMPLETED" followed by a carriage return (0DH) terminator. Displayed by the display-and-exit routine at 4E94H when chaining completes normally. Address of this string is loaded into HL at 4E8CH.
51C5
DEFM "INVALID JCL, CHAINING ABORTED!" + 0DH 49 4E 56 41 4C 49 44 20 4A 43 4C 2C 20 43 48 41 49 4E 49 4E 47 20 41 42 4F 52 54 45 44 21 0D
Message string "INVALID CL," followed by a carriage return terminator. Displayed when an unrecognised keyword or malformed command line is encountered. Address of this string is loaded at 4F52H.
51E4
DEFM "MANUAL CHAINING ABORTED" + 0DH 4D 41 4E 55 41 4C 20 43 48 41 49 4E 49 4E 47 20 41 42 4F 52 54 45 44 0D
Message string "MANUAL CHAINING ABORTED" followed by a carriage return. Displayed when a manually initiated chain sequence is aborted. Address loaded at 4E8CH when the 40H-class dispatch path is taken via the LD HL,51E7H path - note the disassembler shows LD HL,4D0DH at 51E2H which is a misread of the DEFM data bytes 21H 0DH 4DH being decoded as an instruction.
51FF
DEFB 00H 00
Nothing.

51AAH - Keyword Work Buffer

A 8-byte scratch buffer within SYS7's data area used by the keyword reader at 50FFH as the destination for extracted keyword strings. The reader writes up to 6 uppercase alphanumeric characters followed by a 03H terminator into this buffer. The table search at 5143H then compares this buffer against the command keyword table at 50B6H.

51AA
DEFB 00H x 8 00 00 00 00 00 00 00 00
Eight zero bytes initialised at load time. At runtime this buffer is overwritten by 50FFH with the current keyword being searched, then read by 5143H for table comparison. No persistent value; contents are only valid between the CALL 50FFH at 4F3BH and the CALL 5143H at 4F46H.