Model I TRSDOS v2.3 SYS1/SYS Disassembly

Program Overview

SYS1/SYS is TRSDOS 2.3's Command Line Interpreter overlay for the TRS-80 Model I. It loads into the overlay area at 4E00H-51C8H and is invoked by the SYS0 resident module whenever the system needs to accept and process a user command. SYS1 is a mandatory system file that must be present on every bootable TRSDOS 2.3 disk.

SYS1 is entered via a request code passed in Register A, masked to bits 4-6, which selects one of several operational modes. These modes range from full system initialization (enabling interrupts, resetting the stack, and displaying the "DOS READY" prompt) to targeted sub-functions like filespec parsing and option/keyword processing.

The module's primary responsibilities include:

Command Input and Dispatch (Request Code 10H/20H): Initializes the stack and interrupt state, displays the "DOS READY" prompt, and reads a command line from the keyboard into the 63-character buffer at 4318H. After parsing the input into a filespec at 4480H, SYS1 searches two command name tables. The first table (at 4EA4H) contains three resident commands handled within SYS1 itself: BASIC2, DEBUG, and TRACE. The second table (at 4EBDH) contains nineteen overlay commands (APPEND, ATTRIB, AUTO, CLOCK, COPY, DATE, DEVICE, DIR, DUMP, FREE, KILL, LIB, LIST, LOAD, PRINT, PROT, RENAME, TIME, VERIFY) that are dispatched to SYS6 via the overlay loader at 4E90H. If the command is not found in either table, SYS1 assumes it is a program filename and attempts to load and execute it via the SYS0 program loader at 4433H, using "CMD" as the default file extension.

Filespec Parsing (Request Code 50H): The filespec parser at 4F56H extracts a structured filename from the command line into the system DCB buffer at 4480H. It handles up to 8 characters for the name, a "/" separator followed by up to 3 characters for the extension, a "." separator followed by up to 8 characters for the password, and a ":" separator followed by a 1-character drive specifier. The parser also strips TRSDOS "noise words" (TO, ON, OVER) from the command line by checking parsed names against a keyword table at 4FA7H.

Default Extension Insertion: When loading an unrecognized command as a program file, the routine at 4FC0H inserts the default extension "/CMD" (or whatever extension is passed in HL) if the user did not specify one. This is the main purpose of the routine often misdescribed as a "drive specifier extractor".

Option/Keyword Processing (Request Code 60H): The routine at 507DH parses parenthesized option lists from the command line, supporting keyword=value syntax with decimal, hexadecimal (X'nn'), and boolean (YES/NO/ON/OFF) value formats. This allows TRSDOS commands to accept parameters like (DRIVE=1,PROT=ON).

Resident Commands: BASIC2 (at 514CH) starts non-DOS BASIC by performing a warm restart into Level II BASIC, copying the first 36H bytes of ROM vectors back to 4000H, clearing the DOS work area, and jumping to the ROM BASIC entry point at 0075H. Unlike Disk BASIC, non-DOS BASIC has no access to disk files or DOS commands. DEBUG (at 5162H) toggles the DEBUG flag in the system flags byte at 430FH and patches the RST 30H vector and BREAK key handler accordingly. TRACE (at 5191H) toggles the interrupt-driven TRACE callback by enqueueing or dequeueing the trace handler address (4CD9H) via the SYS0 timer callback system.

Variable and Memory Reference List

Address RangePurpose
430FH-430FH
(1 byte)
System flags byte. Bit 4: overlay loaded flag (SYS6 resident). Bit 5: BREAK key context flag. Bit 7: DEBUG active flag.
4315H-4315H
(1 byte)
BREAK key handler opcode. C3H (JP) when BREAK is enabled; 00H or other value when disabled.
4316H-4317H
(2 bytes)
BREAK key handler target address.
4318H-4356H
(63 bytes)
DOS command input buffer. Keyboard input is read here (max 63 characters).
4359H-4359H
(1 byte)
System condition flags. Bit 5: tested during DOS READY initialization.
4030H-4032H
(3 bytes)
Error-already-displayed exit vector. Patched by DEBUG toggle to either LD A,A3H or CALL 400FH.
4031H-4032H
(2 bytes)
Address portion of patched instruction at 4030H. Set to 400FH (RST 30H vector) when DEBUG is active.
4480H-4494H
(21 bytes)
Parsed filespec buffer: NAMENAME/EXT.PASSWORD:D format. Populated by the filespec parser at 4F56H.
5026H-5026H
(1 byte)
Filespec parser remaining-character counter. Self-modified by the character extraction routine at 4FF4H.
51AFH-51B4H
(6 bytes)
Option keyword matching buffer. Used by the option parser at 508EH as the destination for parsed keyword names.
51B5H-51B7H
(3 bytes)
Default extension string: "CMD" (43H 4DH 44H). Used when loading unrecognized commands as program files.
51B8H-51C2H
(11 bytes)
DOS READY prompt string: 0AH + "DOS READY" + 0DH.
51C3H-51C8H
(6 bytes)
Error message string: "WHAT?" + 0DH. Displayed when command parsing fails.

Major Routine List

AddressPurpose
4E00HRequest Code Dispatcher
Entry point. Masks bits 4-6 of Register A and dispatches to the appropriate handler based on the request code (10H/20H/30H/40H/50H/60H).
4E1FHDOS READY and Command Input
Request codes 10H and 20H. Enables interrupts, resets stack to 41FCH, checks system flags, displays "DOS READY" prompt, reads command line, parses and dispatches commands.
4E4EHCommand Line Parser and Dispatcher
Request code 30H. Parses the command buffer into a filespec, searches the resident and overlay command tables, and either dispatches to the matching handler or loads the command as a program file.
4E90HOverlay Command Dispatch
Loads SYS6 via RST 28H with SVC code 88H to handle overlay-based library commands. Sets bit 4 of system flags to track overlay presence.
4EA4HResident Command Table
Data table. Three 8-byte entries for BASIC (514CH), DEBUG (5162H), and TRACE (5191H), terminated by 00H.
4EBDHOverlay Command Table
Data table. Nineteen 8-byte entries for APPEND through VERIFY, all dispatching to 4E90H (SYS6 loader), terminated by 00H.
4F56HFilespec Parser
Request code 50H. Extracts a structured filespec (name/ext.pass:drive) from the command line at (HL) into the buffer at (DE). Strips noise words (TO, ON, OVER).
4FA7HNoise Word Keyword Table
Data table. Three entries: "TO", "ON", "OVER". Used by the filespec parser to strip noise words from command lines.
4FC0HDefault Extension Insertion Routine
Called internally (e.g. from 4E7DH) to add the default extension (typically "/CMD") when the parsed filename has no extension. Uses LDDR block moves to shift the string and insert the extension passed in HL. Drive separator checks are secondary to this purpose.
4FF4HCharacter Extraction Subroutine
Reads up to B characters from (HL), storing valid filename characters (0-9, A-Z) into (DE). Terminates on 03H, 0DH, or non-alphanumeric characters. Self-modifies the remaining count at 5026H.
502AHCommand Table Lookup
Searches an 8-byte-per-entry command table at (BC) for a match against the filespec at (DE). Returns Z flag set and dispatch address in DE on match, with entry index in C.
507DHOption/Keyword Parser
Request code 60H. Parses parenthesized option lists with keyword=value syntax, supporting decimal, hexadecimal, and boolean values.
50DFHBoolean Value Parser
Parses YES/Y, NO/N, OFF, ON from the command line and returns FFFFH (true) or 0000H (false) in BC.
5104HDecimal Number Parser
Converts ASCII decimal digits to a 16-bit binary value in BC using multiply-by-10 accumulation.
511FHHexadecimal Number Parser
Parses X'nn' format hexadecimal values into a 16-bit binary value in BC.
514CHBASIC2 Command Handler
Starts non-DOS BASIC. Copies ROM vectors (36H bytes from 06D2H) back to 4000H, clears 27H bytes of DOS work area, and jumps to ROM BASIC at 0075H.
5162HDEBUG Command Handler
Toggles the DEBUG flag (bit 7 of byte pointed to by 430FH), patches the BREAK key handler and RST 30H vector accordingly.
5191HTRACE Command Handler
Toggles the TRACE timer interrupt callback (address 4CD9H) by enqueueing or dequeueing it via SYS0 routines at 4410H/4413H.

Self-Modifying Code Locations

WriterTargetPurpose
4FF5H5026HRemaining character count stored into the operand of LD A,00H at 5025H. Used by the filespec parser to track how many characters remain in the current field.
5018H5026HSame target. Cleared to 00H after a valid character is stored, resetting the first-character flag.

Cross-Reference Notes

SYS1/SYS is loaded by the SYS0 overlay loader (RST 28H handler at 4BA2H) whenever the system dispatches an SVC code that maps to overlay file 1. SYS0 entry points referenced by SYS1 include: 402DH (no-error exit), 4030H (error-already-displayed exit), 4410H (enqueue timer callback), 4413H (dequeue timer callback), 4433H (load and execute program file), and 4467H (display message to screen). SYS1 dispatches overlay commands to SYS6 via RST 28H with SVC code 88H. The BASIC2 command handler references ROM entry point 0075H (BASIC warm start) and ROM data at 06D2H (vector initialization block). The DEBUG handler patches the RST 30H vector at 400FH and the BREAK handler at 4315H. The TRACE handler uses the timer display routine at 4CD9H as the callback address.

Dissassembly

4E00H - Request Code Dispatcher

Entry point for SYS1/SYS. Register A contains the full SVC code from the RST 28H overlay call. This routine masks out the function bits (bits 4-6) and dispatches to the appropriate handler based on the request code. Request code 10H and 20H both go to the DOS READY prompt and command input handler. Request code 30H goes to the command line parser. Request code 40H goes to the filespec parser. Request code 50H goes to the default extension insertion routine (indirectly). Request code 60H goes to the option/keyword parser. Any other request code returns immediately.

4E00
AND 70H E6 70
Mask Register A to isolate bits 4-6, the function number within the overlay. This strips the overlay file number (bits 0-3) and the overlay call flag (bit 7), leaving only the request code. The result will be one of 10H, 20H, 30H, 40H, 50H, or 60H.
4E02
CP 10H FE 10
Compare Register A against 10H (request code for DOS READY with full initialization). If Register A equals 10H, the Z FLAG is set.
4E04
If the Z FLAG (Zero) has been set because the request code is 10H, JUMP to 4E1FH to enable interrupts, reset the stack, and enter the DOS READY prompt and command input loop.
4E07
CP 20H FE 20
Compare Register A against 20H (alternate request code that also enters DOS READY). If Register A equals 20H, the Z FLAG is set.
4E09
If the Z FLAG (Zero) has been set because the request code is 20H, JUMP to 4E1FH. Both request codes 10H and 20H enter the same DOS READY handler.
4E0B
CP 30H FE 30
Compare Register A against 30H (request code for command line parsing and dispatch). If Register A equals 30H, the Z FLAG is set.
4E0D
If the Z FLAG (Zero) has been set because the request code is 30H, JUMP to 4E4EH to parse the command line in the buffer and dispatch the command.
4E0F
CP 40H FE 40
Compare Register A against 40H. If Register A equals 40H, the Z FLAG is set.
4E11
If the Z FLAG (Zero) has been set because the request code is 40H, JUMP to 4F56H (filespec parser). Note: The default extension insertion routine at 4FC0H is called internally during command processing, not directly as request code 40H.
4E14
CP 50H FE 50
Compare Register A against 50H (request code for filespec parsing with with default extension support). If Register A equals 50H, the Z FLAG is set.
4E16
If the Z FLAG (Zero) has been set because the request code is 50H, this path ultimately leads to default extension handling at 4FC0H when preparing to load a program.
4E19
CP 60H FE 60
Compare Register A against 60H (request code for option/keyword parsing). If Register A equals 60H, the Z FLAG is set.
4E1B
If the Z FLAG (Zero) has been set because the request code is 60H, JUMP to 507DH to parse parenthesized option keywords and their values from the command line.
4E1E
RET C9
If the request code did not match any of the six recognized values (10H, 20H, 30H, 40H, 50H, 60H), return to the caller without taking any action. This is a safety catch for invalid request codes.

4E1FH - DOS READY and Command Input Handler

