TRS-80 DOS - NEWDOS/80 v2.0 for the Model III - SYS15/SYS Disassembled
Page Customization
Page Index
SYS15/SYS
Other Navigation
SYS15/SYS – FORMS and SETCOM Commands
SYS15/SYS is a NEWDOS/80 overlay module that implements two Model III–only DOS commands: FORMS (printer parameter configuration) and SETCOM (RS-232 serial interface configuration). The module loads into memory at 4D00H and occupies addresses 4D00H–51E7H, though only 4D00H–4FD2H contains executable code and data; the remainder (4FD3H–51E7H) is unused padding (NOP bytes).
The FORMS command allows users to set two printer parameters: WIDTH (characters per line, 9–255) and LINES (lines per page, 1–254, where 254 means unlimited). If no parameters are specified, FORMS displays the current values.
The SETCOM command configures the RS-232 serial port with parameters: WORD length (5–8 bits), BAUD rate (50–19200), STOP bits (1–2), PARITY (odd/even/none), and WAIT/NOWAIT mode. If the OFF keyword is specified, the RS-232 interface is disabled. SETCOM always displays the current state after any changes.
Both commands share a common infrastructure: a keyword parsing engine at 4EE7H that matches user input against keyword tables, a multi-base numeric value parser at 4F49H that handles both decimal and hexadecimal input, and a formatted numeric output routine at 4F93H for displaying parameter values.
Variable and RAM Location Reference
Complete list of RAM variables, self-modifying code locations, and system addresses referenced by SYS15/SYS.
DOS System Variables:
| Address | Description |
|---|---|
| 4028H | Printer lines-per-page setting (1–254; 254 = unlimited) |
| 402AH | Printer lines-per-page working copy (2-byte; low byte at 402AH, high byte at 402BH) |
| 402BH | Printer characters-per-line (WIDTH) setting (9–255) |
| 41F8H | RS-232 configuration word (2-byte): low byte contains baud rate index + word length/stop/parity flags; high byte contains additional flags |
| 41F9H | RS-232 configuration word high byte |
| 41FAH | RS-232 WAIT/NOWAIT flag (00H = NOWAIT, FFH = WAIT) |
Self-Modifying Code Locations:
| Address | Description |
|---|---|
| 4D37H | Operand byte inside the LD HL,0000H instruction at 4D36H; patched with the LINES parameter value during FORMS processing |
| 4D42H | Operand byte inside the LD HL,0000H instruction at 4D40H; patched with the WIDTH parameter value during FORMS processing |
| 4DF9H | Two-byte location inside the LD HL,0000H instruction at 4DF8H; patched with the RS-232 configuration word during SETCOM processing |
| 4E02H | Operand byte inside the LD A,00H instruction at 4E01H; patched with the WAIT/NOWAIT flag during SETCOM processing |
| 4F81H | Operand byte inside the OR 00H instruction at 4F80H; patched with 2CH (ASCII comma) after the first parameter is printed, so subsequent parameters are comma-separated |
Subroutine References (in SYS0):
| Address | Description |
|---|---|
| 4409H | DOS error handler entry point; called with error code in Register A |
| 4C6AH | Keyword scanner setup; initializes parsing state for command-line keyword matching |
| 4C7AH | Keyword parser; parses the next keyword=value pair from the command line. Returns: Carry set = end of input; Zero set = no keyword found; NZ = keyword matched with value in registers |
ROM References:
| Address | Description |
|---|---|
| 0033H | ROM character output routine; displays the character in Register A at the current cursor position and advances the cursor |
| 005AH | ROM routine; called by SETCOM after storing default RS-232 parameters to reinitialize the serial port hardware |
Major Routine Reference
Command Handlers:
| Address | Description |
|---|---|
| 4D00H | SYS15 entry point / command dispatcher. Register A contains the command code (F1H for FORMS or SETCOM); Register C contains the sub-command index (1 = FORMS, 2 = SETCOM). Dispatches to the appropriate handler. |
| 4D11H | FORMS command handler. Parses WIDTH and LINES parameters from the command line, updates printer configuration variables at 4028H and 402BH, then displays current settings. |
| 4D70H | SETCOM command handler. Parses RS-232 parameters (WORD, BAUD, STOP, PARITY, WAIT, NOWAIT, OFF) from the command line, updates configuration at 41F8H–41FAH, then displays current settings. |
Shared Parsing Infrastructure:
| Address | Description |
|---|---|
| 4EE7H | Keyword parser engine. Register D = 03H (max keywords per pass). Register BC = pointer to keyword table. Scans the command line for keywords matching the table entries, dispatches to the handler address stored in the table for each matched keyword. |
| 4F0FH | Keyword string scanner. Called by 4EE7H. Uses the SYS0 routine at 4C6AH to scan ahead through the command line, skipping NUL-delimited keyword names and counting through parameter records to find a match. |
| 4F26H | Numeric parameter value parser entry. Sets up the base (decimal or hex) then calls 4F49H to convert an ASCII number string from the command line into a 16-bit binary value in Register Pair DE. |
| 4F49H | Multi-base ASCII-to-binary converter. Converts a decimal or hexadecimal ASCII string pointed to by Register Pair HL into a 16-bit value in Register Pair DE. Register B bit 0 controls hex mode (1 = hex allowed). |
Display Routines:
| Address | Description |
|---|---|
| 4F7FH | Parameter display initiator. Manages comma separation between displayed parameters using self-modifying code at 4F81H. Calls 4FCBH to print a string of characters. |
| 4F93H | Numeric value display. Register A (via E) contains the value to display. Register Pair HL points to a label string. Prints the label followed by the formatted decimal number. |
| 4F96H | Numeric value display (alternate entry). Register Pair DE contains the 16-bit value to display. Register Pair HL points to a label string. |
| 4F99H | Binary-to-decimal ASCII conversion and output. Converts the 16-bit value in Register Pair DE into up to 5 decimal digits and prints them, suppressing leading zeros. |
| 4FCBH | Character output wrapper. Saves Register Pairs DE and AF, calls ROM routine at 0033H to display the character in Register A, then restores registers and returns. |
Disassembly
4D00H – SYS15 Entry Point / Command Dispatcher
Entry point for SYS15/SYS. The DOS command processor has already identified that the user entered a SYS15 command and loaded the overlay into memory. Register A contains F1H (the SYS15 module identifier) and Register C contains the sub-command index: 1 for FORMS, 2 for SETCOM. This dispatcher validates the module code and routes execution to the correct command handler.
When execution reaches 4D00H, the DOS command processor has set up: Register A = command module identifier (expected F1H for SYS15), Register C = sub-command number (1 = FORMS, 2 = SETCOM), and Register Pair HL = pointer to the remainder of the command line after the command name.
If execution falls through to here, neither FORMS nor SETCOM was identified. This means the sub-command index in Register C was neither 1 nor 2, indicating an invalid command code.
4D11H - FORMS Command Handler
Handles the FORMS command, which sets and displays printer parameters. Register Pair HL points to the remainder of the command line. The FORMS command accepts two optional keyword parameters: WIDTH=xxx (characters per line, 9-255) and LINES=yyy (lines per page, 1-254, where 254 = unlimited). If no parameters are given (just a bare ENTER), the command skips directly to displaying the current values. The keyword parsing is handled by the shared keyword parser at 4EE7H, which uses the keyword table at 4D5BH.
When execution arrives here from the dispatcher at 4D05H, Register Pair HL points to the user's command line text following the FORMS command name. Register C has been decremented to 0 (confirming FORMS). The code first checks whether there are any parameters at all.
The command line has parameters. Before invoking the keyword parser, the code saves the current WIDTH value into the self-modifying instruction at 4D42H. This is done so that if the user only specifies one parameter (e.g., only WIDTH or only LINES), the other parameter retains its current value.
The keyword parser at 4EE7H processes the command line and, when it matches a keyword, calls the handler routine associated with that keyword. For the FORMS WIDTH keyword, the handler returns to 4D22H with the parsed numeric value in Register A. For the FORMS LINES keyword, the handler returns to 4D27H.
The LINES keyword handler entry point follows. When the keyword parser matches LINES and parses its numeric value, execution arrives at 4D27H with the parsed value in Register A.
Fall through to 4D30H to continue parsing for more keywords.
If execution falls through (Z flag set with Carry clear: no keyword matched but not end of line), the code below applies the parsed parameter values to the DOS system variables and then displays the results.
[DISPLAY SECTION] The parameter values have been applied (or no changes were made if the user typed bare FORMS). Now display the current printer settings by reading the live values from the DOS variables and formatting them for output.
4D5BH - FORMS Keyword Table (Data Area)
This is a data area, not executable code. It contains the keyword definition table used by the keyword parser at 4EE7H when processing the FORMS command. Each keyword entry consists of: an ASCII keyword name (NUL-terminated), a flags/range byte, and a 2-byte handler return address (little-endian).
Entry 1 - WIDTH keyword (4D5BH-4D64H):
| 4D5BH-4D60H | 57 49 44 54 48 3D = ASCII "WIDTH=" |
| 4D61H | 00 = NUL terminator for keyword name |
| 4D62H | A0 = Flags byte. Bit 7 is set (80H flag) indicating this keyword accepts a numeric parameter. Bit 5 set (20H) provides additional range/type information. |
| 4D63H-4D64H | 22 4D = Handler return address 4D22H (little-endian). When WIDTH is matched, execution dispatches to 4D22H. |
Entry 2 - LINES keyword (4D65H-4D6FH):
| 4D65H-4D6AH | 4C 49 4E 45 53 3D = ASCII "LINES=" (note: 4D64H contains 4CH which is both the high byte of the previous entry's address and the ASCII "L" starting LINES) |
| 4D6BH | 00 = NUL terminator for keyword name |
| 4D6CH | A0 = Flags byte (same structure as WIDTH entry). |
| 4D6DH-4D6EH | 27 4D = Handler return address 4D27H (little-endian). When LINES is matched, execution dispatches to 4D27H. |
| 4D6FH | 00 = End-of-table marker. |
4D70H - SETCOM Command Handler
Handles the SETCOM command, which configures and displays RS-232 serial interface parameters. Register Pair HL points to the remainder of the command line. SETCOM accepts optional keyword parameters: WORD=wl (5-8 bits per byte), BAUD=br (50-19200), STOP=sb (1-2 stop bits), PARITY=pp (1=odd, 2=even, 3=none), WAIT, NOWAIT, and OFF. If no parameters are given, the command displays the current RS-232 state. The RS-232 configuration is stored as a packed bit field in the two-byte value at 41F8H-41F9H, with the WAIT/NOWAIT flag at 41FAH. Before parsing, the code copies the current RS-232 configuration into self-modifying code locations at 4DF9H and 4E02H so that unchanged parameters retain their current values.
When execution arrives here from the dispatcher at 4D09H, Register Pair HL points to the user's command line text following the SETCOM command name. The code first checks whether parameters were provided.
Parameters were provided. Before invoking the keyword parser, the code copies the current RS-232 configuration from the DOS system variables into the self-modifying code locations. This preserves any parameters the user does not explicitly change.
SETCOM WORD= Keyword Handler (4D8AH): Execution arrives here when the keyword parser has matched the WORD keyword and parsed the numeric value. Register A contains the parsed WORD length value. Valid values are 5, 6, 7, or 8, representing the number of data bits per transmitted byte. The value must be converted into the RS-232 configuration bit field encoding used by the Model III hardware: the word length is stored in bits 5-6 of the configuration byte at 4DFAH. The encoding maps 5→00, 6→01, 7→10, 8→11 in the bit field, but with an XOR adjustment for the parity/overflow flag behavior.
SETCOM BAUD= Keyword Handler (4DA6H): Execution arrives here when the keyword parser has matched the BAUD keyword and parsed the numeric value. Register Pair DE contains the parsed baud rate value (e.g., 300, 9600, 19200). The code must look up this value in the baud rate table at 4EC7H to find the corresponding baud rate index (0-15) for the RS-232 hardware register.
[LOOP START — Baud rate table search] This loop scans the baud rate table, comparing each entry against the user's requested baud rate in Register Pair DE. Register A is the index counter (incremented by 11H each iteration to encode the baud rate index in the RS-232 config format).
[LOOP END — Baud rate found] The matching baud rate was found. Register A contains the encoded baud rate index (multiples of 11H: 00H, 11H, 22H, ... FFH for the 16 entries).
SETCOM STOP= Keyword Handler (4DC3H): Execution arrives here when the keyword parser has matched the STOP keyword and parsed the numeric value. Register A contains the parsed stop bits value. Valid values are 1 (one stop bit) or 2 (two stop bits). The stop bit setting is stored in bit 4 of the configuration byte at 4DFAH: bit 4 clear = 1 stop bit, bit 4 set = 2 stop bits.
SETCOM PARITY= Keyword Handler (4DD1H): Execution arrives here when the keyword parser has matched the PARITY keyword and parsed the numeric value. Register A contains the parsed parity value: 1 = odd parity, 2 = even parity, 3 = no parity. The parity setting uses two bits of the configuration byte at 4DFAH: bit 3 (parity enable) and bit 7 (even/odd select).
Common Keyword Handler Exit (4DE7H): All SETCOM keyword handlers (WORD, BAUD, STOP, PARITY, WAIT, NOWAIT) jump here after successfully processing their parameter. This restores the command line pointer and continues parsing.
4DEAH - SETCOM WAIT / NOWAIT / OFF Handlers and Configuration Apply
This section contains the WAIT and NOWAIT keyword handlers, the OFF keyword handler entry at 4E08H, the keyword parsing loop continuation, and the code that applies the parsed RS-232 configuration to the DOS system variables and hardware. After all parameters have been parsed, the configuration stored in the self-modifying instructions at 4DF8H and 4E01H is written to the system variables at 41F8H-41FAH and the RS-232 hardware is reinitialized via the ROM routine at 005AH. Finally, the current RS-232 state is displayed to the user.
SETCOM WAIT Keyword Handler (4DEAH): Execution arrives here when the keyword parser has matched the WAIT keyword (a keyword with no "=value" parameter). The WAIT flag is stored as FFH at 4E02H (the operand byte of the self-modifying instruction at 4E01H).
SETCOM NOWAIT Keyword Handler (4DEEH): Execution arrives here when the keyword parser has matched the NOWAIT keyword.
Keyword Parse Loop Continuation (4DF2H): After each keyword handler stores its value, execution arrives here to check for more keywords on the command line.
Apply RS-232 Configuration (4DF8H): All keyword parameters have been parsed. The self-modifying code locations now contain the final configuration values. The code reads them, performs final adjustments, and writes the configuration to the DOS system variables and hardware.
SETCOM OFF Keyword Handler (4E08H): Execution arrives here when the keyword parser has matched the OFF keyword. The OFF keyword disables the RS-232 interface entirely. The code calls the SYS0 parser once more to confirm no additional keywords follow (OFF must be the only parameter), then sets the RS-232 state to "off" (configuration = 0, flag = 0).
Display Section Entry (4E0FH): This is the common entry point for displaying the RS-232 state. When reached from the bare SETCOM path (no parameters), it loads the current configuration high byte from 41F9H. When reached from the OFF handler, Register A is already 00H.
Display RS-232 Parameters (4E1DH): The RS-232 is active. The code now decodes and displays each parameter value: WORD length, BAUD rate, STOP bits, PARITY, and WAIT/NOWAIT. Register A contains the configuration high byte (from 41F9H) with the packed settings.
Now display the BAUD rate. The baud rate index is stored in bits 0-3 of the configuration low byte at 41F8H. The index is used to look up the actual baud rate value from the table at 4EC7H.
Now display the STOP bits. The stop bit setting is in bit 4 of the configuration high byte (saved on the stack). Value 1 = one stop bit (bit 4 clear), value 2 = two stop bits (bit 4 set).
Now display the PARITY setting. The parity is encoded in bits 3 and 7 of the configuration high byte (saved on the stack). The decoding is: bit 3=1 = no parity (value 3), bit 3=0 and bit 7=1 = even parity (value 2), bit 3=0 and bit 7=0 = odd parity (value 1).
Finally, display the WAIT or NOWAIT state. The WAIT/NOWAIT flag is stored at 41FAH: FFH (non-zero) = WAIT, 00H = NOWAIT.
RS-232 Defaults Reset Subroutine (4E79H): Called when the RS-232 interface is being turned off or when a bare SETCOM is issued with the interface unconfigured. Stores a zeroed configuration word and FFH WAIT flag to the system variables, then reinitializes the hardware.
Fall through to 4E7EH to store the values and reinitialize the hardware.
4E87H - SETCOM Keyword Table (Data Area)
This is a data area which contains the keyword definition table used by the keyword parser at 4EE7H when processing the SETCOM command.
Each keyword entry consists of:
- an ASCII keyword name (NUL-terminated)
- a flags byte
- and a 2-byte handler return address (little-endian)
The table contains seven keyword entries: OFF WORD= BAUD= STOP= PARITY= WAIT NOWAIT
The label strings within this table are also referenced directly by the display routines (e.g., HL=4E8EH for "WORD=", HL=4E97H for "BAUD=", etc.).
4EC7H - Baud Rate Lookup Table (Data Area)
This is a data area containing 16 two-byte (little-endian) baud rate values. The table is used both for matching user-entered baud rate values during SETCOM parsing (at 4DA6H) and for looking up the actual baud rate value during display (at 4E30H). Each entry corresponds to one of the 16 baud rates supported by the Model III RS-232 hardware. The baud rate index (0–15) is stored in bits 0–3 of the RS-232 configuration low byte at 41F8H.
Baud Rate Table — 16 entries, 2 bytes each (little-endian):
4EE7H - Keyword Parser Engine
This is the shared keyword parser engine used by both the FORMS and SETCOM commands. It is called with Register Pair BC pointing to a keyword table and Register Pair HL pointing to the user's command line. The parser calls the keyword string scanner at 4F0FH to match the user's input against the keyword table, then extracts the flags byte and handler address from the matched table entry. If the flags byte has bit 7 set (indicating the keyword requires a numeric "=value" parameter), the parser calls the numeric value parser at 4F26H to convert the ASCII number string. It then performs range validation based on the flags and returns to the handler address extracted from the table.
When execution arrives here, Register Pair BC points to the keyword table (4D5BH for FORMS, 4E87H for SETCOM) and Register Pair HL points to the current position in the command line. Register D is loaded with the maximum number of keyword scan passes.
The keyword requires a numeric parameter. The code now calls the numeric value parser to convert the ASCII number string following the "=" sign into a binary value.
Bit 6 is clear, so this is an 8-bit parameter. Validate that the high byte of DE is zero (the value fits in 8 bits), then pass the low byte in Register A to the handler.
4F0FH - Keyword String Scanner
Scans the user's command line input against keyword names in a keyword table. Called by the keyword parser engine at 4EE7H. Uses the SYS0 keyword matching routine at 4C6AH to compare the user's input against the current keyword name. If the keyword does not match, the scanner skips past the NUL-terminated keyword name and the fixed-size record bytes (flags + handler address) to advance to the next table entry. If no keyword matches and the end-of-table marker (00H) is reached, the scanner reports a parse error. Register Pair BC points to the keyword table; Register D contains the number of bytes to skip per record after the NUL terminator (used to skip the flags byte and handler address).
[LOOP START — Keyword scan loop] Each iteration calls the SYS0 scanner for the current keyword. If no match, the code skips to the next table entry. Register D was loaded with 03H at 4EE7H, meaning 3 bytes must be skipped after each NUL terminator (1 flags byte + 2 handler address bytes).
The keyword did not match. Skip past the remaining bytes of the current keyword name (scan to the NUL terminator), then skip the 3 record bytes (flags + handler address) to reach the next keyword entry.
BC now points to the byte after the NUL terminator (the flags byte). Skip past the 3 record bytes (flags + 2-byte handler address) to reach the start of the next keyword entry.
BC now points to the first byte of the next keyword entry. Check if this is the end-of-table marker (00H).
[LOOP END — no match found] The end-of-table marker was reached without finding a matching keyword. Report a parse error.
4F26H - Numeric Parameter Value Parser
Parses a numeric value from the command line, supporting both decimal and hexadecimal input. Called by the keyword parser engine at 4EE7H after a keyword with bit 7 set in its flags byte has been matched. Register Pair HL points to the command line at the position following the "=" sign. The routine first attempts to parse the number as pure decimal. If the string ends with a character in the range "A"-"H", it re-parses as hexadecimal (with "H" suffix). Returns with the parsed 16-bit value in Register Pair DE and Register A containing the low byte. If the parse fails, jumps to the error handler at 4F44H.
The character following the decimal number is in the range A-H, which suggests this might be a hexadecimal number (e.g., "1AH" or "FFH"). Re-parse from the beginning with hex mode enabled.
4F49H - Multi-Base ASCII-to-Binary Converter
Converts an ASCII numeric string pointed to by Register Pair HL into a 16-bit binary value in Register Pair DE. Supports both decimal (base 10) and hexadecimal (base 16) depending on Register B bit 0: if bit 0 is clear, only decimal digits 0-9 are accepted; if bit 0 is set, hex digits A-F (41H-46H) are also accepted. The multiplication is done in-line: for decimal mode, each new digit multiplies the accumulator by 10 (via shift-and-add: value*4 + value, then *2, then +digit); for hex mode, multiplies by 16 (via four left shifts). On return, Register B bit 1 is set if at least one valid digit was parsed. If the result overflows 16 bits, jumps to error handler at 4F44H.
[LOOP START — Digit parsing loop] Each iteration reads one character from the command line, validates it as a digit, multiplies the accumulator by the base (10 or 16), and adds the new digit value.
The character is not a decimal digit. Check if hex mode is enabled and if the character is a valid hex digit A-F.
Register A now contains the binary value of the current digit (0-9 for decimal, 0-15 for hex). The code below multiplies the accumulator (DE) by the base and adds the new digit. The multiplication uses a shift-and-add technique that differs depending on whether decimal or hex mode is active.
At this point HL = original_value * 4. The next step differs based on mode: in hex mode (bit 0 set), two more shifts give *16; in decimal mode (bit 0 clear), ADD HL,DE gives *5, then one more shift gives *10.
[HEX PATH] Hex mode: need value * 16. Currently HL = value * 4. One more shift gives * 8.
[DECIMAL PATH] Decimal mode: HL = value * 4. Add the original value (in DE) to get value * 5.
Now add the new digit value (saved in Register C) to the multiplied accumulator.
4F7FH - Parameter Display Initiator / String Printer
Manages comma-separated parameter display output. On the first call, no separator is printed; on subsequent calls, a comma is printed before the parameter label. This is achieved through self-modifying code at 4F81H: the operand of the OR instruction starts as 00H (first call, no separator) and is patched to 2CH (ASCII comma) after the first parameter is printed. After handling the separator, the routine prints the NUL-terminated string pointed to by Register Pair HL, which is the keyword label (e.g., "WIDTH=", "BAUD=", "WAIT").
[LOOP START — String print loop] Print each character of the NUL-terminated label string pointed to by Register Pair HL.
4F93H - Numeric Value Display
Displays a keyword label followed by a formatted decimal number. Has three entry points: 4F93H takes an 8-bit value in Register A; 4F94H takes an 8-bit value in Register E; 4F96H takes a 16-bit value in Register Pair DE. All entries call 4F7FH to print the label string (with comma separation), then convert the binary value to up to 5 decimal digits using repeated subtraction with negative powers of 10 from the divisor table at 4FC3H, suppressing leading zeros.
Binary-to-Decimal Conversion (4F99H): Converts the 16-bit value in Register Pair DE to decimal ASCII and prints each digit. Uses repeated subtraction with negative divisors from the table at 4FC3H. Register B counts 4 divisor passes (ten-thousands, thousands, hundreds, tens), then the remainder is the ones digit. Register C is used as a leading-zero suppression flag: starts at 0, and is incremented when the first non-zero digit is encountered.
[LOOP START — Digit extraction loop] For each divisor, the code repeatedly adds the negative divisor to the value until it overflows (carry), counting how many times the addition succeeded. The count is the digit value.
[INNER LOOP START — Repeated subtraction] Each iteration adds the negative divisor (subtracts the divisor) and increments the ASCII digit counter.
[INNER LOOP END] The last subtraction underflowed. Undo it by adding the divisor back (via SBC), and Register A contains the ASCII digit.
Register A contains the ASCII digit for this position. Check for leading-zero suppression: if the digit is "0" and no significant digit has been printed yet (C = 0), skip printing this digit.
[LOOP END] All four divisor passes are complete. The remainder in Register E is the ones digit (0-9). Print it unconditionally (the ones digit is always printed, even if zero).
4FC3H - Decimal Divisor Table (Data Area)
Data area containing four 2-byte negative divisor values used by the binary-to-decimal conversion routine at 4F99H. Each entry is the two's complement (negative) of a power of 10, stored little-endian. The conversion routine adds these negative values to the number being converted, effectively performing repeated subtraction to extract each decimal digit position.
4FCBH - Character Output Wrapper
Wrapper routine that prints the character in Register A to the screen by calling the ROM character output routine at 0033H. Saves and restores Register Pairs DE and AF across the ROM call, ensuring that the caller's register values are not disturbed. Called extensively throughout SYS15 by the display routines.
4FD3H - Unused Space (NOP Padding)
The remainder of the SYS15/SYS overlay from 4FD3H through 51E7H is unused space filled with 00H (NOP) bytes. This padding fills the overlay to its fixed size. The executable code and data for SYS15 ends at 4FD2H.