4E00H - SVC Request Dispatcher
Entry point for SYS1/SYS. Register A contains the SVC code from the RST 28H overlay dispatcher. The request code is encoded in bits 4-6 (masked with 70H). Each request code routes to a different handler: 10H/20H = DOS READY prompt and input, 30H = interpret command from buffer, 40H = extract filespec, 50H = add default extension, 60H = parse parameters, 70H = command interpreter core. If the request code does not match any handler, execution returns to the caller via RET NZ.
4E00
AND A,70H E6 70
SVC Request Dispatcher Entry
Mask Register A with 70H (binary 01110000) to extract bits 4-6. This isolates the request code from the full SVC code, stripping the overlay file number (bits 0-3) and the load flag (bit 7). The result is one of: 10H, 20H, 30H, 40H, 50H, 60H, or 70H.
4E02
CP A,10H FE 10
Compare the request code against 10H. Request 10H = "Display VTOS READY and accept command input."
4E04
If the Z FLAG is set (request code 10H), JUMP to 4E38H for the DOS READY / keyboard input handler.
4E06
CP A,20H FE 20
Compare the request code against 20H. Request 20H = "Display VTOS READY and accept command input" (same as 10H; both share the same handler at 4E38H).
4E08
If the Z FLAG is set (request code 20H), JUMP to 4E38H.
4E0A
CP A,40H FE 40
Compare the request code against 40H. Request 40H = "Extract filespec from command line."
4E0C
If the Z FLAG is set (request code 40H), JUMP to the filespec extractor at 4FCEH.
4E0F
CP A,50H FE 50
Compare the request code against 50H. Request 50H = "Add default extension to filename."
4E11
If the Z FLAG is set (request code 50H), JUMP to the extension inserter at 5042H.
4E14
CP A,60H FE 60
Compare the request code against 60H. Request 60H = "Parse parameters after filename."
4E16
If the Z FLAG is set (request code 60H), JUMP to the parameter parser at 510FH.
4E19
CP A,70H FE 70
Compare the request code against 70H. Request 70H = "Command interpreter core."
4E1B
If the Z FLAG is set (request code 70H), JUMP to the command interpreter core at 4E5CH.
4E1D
CP A,30H FE 30
Compare the request code against 30H. Request 30H = "Copy command from HL to buffer and interpret."
4E1F
RET NZ C0
If the NZ FLAG is set (request code does not match 30H - all other codes were tested above), RETURN to the caller. The request code is unrecognized.
4E20H - Request 30H: Copy and Interpret Command
Copies a command string from the address in HL to the DOS command buffer at 4318H (up to 63 characters), appends a 03H terminator, and falls through to the command interpreter at 4E59H. This request is used when a command string has been constructed in memory (e.g., from an AUTO procedure or CHAIN command) and needs to be interpreted.
4E20
LD DE,4318H 11 18 43
Request 30H Entry
Point Register Pair DE to 4318H, the DOS command input buffer in the SYS0 resident area. The command string from HL will be copied here.
4E23
PUSH DE D5
Save the buffer address (4318H) onto the stack for later use as the HL pointer for the interpreter.
4E24
LD BC,003FH 01 3F 00
Load Register Pair BC with 003FH (63 decimal). Maximum number of characters to copy from the source string to the command buffer.
4E27
LDIR ED B0
Block Move
Copy up to 63 bytes from (HL) to the command buffer at 4318H. Source = caller's command string, Destination = 4318H, Count = 63 bytes.
4E29
LD A,03H 3E 03
Load Register A with 03H (ETX, End of Text). This is the string terminator used by VTOS display routines.
4E2B
LD (DE),A 12
Store the 03H terminator at the byte following the copied string. This ensures the command buffer is properly terminated.
4E2C
POP HL E1
Restore the buffer start address (4318H) from the stack into HL. HL now points to the beginning of the copied command string in the buffer.
4E2D
JUMP to 4E59H to begin interpreting the command string. This enters the command interpreter at the point where the display message with CONFIG/SYS continuation is called, then falls through to the command table search.
4E2FH - "WHAT?" Error Handler
Displays the "WHAT?" error message when an unrecognized command is entered or when the BREAK key is pressed during command input. After displaying the message, jumps to the error exit at 4030H which returns to DOS READY.
4E2F
LD HL,51FAH 21 FA 51
WHAT? Error Entry
Point Register Pair HL to 51FAH, the "WHAT?" error message string ("WHAT?" + 0DH carriage return).
4E32
CALL 447BH CD 7B 44
GOSUB to the display message with continuation routine at 447BH. This displays "WHAT?" on the screen followed by a carriage return.
4E35
JP 4030H C3 30 40
JUMP to the error-already-displayed exit at 4030H in the SYS0 resident area. This invokes SVC A3H which transfers control back to DOS READY without displaying an additional error message.
4E38H - Request 10H/20H: DOS READY Prompt and Input
The primary user interaction handler. Reinitializes the system stack to 41E0H, enables interrupts, sets the BREAK key handler state based on the system mode flags (bit 0 of 430FH controls whether BREAK triggers DEBUG), displays the "VTOS READY" prompt, and accepts a line of keyboard input into the command buffer at 4318H. If the BREAK key is pressed during input (Carry flag set from ROM routine 0040H), displays "WHAT?" and re-prompts. Otherwise, falls through to the command interpreter.
4E38
LD SP,41E0H 31 E0 41
DOS READY Entry
Reset the Stack Pointer to 41E0H. This reinitializes the system stack, discarding any stacked return addresses from previous operations. This is a "clean slate" entry that ensures the stack is in a known state regardless of how deeply nested the previous call chain was.
4E3B
EI FB
Enable Interrupts. Ensures the keyboard ISR and timer callbacks are active for the input loop.
4E3C
LD A,(430FH) 3A 0F 43
Fetch the system mode flags from 430FH into Register A. Bit 0 indicates whether DEBUG mode is active (the system was entered from a DEBUG "Go" command).
4E3F
RLCA 07
Rotate Register A left. Shifts bit 0 (DEBUG mode flag) into the Carry flag. If DEBUG mode is active, Carry is set.
4E40
LD A,0C9H 3E C9
Load Register A with C9H (the opcode for RET). This is the default BREAK handler state: C9H at 4315H means BREAK is disabled (the handler immediately returns).
4E42
If the NO CARRY FLAG is set (DEBUG mode is NOT active), JUMP to 4E46H to store C9H (BREAK disabled). In normal operation, BREAK should not invoke DEBUG.
4E44
LD A,0C3H 3E C3
Load Register A with C3H (the opcode for JP). DEBUG mode IS active, so the BREAK handler should be enabled. C3H at 4315H means BREAK triggers a jump to the BREAK handler target address at 4316H-4317H.
4E46
LD (4315H),A 32 15 43
Store the BREAK handler opcode (C9H = disabled, or C3H = enabled) to the BREAK key enable flag at 4315H in the SYS0 resident area.
4E49
LD HL,51EEH 21 EE 51
Point Register Pair HL to 51EEH, the "VTOS READY" prompt string (0AH line feed + "VTOS READY" + 0DH carriage return).
4E4C
CALL 4467H CD 67 44
GOSUB to the display message routine at 4467H in SYS0. This outputs the "VTOS READY" prompt to the screen.
4E4F
LD HL,4318H 21 18 43
Point Register Pair HL to 4318H, the DOS command input buffer. This is where keyboard input will be stored.
4E52
LD B,3FH 06 3F
Load Register B with 3FH (63 decimal). Maximum number of characters to accept from the keyboard (63-character input buffer).
4E54
CALL 0040H CD 40 00
GOSUB to the ROM line input routine at 0040H. This displays a cursor, accepts keyboard input with editing support (backspace, etc.), and stores the entered text at (HL). Returns with Carry set if BREAK was pressed, Carry clear if ENTER was pressed. HL points to the start of the entered text.
4E57
If the CARRY FLAG is set (BREAK was pressed during input), JUMP to 4E2FH to display "WHAT?" and re-prompt. The command input is discarded.
4E59
CALL 447EH CD 7E 44
GOSUB to the display message with continuation at 447EH in SYS0. This performs a JR to 44F7H which jumps to the CONFIG/SYS processor at 4378H. On return, the system state is updated for the new command.
4E5CH - Command Interpreter Core
The central command interpretation logic. Pushes 402DH (DOS READY address) onto the stack as a safety net return address. Examines the first character of the command: if it is a period (2EH), handles re-entry mode; if it is an exclamation mark (21H), treats the command as a direct SVC code. Otherwise, copies the command to the system DCB at 4480H via the filespec extractor (Request 40H), searches the SYS1 command table at 4EA5H, and if not found, searches the SYS6 parameter table. If still not found, appends "/CMD" and attempts to load the command as a program file.
4E5C
LD BC,402DH 01 2D 40
Command Interpreter Core Entry
Load Register Pair BC with 402DH, the address of the DOS READY SVC stub in SYS0. This address is pushed onto the stack as a fallback return address.
4E5F
PUSH BC C5
Save 402DH onto the stack. If any command handler returns without setting up its own return path, execution falls through to 402DH which invokes DOS READY (SVC 93H). This prevents the system from crashing if a command handler forgets to return properly.
4E60
LD A,(HL) 7E
Fetch the first character of the command from the buffer at (HL) into Register A.
4E61
CP A,2EH FE 2E
Compare Register A against 2EH (ASCII period .). A period as the first character indicates the "re-enter" command (repeat the last command or return to the previous execution context).
4E63
If the Z FLAG is set (command starts with a period), JUMP to 4E8EH to handle the period/re-entry command.
4E65
CP A,21H FE 21
Compare Register A against 21H (ASCII exclamation mark !). An exclamation mark prefix indicates a direct SVC code invocation (the characters after ! are interpreted as a SYS6 command index).
4E67
LD DE,8091H 11 91 80
Load Register Pair DE with 8091H. This preloads the handler value for the ! command: D=80H (bit 7 set = SYS6 dispatch), E=91H (SYS6 command index for CHAIN). This is used if the ! prefix is detected.
4E6A
INC HL 23
INCrement HL past the first character (the !), pointing to the remainder of the command string.
4E6B
If the Z FLAG is set (from the CP 21H at 4E65H, first character was !), JUMP to 4E97H to dispatch with DE=8091H. This executes the CHAIN command on the remainder of the command line.
4E6D
DEC HL 2B
DECrement HL to restore it to the original position (undo the INC at 4E6AH). The first character was not !, so HL should still point to the start of the command.
4E6E
LD DE,4480H 11 80 44
Point Register Pair DE to 4480H, the system DCB (Device Control Block) area. The filespec extractor will copy the parsed command name here.
4E71
GOSUB to the filespec extractor at 4FCEH (Request 40H). Parses the command name from (HL) and stores it in the DCB at 4480H in the format NAME/EXT.PASSWORD:DRIVE with a 03H terminator. Returns with NZ if the parsing failed.
4E74
If the NZ FLAG is set (filespec extraction failed), JUMP to 4E2FH to display "WHAT?" and re-prompt.
4E76
LD A,(DE) 1A
Fetch the first byte of the parsed filespec from the DCB at (DE=4480H) into Register A.
4E77
CP A,2AH FE 2A
Compare Register A against 2AH (ASCII asterisk *). An asterisk as the first character of the parsed command indicates a wildcard or special command prefix that is not valid as a command name.
4E79
If the Z FLAG is set (first character is *), JUMP to 4E2FH to display "WHAT?". Wildcards are not valid in command names.
4E7B
PUSH HL E5
Save Register Pair HL (pointer to the remainder of the command line after the command name) onto the stack.
4E7C
LD BC,4EA5H 01 A5 4E
Load Register Pair BC with 4EA5H, the address of the SYS1 library command table. The table search routine will compare the parsed command against entries in this table.
4E7F
GOSUB to the command table search routine at 50BCH. Searches the table at BC (4EA5H) for a match with the parsed command name at DE (4480H). Returns Z if found (DE = handler value, C = entry index), NZ if not found.
4E82
If the Z FLAG is set (command was found in the SYS1 table), JUMP to 4E96H to dispatch the command using the handler value in DE.
Command Not in SYS1 Table
The command was not found in the SYS1 library table. Try appending "/CMD" and loading it as an external program file.
4E84
LD HL,51EBH 21 EB 51
Point Register Pair HL to 51EBH, the default extension string "CMD" (43H 4DH 44H). This will be appended to the command name as "/CMD".
4E87
GOSUB to the extension inserter at 5042H (Request 50H). This scans the filename in the DCB at 4480H for a "/" character. If none is found, it inserts "/CMD" after the command name. If a "/" already exists, the existing extension is preserved.
4E8A
POP HL E1
Restore Register Pair HL (pointer to the remainder of the command line) from the stack.
4E8B
JP 4433H C3 33 44
JUMP to the "load and execute" routine at 4433H in SYS0. This attempts to open the file named in the DCB (with the "/CMD" extension), load it into memory, and transfer control to it. If the file is not found, an error is displayed.
4E8EH - Period (.) Re-entry Command
Handles the period (.) command, which provides a re-entry or continuation mechanism. Tests bit 5 of the system mode flags at 430FH. If bit 5 is set (a previous execution context exists to return to), returns to the caller via RET. If bit 5 is clear, re-prompts for a new command.
4E8E
LD A,(430FH) 3A 0F 43
Fetch the system mode flags from 430FH into Register A.
4E91
BIT 5,A CB 6F
Test bit 5 of the system mode flags. Bit 5 indicates that a previous program execution context exists that can be resumed (the program was interrupted by BREAK and the user can type . to continue).
4E93
If the Z FLAG is set (bit 5 clear, no execution context to resume), JUMP to 4E4FH to re-display the command input prompt. The period command has no effect when there is nothing to resume.
4E95
RET C9
RETURN to the caller. Since the DOS READY address (402DH) was pushed at 4E5FH, this returns to 402DH which re-invokes the command processor. However, with bit 5 set, the overlay dispatcher may redirect to the interrupted program's context.
4E96H - Command Dispatch
Dispatches the matched command. Called after the table search at 50BCH finds a match. Register Pair DE contains the 2-byte handler value from the table entry. If bit 7 of D is clear, DE is a direct address and execution jumps there. If bit 7 of D is set, E contains the SYS6 overlay command index, and the overlay is loaded via RST 28H with SVC code 88H.
4E96
POP HL E1
Restore Register Pair HL from the stack (the command line remainder pointer, pushed at 4E7BH).
4E97
LD A,0C9H 3E C9
Command Dispatch Entry
Load Register A with C9H (RET opcode). This will disable the BREAK key handler during command execution to prevent interruption of critical code.
4E99
LD (4315H),A 32 15 43
Store C9H into the BREAK key enable flag at 4315H, disabling BREAK. The command handler will re-enable BREAK if appropriate.
4E9C
LD A,D 7A
Load Register A with the high byte of the handler value (Register D). Bit 7 determines the dispatch method.
4E9D
RLCA 07
Rotate Register A left. Shifts bit 7 into the Carry flag. If bit 7 was set (SYS6 dispatch), Carry is set.
4E9E
PUSH DE D5
Save the handler value (Register Pair DE) onto the stack. For direct-address handlers, this becomes the return address for the RET NC below.
4E9F
RET NC D0
If the NO CARRY FLAG is set (bit 7 of D was clear = direct address handler), RETURN. The stacked DE value becomes the return target, so execution transfers to the address in DE. This is an elegant dispatch: PUSH DE / RET effectively performs JP (DE).
SYS6 Overlay Dispatch
Bit 7 of D was set, so this command is handled by the SYS6 overlay. Pop DE, load the command index from E into B, and invoke RST 28H with SVC code 88H to force-load SYS6.
4EA0
POP DE D1
Restore the handler value from the stack (the PUSH DE at 4E9EH was not consumed by the RET NC since Carry was set).
4EA1
LD B,E 43
Load Register B with the low byte of the handler value (Register E). This is the SYS6 command index that identifies which function within SYS6 to execute.
4EA2
LD A,88H 3E 88
Load Register A with 88H. SVC code 88H is the "force-reload SYS6 overlay" code. Bit 7 is set (overlay load request), bits 0-3 = 8 (file number 8, which maps to directory entry 20H via the ADD A,18H at 4C75H in SYS0). The 88H code forces a reload even if SYS6 is already cached.
4EA4
RST 28H EF
Invoke the RST 28H overlay dispatcher. This loads the SYS6 overlay from disk (if not cached) and transfers control to it. Register B contains the command index. After SYS6 executes the command, it returns to the instruction following this RST, which is 4EA5H.
4EA5H - SYS6 Return Handler and Command Table
The bytes at 4EA5H-4EACH serve a dual purpose. As code, they execute after RST 28H returns from SYS6 at 4EA4H: LD C,A saves the return code, LD HL,4020H loads the cursor position, and HALT resets the system. As data, the first byte (4FH = 'O') acts as a dummy command table entry that never matches any real command (no VTOS command starts with 'O'), so the table search at 50BCH always skips past it. The real command table begins at 4EADH with 36 entries of 8 bytes each.
4EA5
LD C,A 4F
SYS6 Return Handler
Save the SYS6 return code from Register A into Register C. This preserves the command result across the subsequent operations. As a table entry byte, 4FH ('O') ensures no command match since no library command begins with 'O'.
4EA6
LD HL,4020H 21 20 40
Point Register Pair HL to 4020H, the cursor position variable. This is used to restore the display state after the SYS6 command returns.
4EA9
HALT 76
BOOT Command Target
HALT instruction. The BOOT command's handler address is 4EA9H, which executes this HALT. On the Model I, HALT stops the Z80 until an interrupt occurs, at which point the ISR executes and returns to the HALT, creating a tight halt-interrupt loop. This effectively freezes the system until the user performs a hardware RESET, which restarts the boot sequence.
4EAA
JP 801DH C3 1D 80
JUMP to 801DH. This instruction is reached if the HALT at 4EA9H is somehow bypassed (e.g., if an interrupt handler does not return to the HALT). Address 801DH is in the upper RAM area. The remaining bytes 4EADH onward are the command table data.
4EADH - Library Command Table
The library command table containing 36 entries, each 8 bytes: 6 bytes of space-padded ASCII command name followed by a 2-byte handler value (little-endian). The handler value is loaded into DE by the table search routine at 50BCH. If the high byte has bit 7 set (80H), the low byte is a SYS6 command index dispatched via RST 28H with A=88H. If bit 7 is clear, the value is a direct address jumped to via the PUSH DE / RET NC mechanism. The table is sorted alphabetically and terminated by a 00H byte at 4FCDH. The only direct-address command is BOOT (handler 4EA9H); all others dispatch through SYS6.
4EAD-4EB4
DEFM "ALLOC " DEFW 8013H 41 4C 4C 4F 43 20 13 80
ALLOC - Allocate disk space for a file. Handler: SYS6 command index 13H.
4EB5-4EBC
DEFM "APPEND" DEFW 8031H 41 50 50 45 4E 44 31 80
APPEND - Append data to an existing file. Handler: SYS6 command index 31H.
4EBD-4EC4
DEFM "ATTRIB" DEFW 8051H 41 54 54 52 49 42 51 80
ATTRIB - Modify file attributes (visibility, protection level). Handler: SYS6 command index 51H.
4EC5-4ECC
DEFM "AUTO " DEFW 8011H 41 55 54 4F 20 20 11 80
AUTO - Set or clear the auto-execute command for boot. Handler: SYS6 command index 11H.
4ECD-4ED4
DEFM "BOOT " DEFW 4EA9H 42 4F 4F 54 20 20 A9 4E
BOOT - Restart the system. Handler: direct jump to 4EA9H (HALT instruction). This is the only command that uses a direct address rather than SYS6 dispatch.
4ED5-4EDC
DEFM "BUILD " DEFW 8033H 42 55 49 4C 44 20 33 80
BUILD - Create a new file or build a JCL procedure. Handler: SYS6 command index 33H.
4EDD-4EE4
DEFM "CHAIN " DEFW 8091H 43 48 41 49 4E 20 91 80
CHAIN - Chain execution to another program. Handler: SYS6 command index 91H.
4EE5-4EEC
DEFM "CLOCK " DEFW 8017H 43 4C 4F 43 4B 20 17 80
CLOCK - Enable or disable the real-time clock display. Handler: SYS6 command index 17H.
4EED-4EF4
DEFM "COPY " DEFW 8032H 43 4F 50 59 20 20 32 80
COPY - Copy a file. Handler: SYS6 command index 32H.
4EF5-4EFC
DEFM "DATE " DEFW 8015H 44 41 54 45 20 20 15 80
DATE - Set or display the system date. Handler: SYS6 command index 15H.
4EFD-4F04
DEFM "DEBUG " DEFW 8014H 44 45 42 55 47 20 14 80
DEBUG - Enter the interactive debugger. Handler: SYS6 command index 14H.
4F05-4F0C
DEFM "DEVICE" DEFW 8061H 44 45 56 49 43 45 61 80
DEVICE - Display I/O device configuration. Handler: SYS6 command index 61H.
4F0D-4F14
DEFM "DIR " DEFW 8021H 44 49 52 20 20 20 21 80
DIR - Display directory listing. Handler: SYS6 command index 21H.
4F15-4F1C
DEFM "DUMP " DEFW 8071H 44 55 4D 50 20 20 71 80
DUMP - Hex dump of memory contents. Handler: SYS6 command index 71H.
4F1D-4F24
DEFM "FILTER" DEFW 8066H 46 49 4C 54 45 52 66 80
FILTER - Manage I/O filter chains. Handler: SYS6 command index 66H.
4F25-4F2C
DEFM "FREE " DEFW 8022H 46 52 45 45 20 20 22 80
FREE - Display free disk space. Handler: SYS6 command index 22H.
4F2D-4F34
DEFM "KILL " DEFW 8018H 4B 49 4C 4C 20 20 18 80
KILL - Delete a file. Handler: SYS6 command index 18H.
4F35-4F3C
DEFM "LIB " DEFW 8019H 4C 49 42 20 20 20 19 80
LIB - Display library command list. Handler: SYS6 command index 19H.
4F3D-4F44
DEFM "LINK " DEFW 8062H 4C 49 4E 4B 20 20 62 80
LINK - Link a device driver module. Handler: SYS6 command index 62H.
4F45-4F4C
DEFM "LIST " DEFW 8041H 4C 49 53 54 20 20 41 80
LIST - List file contents to screen or printer. Handler: SYS6 command index 41H.
4F4D-4F54
DEFM "LOAD " DEFW 8081H 4C 4F 41 44 20 20 81 80
LOAD - Load program into memory without executing. Handler: SYS6 command index 81H.
4F55-4F5C
DEFM "MEMORY" DEFW 801EH 4D 45 4D 4F 52 59 1E 80
MEMORY - Display or set available memory size. Handler: SYS6 command index 1EH.
4F5D-4F64
DEFM "PRINT " DEFW 8042H 50 52 49 4E 54 20 42 80
PRINT - Print file to printer device. Handler: SYS6 command index 42H.
4F65-4F6C
DEFM "PROT " DEFW 8052H 50 52 4F 54 20 20 52 80
PROT - Set file protection level. Handler: SYS6 command index 52H.
4F6D-4F74
DEFM "PURGE " DEFW 8072H 50 55 52 47 45 20 72 80
PURGE - Purge deleted file space. Handler: SYS6 command index 72H.
4F75-4F7C
DEFM "RENAME" DEFW 8053H 52 45 4E 41 4D 45 53 80
RENAME - Rename a file. Handler: SYS6 command index 53H.
4F7D-4F84
DEFM "RESET " DEFW 8063H 52 45 53 45 54 20 63 80
RESET - Reset a disk drive. Handler: SYS6 command index 63H.
4F85-4F8C
DEFM "ROUTE " DEFW 8064H 52 4F 55 54 45 20 64 80
ROUTE - Route I/O device assignment. Handler: SYS6 command index 64H.
4F8D-4F94
DEFM "RUN " DEFW 8082H 52 55 4E 20 20 20 82 80
RUN - Load and execute a program. Handler: SYS6 command index 82H.
4F95-4F9C
DEFM "SET " DEFW 8065H 53 45 54 20 20 20 65 80
SET - Set system parameters. Handler: SYS6 command index 65H.
4F9D-4FA4
DEFM "SPOOL " DEFW 80A2H 53 50 4F 4F 4C 20 A2 80
SPOOL - Control the print spooler. Handler: SYS6 command index A2H.
4FA5-4FAC
DEFM "SYSTEM" DEFW 80A1H 53 59 53 54 45 4D A1 80
SYSTEM - Display system information. Handler: SYS6 command index A1H.
4FAD-4FB4
DEFM "TIME " DEFW 8016H 54 49 4D 45 20 20 16 80
TIME - Set or display the system time. Handler: SYS6 command index 16H.
4FB5-4FBC
DEFM "TRACE " DEFW 801AH 54 52 41 43 45 20 1A 80
TRACE - Enable or disable instruction trace. Handler: SYS6 command index 1AH.
4FBD-4FC4
DEFM "VERIFY" DEFW 801BH 56 45 52 49 46 59 1B 80
VERIFY - Enable or disable write verification. Handler: SYS6 command index 1BH.
4FC5-4FCC
DEFM "XFER " DEFW 8073H 58 46 45 52 20 20 73 80
XFER - Transfer file between devices or disks. Handler: SYS6 command index 73H.
4FCD
DEFB 00H 00
End of Table Marker
A zero byte terminates the command table. The search routine at 50BCH tests each entry's first byte with OR A,A and exits with NZ (not found) when it encounters 00H.
4FCEH - Request 40H: Filespec Extractor
Parses a VTOS-format filespec from the command line at (HL) and stores it into the DCB at (DE). The full 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 1 character. Each section is optional and delimited by the appropriate separator (/ . :). The parsed result is terminated with 03H. After parsing, checks the result against the parameter keyword table at 5021H; if the parsed name matches a keyword (TO, ON, OVER, USING), re-enters the extractor to search for a SYS6 handler. The ! prefix (exclamation mark) followed by asterisk and 2 hex digits is handled as a direct SVC code. Returns with Z flag set on success, NZ on failure.
4FCE
PUSH DE D5
Filespec Extractor Entry
Save the DCB destination address (Register Pair DE) onto the stack for later reference.
4FCF
GOSUB to the filename character reader at 5076H. Reads up to 8 valid filename characters from (HL), converts lowercase to uppercase, stores them at (DE), and appends a 03H terminator. Returns with A containing the delimiter character that stopped the scan, and NZ set if the scan stopped on a non-filename character.
4FD2
If the NZ FLAG is set (the scan stopped on something other than a valid filename character), JUMP to 5012H to check for an asterisk (*) wildcard prefix.
4FD4
CP A,2FH FE 2F
Compare Register A against 2FH (ASCII /). This checks if the filename is followed by an extension separator.
4FD6
If the NZ FLAG is set (not a / separator), JUMP to 4FDFH to check for a password separator.
4FD8
LD (DE),A 12
Store the / separator into the DCB at (DE).
4FD9
INC DE 13
INCrement DE to point past the separator.
4FDA
LD B,03H 06 03
Load Register B with 03H. Read up to 3 characters for the file extension.
4FDC
GOSUB to the filename character reader at 5078H (B-character version). Reads up to B (3) valid characters for the extension field.
4FDF
CP A,2EH FE 2E
Compare Register A against 2EH (ASCII .). This checks for a password separator.
4FE1
If the NZ FLAG is set (not a . separator), JUMP to 4FEAH to check for a drive separator.
4FE3
LD (DE),A 12
Store the . separator into the DCB.
4FE4
INC DE 13
INCrement DE past the separator.
4FE5
GOSUB to 5076H to read up to 8 characters for the password field.
4FE8
If the NZ FLAG is set (parsing error in password), JUMP to 501FH to clean up and return.
4FEA
CP A,3AH FE 3A
Compare Register A against 3AH (ASCII :). This checks for a drive specifier separator.
4FEC
If the NZ FLAG is set (not a : separator), JUMP to 4FF7H. No drive specifier present.
4FEE
LD (DE),A 12
Store the : separator into the DCB.
4FEF
INC DE 13
INCrement DE past the separator.
4FF0
LD B,01H 06 01
Load Register B with 01H. Read 1 character for the drive specifier (0-7).
4FF2
GOSUB to 5078H to read the single drive specifier character.
4FF5
If the NZ FLAG is set (invalid drive specifier), JUMP to 501FH.
4FF7
CP A,21H FE 21
Compare Register A against 21H (ASCII !). Tests if an exclamation mark follows the filespec (used as a special suffix).
4FF9
If the NZ FLAG is set (not !), JUMP to 4FFFH to finalize the DCB entry.
4FFB
LD (DE),A 12
Store the ! suffix into the DCB.
4FFC
INC DE 13
INCrement DE past the !.
4FFD
INC HL 23
INCrement HL past the ! in the source command line.
4FFE
LD A,(HL) 7E
Fetch the next character from the command line (after the !) into Register A.
4FFF
LD C,A 4F
Save the current delimiter character in Register C for later reference.
5000
LD A,03H 3E 03
Load Register A with 03H (ETX terminator).
5002
LD (DE),A 12
Store the 03H terminator at the end of the parsed filespec in the DCB.
5003
XOR A,A AF
Set Register A to ZERO and set the Z flag. Clears Carry. This prepares the success return.
5004
LD A,C 79
Restore the delimiter character from Register C into Register A. The Z flag from the XOR is preserved since LD does not affect flags.
5005
POP DE D1
Restore the original DCB address from the stack (saved at 4FCEH).
5006
PUSH DE D5
Re-save the DCB address for the keyword table search below.
5007
LD BC,5021H 01 21 50
Load Register Pair BC with 5021H, the address of the parameter keyword table. This table contains TO, ON, OVER, USING.
500A
GOSUB to the table search at 50BCH. Searches the keyword table for a match with the parsed filespec. If the user typed a keyword (e.g., "ON") instead of a filename, it needs special handling.
500D
POP DE D1
Restore the DCB address from the stack.
500E
If the Z FLAG is set (the parsed name matched a keyword in the parameter table), JUMP back to 4FCEH to re-parse the next word as the actual filespec. The keyword is consumed and the parser continues past it.
5010
XOR A,A AF
Set Register A to ZERO and set the Z flag. Success return: the filespec has been successfully parsed and no keyword match was found.
5011
RET C9
RETURN with Z flag set (success). The parsed filespec is in the DCB at (DE), HL points to the remainder of the command line.
5012
CP A,2AH FE 2A
Wildcard/Direct SVC Check
Compare Register A against 2AH (ASCII *). An asterisk followed by 2 hex characters is interpreted as a direct SVC code specification.
5014
If the NZ FLAG is set (not an asterisk), JUMP to 501FH to return with failure.
5016
LD (DE),A 12
Store the * into the DCB.
5017
INC DE 13
INCrement DE past the asterisk.
5018
LD B,02H 06 02
Load Register B with 02H. Read up to 2 characters following the asterisk (a hex code).
501A
GOSUB to 5078H to read the 2 hex characters.
501D
If the Z FLAG is set (2 valid characters read), JUMP to 4FFFH to finalize the DCB entry.
501F
POP DE D1
Restore the DCB address from the stack and return with NZ (failure).
5020
RET C9
RETURN with NZ flag set (parsing failure).
5021H - Parameter Keyword Table
A small table of 4 parameter keywords used by the filespec extractor to detect and skip keyword tokens that appear in command lines. Each entry is 8 bytes: 6-byte space-padded keyword name followed by 2 zero bytes (no handler - keywords are just consumed, not dispatched). The table is searched by the same 50BCH routine used for the command table.
5021-5028
DEFM "TO " DEFW 0000H 54 4F 20 20 20 20 00 00
TO - Parameter keyword used in commands like COPY file1 TO file2.
5029-5030
DEFM "ON " DEFW 0000H 4F 4E 20 20 20 20 00 00
ON - Parameter keyword used to enable a feature (e.g., CLOCK ON).
5031-5038
DEFM "OVER " DEFW 0000H 4F 56 45 52 20 20 00 00
OVER - Parameter keyword used in COPY file1 OVER file2 (overwrite).
5039-5040
DEFM "USING " DEFW 0000H 55 53 49 4E 47 20 00 00
USING - Parameter keyword used to specify a format or template.
5041
DEFB 00H 00
End of Table Marker
Zero byte terminates the keyword table.
5042H - Request 50H: Add Default Extension
Scans the filename in the DCB at (DE) for a / extension separator. If one is found, the filename already has an extension and no modification is needed. If no / is found within 9 characters, a 4-byte hole is created in the string via LDDR block move, and "/CMD" (or the extension string pointed to by HL) is inserted. This allows commands typed without an extension (e.g., "MYFILE") to be automatically expanded to "MYFILE/CMD".
5042
PUSH DE D5
Extension Inserter Entry
Save the DCB address (Register Pair DE) onto the stack.
5043
PUSH HL E5
Save the extension string pointer (Register Pair HL) onto the stack. HL points to the 3-byte extension to insert (e.g., "CMD" at 51EBH).
5044
EX DE,HL EB
Exchange DE and HL. HL now points to the DCB (the filespec to scan), DE holds the extension string address.
5045
INC HL 23
INCrement HL to skip the first byte of the filespec (which was already validated as a filename character).
5046
LD B,09H 06 09
Load Register B with 09H (9 decimal). Scan up to 9 characters looking for a / separator. This covers the maximum filename (8 chars) plus one position for the separator.
5048
LD A,(HL) 7E
Extension Scan Loop
Fetch the next character from the filespec at (HL) into Register A.
5049
CP A,2FH FE 2F
Compare Register A against 2FH (ASCII /). If found, the filespec already has an extension.
504B
If the Z FLAG is set (found /), JUMP to 505AH to restore registers and return without modification. The extension already exists.
504D
If the CARRY FLAG is set (character < 2FH, which includes terminators 03H, 0DH, and spaces), JUMP to 505DH to insert the default extension. The filename ended without a / separator.
504F
CP A,3AH FE 3A
Compare Register A against 3AH (ASCII :). A colon indicates a drive specifier, meaning the filename ended without an extension.
5051
If the CARRY FLAG is set (character is between 30H-39H, a digit), JUMP to 5057H to continue scanning. Digits are valid in filenames.
5053
CP A,41H FE 41
Compare Register A against 41H (ASCII 'A'). Characters below 'A' but above '9' (3AH-40H) include the colon, which should trigger extension insertion.
5055
If the CARRY FLAG is set (character is in 3AH-40H range, not alphanumeric), JUMP to 505DH to insert the default extension.
5057
INC HL 23
INCrement HL to the next character in the filespec.
5058
DECrement B and loop back to 5048H if not zero. Continues scanning for up to 9 characters.
505A
POP HL E1
Restore the extension string pointer from the stack.
505B
POP DE D1
Restore the DCB address from the stack.
505C
RET C9
RETURN. The filespec already had an extension (or the scan exhausted 9 characters).
Insert Default Extension
No extension was found in the filespec. Create a 4-byte gap in the string (shifting existing characters right) and insert "/" followed by the 3-byte extension string from HL.
505D
LD BC,000FH 01 0F 00
Load Register Pair BC with 000FH (15 decimal). This is the number of bytes to shift right in the LDDR block move, creating room for the 4-byte extension ("/CMD").
5060
ADD HL,BC 09
ADD 15 to HL. HL now points 15 bytes past the insertion point, which is the destination end address for the LDDR.
5061
LD D,H 54
Copy H into D. Preparing DE as the LDDR destination (4 bytes ahead of HL).
5062
LD E,L 5D
Copy L into E. DE = HL at this point.
5063
INC DE 13
INCrement DE. Move destination 1 byte forward.
5064
INC DE 13
INCrement DE again. 2 bytes forward.
5065
INC DE 13
INCrement DE again. 3 bytes forward.
5066
INC DE 13
INCrement DE again. 4 bytes forward. DE now points to the LDDR destination end (HL + 4).
5067
INC BC 03
INCrement BC to 0010H (16 bytes). Adjusted count for the LDDR block move.
5068
LDDR ED B8
Block Move (Decrementing)
Copy BC bytes from (HL) to (DE), decrementing both addresses. This shifts the existing filespec characters 4 bytes to the right, creating a gap for the extension. The LDDR moves from high addresses to low, avoiding overlap issues when shifting right.
506A
POP HL E1
Restore the extension string pointer from the stack (e.g., pointing to "CMD" at 51EBH).
506B
INC HL 23
INCrement HL to point to the first character of the extension string. (The pointer was to the byte before the string, or the LDDR left HL one position early.)
506C
INC HL 23
INCrement HL again to the second character.
506D
LD C,03H 0E 03
Load Register C with 03H. Copy 3 bytes of extension text (B is 0 from the LDDR, so BC = 0003H).
506F
LDDR ED B8
Block Move (Decrementing)
Copy the 3-byte extension from (HL) to the gap created in the filespec. The extension characters (e.g., "CMD") are written into the 3 bytes after the "/" separator.
5071
LD A,2FH 3E 2F
Load Register A with 2FH (ASCII /). The extension separator character.
5073
LD (DE),A 12
Store the / separator into the gap position, completing the extension insertion. The filespec now reads "NAME/CMD" (or whatever extension was specified).
5074
POP DE D1
Restore the DCB address from the stack.
5075
RET C9
RETURN. The default extension has been inserted into the filespec.
5076H - Filename Character Reader
Reads valid filename characters from the command line at (HL), converts lowercase to uppercase, and stores them in the DCB at (DE). Entry at 5076H reads up to 8 characters; entry at 5078H reads up to B characters. Valid characters are digits (30H-39H) and uppercase letters (41H-5AH). Lowercase letters (61H-7AH) are converted to uppercase by subtracting 20H. The routine terminates the stored string with 03H and returns the delimiter character in A. Uses self-modifying code at 50B8H to track whether any characters were stored (Z flag = no valid chars stored = error, NZ = at least one char stored).
5076
LD B,08H 06 08
8-Character Entry
Load Register B with 08H. Maximum 8 characters to read (standard filename length).
5078
LD A,B 78
B-Character Entry
Load Register A with Register B (the maximum character count).
5079
LD (50B8H),A 32 B8 50
Self-Modifying Code
Store the initial count into the operand at 50B8H. This patches the LD A,00H instruction at 50B7H. If no valid characters are stored, this value remains non-zero, and the NZ test at 50B9H will indicate "no characters stored" (error). When a valid character IS stored, 00H is written to 50B8H (at 50AAH), so the final test returns Z (success).
507C
INC B 04
INCrement B by 1. The DEC B at 50A5H will decrement it before testing, so pre-incrementing ensures the correct count of characters is read.
507D
LD A,(HL) 7E
Character Read Loop
Fetch the next character from the command line at (HL) into Register A.
507E
CP A,03H FE 03
Compare Register A against 03H (ETX terminator). This is the end-of-string marker used by VTOS.
5080
If the Z FLAG is set (ETX terminator found), JUMP to 50B3H to terminate the DCB string and return.
5082
CP A,0DH FE 0D
Compare against 0DH (carriage return). CR also terminates the input.
5084
If CR found, JUMP to 50B3H to terminate.
5086
CP A,28H FE 28
Compare against 28H (ASCII open parenthesis (). A parenthesis starts a parameter list, which terminates the filename.
5088
If ( found, JUMP to 50B3H to terminate.
508A
INC HL 23
INCrement HL to advance past the current character. If the character is valid, it will be stored. If invalid, the INC is already done for the next iteration or exit.
508B
CP A,30H FE 30
Compare against 30H (ASCII '0'). Characters below '0' are not valid in filenames.
508D
If Carry (character < '0'), JUMP to 50B3H. The character is a delimiter (space, separator, etc.).
508F
CP A,3AH FE 3A
Compare against 3AH (ASCII ':'). Characters 30H-39H are digits, valid in filenames.
5091
If Carry (character is a digit 0-9), JUMP to 50A5H to store it.
5093
CP A,41H FE 41
Compare against 41H (ASCII 'A'). Characters 3AH-40H are not valid in filenames.
5095
If Carry (character < 'A', e.g., a colon or semicolon), JUMP to 50B3H. This is a delimiter.
5097
CP A,5BH FE 5B
Compare against 5BH (one past 'Z'). Characters 41H-5AH are uppercase letters, valid in filenames.
5099
If Carry (character is uppercase letter A-Z), JUMP to 50A5H to store it.
509B
CP A,61H FE 61
Compare against 61H (ASCII 'a'). Characters 5BH-60H are brackets and punctuation, not valid.
509D
If Carry (character < 'a'), JUMP to 50B3H.
509F
CP A,7BH FE 7B
Compare against 7BH (one past 'z'). Characters 61H-7AH are lowercase letters.
50A1
If No Carry (character >= 7BH, e.g., curly braces or DEL), JUMP to 50B3H. Not a valid filename character.
50A3
SUB A,20H D6 20
Lowercase to Uppercase Conversion
SUBtract 20H from Register A. This converts lowercase letters (61H-7AH) to uppercase (41H-5AH) by subtracting the difference between lowercase and uppercase ASCII values.
50A5
DEC B 05
Store Valid Character
DECrement the remaining character count in Register B.
50A6
If the Z FLAG is set (character count exhausted, maximum filename length reached), JUMP to 50B0H to continue reading but discard additional characters.
50A8
LD (DE),A 12
Store the valid (and possibly uppercased) character into the DCB at (DE).
50A9
XOR A,A AF
Set Register A to ZERO.
50AA
LD (50B8H),A 32 B8 50
Self-Modifying Code
Store 00H into the operand at 50B8H. This patches the LD A,00H at 50B7H so that the final success test at 50B9H will read A=00H, and OR A,A will set Z (success = at least one character was stored).
50AD
INC DE 13
INCrement DE to the next DCB position.
50AE
LOOP BACK to 507DH to read the next character.
50B0
INC B 04
Overflow Handler
INCrement B back to 1 so the DJNZ at the top of the loop does not exit. This allows the loop to continue consuming (but discarding) characters past the maximum length.
50B1
LOOP BACK to 507DH to continue reading characters (but they are discarded since B stays at 1).
50B3
LD C,A 4F
Exit Handler
Save the delimiter character (that stopped the scan) from Register A into Register C.
50B4
LD A,03H 3E 03
Load Register A with 03H (ETX terminator).
50B6
LD (DE),A 12
Store the 03H terminator at the end of the parsed text in the DCB.
50B7
LD A,00H 3E 00
Self-Modifying Code
Load Register A with 00H. The operand at 50B8H was initialized at 5079H with the character count, and cleared to 00H at 50AAH if at least one valid character was stored. If no valid characters were stored, the operand still contains the non-zero count.
50B9
OR A,A B7
OR Register A with itself. Sets Z if A=00H (at least one character was stored = success), NZ if A is non-zero (no valid characters = failure).
50BA
LD A,C 79
Restore the delimiter character from Register C into Register A. The Z/NZ flag from the OR is preserved.
50BB
RET C9
RETURN with Z = success (A = delimiter), NZ = failure (no valid characters found).
50BCH - Command/Keyword Table Search
Searches a table of 8-byte entries for a match with the string at (DE). Register Pair BC points to the table on entry. Each entry has a 6-byte name followed by a 2-byte handler value. The search is linear: compare the first byte, if it matches, compare the remaining 5 bytes. If all 6 match, load the handler value from offset 6-7 into DE and return with Z set. If no match, advance by 8 bytes and try the next entry. The table is terminated by a 00H byte. Returns NZ (A=1) if the entry is not found.
50BC
PUSH HL E5
Table Search Entry
Save Register Pair HL onto the stack (preserved across the search).
50BD
LD H,B 60
Load Register H with Register B (high byte of table address).
50BE
LD L,C 69
Load Register L with Register C (low byte). HL now points to the start of the table.
50BF
LD C,01H 0E 01
Load Register C with 01H. C serves as a 1-based entry index counter.
50C1
LD A,(DE) 1A
First Byte Compare
Fetch the first byte of the search string from (DE) into Register A.
50C2
CP A,(HL) BE
Compare Register A against the first byte of the current table entry at (HL).
50C3
If the Z FLAG is set (first bytes match), JUMP to 50D3H to compare the remaining 5 bytes.
50C5
PUSH BC C5
Advance to Next Entry
Save Register Pair BC (entry counter) onto the stack.
50C6
LD BC,0008H 01 08 00
Load Register Pair BC with 0008H (8 bytes per table entry).
50C9
ADD HL,BC 09
ADD 8 to HL. Advance the table pointer to the next entry.
50CA
POP BC C1
Restore the entry counter from the stack.
50CB
INC C 0C
INCrement the entry index counter.
50CC
LD A,(HL) 7E
Fetch the first byte of the next entry. If this byte is 00H, we have reached the end of the table.
50CD
OR A,A B7
Test Register A for zero (end of table marker).
50CE
If NZ (not end of table), LOOP BACK to 50C1H to compare the next entry.
50D0
POP HL E1
Not Found Exit
Restore HL from the stack.
50D1
INC A 3C
INCrement Register A (which was 00H from the table terminator). A becomes 01H, setting NZ to indicate "not found."
50D2
RET C9
RETURN with NZ flag set (entry not found). Register A = 01H.
Full Name Comparison
The first byte matched. Now compare the remaining 5 bytes of the command name.
50D3
LD B,05H 06 05
Full Compare
Load Register B with 05H. Compare 5 more bytes (6 total including the first byte already matched).
50D5
PUSH HL E5
Save the current table entry pointer onto the stack.
50D6
PUSH DE D5
Save the search string pointer onto the stack.
50D7
INC DE 13
Compare Loop
INCrement DE to the next search string byte.
50D8
INC HL 23
INCrement HL to the next table entry byte.
50D9
LD A,(DE) 1A
Fetch the next byte from the search string.
50DA
CP A,03H FE 03
Compare against 03H (ETX terminator). If the search string ends before 6 characters, check if the table entry has spaces in the remaining positions.
50DC
If Z (search string terminated with ETX), JUMP to 5105H to check if the table entry's remaining characters are spaces (a valid match for a short command name).
50DE
CP A,0DH FE 0D
Compare against 0DH (carriage return). CR also terminates the search string.
50E0
If Z (CR terminator), JUMP to 5105H for the same short-name match check.
50E2
CP A,(HL) BE
Compare the search string byte against the table entry byte.
50E3
If NZ (mismatch), JUMP to 50F5H to check for alphanumeric padding differences.
50E5
DECrement B and loop back to 50D7H if not zero. Continue comparing bytes.
Full Match Found
All 6 bytes of the command name match. Load the 2-byte handler value from bytes 6-7 of the table entry into DE and return with Z set.
50E7
POP DE D1
Discard the saved search string pointer (no longer needed).
50E8
LD A,C 79
Load Register A with the entry index counter (Register C). This is the 1-based position of the matched entry in the table.
50E9
POP BC C1
Restore the table entry base pointer from the stack into BC.
50EA
LD HL,0006H 21 06 00
Load Register Pair HL with 0006H. Offset to the handler value within the table entry (bytes 6-7).
50ED
ADD HL,BC 09
ADD the offset to the table entry base. HL now points to the handler value.
50EE
LD C,A 4F
Save the entry index in Register C for the caller.
50EF
LD E,(HL) 5E
Load Register E with the low byte of the handler value.
50F0
INC HL 23
INCrement HL to the high byte.
50F1
LD D,(HL) 56
Load Register D with the high byte. Register Pair DE now contains the handler value.
50F2
POP HL E1
Restore HL from the initial PUSH at 50BCH.
50F3
XOR A,A AF
Set Register A to ZERO and set Z flag. Z = match found.
50F4
RET C9
RETURN with Z set (match found), DE = handler value, C = entry index.
Partial Match - Check for Alphanumeric vs Space Padding
The bytes did not match directly. Check if the mismatch is because the search string has additional characters where the table entry has spaces (short-name matching).
50F5
CP A,30H FE 30
Compare the mismatched search byte against 30H ('0').
50F7
If Carry (character < '0', e.g., a space or terminator), JUMP to 5105H for short-name check.
50F9
CP A,3AH FE 3A
Compare against 3AH (':').
50FB
If Carry (character is a digit 0-9), JUMP to 510AH. The search string has more characters than the table entry, so this is not a match.
50FD
CP A,41H FE 41
Compare against 41H ('A').
50FF
If Carry (character < 'A'), JUMP to 5105H for short-name check.
5101
CP A,5BH FE 5B
Compare against 5BH (one past 'Z').
5103
If Carry (character is A-Z), JUMP to 510AH. Not a match - the search string has more letters.
5105
LD A,(HL) 7E
Short Name Match Check
Load Register A with the current table entry byte. Check if the remaining table entry bytes are all spaces (20H), which would indicate a valid match for a short command name.
5106
CP A,20H FE 20
Compare the table entry byte against 20H (ASCII space).
5108
If Z (table entry byte is a space), JUMP to 50E7H. The remaining table entry positions are spaces, so the shorter search string matches this entry.
510A
POP DE D1
No Match - Try Next Entry
Restore the search string pointer from the stack.
510B
POP HL E1
Restore the table entry pointer from the stack.
510C
JUMP to 50C5H to advance to the next table entry and continue searching.
510FH - Request 60H: Parameter Parser
Parses command parameters that follow a filename in the command line. Parameters are enclosed in parentheses and separated by commas: (KEYWORD=VALUE,KEYWORD=VALUE,...). The value can be a decimal number, a hex number (prefixed with X'), a quoted string (enclosed in double quotes), or a YES/NO/ON/OFF boolean. The parser uses the keyword table at 5021H to identify known keywords and calls specialized value parsers at 5181H (YES/NO), 51A6H (decimal), and 51C0H (hex).
510E
INC HL 23
Skip Spaces Continuation
INCrement HL to skip over the current space character.
510F
LD A,(HL) 7E
Parameter Parser Entry
Fetch the next character from the command line at (HL).
5110
CP A,0DH FE 0D
Compare against 0DH (carriage return). End of command line.
5112
RET Z C8
If Z (end of line), RETURN with Z set. No more parameters to parse.
5113
CP A,20H FE 20
Compare against 20H (space). Skip leading spaces.
5115
If Z (space), JUMP to 510EH to skip it and read the next character.
5117
CP A,28H FE 28
Compare against 28H (ASCII open parenthesis (). This starts the parameter list.
5119
If NZ (not a parenthesis), JUMP to 514CH to return success (no parameter list present).
511B
PUSH DE D5
Parse One Parameter
Save Register Pair DE (result buffer pointer) onto the stack.
511C
LD B,06H 06 06
Load Register B with 06H. Read up to 6 characters for the keyword name.
511E
LD DE,4200H 11 00 42
Point Register Pair DE to 4200H, a temporary buffer for parsing the keyword.
5121
INC HL 23
INCrement HL to skip past the ( or , delimiter.
5122
GOSUB to the filename reader at 5078H. Reads up to 6 keyword characters into 4200H.
5125
DEC HL 2B
DECrement HL back to the delimiter character that stopped the read.
5126
POP DE D1
Restore the result buffer pointer from the stack.
5127
RET NZ C0
If NZ (no valid keyword characters found), RETURN with NZ (error).
5128
PUSH DE D5
Re-save the result buffer pointer.
5129
LD B,D 42
Copy D into B. Part of preparing BC for the keyword table search.
512A
LD C,E 4B
Copy E into C. BC now holds the result buffer pointer (used as the table address in a second search call, but here it's the buffer that was just filled).
512B
LD DE,4200H 11 00 42
Point DE to 4200H (the parsed keyword in the temporary buffer).
512E
GOSUB to the table search at 50BCH. Searches the caller's parameter table (passed in BC from the original DE) for the parsed keyword.
5131
If Z (keyword found in the parameter table), JUMP to 5135H to parse the value.
5133
POP DE D1
Keyword not found. Restore DE and return with NZ (error).
5134
RET C9
RETURN with NZ (unrecognized parameter keyword).
5135
LD A,(HL) 7E
Fetch the character after the keyword from the command line. Should be = for keyword=value pairs.
5136
CP A,3DH FE 3D
Compare against 3DH (ASCII =).
5138
If Z (equals sign found), JUMP to 514EH to parse the value after the =.
No Value Specified
The keyword appeared without an = sign (e.g., a standalone flag). Store FFFFH as the default value and continue.
513A
LD BC,0FFFFH 01 FF FF
Load Register Pair BC with FFFFH. This is the default "no value specified" marker.
513D
LD A,C 79
Store Parameter Value
Load Register A with the low byte of the parsed value (Register C).
513E
LD (DE),A 12
Store the low byte into the result buffer at (DE).
513F
INC DE 13
INCrement DE to the next byte.
5140
LD A,B 78
Load Register A with the high byte of the parsed value (Register B).
5141
LD (DE),A 12
Store the high byte into the result buffer.
5142
POP DE D1
Restore the original result buffer pointer from the stack.
5143
LD A,(HL) 7E
Fetch the next delimiter from the command line.
5144
CP A,2CH FE 2C
Compare against 2CH (ASCII comma ,). A comma separates multiple parameters.
5146
If Z (comma found), LOOP BACK to 511BH to parse the next parameter.
5148
CP A,29H FE 29
Compare against 29H (ASCII close parenthesis )). This ends the parameter list.
514A
RET NZ C0
If NZ (not a closing parenthesis, syntax error), RETURN with NZ.
514B
INC HL 23
INCrement HL past the closing parenthesis.
514C
XOR A,A AF
Set Register A to ZERO and set Z flag. Success.
514D
RET C9
RETURN with Z set (parameters parsed successfully).
Parse Value After = Sign
The keyword was followed by =. Now determine the value type: quoted string, hex number (X'nn'), decimal number, or YES/NO boolean.
514E
INC HL 23
INCrement HL past the = sign.
514F
LD A,(HL) 7E
Fetch the first character of the value.
5150
CP A,22H FE 22
Compare against 22H (ASCII double quote "). A quoted string value.
5152
If Z (quoted string), JUMP to 516EH to parse the quoted string.
5154
CP A,58H FE 58
Compare against 58H (ASCII 'X'). An 'X' prefix indicates a hexadecimal value (X'nn' format).
5156
If Z ('X' prefix found), JUMP to 5161H to parse the hex value.
5158
CP A,41H FE 41
Compare against 41H ('A'). If the value starts with a letter (A-Z), it is a YES/NO/ON/OFF boolean.
515A
If Carry (character < 'A', i.e., a digit), JUMP to 5169H to parse as a decimal number.
515C
GOSUB to the YES/NO parser at 5181H. Parses Y/N/YES/NO/ON/OFF and returns BC = FFFFH (yes/on) or 0000H (no/off).
515F
JUMP to 5165H to check the result and store the value.
5161
INC HL 23
Hex Parser Entry
INCrement HL past the 'X' prefix.
5162
GOSUB to the hex number parser at 51C0H. Parses X'nnnn' format hex digits and returns the value in BC.
5165
If Z (parse succeeded), JUMP to 513DH to store the parsed value from BC.
5167
Parse failed. JUMP to 5133H to return with NZ (error).
5169
Decimal Parser Entry
GOSUB to the decimal number parser at 51A6H. Parses a decimal digit string and returns the 16-bit value in BC.
516C
JUMP to 513DH to store the parsed decimal value from BC.
Quoted String Parser
The value is enclosed in double quotes. Copy everything between the quotes into the result buffer, replacing the closing quote with a 0DH terminator.
516E
INC HL 23
INCrement HL past the opening double quote.
516F
LD B,H 44
Save H in B (start of quoted string for BC reference).
5170
LD C,L 4D
Save L in C. BC now points to the start of the quoted string content.
5171
LD A,(HL) 7E
Quote Scan Loop
Fetch the next character from the quoted string.
5172
CP A,20H FE 20
Compare against 20H (space). Characters below space (control characters) indicate a premature end of the quoted string.
5174
If Carry (control character found before closing quote), JUMP to 5133H to return with error.
5176
INC HL 23
INCrement HL to the next character.
5177
CP A,22H FE 22
Compare against 22H (closing double quote).
5179
If NZ (not closing quote), LOOP BACK to 5171H to continue scanning.
517B
DEC HL 2B
DECrement HL back to the closing quote position.
517C
LD (HL),0DH 36 0D
Overwrite the closing quote with 0DH (carriage return). This terminates the quoted string in the command buffer itself.
517E
INC HL 23
INCrement HL past the (now overwritten) quote position.
517F
JUMP to 513DH to store BC (pointer to the start of the quoted string) as the parameter value.
5181H - YES/NO Boolean Parser
Parses a boolean parameter value. Recognizes Y, YES, N, NO, ON, and OFF. Returns BC=FFFFH for true values (Y, YES) and BC=0000H for false values (N, NO, OFF, ON treated as a special case). Scans characters with case-insensitive comparison (RES 5,A converts to uppercase). Returns Z on success, NZ on unrecognized value.
5181
LD BC,0000H 01 00 00
YES/NO Parser Entry
Initialize BC to 0000H (default: false/NO).
5184
LD A,(HL) 7E
Fetch the first character of the boolean value.
5185
RES 5,A CB AF
Reset bit 5 of Register A. This converts lowercase to uppercase (e.g., 'y' -> 'Y').
5187
CP A,59H FE 59
Compare against 59H ('Y'). If the value starts with Y, it is YES or Y.
5189
If Z ('Y' found), JUMP to 519BH to set BC=FFFFH (true) and scan to the next delimiter.
518B
CP A,4EH FE 4E
Compare against 4EH ('N'). If the value starts with N, it is NO or N.
518D
If Z ('N' found), JUMP to 519CH. BC remains 0000H (false).
518F
CP A,4FH FE 4F
Compare against 4FH ('O'). Could be ON or OFF.
5191
RET NZ C0
If NZ (not Y, N, or O), RETURN with NZ (unrecognized boolean value).
5192
INC HL 23
INCrement HL to the second character.
5193
LD A,(HL) 7E
Fetch the second character.
5194
RES 5,A CB AF
Convert to uppercase.
5196
CP A,46H FE 46
Compare against 46H ('F'). "OF" = start of "OFF".
5198
If Z ('F' found, value is "OFF"), JUMP to 519CH. BC = 0000H (false).
519A
NOP 00
NOP placeholder. If the second character was 'N' (ON), fall through. ON is treated same as YES in some contexts but BC remains 0000H here.
519B
DEC BC 0B
Set True Value
DECrement BC from 0000H to FFFFH. This sets the boolean result to "true" (all bits set). For Y and YES, execution reaches here. For ON, the NOP at 519AH allows fall-through to here, setting BC=FFFFH.
519C
INC HL 23
Scan to Delimiter
INCrement HL past the current character.
519D
LD A,(HL) 7E
Fetch the next character.
519E
CP A,29H FE 29
Compare against 29H (ASCII )). Closing parenthesis ends the parameter value.
51A0
RET Z C8
If Z (closing parenthesis), RETURN with Z (success). BC holds the boolean value.
51A1
CP A,2CH FE 2C
Compare against 2CH (ASCII comma ,). Comma separates parameters.
51A3
RET Z C8
If Z (comma), RETURN with Z (success).
51A4
Neither ) nor , found. Loop back to 519CH to skip remaining characters of the boolean keyword (e.g., the 'ES' in 'YES' or the 'FF' in 'OFF').
51A6H - Decimal Number Parser
Parses a decimal number string from (HL) and returns the 16-bit result in Register Pair BC. Uses the standard multiply-by-10-and-add algorithm: for each digit, compute BC = BC * 10 + digit. The multiply-by-10 is implemented as BC * 2 * 2 + BC (= BC * 5), then double the result (BC * 10). Stops on the first non-digit character. Returns with Carry set if the first character is not a digit, or NC on success.
51A6
LD BC,0000H 01 00 00
Decimal Parser Entry
Initialize BC to 0000H (accumulated result starts at zero).
51A9
LD A,(HL) 7E
Digit Read Loop
Fetch the next character from (HL).
51AA
SUB A,30H D6 30
SUBtract 30H (ASCII '0') from Register A. Converts ASCII digit to binary value (0-9). If the character was not a digit, Carry is set or the result is >= 10.
51AC
RET C D8
If Carry (character < '0', not a digit), RETURN. BC holds the accumulated value.
51AD
CP A,0AH FE 0A
Compare against 0AH (10 decimal). If A >= 10, the character was not a valid digit (e.g., ':' or a letter).
51AF
RET NC D0
If No Carry (A >= 10, not a digit), RETURN. BC holds the accumulated value.
51B0
PUSH BC C5
Save the current accumulated value (BC) onto the stack.
51B1
EX (SP),HL E3
Exchange (SP) with HL. HL now holds the accumulated BC value; the command line pointer is saved on the stack. This is a trick to transfer BC into HL for arithmetic.
51B2
ADD HL,HL 29
HL = HL * 2 (accumulated value * 2).
51B3
ADD HL,HL 29
HL = HL * 2 (accumulated value * 4).
51B4
ADD HL,BC 09
HL = HL + BC (accumulated * 4 + accumulated * 1 = accumulated * 5).
51B5
ADD HL,HL 29
HL = HL * 2 (accumulated * 5 * 2 = accumulated * 10). The accumulated value has been multiplied by 10.
51B6
LD B,00H 06 00
Load Register B with 00H. Prepare BC for the digit addition.
51B8
LD C,A 4F
Load Register C with the current digit value (0-9). BC = 00:digit.
51B9
ADD HL,BC 09
HL = HL + BC (accumulated * 10 + new digit). The new digit has been incorporated.
51BA
LD B,H 44
Copy H into B. Transfer the updated accumulated value from HL back to BC.
51BB
LD C,L 4D
Copy L into C. BC now holds the new accumulated value (previous * 10 + digit).
51BC
POP HL E1
Restore the command line pointer from the stack (saved by EX (SP),HL at 51B1H).
51BD
INC HL 23
INCrement HL to the next character in the command line.
51BE
LOOP BACK to 51A9H to read the next digit.
51C0H - Hexadecimal Number Parser
Parses a hexadecimal number in X'nnnn' format from (HL) and returns the 16-bit result in Register Pair BC. On entry, HL points to the opening single quote (the 'X' prefix was already consumed by the caller at 5161H). Each hex digit is converted from ASCII to binary (0-9 via SUB 30H, A-F via additional SUB 07H) and shifted into BC using four left shifts (multiply by 16). The closing single quote terminates the parse. Returns Z on success, NZ on failure.
51C0
LD BC,0000H 01 00 00
Hex Parser Entry
Initialize BC to 0000H (accumulated result starts at zero).
51C3
LD A,(HL) 7E
Hex Digit Read Loop
Fetch the next character from (HL).
51C4
CP A,27H FE 27
Compare against 27H (ASCII single quote '). The opening quote delimiter of the X'nn' format.
51C6
RET NZ C0
If NZ (not a single quote on the first call), RETURN with NZ (error). The X' prefix must be followed by a single quote. On subsequent iterations this instruction is skipped because execution jumps to 51C7H from 51E9H.
51C7
INC HL 23
Read Next Hex Digit
INCrement HL past the quote or current hex digit.
51C8
LD A,(HL) 7E
Fetch the next character.
51C9
SUB A,30H D6 30
SUBtract 30H (ASCII '0'). Converts digits '0'-'9' to values 0-9.
51CB
If Carry (character < '0'), JUMP to 51D7H to check for the closing quote.
51CD
CP A,0AH FE 0A
Compare against 0AH (10). If A < 10, it is a valid decimal digit (0-9).
51CF
If Carry (A < 10, valid digit 0-9), JUMP to 51DFH to shift it into BC.
51D1
SUB A,07H D6 07
SUBtract 07H. Converts 'A'-'F' (which after the first SUB 30H gave 11H-16H) to values 0AH-0FH.
51D3
CP A,10H FE 10
Compare against 10H (16). If A < 16, it is a valid hex digit (A-F).
51D5
If Carry (valid hex digit A-F), JUMP to 51DFH to shift it into BC.
51D7
LD A,(HL) 7E
Closing Quote Check
Re-fetch the original character (the SUB operations destroyed it).
51D8
CP A,27H FE 27
Compare against 27H (closing single quote).
51DA
INC HL 23
INCrement HL past the closing quote (or the invalid character).
51DB
RET Z C8
If Z (closing quote found), RETURN with Z (success). BC holds the parsed hex value.
51DC
DEC HL 2B
DECrement HL back. The character was not a closing quote and not a valid hex digit - this is an error.
51DD
XOR A,A AF
Set Register A to ZERO. However, this sets Z which would indicate success - but the next instruction is RET which returns with Z. This appears to be a graceful exit for unterminated hex strings, returning whatever was accumulated.
51DE
RET C9
RETURN. The hex parse is terminated with whatever value accumulated in BC.
Shift Hex Digit Into Accumulator
A valid hex digit (0-F) has been converted to its binary value in A. Shift BC left by 4 bits (multiply by 16) and add the new digit.
51DF
PUSH BC C5
Save the current accumulated value onto the stack.
51E0
EX (SP),HL E3
Exchange (SP) with HL. HL now holds the accumulated value; the command line pointer is on the stack.
51E1
ADD HL,HL 29
HL = HL * 2 (shift left 1 bit).
51E2
ADD HL,HL 29
HL = HL * 2 (shift left 2 bits total).
51E3
ADD HL,HL 29
HL = HL * 2 (shift left 3 bits total).
51E4
ADD HL,HL 29
HL = HL * 2 (shift left 4 bits total = multiply by 16). The accumulated value has been shifted left one full hex digit position.
51E5
LD B,H 44
Copy H into B.
51E6
ADD A,L 85
ADD the low byte of the shifted value (L) to the new hex digit (A). This combines the shifted accumulator with the new nibble.
51E7
LD C,A 4F
Store the combined low byte in C. BC now holds (old_value * 16) + new_digit.
51E8
POP HL E1
Restore the command line pointer from the stack.
51E9
LOOP BACK to 51C7H to read the next hex digit. Note this jumps past the opening-quote check at 51C3H-51C6H.
51EBH - String Data
Constant string data used by the SYS1 command interpreter. The default file extension "CMD" is referenced when no extension is specified on the command line. The "VTOS READY" prompt is displayed at the start of each command input cycle. The "WHAT?" message is displayed for unrecognized commands.
51EB-51ED
DEFM "CMD" 43 4D 44
Default Extension
The 3-byte string "CMD" used by the extension inserter at 5042H. When a command is not found in the library command table, this extension is appended as "/CMD" to attempt loading it as a program file.
51EE-51F9
DEFM 0AH,"VTOS READY",0DH 0A 56 54 4F 53 20 52 45 41 44 59 0D
DOS READY Prompt
The 12-byte prompt string displayed at 4E4CH before accepting command input. Begins with 0AH (line feed) to move to a new line, followed by "VTOS READY", and terminated with 0DH (carriage return). This prompt identifies the operating system and signals that the system is waiting for user input.
51FA-51FF
DEFM "WHAT?",0DH 57 48 41 54 3F 0D
Error Message
The 6-byte error string displayed at 4E2FH when an unrecognized command is entered or BREAK is pressed during input. "WHAT?" followed by 0DH (carriage return). This is the only error message in SYS1 - all other error handling is delegated to SYS0 or the SYS6 overlay.