This is the main DOS READY handler, entered for request codes 10H and 20H. It enables interrupts, resets the stack pointer to 41FCH, checks system condition flags to determine if DEBUG is active and if the BREAK key should be tested, displays the "DOS READY" prompt, reads a command line from the keyboard, and falls through to the command parser at 4E4EH. The stack reset to 41FCH ensures a clean stack regardless of how deeply nested the previous operation was.

4E1F
EI FB
Enable interrupts. This ensures the timer interrupt service routine can run for clock updates and the TRACE display callback.
4E20
LD SP,41FCH 31 FC 41
Reset the stack pointer to 41FCH. This gives a clean stack with room for one return address below the system variable area. Any previous stack contents from prior command execution are discarded.
4E23
LD HL,4359H 21 59 43
Point Register Pair HL to the system condition flags byte at 4359H. This byte tracks various system states: bit 5 indicates whether the system was entered from a specific context requiring special handling.
4E26
BIT 5,(HL) CB 6E
Test bit 5 of the system condition flags at 4359H. This bit indicates a context flag that affects whether the BREAK key check and DEBUG initialization should be performed. The Z FLAG is set if bit 5 is clear.
4E28
LD HL,(430FH) 2A 0F 43
Fetch the 16-bit value at 430FH-4310H into Register Pair HL. The low byte at 430FH is the system flags byte (bit 4 = overlay loaded, bit 5 = BREAK context, bit 7 = DEBUG active). The high byte at 4310H provides the address context for the BIT 7 test that follows.

Note: The LD HL,(430FH) loads a 16-bit value, but the subsequent BIT 7,(HL) uses HL as a pointer. This means the system flags byte at 430FH and its successor byte at 4310H together form an address that points to a location whose bit 7 is tested. In practice, 430FH typically contains a flags value and 4310H contains a related context byte, and the combination is used as an indirect pointer to test the DEBUG state.

4E2B
BIT 7,(HL) CB 7E
Test bit 7 of the byte pointed to by Register Pair HL. If the DEBUG flag is set (bit 7 = 1), the Z FLAG is cleared (NZ). If DEBUG is not active, the Z FLAG is set.
4E2D
If the Z FLAG (Zero) has been set because DEBUG is not active, JUMP forward to 4E34H to skip the BREAK key handler setup.
4E2F
LD A,0C3H 3E C3
Load Register A with C3H, which is the opcode for the JP (Jump) instruction. This will be stored into the BREAK key handler vector to enable BREAK key detection.
4E31
LD (4315H),A 32 15 43
Store C3H (JP opcode) into the BREAK key handler opcode byte at 4315H. Together with the address at 4316H-4317H, this forms a complete JP instruction that enables the BREAK key handler. When the BREAK key is pressed, the interrupt service routine will find a valid JP instruction here and branch to the handler.
4E34
BIT 5,(HL) CB 6E
Test bit 5 of the byte pointed to by Register Pair HL. This bit indicates whether the system should check the BREAK key before displaying the DOS READY prompt. If bit 5 is set, the BREAK key is checked; if clear, the prompt is displayed immediately.
4E36
If the Z FLAG (Zero) has been set because bit 5 is clear, JUMP forward to 4E40H to skip the BREAK key check and proceed directly to displaying the DOS READY prompt.
4E38
LD A,(3840H) 3A 40 38
Fetch the keyboard row 6 status from the memory-mapped keyboard address 3840H. Row 6 contains: ENTER (bit 0), CLEAR (bit 1), BREAK (bit 2), UP (bit 3), DOWN (bit 4), LEFT (bit 5), RIGHT (bit 6), SPACE (bit 7). Active keys pull the bit LOW.
4E3B
AND 04H E6 04
Mask Register A with 04H to isolate bit 2 (the BREAK key). If the BREAK key is currently pressed, bit 2 will be 0 (active low), so the result is 00H and Z is set. If BREAK is not pressed, bit 2 is 1, giving a non-zero result.
4E3D
If the NZ FLAG (Not Zero) has been set because the BREAK key is NOT pressed (bit 2 = 1, meaning inactive), JUMP to 4030H in SYS0 to execute the error-already-displayed exit. This handles the case where the system was waiting for a BREAK key press to continue and the user did not press it.

The BREAK key logic here is inverted from what might be expected. The keyboard is active-low, so a pressed key reads as 0. The AND 04H isolates the BREAK bit, and JP NZ means "BREAK is NOT pressed". The jump to 4030H exits back to the calling context. If BREAK IS pressed (result is zero, Z flag set), execution falls through to the DOS READY prompt below.

4E40
LD HL,51B8H 21 B8 51
Point Register Pair HL to the DOS READY prompt string at 51B8H. This string contains: 0AH (line feed) + "DOS READY" + 0DH (carriage return).
4E43
GOSUB to the SYS0 display message routine at 4467H to send the DOS READY prompt string pointed to by Register Pair HL to the video display. The routine outputs characters until it encounters 0DH (carriage return) or 00H.
4E46
LD HL,4318H 21 18 43
Point Register Pair HL to the DOS command input buffer at 4318H. This 63-byte buffer will receive the user's keyboard input.
4E49
LD B,3FH 06 3F
Load Register B with 3FH (63 decimal), the maximum number of characters that can be entered into the command buffer. This is passed to the ROM line input routine as the buffer size limit.
4E4B
GOSUB to the ROM line input routine at 0040H. Entry: HL = buffer address (4318H), B = maximum character count (63). The routine reads characters from the keyboard, echoing them to the screen, until ENTER is pressed. On return, HL points past the last character entered, and the buffer is terminated with 0DH.

4E4EH - Command Line Parser and Dispatcher

This section parses the command line from the buffer at 4318H, extracts the command name into the filespec buffer at 4480H, and searches two command tables to determine how to handle the command. The first table at 4EA4H contains resident commands (BASIC, DEBUG, TRACE) handled within SYS1 itself. The second table at 4EBDH contains overlay commands dispatched to SYS6. If the command is not found in either table, it is assumed to be a program filename and is loaded and executed via the SYS0 program loader.

4E4E
LD BC,402DH 01 2D 40
Load Register Pair BC with the address 402DH, which is the SYS0 no-error exit entry point. This address will be pushed onto the stack as a return address, so that after command execution completes, control returns to the no-error exit handler which reloads SYS1 and re-enters the DOS READY prompt.
4E51
PUSH BC C5
Save the no-error exit address (402DH) onto the stack. This becomes the return address for whatever command handler is eventually called. When the handler executes RET, it will return to 402DH.
4E52
LD DE,4480H 11 80 44
Point Register Pair DE to the filespec buffer at 4480H. The filespec parser will store the extracted filename components (name, extension, password, drive specifier) starting at this address.
4E55
GOSUB to the filespec parser at 4F56H to extract the first word from the command line (pointed to by HL from the keyboard input routine) into the filespec buffer at 4480H. On return, Z flag set = parse successful, NZ = error or no valid input.
4E58
If the NZ FLAG (Not Zero) has been set because the filespec parser encountered an error or found no valid filename, JUMP to 4E87H to display the "WHAT?" error message and return to the DOS READY prompt.
4E5B
LD A,(DE) 1A
Fetch the first character of the parsed filespec from the buffer at (DE) = 4480H into Register A. This is the first character of the command name as entered by the user.
4E5C
CP 2AH FE 2A
Compare Register A against 2AH (ASCII: *). The asterisk is the wildcard character. If Register A equals 2AH, the Z FLAG is set. Wildcard characters are not valid as command names.
4E5E
If the Z FLAG (Zero) has been set because the first character is a wildcard *, JUMP to 4E87H to display "WHAT?" and return to the DOS READY prompt. Wildcards cannot be used as command names.
4E61
PUSH HL E5
Save Register Pair HL onto the stack. HL points to the remainder of the command line after the parsed command name. This position will be needed later to pass to the command handler so it can parse its own arguments.
4E62
LD BC,4EA4H 01 A4 4E
Load Register Pair BC with the address of the resident command table at 4EA4H. This table contains three entries: BASIC (514CH), DEBUG (5162H), and TRACE (5191H). Each entry is 8 bytes: 6 characters of command name followed by a 2-byte dispatch address.
4E65
GOSUB to the command table lookup routine at 502AH to search the resident command table for a match against the parsed command name at (DE) = 4480H. On return: Z flag set = match found (dispatch address in DE, entry index in C), NZ = no match.
4E68
If the Z FLAG (Zero) has been set because the command was found in the resident table, JUMP to 4E84H to dispatch to the matching command handler.
4E6A
LD BC,4EBDH 01 BD 4E
Load Register Pair BC with the address of the overlay command table at 4EBDH. This table contains nineteen entries for library commands (APPEND, ATTRIB, AUTO, CLOCK, COPY, DATE, DEVICE, DIR, DUMP, FREE, KILL, LIB, LIST, LOAD, PRINT, PROT, RENAME, TIME, VERIFY), all dispatching to 4E90H.
4E6D
GOSUB to the command table lookup routine at 502AH to search the overlay command table for a match against the parsed command name at (DE) = 4480H.
4E70
If the Z FLAG (Zero) has been set because the command was found in the overlay table, JUMP to 4E84H to dispatch to the overlay loader at 4E90H.

If neither table contained the command name, the code falls through to treat the input as a program filename to be loaded and executed from disk.

4E72
LD A,(430FH) 3A 0F 43
Fetch the system flags byte from 430FH into Register A. Bit 4 of this byte indicates whether the SYS6 overlay is currently loaded in the overlay area.
4E75
RES 4,A CB A7
Clear bit 4 of Register A. This resets the "SYS6 overlay loaded" flag because loading a program file will overwrite the overlay area where SYS6 resides.
4E77
LD (430FH),A 32 0F 43
Store the updated system flags byte (with bit 4 cleared) back to 430FH.
4E7A
LD HL,51B5H 21 B5 51
Point Register Pair HL to the default extension string "CMD" at 51B5H. This will be appended to the filename if no extension was specified by the user, so that typing "MYPROG" will look for "MYPROG/CMD" on disk.
4E7D
GOSUB to the default extension insertion routine at 4FC0H. If the parsed command name has no extension, this inserts "/CMD" (the extension pointed to by HL) so that typing "MYPROG" becomes "MYPROG/CMD" before loading.
4E80
POP HL E1
Restore Register Pair HL from the stack. HL now points to the remainder of the command line after the command name, which may contain arguments for the program being loaded.
4E81
JUMP to the SYS0 program loader entry point at 4433H to load and execute the command as a program file. The filespec at 4480H contains the filename with "CMD" as the default extension. The 402DH return address is already on the stack (pushed at 4E51H), so when the loaded program finishes and returns, control goes back to the DOS READY prompt.

4E84H - Command Table Match Dispatch

This short routine is reached when either the resident or overlay command table contains a match for the entered command. Register Pair DE holds the dispatch address from the matching table entry, and the saved HL (command line position) is on the stack. The routine pops HL, pushes the dispatch address, and uses RET to jump to the handler.

4E84
POP HL E1
Restore Register Pair HL from the stack. HL now points to the remainder of the command line after the command name. This is passed to the command handler so it can parse any arguments that follow the command.
4E85
PUSH DE D5
Save the dispatch address (from the matched table entry) onto the stack. For resident commands: 514CH (BASIC), 5162H (DEBUG), or 5191H (TRACE). For overlay commands: 4E90H (SYS6 loader).
4E86
RET C9
RETURN via the dispatch address just pushed onto the stack. This is a standard "computed GOTO" pattern: the RET instruction pops the dispatch address and jumps to it. The 402DH no-error exit address (pushed at 4E51H) remains on the stack as the return address for the command handler.

4E87H - Command Parse Error Handler

Reached when the filespec parser returned an error, the first character was a wildcard, or any other invalid command condition. Displays the "WHAT?" error message and exits to the error-already-displayed handler to return to the DOS READY prompt.

4E87
LD HL,51C3H 21 C3 51
Point Register Pair HL to the "WHAT?" error message string at 51C3H. This string contains: "WHAT?" + 0DH (carriage return).
4E8A
GOSUB to the SYS0 display message routine at 4467H to output the "WHAT?" error message to the video display.
4E8D
JUMP to the SYS0 error-already-displayed exit at 4030H. This reloads SYS1 with request code 10H/20H and re-enters the DOS READY prompt, ready for the next command.

4E90H - Overlay Command Dispatch (Load SYS6)

This routine handles all nineteen overlay commands by loading SYS6/SYS via the RST 28H overlay mechanism. It first checks if SYS6 is already loaded in the overlay area (bit 4 of system flags at 430FH). If so, it jumps directly to 5200H where SYS6's entry point resides. If not, it sets the overlay-loaded flag and invokes RST 28H with SVC code 88H to load SYS6 from disk. The RST 28H handler does not return to 4EA4H; instead, the loaded overlay takes control and processes the command, eventually returning to the DOS READY prompt via the no-error exit at 402DH.

4E90
LD A,(430FH) 3A 0F 43
Fetch the system flags byte from 430FH into Register A. Bit 4 indicates whether SYS6 is currently loaded in the overlay area.
4E93
BIT 4,A CB 67
Test bit 4 of Register A. If bit 4 is set (1), SYS6 is already loaded in memory and does not need to be read from disk again. The Z FLAG is set if bit 4 is clear (SYS6 not loaded).
4E95
JP NZ,5200H C2 00 52
If the NZ FLAG (Not Zero) has been set because SYS6 is already loaded (bit 4 = 1), JUMP directly to 5200H. This is the entry point of SYS6/SYS in the overlay area, which starts above the SYS1 code space. SYS6 will use the command index and command line to execute the appropriate library command.
4E98
LD A,(430FH) 3A 0F 43
Fetch the system flags byte from 430FH again into Register A. This re-read is necessary because the previous BIT instruction only tested A without preserving the full flags state needed for the SET operation.
4E9B
SET 4,A CB E7
Set bit 4 of Register A to mark that SYS6 is now being loaded into the overlay area. This prevents redundant disk reads if another overlay command is issued before SYS6 is overwritten.
4E9D
LD (430FH),A 32 0F 43
Store the updated system flags byte (with bit 4 set) back to 430FH.
4EA0
LD A,88H 3E 88
Load Register A with 88H, the SVC code for loading SYS6 with function 0. Encoding: bits 0-2 = 000 (directory sector 2), bits 3-4 = 01 (file 1 in that sector = SYS6), bits 5-7 = 100 (function 4). The overlay loader will read SYS6/SYS from disk into the overlay area starting at 4E00H (overwriting SYS1) and transfer control to it.
4EA2
PUSH AF F5
Save Register A (88H) and the flags onto the stack. The overlay loader may need the original SVC code after loading the overlay file, so PUSH AF preserves it for the loaded overlay to retrieve if needed.
4EA3
RST 28H EF
Invoke the RST 28H overlay dispatch handler at 400CH (which jumps to the overlay loader at 4BA2H in SYS0). Register A = 88H directs the loader to read SYS6/SYS from disk. The overlay loader does NOT return to 4EA4H; instead, SYS6 takes control and handles the command. Execution of SYS1 code ends here for overlay commands.

4EA4H - Resident Command Name Table

Data table containing three 8-byte entries for commands handled directly within SYS1/SYS. Each entry consists of a 6-character command name (padded with spaces or version characters) followed by a 2-byte little-endian dispatch address. The table is terminated by a 00H byte. The command table lookup routine at 502AH searches this table by comparing the parsed command name character-by-character against each entry. The disassembler has misinterpreted these data bytes as Z80 instructions.

4EA4-4EABH
DEFM "BASIC2" / DEFW 514CH 42 41 53 49 43 32 4C 51
Resident Command Entry 1
Command name "BASIC2" (42H 41H 53H 49H 43H 32H), a full 6-character name with no padding, followed by dispatch address 514CH (little-endian: 4CH 51H). BASIC2 is a library command that starts non-DOS BASIC (Level II BASIC without disk support). The handler at 514CH copies the original ROM vector table from 06D2H back to 4000H, clears the DOS work area, and jumps to the ROM BASIC entry point at 0075H, permanently abandoning all TRSDOS state. The user must type "BASIC2" (all 6 characters) to match this entry.
4EACH-4EB3H
DEFM "DEBUG " / DEFW 5162H 44 45 42 55 47 20 62 51
Resident Command Entry 2
Command name "DEBUG " (44H 45H 42H 55H 47H 20H) padded to 6 characters with a trailing space, followed by dispatch address 5162H (little-endian). The dispatch address 5162H points to the DEBUG command handler, which toggles the DEBUG active flag and patches the BREAK key handler and RST 30H vector.
4EB4H-4EBBH
DEFM "TRACE " / DEFW 5191H 54 52 41 43 45 20 91 51
Resident Command Entry 3
Command name "TRACE " (54H 52H 41H 43H 45H 20H) padded to 6 characters with a trailing space, followed by dispatch address 5191H (little-endian). The dispatch address 5191H points to the TRACE command handler, which toggles the timer interrupt callback for the real-time trace display.
4EBC
DEFB 00H 00
Table Terminator
A 00H byte marks the end of the resident command table. The lookup routine at 502AH checks the first byte of each entry and stops searching when it finds 00H.

4EBDH - Overlay Command Name Table

Data table containing nineteen 8-byte entries for library commands handled by SYS6/SYS. Each entry consists of a 6-character command name (padded with trailing spaces for names shorter than 6 characters) followed by the 2-byte little-endian dispatch address 4E90H. All entries share the same dispatch address because they all route through the SYS6 overlay loader at 4E90H. The specific command within SYS6 is identified by the entry index returned in Register C by the lookup routine at 502AH. The table is terminated by a 00H byte at 4F55H. The disassembler has misinterpreted these data bytes as Z80 instructions.

4EBD-4EC4
DEFM "APPEND" / DEFW 4E90H 41 50 50 45 4E 44 90 4E
Overlay Command Entry 1
APPEND: Appends one disk file to another.
4EC5-4ECC
DEFM "ATTRIB" / DEFW 4E90H 41 54 54 52 49 42 90 4E
Overlay Command Entry 2
ATTRIB: Displays or changes file attributes (visibility, protection level, access password).
4ECD-4ED4
DEFM "AUTO " / DEFW 4E90H 41 55 54 4F 20 20 90 4E
Overlay Command Entry 3
AUTO: Sets or clears the auto-execute command that runs at boot time.
4ED5-4EDC
DEFM "CLOCK " / DEFW 4E90H 43 4C 4F 43 4B 20 90 4E
Overlay Command Entry 4
CLOCK: Toggles the real-time clock display on or off.
4EDD-4EE4
DEFM "COPY " / DEFW 4E90H 43 4F 50 59 20 20 90 4E
Overlay Command Entry 5
COPY: Copies a file from one location to another.
4EE5-4EEC
DEFM "DATE " / DEFW 4E90H 44 41 54 45 20 20 90 4E
Overlay Command Entry 6
DATE: Displays or sets the system date.
4EED-4EF4
DEFM "DEVICE" / DEFW 4E90H 44 45 56 49 43 45 90 4E
Overlay Command Entry 7
DEVICE: Displays or manages device routing.
4EF5-4EFC
DEFM "DIR " / DEFW 4E90H 44 49 52 20 20 20 90 4E
Overlay Command Entry 8
DIR: Displays the disk directory listing.
4EFD-4F04
DEFM "DUMP " / DEFW 4E90H 44 55 4D 50 20 20 90 4E
Overlay Command Entry 9
DUMP: Displays a hexadecimal memory dump.
4F05-4F0C
DEFM "FREE " / DEFW 4E90H 46 52 45 45 20 20 90 4E
Overlay Command Entry 10
FREE: Displays available disk space (free granules).
4F0D-4F14
DEFM "KILL " / DEFW 4E90H 4B 49 4C 4C 20 20 90 4E
Overlay Command Entry 11
KILL: Deletes a file from the disk.
4F15-4F1C
DEFM "LIB " / DEFW 4E90H 4C 49 42 20 20 20 90 4E
Overlay Command Entry 12
LIB: Displays a list of available library commands.
4F1D-4F24
DEFM "LIST " / DEFW 4E90H 4C 49 53 54 20 20 90 4E
Overlay Command Entry 13
LIST: Displays the contents of a file to the screen.
4F25-4F2C
DEFM "LOAD " / DEFW 4E90H 4C 4F 41 44 20 20 90 4E
Overlay Command Entry 14
LOAD: Loads a program file into memory.
4F2D-4F34
DEFM "PRINT " / DEFW 4E90H 50 52 49 4E 54 20 90 4E
Overlay Command Entry 15
PRINT: Sends a file to the printer.
4F35-4F3C
DEFM "PROT " / DEFW 4E90H 50 52 4F 54 20 20 90 4E
Overlay Command Entry 16
PROT: Sets file protection attributes.
4F3D-4F44
DEFM "RENAME" / DEFW 4E90H 52 45 4E 41 4D 45 90 4E
Overlay Command Entry 17
RENAME: Changes the name of a disk file.
4F45-4F4C
DEFM "TIME " / DEFW 4E90H 54 49 4D 45 20 20 90 4E
Overlay Command Entry 18
TIME: Displays or sets the system time.
4F4D-4F54
DEFM "VERIFY" / DEFW 4E90H 56 45 52 49 46 59 90 4E
Overlay Command Entry 19
VERIFY: Toggles write-verify mode on or off for all disk writes.
4F55
DEFB 00H 00
Table Terminator
A 00H byte marks the end of the overlay command table. The lookup routine at 502AH stops searching when it encounters this byte as the first character of an entry.

4F56H - Filespec Parser

This routine extracts a structured filespec from the command line at (HL) into the buffer at (DE). The filespec format is: NAME/EXT.PASSWORD:DRIVE, where NAME is up to 8 characters, EXT is up to 3 characters, PASSWORD is up to 8 characters, and DRIVE is a single character. Each field separator ("/", ".", ":") is stored in the output buffer. After parsing, the routine checks the result against the noise word keyword table at 4FA7H (containing "TO", "ON", and "OVER") and, if a match is found, restarts parsing at 4F56H to skip the noise word and extract the next word. TRSDOS supports noise words like "COPY file1 TO file2" where "TO" is silently consumed. On return, Z flag set indicates successful parsing; NZ indicates the input was exhausted or contained no valid characters.

4F56
PUSH DE D5
Save Register Pair DE (the filespec output buffer pointer, initially 4480H) onto the stack. This saved value will be restored later to check the parsed name against the noise word table and potentially restart parsing.
4F57
LD B,08H 06 08
Load Register B with 08H (8 decimal), the maximum number of characters allowed in the filename portion of the filespec.
4F59
GOSUB to the character extraction subroutine at 4FF4H to read up to 8 characters from the command line at (HL), storing valid filename characters (0-9, A-Z) into the output buffer at (DE). On return: A = the character that caused the scan to stop (a separator, terminator, or invalid character), Z flag = set if no valid characters were found, NZ = valid characters were extracted.
4F5C
If the NZ FLAG (Not Zero) has been set because the character extraction found at least one valid character AND the stopping character was not a field separator, JUMP to 4F98H to check for a wildcard character.

If we reach here, either no valid characters were found (error), or the scan stopped on a recognized separator character. The code checks for the "/" extension separator, "." password separator, and ":" drive separator in sequence.

4F5E
CP 2FH FE 2F
Compare Register A against 2FH (ASCII: /). This is the extension separator in TRSDOS filespecs. If Register A equals 2FH, the Z FLAG is set.
4F60
If the NZ FLAG (Not Zero) has been set because the stopping character is not "/", JUMP forward to 4F6BH to check for the "." password separator.
4F62
LD (DE),A 12
Store the "/" separator character into the output buffer at (DE). The filespec format preserves separators in the buffer.
4F63
INC DE 13
Advance the output buffer pointer to the next position after the "/" separator.
4F64
LD B,03H 06 03
Load Register B with 03H (3 decimal), the maximum number of characters allowed in the file extension.
4F66
GOSUB to the character extraction subroutine at 4FF4H to read up to 3 extension characters from the command line.
4F69
If the NZ FLAG (Not Zero) has been set because the extraction ended on a non-separator character (or no characters were found), JUMP to 4FA5H to terminate parsing and return.
4F6B
CP 2EH FE 2E
Compare Register A against 2EH (ASCII: .). This is the password separator in TRSDOS filespecs. If Register A equals 2EH, the Z FLAG is set.
4F6D
If the NZ FLAG (Not Zero) has been set because the stopping character is not ".", JUMP forward to 4F78H to check for the ":" drive separator.
4F6F
LD (DE),A 12
Store the "." password separator character into the output buffer at (DE).
4F70
INC DE 13
Advance the output buffer pointer past the "." separator.
4F71
LD B,08H 06 08
Load Register B with 08H (8 decimal), the maximum number of characters allowed in the password field.
4F73
GOSUB to the character extraction subroutine at 4FF4H to read up to 8 password characters from the command line.
4F76
If the NZ FLAG (Not Zero) has been set because the extraction ended on a non-separator character, JUMP to 4FA5H to terminate parsing and return.
4F78
CP 3AH FE 3A
Compare Register A against 3AH (ASCII: :). This is the drive specifier separator in TRSDOS filespecs. If Register A equals 3AH, the Z FLAG is set.
4F7A
If the NZ FLAG (Not Zero) has been set because the stopping character is not ":", JUMP forward to 4F85H to finish parsing without a drive specifier.
4F7C
LD (DE),A 12
Store the ":" drive separator character into the output buffer at (DE).
4F7D
INC DE 13
Advance the output buffer pointer past the ":" separator.
4F7E
LD B,01H 06 01
Load Register B with 01H (1 decimal), allowing exactly one character for the drive specifier (0-3 for drives 0 through 3).
4F80
GOSUB to the character extraction subroutine at 4FF4H to read the single drive specifier character.
4F83
If the NZ FLAG (Not Zero) has been set because the extraction encountered an unexpected character, JUMP to 4FA5H to terminate parsing.
4F85
LD C,A 4F
Save the stopping character from Register A into Register C for later restoration. Register A will be overwritten by the buffer terminator write.
4F86
LD A,03H 3E 03
Load Register A with 03H, the buffer terminator byte. This marks the end of the filespec string in the output buffer.
4F88
LD (DE),A 12
Store the 03H terminator into the output buffer at the current position (DE), marking the end of the parsed filespec.
4F89
XOR A AF
Set Register A to zero and set the Z FLAG. The Z flag will be used to signal success, but it will be overridden by the noise word check below.
4F8A
LD A,C 79
Restore the stopping character from Register C back into Register A. This preserves the character that terminated the scan for use by the caller.
4F8B
POP DE D1
Restore the original output buffer start address from the stack into Register Pair DE. DE now points back to the beginning of the parsed filespec (4480H on first call), allowing the noise word check to examine the parsed name.
4F8C
PUSH DE D5
Save the output buffer start address back onto the stack. This re-saves it in case the parser needs to restart after stripping a noise word.
4F8D
LD BC,4FA7H 01 A7 4F
Load Register Pair BC with the address of the noise word keyword table at 4FA7H. This table contains "TO", "ON", and "OVER" with null-padded entries.
4F90
GOSUB to the command table lookup routine at 502AH to check if the parsed filespec matches any of the noise words (TO, ON, OVER). If the user typed something like "COPY FILE1 TO FILE2", the word "TO" should be silently consumed.
4F93
POP DE D1
Restore the output buffer start address from the stack into Register Pair DE.
4F94
If the Z FLAG (Zero) has been set because the parsed word matched a noise word in the keyword table, LOOP BACK to 4F56H to restart the filespec parser. This effectively skips the noise word and parses the next word from the command line. HL still points to the command line position after the noise word.
4F96
XOR A AF
Set Register A to zero and set the Z FLAG. The Z flag signals to the caller that parsing was successful and a valid filespec is in the buffer.
4F97
RET C9
RETURN to the caller. Z flag is set (success), DE points to the start of the parsed filespec, HL points to the remainder of the command line after the parsed filespec.

4F98H - Wildcard Check During Filespec Parse

Reached when the character extraction routine returned NZ (valid characters found, but stopped on a non-separator). This checks if the stopping character was an asterisk wildcard, and if so, continues extracting characters after it.

4F98
CP 2AH FE 2A
Compare Register A against 2AH (ASCII: *). If the stopping character is a wildcard asterisk, the Z FLAG is set.
4F9A
If the NZ FLAG (Not Zero) has been set because the character is not a wildcard, JUMP to 4FA5H to terminate parsing. The character is not a recognized separator or wildcard, so parsing is complete.
4F9C
LD (DE),A 12
Store the "*" wildcard character into the output buffer at (DE). The wildcard is preserved in the filespec for pattern matching by other routines.
4F9D
INC DE 13
Advance the output buffer pointer past the wildcard character.
4F9E
LD B,02H 06 02
Load Register B with 02H (2 decimal). After the wildcard, up to 2 more characters are allowed before the filespec must terminate. This allows patterns like "*AB" for partial wildcard matches.
4FA0
GOSUB to the character extraction subroutine at 4FF4H to read up to 2 more characters after the wildcard.
4FA3
If the Z FLAG (Zero) has been set because no more characters were found (input terminated), JUMP to 4F85H to write the 03H terminator and finish parsing the filespec.
4FA5
POP DE D1
Restore the original output buffer start address from the stack into Register Pair DE. This cleans up the stack from the PUSH DE at 4F56H.
4FA6
RET C9
RETURN to the caller. The NZ flag is set (from the non-separator character or error condition), indicating that parsing stopped due to an unusual condition. The caller at 4E58H will check NZ and branch to the error handler.

4FA7H - Noise Word Keyword Table

Data table containing three 8-byte entries for TRSDOS "noise words" that are silently consumed during filespec parsing. Noise words are common English prepositions and conjunctions used in TRSDOS command syntax for readability (e.g., "COPY FILE1 TO FILE2"). When the filespec parser encounters one of these words, it discards it and parses the next word instead. Each entry uses the same 8-byte format as the command tables: 6 characters of name (padded with spaces) followed by a 2-byte value (set to 0000H since noise words have no dispatch address). The table is terminated by a 00H byte.

4FA7-4FAE
DEFM "TO " / DEFW 0000H 54 4F 20 20 20 20 00 00
Noise Word Entry 1
The word "TO" (54H 4FH) padded with four spaces. Used in commands like "COPY file1 TO file2" and "RENAME oldname TO newname". The 2-byte address field is 0000H (unused for noise words).
4FAF-4FB6
DEFM "ON " / DEFW 0000H 4F 4E 20 20 20 20 00 00
Noise Word Entry 2
The word "ON" (4FH 4EH) padded with four spaces. Used in commands like "CLOCK ON" or parameter specifications.
4FB7-4FBF
DEFM "OVER " / DEFB 00H 00H 00H 4F 56 45 52 20 20 00 00 00
Noise Word Entry 3
The word "OVER" (4FH 56H 45H 52H) padded with two spaces, followed by 00H 00H. Used in commands like "APPEND file1 OVER file2". The final 00H byte also serves as the table terminator.

4FC0H - Default Extension Insertion Routine

This routine inserts the default file extension (typically "/CMD") when the user did not specify one. It is called from the command dispatcher (at 4E7DH) when an unrecognized command is to be loaded as a program file. HL points to the default extension string (e.g. "CMD" at 51B5H). The routine scans the filespec buffer looking for the end of the name field. If no extension separator ("/") is present, it uses LDDR block moves to shift the existing string and insert the extension, producing e.g. "MYPROG/CMD". Checks for the drive separator (":") help determine name boundaries but are not the primary purpose of this routine.

4FC0
PUSH DE D5
Save Register Pair DE (the filespec buffer address) onto the stack for later restoration.
4FC1
PUSH HL E5
Save Register Pair HL (the default extension string pointer) onto the stack.
4FC2
EX DE,HL EB
Exchange DE and HL. Now HL points to the filespec buffer (e.g., 4480H) and DE points to the default extension string (e.g., 51B5H for "CMD").
4FC3
INC HL 23
Advance HL past the first character of the filespec buffer. The first character has already been validated by the caller, so scanning starts at the second character.
4FC4
LD B,09H 06 09
Load Register B with 09H (9 decimal), the maximum number of characters to scan in the filespec. This covers up to the full 8-character name plus one separator.
4FC6
LD A,(HL) 7E
Loop Start
Fetch the next character from the filespec buffer at (HL) into Register A.
4FC7
CP 2FH FE 2F
Compare Register A against 2FH (ASCII: /). This is the extension separator. If found, the name portion is complete and the routine exits without modifying the string.
4FC9
If the Z FLAG (Zero) has been set because the character is "/", JUMP to 4FD8H to exit. The filespec already has an extension separator, so no default extension needs to be inserted.
4FCB
If the CARRY FLAG has been set because the character is less than 2FH (below the "/" character in ASCII), JUMP to 4FDBH to insert the default extension. Characters below "/" include the 03H terminator, control characters, and the space character, all indicating the name has ended without an explicit extension.
4FCD
CP 3AH FE 3A
Compare Register A against 3AH (ASCII: :). This is the drive specifier separator.
4FCF
If the CARRY FLAG has been set because the character is between 2FH and 3AH exclusive (i.e., digits 0-9 at ASCII 30H-39H), JUMP to 4FD5H to continue scanning. Digits are valid filename characters.
4FD1
CP 41H FE 41
Compare Register A against 41H (ASCII: A). Characters between 3AH and 40H (colon through at-sign) are not valid in filenames.
4FD3
If the CARRY FLAG has been set because the character is between 3AH and 40H (not a digit and not a letter), JUMP to 4FDBH to insert the default extension. The ":" drive separator falls in this range and triggers the insertion.
4FD5
INC HL 23
Advance HL to the next character in the filespec buffer.
4FD6
DECrement B and loop back to 4FC6H if not zero. Continue scanning until all 9 characters have been checked or a stopping condition is met.
Loop End
4FD8
POP HL E1
Restore Register Pair HL (the default extension string pointer) from the stack. Since the filespec already has an extension or the scan completed without finding a place to insert one, the default extension is not needed.
4FD9
POP DE D1
Restore Register Pair DE (the original filespec buffer address) from the stack.
4FDA
RET C9
RETURN to the caller. The filespec was not modified because it already contained an extension separator or was fully alphanumeric.

4FDBH - Insert Default Extension Into Filespec

Reached when the drive specifier extractor finds a position in the filespec where the default extension should be inserted. HL points to the current position in the filespec (where the name ends), and the default extension string address is saved on the stack. This routine uses LDDR (block move decrementing) to shift the existing filespec characters to make room, then copies the default extension into the gap.

4FDB
LD BC,000FH 01 0F 00
Load Register Pair BC with 000FH (15 decimal). This is the number of bytes to shift in the LDDR block move, making room for the extension data in the filespec buffer.
4FDE
ADD HL,BC 09
Add 15 to HL, pointing HL to the end of the region that will be the destination for the LDDR move. HL now points 15 bytes past the insertion point.
4FDF
LD D,H 54
Copy H into D, starting to set up DE as the destination pointer for LDDR. DE will point 4 bytes past HL.
4FE0
LD E,L 5D
Copy L into E, completing the DE = HL copy.
4FE1
INC DE 13
INCrement DE by 1. DE is now HL + 1.
4FE2
INC DE 13
INCrement DE by 1. DE is now HL + 2.
4FE3
INC DE 13
INCrement DE by 1. DE is now HL + 3.
4FE4
INC DE 13
INCrement DE by 1. DE is now HL + 4. The 4-byte offset creates space for the extension separator "/" plus 3 extension characters to be inserted.
4FE5
INC BC 03
INCrement BC by 1, making BC = 0010H (16 decimal). This adjusts the byte count for the LDDR block move to include one more byte in the shift operation.
4FE6
LDDR ED B8
Block move with decrement: copy BC bytes from (HL) to (DE), decrementing HL and DE after each byte. This shifts the existing filespec data 4 bytes toward higher addresses, creating a 4-byte gap for the default extension to be inserted. Source = (HL) decrementing, Destination = (DE) decrementing, Count = BC (16 bytes).
4FE8
POP HL E1
Restore Register Pair HL from the stack. HL now points to the default extension string (e.g., 51B5H for "CMD").
4FE9
INC HL 23
Advance HL past the first byte of the default extension string. The first byte is a length or marker byte that is not part of the extension text itself.
4FEA
INC HL 23
Advance HL to the third byte of the default extension string. HL now points to the last character of the 3-character extension (since LDDR copies in reverse, we start from the end).
4FEB
LD C,03H 0E 03
Load Register C with 03H (3 decimal). BC was decremented to zero by LDDR, so B is already 00H. BC = 0003H sets the count for copying the 3-character extension.
4FED
LDDR ED B8
Block move with decrement: copy 3 bytes from (HL) to (DE), decrementing both pointers after each byte. This copies the default extension characters (e.g., "CMD") into the gap created by the previous LDDR. After this, the filespec contains the original name followed by the default extension.
4FEF
LD A,2FH 3E 2F
Load Register A with 2FH (ASCII: /), the extension separator character.
4FF1
LD (DE),A 12
Store the "/" extension separator into the filespec buffer at (DE). This is placed immediately before the 3-character extension that was just copied, completing the "NAME/EXT" format.
4FF2
POP DE D1
Restore Register Pair DE (the original filespec buffer start address) from the stack.
4FF3
RET C9
RETURN to the caller. The filespec buffer now contains the original filename with the default extension (e.g., "CMD") inserted after the name.

4FF4H - Character Extraction Subroutine

Reads up to B characters from the command line at (HL), storing valid filename characters (digits 0-9 and uppercase letters A-Z) into the output buffer at (DE). Skips over excess characters when the maximum count is reached. Terminates when it encounters a 03H end-of-buffer marker, 0DH carriage return, or any character outside the valid range (below 30H or between 3AH-40H or above 5AH). On return: A = the character that caused termination, Z flag set = no valid characters were stored (first-character flag still set), NZ = at least one character was stored. Self-modifies the byte at 5026H to track whether a character has been stored in the current field.

4FF4
LD A,B 78
Copy the maximum character count from Register B into Register A. This value will be stored as the "remaining count" marker at 5026H.
4FF5
LD (5026H),A 32 26 50
Store the maximum character count into the self-modifying operand at 5026H. Self-Modifying Code
This writes the initial count (from B) into the operand byte of the LD A,00H instruction at 5025H. When the first valid character is stored, this value is reset to 00H at 5018H. The instruction at 5025H then reads back this byte: if non-zero, no characters have been stored yet (first-character flag); if zero, at least one character was stored.
4FF8
INC B 04
INCrement Register B by 1. This pre-increments the counter so that the DJNZ loop at 5014H will correctly count down the maximum number of characters. The actual count loop uses DEC B at 5013H followed by JR Z at 5014H.
4FF9
LD A,(HL) 7E
Loop Start
Fetch the next character from the command line at (HL) into Register A.
4FFA
CP 03H FE 03
Compare Register A against 03H (end-of-buffer terminator). If the command line buffer has been exhausted, the Z FLAG is set.
4FFC
If the Z FLAG (Zero) has been set because the end-of-buffer terminator (03H) was reached, JUMP to 5021H to terminate character extraction and prepare the return status.
4FFE
CP 0DH FE 0D
Compare Register A against 0DH (ASCII carriage return). This marks the end of the command line input.
5000
If the Z FLAG (Zero) has been set because a carriage return (0DH) was reached, JUMP to 5021H to terminate character extraction.
5002
INC HL 23
Advance HL to the next character in the command line. The current character has been read into A and will be validated below. HL is advanced now so that if the character is invalid, HL already points past it.
5003
CP 30H FE 30
Compare Register A against 30H (ASCII: 0). Characters below 30H are not valid filename characters (this range includes spaces 20H, separators like "/" 2FH, and control characters).
5005
If the CARRY FLAG has been set because the character is less than 30H (below digit "0"), JUMP to 5021H to terminate extraction. This catches spaces, separators, and control characters.
5007
CP 3AH FE 3A
Compare Register A against 3AH (ASCII: :). Characters in the range 30H-39H are digits 0-9 (valid). Characters 3AH and above need further checking.
5009
If the CARRY FLAG has been set because the character is less than 3AH (i.e., it is a digit 0-9 in the range 30H-39H), JUMP to 5013H to store this valid character in the output buffer.
500B
CP 41H FE 41
Compare Register A against 41H (ASCII: A). Characters between 3AH-40H (colon through at-sign) are not valid filename characters.
500D
If the CARRY FLAG has been set because the character is between 3AH and 40H (not a digit and not a letter), JUMP to 5021H to terminate extraction. This catches the ":" drive separator (3AH) and other punctuation.
500F
CP 5BH FE 5B
Compare Register A against 5BH (one past ASCII: Z). Characters 41H-5AH are uppercase letters A-Z (valid). Characters 5BH and above (brackets, backslash, etc.) are not valid.
5011
If the NO CARRY FLAG has been set because the character is 5BH or above (beyond 'Z'), JUMP to 5021H to terminate extraction.

If we reach here, the character is a valid filename character: a digit (30H-39H) or an uppercase letter (41H-5AH).

5013
DEC B 05
DECrement Register B (the remaining character counter). If B reaches zero, the maximum field length has been filled.
5014
If the Z FLAG (Zero) has been set because B reached zero (maximum characters already stored), JUMP to 501EH to skip storing this character and continue scanning past any remaining characters in the field.
5016
LD (DE),A 12
Store the valid filename character from Register A into the output buffer at (DE).
5017
XOR A AF
Set Register A to zero. This value will be stored at 5026H to clear the "first character" flag.
5018
LD (5026H),A 32 26 50
Store 00H into the self-modifying operand at 5026H. Self-Modifying Code
This clears the first-character flag that was set at 4FF5H. When the routine terminates, the value at 5026H is read back: 00H means at least one character was stored (success), non-zero means no characters were stored.
501B
INC DE 13
Advance the output buffer pointer to the next position.
501C
LOOP BACK to 4FF9H to continue reading characters from the command line.
Loop End
501E
INC B 04
INCrement Register B back to 1. B was decremented to zero (field full), but the loop at 4FF9H needs B to be non-zero so DJNZ-style logic can continue scanning past excess characters without storing them.
501F
LOOP BACK to 4FF9H to continue scanning the command line. Excess characters beyond the maximum field width are consumed but not stored.
5021
LD C,A 4F
Save the terminating character from Register A into Register C. This preserves the stopping character (03H, 0DH, or a separator/invalid character) for the caller to examine.
5022
LD A,03H 3E 03
Load Register A with 03H, the buffer terminator byte.
5024
LD (DE),A 12
Store the 03H terminator into the output buffer at (DE), marking the end of the extracted characters.
5025
LD A,00H 3E 00
Self-Modifying Code
The operand byte (00H shown here) is the target of the self-modifying writes at 4FF5H and 5018H. At runtime, this byte contains either the initial count (non-zero, meaning no characters were stored) or 00H (meaning at least one character was stored). The LD A instruction loads this flag value into Register A.
5027
OR A B7
OR Register A with itself to set the flags based on A's value. If A is 00H (characters were stored), the Z FLAG is set. If A is non-zero (no characters were stored), the NZ FLAG is set. This provides the return status to the caller.
5028
LD A,C 79
Restore the terminating character from Register C back into Register A. The caller can examine A to determine what character caused the extraction to stop (separator, terminator, or invalid character).
5029
RET C9
RETURN to the caller. Z flag indicates the result: Z set = no valid characters were stored (first call yielded nothing), NZ = at least one character was stored. Register A holds the terminating character.

502AH - Command Table Lookup

This routine searches an 8-byte-entry command/keyword table for a match against the parsed name in the buffer at (DE). Each table entry contains a 6-character name followed by a 2-byte dispatch address or value. The table is terminated by a 00H byte. On entry: BC = table start address, DE = parsed name buffer. On return: Z flag set = match found (DE = dispatch address from the table entry, C = 1-based entry index, HL restored from stack); NZ flag = no match found. The routine compares up to 5 characters of the parsed name against each entry, and also checks for padding matches where the table entry has spaces and the input has a 03H or 0DH terminator.

502A
PUSH HL E5
Save Register Pair HL (current command line position) onto the stack. HL will be restored before returning to the caller.
502B
LD H,B 60
Copy the high byte of the table address from Register B into Register H.
502C
LD L,C 69
Copy the low byte of the table address from Register C into Register L. Register Pair HL now points to the start of the command table.
502D
LD C,01H 0E 01
Initialize Register C to 01H as the 1-based entry index counter. The first entry is index 1, second is index 2, and so on. This index is returned in C when a match is found.

Table Search Loop Start
The outer loop iterates through each 8-byte entry in the command table. For each entry, it compares the first character against the parsed name. If the first character matches, it enters the inner comparison loop.

502F
LD A,(DE) 1A
Loop Start
Fetch the first character of the parsed name from the buffer at (DE) into Register A.
5030
CP (HL) BE
Compare Register A (first character of parsed name) against the first character of the current table entry at (HL). If they match, the Z FLAG is set.
5031
If the Z FLAG (Zero) has been set because the first characters match, JUMP to 5042H to perform a detailed character-by-character comparison of the rest of the entry.
5033
PUSH BC C5
Save Register Pair BC (C = entry index, B = comparison counter from inner loop) onto the stack. BC will be used to advance HL to the next table entry.
5034
LD BC,0008H 01 08 00
Load Register Pair BC with 0008H (8 decimal), the size of each entry in the command table (6 name characters + 2 address bytes).
5037
ADD HL,BC 09
ADD 8 to HL to advance the table pointer to the next entry.
5038
POP BC C1
Restore Register Pair BC (C = entry index) from the stack.
5039
INC C 0C
INCrement Register C (the entry index counter) by 1 to track the current table position.
503A
LD A,(HL) 7E
Fetch the first byte of the next table entry into Register A. If this is 00H, we have reached the end of the table.
503B
OR A B7
OR Register A with itself to set the flags. If A is 00H (table terminator), the Z FLAG is set.
503C
If the NZ FLAG (Not Zero) has been set because A is not 00H (more entries remain), LOOP BACK to 502FH to compare the parsed name against the next table entry.
503E
POP HL E1
Restore Register Pair HL (the saved command line position) from the stack.
Loop End
503F
OR 01H F6 01
OR Register A with 01H to force the NZ flag. This ensures the return status signals "no match found" to the caller.
5041
RET C9
RETURN to the caller. NZ flag is set, indicating no matching entry was found in the command table.

5042H - Command Table Entry Comparison

Reached when the first character of the parsed name matches a table entry. This code performs a detailed character-by-character comparison of the next 5 characters (the remaining bytes of the 6-character name field). The comparison accounts for the parsed name being shorter than the table entry by treating 03H and 0DH terminators as matching any space (20H) padding in the table entry.

5042
LD B,05H 06 05
Load Register B with 05H (5 decimal), the number of remaining characters to compare after the first character already matched. The table entry has 6 name characters total; 1 has been matched, leaving 5.
5044
PUSH HL E5
Save Register Pair HL (pointer to the matched table entry) onto the stack. This will be used later to extract the dispatch address if the full match succeeds.
5045
PUSH DE D5
Save Register Pair DE (pointer to the parsed name buffer) onto the stack. This allows restoring DE if the comparison fails and the search must continue.

Character Comparison Loop Start
This inner loop compares up to 5 more characters of the parsed name against the table entry. If the parsed name terminates early (with 03H or 0DH), the remaining table characters are checked for space padding.

5046
INC DE 13
Loop Start
Advance DE to the next character in the parsed name buffer.
5047
INC HL 23
Advance HL to the next character in the table entry.
5048
LD A,(DE) 1A
Fetch the next character from the parsed name buffer at (DE) into Register A.
5049
CP 03H FE 03
Compare Register A against 03H (the buffer terminator). If the parsed name has ended, the remaining table entry characters must all be spaces for a match.
504B
If the Z FLAG (Zero) has been set because the parsed name has ended with a 03H terminator, JUMP to 5074H to check if the remaining table characters are spaces (padding).
504D
CP 0DH FE 0D
Compare Register A against 0DH (carriage return, the command line terminator). A carriage return also indicates the parsed name has ended.
504F
If the Z FLAG (Zero) has been set because the input ended with a carriage return, JUMP to 5074H to check remaining table entry characters for space padding.
5051
CP (HL) BE
Compare Register A (parsed name character) against the corresponding character in the table entry at (HL).
5052
If the NZ FLAG (Not Zero) has been set because the characters do not match, JUMP to 5064H to check for valid filename characters that might indicate a partial match with more input remaining.
5054
DECrement B and LOOP BACK to 5046H if B is not zero. Continue comparing characters until all 5 remaining characters have been checked.
Loop End

Full Match Found
All 6 characters of the table entry matched the parsed name. Now extract the 2-byte dispatch address from bytes 7-8 of the entry.

5056
POP DE D1
Discard the saved parsed name buffer pointer from the stack (no longer needed since a match was found).
5057
LD A,C 79
Copy the entry index from Register C into Register A. This preserves the 1-based index of the matched entry.
5058
POP BC C1
Restore the original BC value from the stack (this was the HL save from 5044H going through the wrong register pair name - actually this pops the saved HL from PUSH HL at 5044H into BC). BC now holds the address of the matched table entry's first character.
5059
LD HL,0006H 21 06 00
Load Register Pair HL with 0006H, the byte offset from the start of a table entry to the 2-byte dispatch address field (6 name characters, then the address at offset +6).
505C
ADD HL,BC 09
ADD BC (table entry start address) to HL (offset 6). HL now points to the dispatch address field of the matched entry.
505D
LD C,A 4F
Restore the entry index from Register A back into Register C. C now holds the 1-based index of the matched command.
505E
LD E,(HL) 5E
Fetch the low byte of the dispatch address from the table entry at (HL) into Register E.
505F
INC HL 23
Advance HL to the high byte of the dispatch address.
5060
LD D,(HL) 56
Fetch the high byte of the dispatch address from (HL) into Register D. Register Pair DE now holds the complete 16-bit dispatch address from the matched table entry.
5061
POP HL E1
Restore Register Pair HL (the original command line position saved at 502AH) from the stack.
5062
XOR A AF
Set Register A to zero and set the Z FLAG. The Z flag signals to the caller that a match was found.
5063
RET C9
RETURN to the caller. Z flag set = match found, DE = dispatch address, C = entry index, HL = command line position.

5064H - Mismatch Character Validation

Reached when a character in the parsed name does not match the corresponding table entry character. This code checks whether the mismatched character is a valid filename character (digit or letter). If it is, the mismatch might just be because the command name is a prefix of a longer filename, so the search continues with the next table entry. If the character is not a valid filename character (it is a separator, terminator, or invalid), the code checks if the table entry has space padding where the input terminates.

5064
CP 30H FE 30
Compare Register A (the mismatched character from the parsed name) against 30H (ASCII: 0). Characters below 30H include terminators and separators.
5066
If the CARRY FLAG has been set because the character is less than 30H (a separator or terminator), JUMP to 5074H to check if the table entry's remaining characters are space padding. This handles the case where a shorter command name like "DIR" matches against a table entry padded as "DIR ".
5068
CP 3AH FE 3A
Compare Register A against 3AH (ASCII: :). Characters 30H-39H are digits (valid filename chars).
506A
If the CARRY FLAG has been set because the character is a digit (30H-39H), JUMP to 5079H to abandon this table entry and continue searching. A digit in the parsed name that doesn't match the table entry means this is not the right command.
506C
CP 41H FE 41
Compare Register A against 41H (ASCII: A). Characters 3AH-40H are not valid filename characters.
506E
If the CARRY FLAG has been set because the character is between 3AH and 40H (not alphanumeric), JUMP to 5074H to check for space padding in the table entry. This handles ":" drive specifiers that follow short command names.
5070
CP 5BH FE 5B
Compare Register A against 5BH (one past ASCII: Z). Characters 41H-5AH are uppercase letters (valid).
5072
If the CARRY FLAG has been set because the character is an uppercase letter (41H-5AH), JUMP to 5079H to abandon this table entry. A letter that doesn't match means the input is a different word, not this command.
5074
LD A,(HL) 7E
Fetch the current table entry character at (HL) into Register A. This is checked to see if it is a space (20H), which would indicate the table entry name is shorter than the full 6-character field and the remaining characters are padding.
5075
CP 20H FE 20
Compare Register A against 20H (ASCII space). If the table entry character is a space, it is padding and the shorter parsed name has matched the significant portion of the entry.
5077
If the Z FLAG (Zero) has been set because the table character is a space (padding), JUMP back to 5056H. The parsed name matches the command name portion of this entry. This is the successful match path for commands shorter than 6 characters.
5079
POP DE D1
Restore Register Pair DE (the parsed name buffer pointer) from the stack, undoing the PUSH DE at 5045H.
507A
POP HL E1
Restore Register Pair HL (the matched table entry start address) from the stack, undoing the PUSH HL at 5044H.
507B
JUMP back to 5033H to advance to the next table entry and continue the search loop.

507DH - Option/Keyword Parser

This routine parses parenthesized option lists from the command line. TRSDOS commands can include options in the format "(KEYWORD=VALUE,KEYWORD=VALUE)". Entry: HL points to the current position in the command line. The routine first scans past any spaces to find an opening parenthesis "(" (28H). If found, it enters a loop that extracts keyword names (up to 6 characters) and their associated values. Values can be decimal numbers, hexadecimal numbers (prefixed with "X'"), or boolean keywords (YES/NO/ON/OFF). On return: Z flag set = options parsed successfully (closing ")" found), NZ = no parenthesized options found or the input terminated before ")". Register Pair DE points to the keyword lookup buffer at 51AFH.

507D
LD A,(HL) 7E
Fetch the current character from the command line at (HL) into Register A.
507E
CP 0DH FE 0D
Compare Register A against 0DH (carriage return). If the command line has ended, there are no options to parse.
5080
RET Z C8
If the Z FLAG (Zero) has been set because a carriage return was found, RETURN immediately. Z flag set indicates normal completion with no options present.
5081
CP 28H FE 28
Compare Register A against 28H (ASCII: (). The opening parenthesis marks the start of an option list.
5083
If the Z FLAG (Zero) has been set because an opening parenthesis was found, JUMP to 508EH to begin parsing the option list.
5085
CP 20H FE 20
Compare Register A against 20H (ASCII space). Spaces before the option list are silently consumed.
5087
If the Z FLAG (Zero) has been set because the character is a space, JUMP to 508BH to skip it and check the next character.
5089
OR A B7
OR Register A with itself. Since A is not 0DH, 28H, or 20H, it is a non-space, non-paren character. This sets NZ flag.
508A
RET C9
RETURN to the caller. NZ flag is set, indicating that the character at (HL) is not a parenthesized option list. The caller can process it differently.
508B
INC HL 23
Advance HL past the space character.
508C
LOOP BACK to 507DH to check the next character after the space.

508EH - Parse Single Option Keyword and Value

Parses one keyword=value pair from within the parenthesized option list. First extracts the keyword name (up to 6 characters) into the buffer at 51AFH using the character extraction routine at 4FF4H, then looks up the keyword in a caller-provided command table. If the keyword is found and is followed by "=" then the value is parsed according to its format. On return: Z flag set = option pair parsed successfully and the caller should look for more options; NZ = option list ended or error.

508E
PUSH DE D5
Save Register Pair DE (the caller's keyword table address or other context pointer) onto the stack.
508F
LD B,06H 06 06
Load Register B with 06H (6 decimal), the maximum number of characters for a keyword name.
5091
LD DE,51AFH 11 AF 51
Load Register Pair DE with the address 51AFH, the keyword extraction buffer. The keyword name will be written here.
5094
INC HL 23
Advance HL past the "(" or "," separator to the first character of the keyword name.
5095
GOSUB to the character extraction subroutine at 4FF4H to read up to 6 keyword characters from the command line into the buffer at 51AFH.
5098
DEC HL 2B
DECrement HL to back up one position. The character extraction routine advanced HL past the terminating character, but the caller needs HL to point at the terminator for subsequent processing.
5099
POP DE D1
Restore Register Pair DE (the caller's context pointer) from the stack.
509A
RET NZ C0
If the NZ FLAG (Not Zero) has been set because no valid characters were extracted (the character extraction returned NZ), RETURN to the caller with NZ indicating the option list ended without a valid keyword.
509B
PUSH DE D5
Save Register Pair DE (caller's context pointer) onto the stack again before the keyword lookup.
509C
LD B,D 42
Copy the high byte of DE into Register B. DE holds the caller's keyword table address.
509D
LD C,E 4B
Copy the low byte of DE into Register C. BC now holds the keyword table address for the lookup routine.
509E
LD DE,51AFH 11 AF 51
Load Register Pair DE with the address 51AFH, pointing to the extracted keyword name in the buffer.
50A1
GOSUB to the command table lookup routine at 502AH to search the keyword table (BC) for a match against the extracted keyword name at (DE). On return: Z = match found (DE = value address from table), NZ = no match.
50A4
If the Z FLAG (Zero) has been set because the keyword was found in the table, JUMP to 50A8H to parse the value portion.
50A6
POP DE D1
Restore Register Pair DE from the stack (cleanup for the no-match exit path).
50A7
RET C9
RETURN to the caller. NZ flag is set (from the failed lookup), indicating the keyword was not recognized.

50A8H - Parse Option Value After Keyword Match

Reached after a keyword has been found in the option table. The dispatch address from the table entry is in DE, pointing to a 2-byte storage location for the value. This code checks for an "=" sign; if present, it parses the value in one of three formats: hexadecimal (X'nn'), boolean (YES/NO/ON/OFF), or decimal. If no "=" is present, the keyword is treated as a boolean flag and assigned the value FFFFH (true). The parsed value is stored at the address in DE.

50A8
LD A,(HL) 7E
Fetch the current character from the command line at (HL) into Register A. After the keyword name, this should be either "=" (value follows) or "," / ")" (keyword is a standalone flag).
50A9
CP 3DH FE 3D
Compare Register A against 3DH (ASCII: =). If the character is "=", a value follows the keyword.
50AB
If the Z FLAG (Zero) has been set because "=" was found, JUMP to 50C1H to parse the value.

No Value Specified
The keyword has no "=" sign, so it is treated as a boolean flag. The value FFFFH is stored to indicate "true" or "present".

50AD
LD BC,0FFFFH 01 FF FF
Load Register Pair BC with FFFFH, the default value for a keyword specified without an explicit value. FFFFH represents "true" or "enabled".
50B0
LD A,C 79
Copy the low byte of the parsed value from Register C into Register A.
50B1
LD (DE),A 12
Store the low byte of the value at the storage address in (DE). DE points to the 2-byte storage location identified by the keyword table entry's dispatch address field.
50B2
INC DE 13
Advance DE to the high byte of the storage location.
50B3
LD A,B 78
Copy the high byte of the parsed value from Register B into Register A.
50B4
LD (DE),A 12
Store the high byte of the value at (DE). The complete 16-bit value is now stored in little-endian format at the keyword's storage address.
50B5
POP DE D1
Restore Register Pair DE (the caller's context/keyword table pointer) from the stack.
50B6
LD A,(HL) 7E
Fetch the current character from the command line at (HL). After storing the value, check if more options follow.
50B7
CP 2CH FE 2C
Compare Register A against 2CH (ASCII: ,). A comma separates multiple keyword=value pairs within the option list.
50B9
If the Z FLAG (Zero) has been set because a comma was found, LOOP BACK to 508EH to parse the next keyword=value pair.
50BB
CP 29H FE 29
Compare Register A against 29H (ASCII: )). A closing parenthesis marks the end of the option list.
50BD
RET NZ C0
If the NZ FLAG (Not Zero) has been set because the character is neither "," nor ")", RETURN with NZ indicating an unexpected character in the option list (error condition).
50BE
INC HL 23
Advance HL past the closing ")" parenthesis.
50BF
XOR A AF
Set Register A to zero and set the Z FLAG. The Z flag signals successful completion of option parsing.
50C0
RET C9
RETURN to the caller. Z flag set = option list parsed successfully and HL points past the closing ")".

50C1H - Parse Value After Equals Sign

Reached when "=" was found after a keyword. Advances past the "=" and examines the first character of the value to determine its format: "X" indicates hexadecimal (X'nn' format), a letter A-Z indicates a boolean keyword (YES/NO/ON/OFF), and a digit 0-9 indicates a decimal number.

50C1
INC HL 23
Advance HL past the "=" character to the start of the value.
50C2
LD A,(HL) 7E
Fetch the first character of the value from the command line at (HL) into Register A.
50C3
CP 58H FE 58
Compare Register A against 58H (ASCII: X). An "X" prefix indicates the value is in hexadecimal format (X'nn').
50C5
If the Z FLAG (Zero) has been set because the value starts with "X", JUMP to 50D2H to parse a hexadecimal value.
50C7
CP 41H FE 41
Compare Register A against 41H (ASCII: A). Characters below "A" include digits (30H-39H) and separators.
50C9
If the CARRY FLAG has been set because the character is less than "A" (i.e., a digit or separator), JUMP to 50DAH to parse a decimal number.
50CB
GOSUB to the boolean value parser at 50DFH to check for YES, NO, ON, or OFF. On return: Z = recognized boolean (BC = FFFFH for true, 0000H for false), NZ = not recognized.
50CE
If the Z FLAG (Zero) has been set because a valid boolean keyword was found, JUMP back to 50B0H to store the value (in BC) and check for more options.
50D0
JUMP to 50A6H for the error exit. The value was not a recognized boolean keyword, hex number, or decimal number.
50D2
INC HL 23
Advance HL past the "X" prefix character.
50D3
GOSUB to the hexadecimal value parser at 511FH to parse a hex value in X'nnnn' format. On return: BC = parsed 16-bit hex value, Z = success, NZ = error.
50D6
If the Z FLAG (Zero) has been set because the hex value was parsed successfully, JUMP back to 50B0H to store the value and check for more options.
50D8
JUMP to 50A6H for the error exit. The hex value could not be parsed.
50DA
GOSUB to the decimal value parser at 5104H to parse a decimal number from the command line. On return: BC = parsed 16-bit value.
50DD
JUMP back to 50B0H to store the parsed decimal value (in BC) and check for more options.

50DFH - Boolean Value Parser (YES/NO/ON/OFF)

Parses boolean option values. Recognizes "Y" (YES), "N" (NO), "ON" (two characters: "O" then "N"), and "OF" (OFF, checked as "O" then "F"). For true values (Y, ON), BC is set to FFFFH. For false values (N, OFF), BC is set to 0000H. On return: Z flag set = valid boolean parsed, NZ = not a recognized boolean keyword.

50DF
LD BC,0000H 01 00 00
Initialize Register Pair BC to 0000H, the default value for "false" or "no". This will be changed to FFFFH if a "true" keyword is found.
50E2
LD A,(HL) 7E
Fetch the current character from the command line at (HL) into Register A.
50E3
CP 59H FE 59
Compare Register A against 59H (ASCII: Y). "Y" (or YES) means true.
50E5
If the Z FLAG (Zero) has been set because the character is "Y", JUMP to 50F7H to set BC = FFFFH (true) and advance past the value.
50E7
CP 4EH FE 4E
Compare Register A against 4EH (ASCII: N). "N" (or NO) means false.
50E9
If the Z FLAG (Zero) has been set because the character is "N", JUMP to 50FAH. BC remains 0000H (false). The routine will advance past the remaining characters.
50EB
CP 4FH FE 4F
Compare Register A against 4FH (ASCII: O). "O" could be the start of "ON" (true) or "OFF" (false).
50ED
RET NZ C0
If the NZ FLAG (Not Zero) has been set because the character is not "Y", "N", or "O", RETURN with NZ indicating this is not a recognized boolean keyword.
50EE
INC HL 23
Advance HL past the "O" to the next character.
50EF
LD A,(HL) 7E
Fetch the next character from the command line at (HL) into Register A. This should be "N" (for ON) or "F" (for OFF).
50F0
CP 46H FE 46
Compare Register A against 46H (ASCII: F). "OF" is the start of "OFF" (false).
50F2
If the Z FLAG (Zero) has been set because the character is "F" (making "OF" for OFF), JUMP to 50FAH. BC remains 0000H (false).
50F4
CP 4EH FE 4E
Compare Register A against 4EH (ASCII: N). "ON" means true.
50F6
RET NZ C0
If the NZ FLAG (Not Zero) has been set because the character is neither "F" nor "N" after "O", RETURN with NZ indicating an unrecognized keyword.
50F7
LD BC,0FFFFH 01 FF FF
Load Register Pair BC with FFFFH, the value for "true" or "enabled". This handles "Y" (YES) and "ON".
50FA
INC HL 23
Loop Start
Advance HL past the current character of the boolean keyword.
50FB
LD A,(HL) 7E
Fetch the next character from the command line.
50FC
CP 29H FE 29
Compare Register A against 29H (ASCII: )). A closing parenthesis ends the boolean keyword and the option list.
50FE
RET Z C8
If the Z FLAG (Zero) has been set because ")" was found, RETURN with Z flag set. The boolean value is in BC and the option list is complete.
50FF
CP 2CH FE 2C
Compare Register A against 2CH (ASCII: ,). A comma separates this option from the next one.
5101
RET Z C8
If the Z FLAG (Zero) has been set because "," was found, RETURN with Z flag set. The boolean value is in BC and more options follow.
5102
LOOP BACK to 50FAH to skip past remaining characters of the boolean keyword (e.g., the "ES" in "YES" or the second "F" in "OFF"). The loop continues until ")" or "," is found.
Loop End

5104H - Decimal Number Parser

Parses a decimal number from the command line into a 16-bit value in Register Pair BC. Uses the multiply-by-10-and-add algorithm: for each digit, BC = BC x 10 + digit. The multiply-by-10 is implemented as (BC x 4 + BC) x 2, using ADD HL,HL and ADD HL,BC instructions. On return: BC = the parsed 16-bit value. Returns when a non-digit character is encountered.

5104
LD BC,0000H 01 00 00
Initialize Register Pair BC to 0000H as the accumulator for the decimal value.
5107
LD A,(HL) 7E
Loop Start
Fetch the current character from the command line at (HL) into Register A.
5108
SUB 30H D6 30
SUBtract 30H from Register A, converting ASCII digit '0'-'9' (30H-39H) to binary value 0-9. If the character was below '0', the Carry flag is set.
510A
RET C D8
If the CARRY FLAG has been set because the character was below ASCII '0' (not a digit), RETURN. BC holds the accumulated value so far.
510B
CP 0AH FE 0A
Compare Register A against 0AH (10 decimal). Digits 0-9 produce values 00H-09H. A value of 0AH or above means the character was above '9' (not a digit).
510D
RET NC D0
If the NO CARRY FLAG has been set because A >= 0AH (the character was above '9'), RETURN. BC holds the accumulated value.

Multiply BC by 10 and Add Digit
The new value is computed as: BC = (BC x 4 + BC) x 2 + digit. This uses the identity: x * 10 = (x * 4 + x) * 2. The sequence is: HL = BC, HL = HL x 2, HL = HL x 2 (now HL = BC x 4), HL = HL + BC (now HL = BC x 5), HL = HL x 2 (now HL = BC x 10), then HL = HL + digit.

510E
PUSH HL E5
Save Register Pair HL (command line pointer) onto the stack. HL will be used for the multiply-by-10 arithmetic.
510F
LD H,B 60
Copy the high byte of the accumulator from B into H.
5110
LD L,C 69
Copy the low byte of the accumulator from C into L. HL now equals BC (the current accumulated value).
5111
ADD HL,HL 29
ADD HL to itself, doubling the value. HL = BC x 2.
5112
ADD HL,HL 29
ADD HL to itself again. HL = BC x 4.
5113
ADD HL,BC 09
ADD BC (the original value) to HL. HL = BC x 4 + BC = BC x 5.
5114
ADD HL,HL 29
ADD HL to itself. HL = BC x 5 x 2 = BC x 10.
5115
LD B,00H 06 00
Clear Register B to zero. The digit value (0-9) is in Register A and will be placed in C for the final ADD.
5117
LD C,A 4F
Copy the current digit value (0-9) from Register A into Register C. BC now holds 00:digit.
5118
ADD HL,BC 09
ADD the digit value to HL. HL = BC_old x 10 + digit. This is the new accumulated decimal value.
5119
LD B,H 44
Copy the high byte of the new value from H into B.
511A
LD C,L 4D
Copy the low byte of the new value from L into C. BC now holds the updated accumulated value.
511B
POP HL E1
Restore Register Pair HL (command line pointer) from the stack.
511C
INC HL 23
Advance HL to the next character in the command line.
511D
LOOP BACK to 5107H to process the next digit.
Loop End

511FH - Hexadecimal Value Parser (X'nnnn' Format)

Parses a hexadecimal value enclosed in single quotes after an "X" prefix. The "X" has already been consumed by the caller. This routine expects the next character to be a single quote (27H), followed by hex digits (0-9, A-F), and a closing single quote. Each hex digit is accumulated into BC by shifting BC left 4 bits and adding the digit. On return: Z flag set = valid hex parsed (BC = value), NZ = parse error.

511F
LD BC,0000H 01 00 00
Initialize Register Pair BC to 0000H as the accumulator for the hexadecimal value.
5122
LD A,(HL) 7E
Fetch the current character from the command line at (HL) into Register A. This should be the opening single quote.
5123
CP 27H FE 27
Compare Register A against 27H (ASCII: single quote '). The hex value must be enclosed in single quotes.
5125
RET NZ C0
If the NZ FLAG (Not Zero) has been set because the character is not a single quote, RETURN with NZ indicating a parse error.
5126
INC HL 23
Advance HL past the opening single quote.
5127
LD A,(HL) 7E
Loop Start
Fetch the next character from the command line at (HL) into Register A.
5128
SUB 30H D6 30
SUBtract 30H from Register A, converting ASCII '0'-'9' to binary 0-9. For hex letters 'A'-'F' (41H-46H), this yields 11H-16H.
512A
If the CARRY FLAG has been set because the character was below '0' (including the closing single quote at 27H), JUMP to 5136H to check for the closing quote.
512C
CP 0AH FE 0A
Compare Register A against 0AH. Values 00H-09H are digits 0-9; values 0AH and above need further checking for hex letters.
512E
If the CARRY FLAG has been set because A < 0AH (a digit 0-9), JUMP to 513EH to accumulate this digit into BC.
5130
SUB 07H D6 07
SUBtract 07H from Register A. This converts hex letters: 'A'(41H) - 30H = 11H - 07H = 0AH, 'B' = 0BH, ..., 'F' = 0FH.
5132
CP 10H FE 10
Compare Register A against 10H. Valid hex digits (0-F) yield values 00H-0FH. A value of 10H or above means the character was above 'F' (not a valid hex digit).
5134
If the CARRY FLAG has been set because A < 10H (a valid hex digit 0-F), JUMP to 513EH to accumulate this digit into BC.
5136
LD A,(HL) 7E
Re-fetch the original character from the command line (before SUB 30H mangled it) to check for the closing quote.
5137
CP 27H FE 27
Compare Register A against 27H (ASCII: single quote '). This should be the closing quote of the X'nn' format.
5139
INC HL 23
Advance HL past the current character (whether it is the closing quote or not). Note: INC does not affect the Z flag set by the CP instruction.
513A
RET Z C8
If the Z FLAG (Zero) has been set because the character was the closing single quote, RETURN with Z flag set. BC holds the parsed hexadecimal value and HL points past the closing quote.
513B
DEC HL 2B
DECrement HL to back up. The character was not a closing quote and not a valid hex digit, so this is a parse error. HL is restored to point at the offending character.
513C
XOR A AF
Set Register A to zero and set the Z FLAG. This is misleading - the routine returns Z even though the parse failed. The caller relies on the context (no closing quote found) to detect the error condition. However, since BC contains a partial value and HL doesn't point past a closing quote, the caller's subsequent processing handles this case.
513D
RET C9
RETURN to the caller.

Accumulate Hex Digit
Shift BC left by 4 bits and add the new hex digit. This is equivalent to: BC = BC x 16 + digit.

513E
PUSH HL E5
Save Register Pair HL (command line pointer) onto the stack. HL will be used for the shift arithmetic.
513F
LD H,B 60
Copy the high byte of the accumulator from B into H.
5140
LD L,C 69
Copy the low byte of the accumulator from C into L. HL now equals BC.
5141
ADD HL,HL 29
Shift HL left by 1 bit. HL = BC x 2.
5142
ADD HL,HL 29
Shift HL left by 1 bit. HL = BC x 4.
5143
ADD HL,HL 29
Shift HL left by 1 bit. HL = BC x 8.
5144
ADD HL,HL 29
Shift HL left by 1 bit. HL = BC x 16. Four left shifts multiply by 16, equivalent to shifting left by one hex digit position.
5145
LD B,H 44
Copy the shifted high byte from H into B.
5146
ADD A,L 85
ADD the shifted low byte (L) to Register A (the current hex digit value 0-F). This combines the low byte of BC x 16 with the new digit.
5147
LD C,A 4F
Store the combined low byte into Register C. BC now holds BC_old x 16 + digit.
5148
POP HL E1
Restore Register Pair HL (command line pointer) from the stack.
5149
INC HL 23
Advance HL to the next character in the command line.
514A
LOOP BACK to 5127H to process the next hex digit.
Loop End

514CH - BASIC2 Command Handler

The BASIC2 resident command handler. BASIC2 starts non-DOS BASIC (Level II BASIC without disk support). This routine performs a warm restart into Level II BASIC by copying the first 36H (54) bytes from ROM address 06D2H to RAM address 4000H, which restores the original BASIC RST vector table and system hooks that were overwritten when TRSDOS loaded. It then clears the next 27H (39) bytes of the work area (4036H-405CH) to zero and jumps to the ROM BASIC initialization entry point at 0075H. This effectively exits TRSDOS and returns full control to Level II BASIC, permanently abandoning all DOS state. Unlike Disk BASIC, non-DOS BASIC has no access to disk files or DOS commands.

514C
LD HL,06D2H 21 D2 06
Point Register Pair HL to ROM address 06D2H, which contains the original BASIC vector initialization data. This is a table in the Level II BASIC ROM that holds the default JP instructions for RST 08H through RST 38H and related system vectors at 4000H-4035H.
514F
LD DE,4000H 11 00 40
Point Register Pair DE to the start of the DOS vector area at 4000H. This is the destination where the original BASIC vectors will be restored, overwriting the TRSDOS RST vectors.
5152
LD BC,0036H 01 36 00
Load Register Pair BC with 0036H (54 decimal), the number of bytes to copy. This covers the complete vector table from 4000H through 4035H.
5155
LDIR ED B0
Block Move
Copy 54 bytes from ROM at 06D2H (HL) to RAM at 4000H (DE), incrementing both pointers. Source: ROM vector initialization table at 06D2H. Destination: RAM vector area at 4000H. After the move, HL = 0708H, DE = 4036H, BC = 0000H. This restores the original BASIC RST handlers, removing all TRSDOS hooks from the vector table.
5157
XOR A AF
Set Register A to zero. This will be used to clear the DOS work area bytes that follow the vector table.
5158
LD B,27H 06 27
Load Register B with 27H (39 decimal), the number of bytes to clear. DE is already at 4036H (set by LDIR), so this clears 4036H through 405CH, which includes the keyboard image buffer, clock variables, and system state flags.
515A
LD (DE),A 12
Loop Start
Store 00H at the address in (DE) to clear the byte.
515B
INC DE 13
Advance DE to the next byte in the work area.
515C
DECrement B and LOOP BACK to 515AH if B is not zero. Continue clearing until all 39 bytes are zeroed.
Loop End
515E
DI F3
Disable interrupts. The ROM BASIC initialization at 0075H will re-enable interrupts as needed during its own setup.
515F
JUMP to ROM address 0075H, the Level II BASIC warm start initialization entry point. This completes the exit from TRSDOS. BASIC will reinitialize its workspace and display the READY prompt. This is a one-way jump; TRSDOS state is permanently destroyed.

5162H - DEBUG Command Handler

The DEBUG resident command handler. Toggles the DEBUG mode on or off based on a boolean parameter. When DEBUG is enabled, the system flags byte at 430FH has bit 7 set, the BREAK key handler is patched to jump to the RST 30H vector (400FH for the debug entry point), and the error exit vector at 4030H is patched to CALL 400FH instead of LD A,A3H. When DEBUG is disabled, these patches are reversed. Entry: HL points to the command line after "DEBUG". The routine calls 51A0H to parse an optional boolean parameter (ON/OFF/YES/NO).

5162
GOSUB to the parameter parser at 51A0H, which skips spaces then looks for a parenthesized boolean parameter. On return: Z flag set = "true" (ON/YES/Y), NZ = "false" (OFF/NO/N) or no parameter. Register A = 0 for NZ (false/absent), non-zero for Z (true).
5165
LD HL,430FH 21 0F 43
Point Register Pair HL to the system flags byte at 430FH. Bit 7 of this byte is the DEBUG active flag.
5168
DI F3
Disable interrupts during the patching operation to prevent interrupt handlers from executing partially-patched code.
5169
If the Z FLAG (Zero) has been set because the parameter was false (OFF/NO/N) or absent, JUMP to 5184H to disable DEBUG mode.

Enable DEBUG Mode
Set bit 7 of the system flags, patch the BREAK key handler to jump to 400FH (RST 30H / DEBUG entry), and patch the error exit at 4030H to CALL 400FH.

516B
SET 7,(HL) CB FE
Set bit 7 of the system flags byte at (HL) = 430FH. This marks DEBUG mode as active.
516D
LD HL,400FH 21 0F 40
Load Register Pair HL with 400FH, the RST 30H vector address. This is the target for the BREAK key handler and error exit patches when DEBUG is active.
5170
LD A,0C3H 3E C3
Load Register A with 0C3H, the opcode for the JP instruction. This will be written into the BREAK key handler at 4315H.
5172
LD (4316H),HL 22 16 43
Store the address 400FH into the BREAK key handler target at 4316H-4317H. Self-Modifying Code
When the BREAK key is pressed, the handler at 4315H will now execute JP 400FH, entering the DEBUG monitor.
5175
LD (4315H),A 32 15 43
Store 0C3H (JP opcode) into the BREAK key handler opcode byte at 4315H. Self-Modifying Code
This creates a complete JP 400FH instruction at 4315H-4317H. The BREAK key interrupt now enters DEBUG mode.
5178
LD A,0CDH 3E CD
Load Register A with 0CDH, the opcode for the CALL instruction. This will replace the LD A opcode at 4030H.
517A
LD (4031H),HL 22 31 40
Store the address 400FH into the operand at 4031H-4032H. Self-Modifying Code
Combined with the CALL opcode at 4030H, this creates "CALL 400FH" which invokes the DEBUG monitor when a DOS error occurs with the error-already-displayed flag.
517D
EI FB
Re-enable interrupts. The patching is complete.
517E
LD (4030H),A 32 30 40
Store 0CDH (CALL opcode) into the error exit vector at 4030H. Self-Modifying Code
The error exit at 4030H is now "CALL 400FH" instead of the original "LD A,A3H". When a DOS error occurs, the DEBUG monitor is entered before returning to DOS READY.
5181
JUMP to the DOS READY prompt handler at 4E1FH. DEBUG mode is now active and the user is returned to the command prompt.

Disable DEBUG Mode
Clear bit 7 of the system flags, restore the BREAK key handler to disabled, and restore the error exit at 4030H to its original LD A,A3H instruction.

5184
RES 7,(HL) CB BE
Clear bit 7 of the system flags byte at (HL) = 430FH. This marks DEBUG mode as inactive.
5186
XOR A AF
Set Register A to zero.
5187
LD (4315H),A 32 15 43
Store 00H into the BREAK key handler opcode byte at 4315H. Self-Modifying Code
This disables the BREAK key handler by replacing the JP opcode (C3H) with NOP (00H). The BREAK key will no longer enter DEBUG mode.
518A
LD A,3EH 3E 3E
Load Register A with 3EH, the opcode for the LD A,nn instruction. This restores the original instruction at 4030H.
518C
LD HL,0EFA3H 21 A3 EF
Load Register Pair HL with 0EFA3H. The low byte A3H will become the operand of the LD A instruction at 4031H (making "LD A,A3H"), and EFH at 4032H becomes the RST 28H instruction. Together, 4030H-4032H will contain "LD A,A3H / RST 28H" (3E A3 EF), the original error-already-displayed exit sequence.
518F
JUMP back to 517AH to store HL (A3H/EFH) at 4031H-4032H and A (3EH) at 4030H. This restores the original "LD A,A3H / RST 28H" sequence at the error exit. The code at 517AH also re-enables interrupts and then falls through to store A at 4030H and jump to 4E1FH.

5191H - TRACE Command Handler

The TRACE resident command handler. Toggles the interrupt-driven trace display by enqueueing or dequeueing the trace callback handler at 4CD9H through the SYS0 timer callback system. When TRACE is enabled, the timer interrupt service routine calls 4CD9H on each tick, which displays register contents on the screen in real time. Entry: HL points to the command line after "TRACE".

5191
GOSUB to the parameter parser at 51A0H to parse an optional boolean parameter (ON/OFF/YES/NO). On return: Z = false/disable, NZ = true/enable. Register A holds the parsed boolean result.
5194
LD DE,4CD9H 11 D9 4C
Load Register Pair DE with the address 4CD9H, the trace display callback routine in SYS0. This is the routine that will be enqueued or dequeued from the timer interrupt chain.
5197
LD A,0BH 3E 0B
Load Register A with 0BH (11 decimal), the timer tick interval for the trace callback. The trace display will be updated every 11 timer ticks.
5199
If the Z FLAG (Zero) has been set because the parameter was false (disable TRACE), JUMP to the SYS0 dequeue timer callback routine at 4413H to remove the trace handler from the interrupt chain. DE = 4CD9H (callback address). This stops the real-time trace display.
519C
JUMP to the SYS0 enqueue timer callback routine at 4410H to add the trace handler to the interrupt chain. DE = 4CD9H (callback address), A = 0BH (tick interval). This starts the real-time trace display.

519FH - Parameter Parser Helper

Helper routine that skips spaces, then parses a parenthesized boolean value. Used by the DEBUG and TRACE command handlers. Entry: HL points into the command line. First calls 51A0H (which skips spaces), then if "(" is found, parses the boolean value. On return: Z = false or no parameter, NZ = true. Register A reflects the boolean result (0 = false/absent, non-zero = true).

519F
INC HL 23
Advance HL past the current character (a space that was detected by the caller before jumping here).
51A0
LD A,(HL) 7E
Fetch the current character from the command line at (HL) into Register A.
51A1
CP 20H FE 20
Compare Register A against 20H (ASCII space). Spaces are skipped before the parenthesized parameter.
51A3
If the Z FLAG (Zero) has been set because the character is a space, LOOP BACK to 519FH to advance past it and check the next character.
51A5
CP 28H FE 28
Compare Register A against 28H (ASCII: (). The boolean parameter must be enclosed in parentheses.
51A7
RET NZ C0
If the NZ FLAG (Not Zero) has been set because the character is not "(", RETURN with NZ. No parameter was specified, which is treated as "false" (disable).
51A8
INC HL 23
Advance HL past the "(" opening parenthesis.
51A9
GOSUB to the boolean value parser at 50DFH to parse YES/NO/ON/OFF from the command line. On return: BC = FFFFH (true) or 0000H (false).
51AC
LD A,B 78
Copy the high byte of the boolean result from Register B into Register A. For "true" (FFFFH), A = FFH (non-zero). For "false" (0000H), A = 00H.
51AD
OR A B7
OR Register A with itself to set the flags based on the boolean result. Z = false (A = 00H), NZ = true (A = FFH).
51AE
RET C9
RETURN to the caller. Z flag reflects the boolean parameter: Z = false/disable, NZ = true/enable.

51AFH - Data Area: Buffers and Message Strings

This area contains keyword buffers, the default extension string, and system message strings used by SYS1. These are not executable code; the disassembler has misinterpreted the bytes as Z80 instructions.

51AF-51B4
DEFM (6 bytes reserved) xx xx xx xx xx xx
Keyword Buffer
6-byte buffer used by the option keyword parser at 508EH to store extracted keyword names. The contents are runtime-variable and not meaningful at load time.
51B5-51B7
DEFM "CMD" 43 4D 44
Default Extension String
The 3-character string "CMD" (43H 4DH 44H). Used by the command dispatcher at 4E7AH when an unrecognized command is treated as a program filename: the default extension "CMD" is passed to the insert-default-extension routine at 4FC0H so that typing "MYPROG" is equivalent to "MYPROG/CMD".
51B8-51C2
DEFM 0AH + "DOS READY" + 0DH 0A 44 4F 53 20 52 45 41 44 59 0D
DOS READY Prompt String
The DOS READY prompt string. Begins with 0AH (line feed) to advance to a new line, followed by the text "DOS READY" in ASCII, and ends with 0DH (carriage return). Displayed by the command input handler at 4E43H via the SYS0 display message routine at 4467H.
51C3-51C8
DEFM "WHAT?" + 0DH 57 48 41 54 3F 0D
Error Message String
The "WHAT?" error message (57H 48H 41H 54H 3FH) followed by 0DH (carriage return). Displayed by the error handler at 4E87H when a command line cannot be parsed or the command name is not found in any command table and also cannot be loaded as a program file.