TRS-80 DOS - NEWDOS/80 v2.0 for the Model I - SYS15/SYS Disassembled

Page Customization

Description:

SYS15/SYS is a system utility module that provides display configuration and RS-232 serial communication settings for NEWDOS/80. The module handles two primary functions:

1. Display Configuration (F1H+01H):

  • WIDTH= - Sets the screen width (number of columns) stored at 402BH
  • LINES= - Sets the number of display lines stored at 4028H

2. RS-232 Serial Communication Setup (F1H+02H):

  • WORD= - Sets word length (5-8 bits)
  • BAUD= - Sets baud rate (50, 110, 150, 300, 600, 1200, 2400, 4800, 9600)
  • STOP= - Sets stop bits (1 or 2)
  • PARITY= - Sets parity (EVEN, ODD, or NONE)
  • WAIT/NOWAIT - Controls handshaking mode

The module includes hexadecimal number parsing, parameter validation, display formatting routines, and RS-232 control register manipulation at 41F8H-41FAH.

Variables:

AddressBytesPurpose
402BH1Display width (columns) - system variable in SYS0
4028H1Display lines (rows) - system variable in SYS0
402AH2Related display parameter - system variable in SYS0
41F8H2RS-232 control register (word/baud/stop configuration)
41FAH1RS-232 parity and wait mode flags
4D37H1Stored LINES value (self-modifying code target)
4D42H1Stored WIDTH value (self-modifying code target)
4DF9H2Working copy of RS-232 control register (self-modifying code)
4E02H1Stored parity/wait flags (self-modifying code target)
4F81H1Display separator character (self-modifying code - comma/null toggle)
4D5BH-4D61H7String "WIDTH=" with flags and handler address
4D65H-4D6FH11String "LINES=" with flags and handler address
4E87H-4E8DH7String "OFF" with flags and handler address
4E8EH-4E96H9String "WORD=" with flags and handler address
4E97H-4E9FH9String "BAUD=" with flags and handler address
4EA0H-4EA8H9String "STOP=" with flags and handler address
4EA9H-4EB3H11String "PARITY=" with flags and handler address
4EB4H-4EBBH8String "WAIT" with flags and handler address
4EBCH-4EC6H11String "NOWAIT" with flags and handler address
4EC7H-4EE6H32Baud rate lookup table (16 entries × 2 bytes = base clock divisor values)
4FC3H-4FCAH8Decimal display divisor table (10000, 1000, 100, 10 for conversion)
4FD3H-51E7H533Unused/padding area (all 00H bytes)

Disasembly:

4D00H - Command Entry and Function Code Validation

This is the main entry point for SYS15/SYS. The code receives function code F1H and validates it, then dispatches based on sub-function in Register C: 01H for WIDTH/LINES display configuration, 02H for RS-232 serial communication settings.

4D00
CP F1H FEF1
Compare Register A against F1H (the base SVC function code for this module). If Register A equals F1H, the Z FLAG is set; otherwise the NZ FLAG is set.
4D02
If the NZ FLAG (Not Zero) has been set (meaning this is NOT an F1H command), JUMP to 4D0CH to trigger error 2AH (general error).

Function code is valid (F1H). Dispatch based on sub-function offset in Register C.

4D04
DEC C 0D
DECrement Register C by 1. If C becomes zero, the Z FLAG is set.
4D05
If the Z FLAG (Zero) has been set (meaning C was 01H, now 00H = F1H+01H = WIDTH/LINES command), JUMP to 4D11H to handle display configuration.
4D08
DEC C 0D
DECrement Register C by 1. If C becomes zero, the Z FLAG is set.
4D09
If the Z FLAG (Zero) has been set (meaning original C was 02H = F1H+02H = RS-232 configuration command), JUMP to 4D70H to handle serial communication settings.

If execution reaches here, the sub-function code was out of range (greater than 02H). Fall through to error handler.

4D0CH - Invalid Command Error Handler

This routine handles invalid function codes by triggering error 2AH (general error).

4D0C
LD A,2AH 3E2A
Load Register A with 2AH, the error code for "general error" (invalid command or parameter).
4D0E
JUMP to 4F23H to display the error message and return to DOS Ready.

4D11H - WIDTH/LINES Display Configuration Handler

This handler processes the WIDTH= and LINES= commands (F1H+01H). It parses the command line for these keywords, extracts numeric values, validates them, and stores them in system variables at 402BH (width) and 4028H (lines). If no parameters are given, it displays the current settings.

4D11
LD A,(HL) 7E
Fetch the current character from the command line at (HL) into Register A.
4D12
CP 0DH FE0D
Compare Register A against 0DH (ASCII carriage return, end-of-line marker). If Register A equals 0DH, the Z FLAG is set; otherwise the NZ FLAG is set.
4D14
If the Z FLAG (Zero) has been set (meaning end-of-line reached, no parameters), JUMP to 4D46H to display the current WIDTH and LINES settings.

Command line has parameters. Parse WIDTH= and/or LINES= keywords.

4D16
LD A,(402BH) 3A2B40
Fetch the current WIDTH setting from system variable at 402BH into Register A.
4D19
LD (4D42H),A 32424D
Store Register A (current width) into memory location 4D42H. This is self-modifying code - the stored value will be used at instruction 4D40H as an LD HL,nnnn operand's low byte.
4D1C
LD BC,4D5BH 015B4D
Point Register Pair BC to 4D5BH, the keyword lookup table containing "WIDTH=" and "LINES=" command strings with their flags and handler addresses.
4D1F
JUMP to 4EE7H to begin parsing keywords from the command line against the table at BC.

4D22H - Store Parsed Value and Continue

This routine is called after a numeric value has been parsed for WIDTH= or LINES=. It stores the value using self-modifying code and continues processing.

4D22
LD (4D42H),A 32424D
Store Register A (the parsed WIDTH value) into memory location 4D42H. This is self-modifying code at instruction 4D40H.
4D25
JUMP (unconditionally) to 4D30H to continue parsing the command line.

4D27H - Store LINES Value

This routine stores the parsed LINES= value using self-modifying code.

4D27
INC A 3C
INCrement Register A by 1. This adjusts the parsed value (possibly compensating for zero-based vs one-based counting).
4D28
If the NZ FLAG (Not Zero) has been set (meaning A did not overflow to 00H), JUMP to 4D2DH to store the value.
4D2A
LD A,(4028H) 3A2840
If A overflowed to 00H (was FFH), fetch the current LINES setting from system variable at 4028H into Register A to use as default.
4D2D
LD (4D37H),A 32374D
Store Register A (the LINES value) into memory location 4D37H. This is self-modifying code at instruction 4D36H.

4D30H - Parse Next Parameter

This routine continues parsing the command line for additional WIDTH= or LINES= parameters.

4D30
GOSUB to 4C7AH (command line parser in SYS0 or this module) to skip delimiters and check for more parameters. Returns with Z FLAG set if end-of-line, CARRY FLAG set if invalid character.
4D33
RET C D8
RETurn if the CARRY FLAG has been set (meaning invalid character encountered, error already flagged).
4D34
If the NZ FLAG (Not Zero) has been set (meaning more parameters exist), LOOP BACK to 4D1CH to parse the next keyword.

End of command line reached. Store the parsed values into system variables.

4D36
LD HL,0000H 210000
Load Register Pair HL with 0000H. This is self-modifying code - the low byte at 4D37H was stored by instruction at 4D2DH and contains the LINES value. So HL = 00LLH where LL = LINES.
4D39
LD A,L 7D
Copy Register L (the LINES value) into Register A for testing.
4D3A
OR A B7
Perform OR operation on Register A with itself to test if it's zero. The Z FLAG will be set if A = 00H.
4D3B
If the Z FLAG (Zero) has been set (meaning LINES value is 00H, not changed), JUMP to 4D40H to skip storing LINES.
4D3D
LD (4028H),HL 222840
Store Register Pair HL (00LLH) into memory location 4028H, updating the system LINES variable. This stores the new LINES value.
4D40
LD HL,0000H 210000
Load Register Pair HL with 0000H. This is self-modifying code - the low byte at 4D42H was stored by instruction at 4D19H or 4D22H and contains the WIDTH value. So HL = 00WWH where WW = WIDTH.
4D43
LD (402AH),HL 222A40
Store Register Pair HL (00WWH) into memory location 402AH, updating a related display parameter in the SYS0 area.

4D46H - Display Current WIDTH and LINES Settings

This routine displays the current WIDTH= and LINES= settings by fetching the values from system variables and formatting them for output.

4D46
LD A,(402BH) 3A2B40
Fetch the current WIDTH setting from system variable at 402BH into Register A.
4D49
LD HL,4D5BH 215B4D
Point Register Pair HL to 4D5BH, the "WIDTH=" string for display.
4D4C
GOSUB to 4F93H to display the string at HL followed by the decimal value in Register A (WIDTH=nn format).
4D4F
LD A,(4028H) 3A2840
Fetch the current LINES setting from system variable at 4028H into Register A.
4D52
LD HL,4D65H 21654D
Point Register Pair HL to 4D65H, the "LINES=" string for display.
4D55
DEC A 3D
DECrement Register A by 1. This adjusts the LINES value for display (possibly converting from internal representation to user-visible value).
4D56
GOSUB to 4F93H to display the string at HL followed by the decimal value in Register A (LINES=nn format).
4D59
XOR A AF
Set Register A to ZERO by XORing it with itself, indicating successful completion (no error).
4D5A
RET C9
RETurn to caller. The WIDTH and LINES settings have been displayed.

4D5BH - WIDTH= Command String and Handler Data

This data structure contains the "WIDTH=" keyword string followed by flags and handler address for the WIDTH parameter.

4D5B
DEFM "WIDTH=" 57 49 44 54 48 3D
DATA: String "WIDTH=" for keyword matching.
4D61
DEFB 00H 00
DATA: Null terminator for the string.
4D62
DEFB A0H A0
DATA: Flags byte A0H (binary 10100000): bit 7=1 (valid keyword), bit 5=1 (numeric parameter expected).
4D63
DEFW 4D22H 22 4D
DATA: Handler address 4D22H - points to the routine that stores the parsed WIDTH value.

4D65H - LINES= Command String and Handler Data

This data structure contains the "LINES=" keyword string followed by flags and handler address for the LINES parameter.

4D65
DEFM "LINES=" 4C 49 4E 45 53 3D
DATA: String "LINES=" for keyword matching.
4D6B
DEFB 00H 00
DATA: Null terminator for the string.
4D6C
DEFB A0H A0
DATA: Flags byte A0H (binary 10100000): bit 7=1 (valid keyword), bit 5=1 (numeric parameter expected).
4D6D
DEFW 4D27H 27 4D
DATA: Handler address 4D27H - points to the routine that stores the parsed LINES value.
4D6F
DEFB 00H 00
DATA: Table terminator (null byte indicating end of keyword table).

4D70H - RS-232 Serial Configuration Handler

This handler processes RS-232 serial communication settings (F1H+02H). It parses command line parameters for WORD=, BAUD=, STOP=, PARITY=, WAIT/NOWAIT and configures the RS-232 control registers at 41F8H-41FAH. If no parameters are given, it displays the current serial configuration.

4D70
LD A,(HL) 7E
Fetch the current character from the command line at (HL) into Register A.
4D71
CP 0DH FE0D
Compare Register A against 0DH (ASCII carriage return, end-of-line marker). If Register A equals 0DH, the Z FLAG is set.
4D73
If the Z FLAG (Zero) has been set (meaning end-of-line reached, no parameters), JUMP to 4E0FH to display the current RS-232 configuration.

Command line has parameters. Load current RS-232 settings and prepare for parsing.

4D76
LD DE,(41F8H) ED5BF841
Fetch the 16-bit RS-232 control register value from memory location 41F8H into Register Pair DE. This contains the current word/baud/stop bit configuration.
4D7A
LD (4DF9H),DE ED53F94D
Store Register Pair DE into memory location 4DF9H. This is self-modifying code - creates a working copy of the control register at instruction 4DF8H.
4D7E
LD A,(41FAH) 3AFA41
Fetch the parity and wait mode flags from memory location 41FAH into Register A.
4D81
LD (4E02H),A 32024E
Store Register A into memory location 4E02H. This is self-modifying code - creates a working copy of the parity/wait flags at instruction 4E01H.
4D84
LD BC,4E87H 01874E
Point Register Pair BC to 4E87H, the RS-232 keyword lookup table containing "OFF", "WORD=", "BAUD=", "STOP=", "PARITY=", "WAIT", "NOWAIT" strings with flags and handlers.
4D87
JUMP to 4EE7H to begin parsing RS-232 keywords from the command line.

4D8AH - WORD= Parameter Handler

This routine processes the WORD= parameter (word length 5-8 bits). It validates the numeric value and updates the RS-232 control register bits accordingly.

4D8A
SUB 05H D605
SUBtract 05H from Register A. This converts values 5-8 to range 0-3. If A was 5, result is 0; if 8, result is 3.
4D8C
CP 09H FE09
Compare Register A against 09H. If A < 09H, the CARRY FLAG is set. Since we subtracted 5, valid range is now 00H-03H (was 05H-08H).
4D8E
If the NO CARRY FLAG has been set (meaning A >= 09H, value was outside 5-8 range), JUMP to 4F44H to trigger error 2FH (invalid parameter).

Value is valid (0-3 representing 5-8 bits). Encode it into the control register format.

4D91
OR A B7
Perform OR operation on Register A with itself to test the parity flag from the subtract. The P/V FLAG will be set if parity is even.
4D92
If the PE FLAG (Parity Even) has been set, JUMP to 4D97H to skip the XOR adjustment.
4D95
XOR 03H EE03
Perform XOR operation between Register A and 03H (binary 00000011). This flips bits 0-1, adjusting the encoding for odd parity values.
4D97
RRCA 0F
Rotate Register A Right Circular. Bit 0 moves to bit 7 and CARRY FLAG.
4D98
RRCA 0F
Rotate Register A Right Circular again.
4D99
RRCA 0F
Rotate Register A Right Circular a third time. After three right rotates, bits 0-1 have moved to bits 5-6 position (shifted left by 5).
4D9A
LD C,A 4F
Copy the shifted word length bits from Register A into Register C for later merging.
4D9B
PUSH HL E5
Save Register Pair HL (command line pointer) onto the stack.
4D9C
LD HL,4DFAH 21FA4D
Point Register Pair HL to 4DFAH, which is the high byte of the self-modifying control register copy at 4DF9H.
4D9F
LD A,(HL) 7E
Fetch the current control register high byte from (HL) into Register A.
4DA0
AND 9FH E69F
Perform AND operation between Register A and 9FH (binary 10011111). This clears bits 5-6 (the word length bits) while preserving all others.
4DA2
OR C B1
Perform OR operation between Register A and Register C. This merges the new word length bits (from C) with the preserved bits.
4DA3
LD (HL),A 77
Store the updated control register high byte back into (HL) at 4DFAH.
4DA4
JUMP (unconditionally) to 4DE7H to restore HL and continue parsing.

4DA6H - BAUD= Parameter Handler

This routine processes the BAUD= parameter by looking up the baud rate value in a table at 4EC7H and encoding it into the RS-232 control register. Supported baud rates: 50, 110, 150, 300, 600, 1200, 2400, 4800, 9600.

4DA6
PUSH HL E5
Save Register Pair HL (command line pointer) onto the stack.
4DA7
LD HL,4EC7H 21C74E
Point Register Pair HL to 4EC7H, the start of the baud rate lookup table containing 16 entries of 2-byte clock divisor values.
4DAA
XOR A AF
Set Register A to ZERO by XORing it with itself. This initializes the table index counter.
4DAB
LD C,(HL) 4E
[BAUD TABLE SEARCH LOOP START] Fetch the low byte of the table entry's divisor value from (HL) into Register C.
4DAC
INC HL 23
INCrement Register Pair HL by 1 to point to the high byte.
4DAD
LD B,(HL) 46
Fetch the high byte of the divisor value from (HL) into Register B. Register Pair BC now contains the table entry's divisor.
4DAE
INC HL 23
INCrement Register Pair HL by 1 to point to the next table entry.
4DAF
EX DE,HL EB
EXchange Register Pairs DE and HL. The parsed baud rate value (previously in DE) is now in HL for comparison, and the table pointer is now in DE.
4DB0
OR A B7
Clear the CARRY FLAG by ORing A with itself (A is the index counter). This prepares for the 16-bit subtraction.
4DB1
SBC HL,BC ED42
SuBtract with Carry: subtract BC from HL (HL = HL - BC). If the result is zero, the parsed baud rate matches this table entry.
4DB3
ADD HL,BC 09
ADD Register Pair BC to Register Pair HL, restoring HL to its original value (undoing the subtraction).
4DB4
EX DE,HL EB
EXchange Register Pairs DE and HL back. HL is now the table pointer again, DE contains the baud rate value.
4DB5
If the Z FLAG (Zero) has been set (meaning HL-BC was zero, baud rate matched), JUMP to 4DBEH to use this table index.

Baud rate didn't match this entry. Advance to next entry and increment index.

4DB7
ADD 11H C611
ADD 11H (17 decimal) to Register A (the index). This advances the index by one entry (with some scaling factor).
4DB9
[LOOP] If the NO CARRY FLAG has been set (meaning addition didn't overflow), LOOP BACK to 4DABH to check the next table entry.
4DBB
If addition overflowed (reached end of table without match), JUMP to 4F44H to trigger error 2FH (invalid baud rate).

[BAUD TABLE SEARCH LOOP END - MATCH FOUND] Store the table index as the baud rate code in the control register.

4DBE
LD (4DF9H),A 32F94D
Store Register A (the baud rate table index) into memory location 4DF9H, the low byte of the self-modifying control register copy. This encodes the baud rate into bits 0-3 of the control register.
4DC1
JUMP (unconditionally) to 4DE7H to restore HL and continue parsing.

4DC3H - STOP= Parameter Handler

This routine processes the STOP= parameter (1 or 2 stop bits). It validates the value and updates bit 4 of the RS-232 control register high byte accordingly.

4DC3
PUSH HL E5
Save Register Pair HL (command line pointer) onto the stack.
4DC4
LD HL,4DFAH 21FA4D
Point Register Pair HL to 4DFAH, the high byte of the control register copy.
4DC7
RES 4,(HL) CBA6
RESET bit 4 of the byte at (HL). This sets the stop bits to 1 by default.
4DC9
DEC A 3D
DECrement Register A by 1. If A was 1, it becomes 0 (Z FLAG set). If A was 2, it becomes 1 (NZ FLAG set).
4DCA
If the Z FLAG (Zero) has been set (meaning A was 1, now 0 = 1 stop bit desired), JUMP to 4DE7H with bit 4 clear (already done).
4DCC
SET 4,(HL) CBE6
SET bit 4 of the byte at (HL). This configures for 2 stop bits.
4DCE
DEC A 3D
DECrement Register A by 1. If A was 1 (original value 2), it becomes 0. This validates that the value was exactly 2.
4DCF
JUMP (unconditionally) to 4DE5H to validate that A is now zero (was value 2).

4DD1H - PARITY= Parameter Handler

This routine processes the PARITY= parameter (EVEN, ODD, NONE). It encodes the parity setting into bits 3 and 7 of the parity/wait flags byte at 4E02H.

4DD1
PUSH HL E5
Save Register Pair HL (command line pointer) onto the stack.
4DD2
LD HL,4DFAH 21FA4D
Point Register Pair HL to 4DFAH. Wait, this should be 4E02H for parity flags. This appears to be an error or the code is more complex.
4DD5
SET 3,(HL) CBDE
SET bit 3 of the byte at (HL). This sets parity enable bit.
4DD7
SUB 03H D603
SUBtract 03H from Register A. This adjusts the parity type value. If A was 03H (EVEN), result is 00H. If 04H (ODD), result is 01H. If 05H (NONE), result is 02H.
4DD9
If the Z FLAG (Zero) has been set (meaning A was 03H = EVEN parity), JUMP to 4DE7H with bit 3 set, bit 7 clear.
4DDB
RES 3,(HL) CB9E
RESET bit 3 of the byte at (HL). This clears parity enable for ODD or NONE.
4DDD
SET 7,(HL) CBFE
SET bit 7 of the byte at (HL). This marks ODD parity mode.
4DDF
INC A 3C
INCrement Register A by 1. If A was 01H (ODD), it becomes 02H. If A was 02H (NONE), it becomes 03H.
4DE0
If the Z FLAG (Zero) has been set (this won't happen since A is now 02H or 03H, both non-zero), JUMP to 4DE7H.
4DE2
RES 7,(HL) CBBE
RESET bit 7 of the byte at (HL). This configures for NONE (no parity).
4DE4
INC A 3C
INCrement Register A by 1. If A was 03H (from NONE=05H), it becomes 04H.

4DE5H - Validate Parameter Value is Zero

This routine validates that the parameter value has been fully consumed (A should be zero after adjustments).

4DE5
If the NZ FLAG (Not Zero) has been set (meaning A is not zero, parameter was invalid), JUMP to 4DBBH which leads to error 2FH.

4DE7H - Restore Command Line Pointer and Continue

This routine restores the command line pointer and continues parsing for more RS-232 parameters.

4DE7
POP HL E1
Restore Register Pair HL (command line pointer) from the stack.
4DE8
JUMP (unconditionally) to 4DF2H to continue parsing the command line.

4DEAH - WAIT Mode Handler

This routine sets the WAIT flag (FFH) for hardware handshaking mode.

4DEA
LD A,FFH 3EFF
Load Register A with FFH, indicating WAIT mode enabled (hardware handshaking on).
4DEC
JUMP (unconditionally) to 4DEFH to store the WAIT flag.

4DEEH - NOWAIT Mode Handler

This routine clears the WAIT flag (00H) for no hardware handshaking.

4DEE
XOR A AF
Set Register A to ZERO by XORing it with itself, indicating NOWAIT mode (hardware handshaking off).

4DEFH - Store WAIT Mode Flag

This routine stores the WAIT/NOWAIT flag into the self-modifying code location.

4DEF
LD (4E02H),A 32024E
Store Register A (FFH for WAIT or 00H for NOWAIT) into memory location 4E02H. This is self-modifying code at instruction 4E01H.

4DF2H - Parse Next RS-232 Parameter

This routine continues parsing the command line for additional RS-232 configuration keywords.

4DF5
RET C D8
RETurn if the CARRY FLAG has been set (meaning invalid character encountered).
4DF6
If the NZ FLAG (Not Zero) has been set (meaning more parameters exist), LOOP BACK to 4D84H to parse the next RS-232 keyword.

End of command line reached. Apply the RS-232 configuration by writing to the control registers.

4DF8H - Write RS-232 Configuration to Hardware

This routine takes the RS-232 configuration values stored in self-modifying code locations and writes them to the hardware control registers at 41F8H-41FAH, then calls a ROM routine to activate the settings.

4DF8
LD HL,0000H 210000
Load Register Pair HL with 0000H. This is self-modifying code - the 16-bit value at 4DF9H was stored by instructions at 4D7AH (control register) and 4DBEH (baud rate). HL now contains the complete RS-232 control register value.
4DFB
LD A,H 7C
Copy Register H (high byte of control register) into Register A for bit manipulation.
4DFC
AND FCH E6FC
Perform AND operation between Register A and FCH (binary 11111100). This clears bits 0-1 of the high byte.
4DFE
OR 04H F604
Perform OR operation between Register A and 04H (binary 00000100). This sets bit 2 of the high byte.
4E00
LD H,A 67
Copy the modified value from Register A back into Register H. The control register high byte now has bits 0-1 clear and bit 2 set.
4E01
LD A,00H 3E00
Load Register A with 00H. This is self-modifying code - the operand at 4E02H was stored by instructions at 4D81H (initial parity/wait) or 4DEFH (WAIT/NOWAIT). Register A now contains the parity and wait mode flags.
4E03
GOSUB to 4E7EH to write the RS-232 configuration in HL and A to the hardware registers and activate the settings.
4E06
JUMP (unconditionally) to 4E0FH to display the RS-232 configuration.

4E08H - OFF Command Handler

This routine handles the OFF keyword, which disables RS-232 serial communication by clearing all configuration registers.

4E08
GOSUB to 4C7AH (command line parser) to verify end of command line. Returns with Z FLAG set if end-of-line.
4E0B
RET NZ C0
RETurn if the NZ FLAG (Not Zero) has been set (meaning extra parameters after OFF, which is invalid).
4E0C
XOR A AF
Set Register A to ZERO by XORing it with itself. This will be used to clear all RS-232 flags.
4E0D
JUMP (unconditionally) to 4E13H to disable RS-232 with A=00H.

4E0FH - Display Current RS-232 Configuration

This routine displays the current RS-232 serial communication settings by reading the control registers and formatting them for output.

4E0F
LD A,(41F9H) 3AF941
Fetch the RS-232 control register high byte from memory location 41F9H into Register A.
4E12
OR A B7
Perform OR operation on Register A with itself to test if it's zero. The Z FLAG will be set if A = 00H (RS-232 is OFF).

4E13H - Write RS-232 Disable or Display Configuration

This routine either disables RS-232 (if A=00H from OFF command) or displays the current configuration.

4E13
PUSH AF F5
Save Register Pair AF (contains RS-232 status) onto the stack.
4E14
If the Z FLAG (Zero) has been set (meaning RS-232 is OFF or being disabled), GOSUB to 4E79H to clear all RS-232 configuration registers.
4E17
POP AF F1
Restore Register Pair AF from the stack.
4E18
LD HL,4E87H 21874E
Point Register Pair HL to 4E87H, the "OFF" string for display.
4E1B
If the Z FLAG (Zero) has been set (meaning RS-232 is OFF), JUMP to 4E74H to display "OFF" and return.

RS-232 is active. Display the full configuration: WORD=, BAUD=, STOP=, PARITY=, WAIT/NOWAIT.

4E1D
PUSH AF F5
Save Register Pair AF (control register high byte) onto the stack.
4E1E
AND 60H E660
Perform AND operation between Register A and 60H (binary 01100000). This isolates bits 5-6 (word length bits).
4E20
If the PE FLAG (Parity Even) has been set (based on the bit pattern), JUMP to 4E25H to skip the XOR.
4E23
XOR 60H EE60
Perform XOR operation between Register A and 60H. This flips bits 5-6 for odd parity word length encoding.
4E25
RLCA 07
Rotate Register A Left Circular. Bit 7 moves to bit 0 and CARRY FLAG.
4E26
RLCA 07
Rotate Register A Left Circular again.
4E27
RLCA 07
Rotate Register A Left Circular a third time. After three left rotates, bits 5-6 have moved to bits 0-1 position (shifted right by 5, wrapping around).
4E28
ADD 05H C605
ADD 05H to Register A. This converts the 0-3 word length code back to 5-8 bits for display.
4E2A
LD HL,4E8EH 218E4E
Point Register Pair HL to 4E8EH, the "WORD=" string.
4E2D
GOSUB to 4F93H to display "WORD=" followed by the decimal value in A (5-8).

Display the BAUD= setting by looking up the divisor value in the table.

4E30
LD A,(41F8H) 3AF841
Fetch the RS-232 control register low byte from memory location 41F8H into Register A. This contains the baud rate code in bits 0-3.
4E33
AND 0FHAND 00001111 E60F
Perform AND operation between Register A and 0FH (binary 00001111). This isolates bits 0-3 (the baud rate table index).
4E35
ADD A,A 87
ADD Register A to itself (multiply by 2). This converts the table index to a byte offset since each table entry is 2 bytes.
4E36
LD HL,4EC7H 21C74E
Point Register Pair HL to 4EC7H, the start of the baud rate lookup table.
4E39
LD E,A 5F
Copy Register A (the byte offset) into Register E.
4E3A
LD D,00H 1600
Load Register D with 00H. Register Pair DE now contains the 16-bit offset into the table.
4E3C
ADD HL,DE 19
ADD Register Pair DE to Register Pair HL. HL now points to the table entry for this baud rate.
4E3D
LD E,(HL) 5E
Fetch the low byte of the baud rate divisor from (HL) into Register E.
4E3E
INC HL 23
INCrement Register Pair HL by 1 to point to the high byte.
4E3F
LD D,(HL) 56
Fetch the high byte of the baud rate divisor from (HL) into Register D. Register Pair DE now contains the baud rate value to display.
4E40
LD HL,4E97H 21974E
Point Register Pair HL to 4E97H, the "BAUD=" string.
4E43
GOSUB to 4F96H to display "BAUD=" followed by the decimal baud rate value in DE.

Display the STOP= setting (1 or 2 stop bits).

4E46
LD E,01H 1E01
Load Register E with 01H (default to 1 stop bit for display).
4E48
POP BC C1
Restore the saved control register high byte from the stack into Register Pair BC (specifically into B).
4E49
BIT 4,B CB60
Test bit 4 of Register B (the stop bits flag). If bit 4 is set, the Z FLAG is cleared (NZ).
4E4B
PUSH BC C5
Save Register Pair BC back onto the stack for later use.
4E4C
If the Z FLAG (Zero) has been set (meaning bit 4 is clear = 1 stop bit), JUMP to 4E4FH to display with E=01H.
4E4E
INC E 1C
INCrement Register E by 1 (E becomes 02H for 2 stop bits).
4E4F
LD HL,4EA0H 21A04E
Point Register Pair HL to 4EA0H, the "STOP=" string.
4E52
GOSUB to 4F94H to display "STOP=" followed by the value in E (1 or 2).

Display the PARITY= setting (EVEN, ODD, or NONE).

4E55
LD E,03H 1E03
Load Register E with 03H (EVEN parity index for display table).
4E57
POP BC C1
Restore the control register high byte from the stack into Register Pair BC.
4E58
BIT 3,B CB58
Test bit 3 of Register B (parity enable bit). If bit 3 is set, the Z FLAG is cleared (NZ).
4E5A
If the NZ FLAG (Not Zero) has been set (meaning bit 3 is set = parity enabled, EVEN), JUMP to 4E62H with E=03H.
4E5C
DEC E 1D
DECrement Register E by 1 (E becomes 02H).
4E5D
BIT 7,B CB78
Test bit 7 of Register B (ODD parity marker). If bit 7 is set, the Z FLAG is cleared (NZ).
4E5F
If the NZ FLAG (Not Zero) has been set (meaning bit 7 is set = ODD parity), JUMP to 4E62H with E=02H for ODD.
4E61
DEC E 1D
DECrement Register E by 1 (E becomes 01H for NONE parity).
4E62
LD HL,4EA9H 21A94E
Point Register Pair HL to 4EA9H, the "PARITY=" string.
4E65
GOSUB to 4F94H to display "PARITY=" followed by the string indexed by E (EVEN/ODD/NONE).

Display the WAIT/NOWAIT setting.

4E68
LD HL,4EB4H 21B44E
Point Register Pair HL to 4EB4H, the "WAIT" string (default).
4E6B
LD A,(41FAH) 3AFA41
Fetch the parity and wait mode flags from memory location 41FAH into Register A.
4E6E
OR A B7
Perform OR operation on Register A with itself to test if it's zero. The Z FLAG will be set if A = 00H (NOWAIT mode).
4E6F
If the NZ FLAG (Not Zero) has been set (meaning A is non-zero = WAIT mode), JUMP to 4E74H to display "WAIT".
4E71
LD HL,4EBCH 21BC4E
Point Register Pair HL to 4EBCH, the "NOWAIT" string instead.

4E74H - Display String and Return

This routine displays the final configuration string and returns to DOS Ready.

4E74
GOSUB to 4F7FH to display the null-terminated string at HL (either "OFF", "WAIT", or "NOWAIT").
4E77
XOR A AF
Set Register A to ZERO by XORing it with itself, indicating successful completion (no error).
4E78
RET C9
RETurn to caller. The RS-232 configuration has been displayed.

4E79H - Clear RS-232 Configuration (Disable Serial Port)

This routine disables RS-232 serial communication by clearing all control registers and calling a ROM routine.

4E79
LD HL,0000H 210000
Load Register Pair HL with 0000H to clear the RS-232 control register.
4E7C
LD A,FFH 3EFF
Load Register A with FFH to clear the parity/wait flags register.

4E7EH - Write RS-232 Registers and Call ROM Setup

This routine writes the RS-232 configuration in HL and A to the hardware control registers at 41F8H-41FAH, then calls ROM routine at 005AH to activate the serial port configuration.

4E7E
LD (41F8H),HL 22F841
Store Register Pair HL (RS-232 control register value) into memory location 41F8H. This writes both the low byte (41F8H) and high byte (41F9H).
4E81
LD (41FAH),A 32FA41
Store Register A (parity and wait flags) into memory location 41FAH.
4E84
JUMP to ROM routine at 005AH to initialize the RS-232 hardware with the new configuration. This is a ROM entry point for serial port setup.

4E87H - RS-232 Keyword Strings and Handler Data

This section contains the keyword lookup table for RS-232 commands. Each entry consists of a null-terminated string, a flags byte, and a 16-bit handler address.

OFF Keyword

4E87
DEFM "OFF" 4F 46 46
DATA: String "OFF" for RS-232 disable command.
4E8A
DEFB 00H,00H 00 00
DATA: Null terminator and unused byte.
4E8C
DEFB 08H 08
DATA: Flags byte 08H (binary 00001000): bit 3=1 (special handler flag).
4E8D
DEFB 4EH 4E
DATA: Handler address high byte - combined with next byte forms 4E08H (but stored as single byte here, requires next byte).

WORD= Keyword

4E8E
DEFM "WORD=" 57 4F 52 44 3D
DATA: String "WORD=" for word length parameter.
4E93
DEFB 00H 00
DATA: Null terminator for the string.
4E94
DEFB 80H 80
DATA: Flags byte 80H (binary 10000000): bit 7=1 (valid keyword).
4E95
DEFW 4D8AH 8A 4D
DATA: Handler address 4D8AH - points to the WORD= parameter processing routine.

BAUD= Keyword

4E97
DEFM "BAUD=" 42 41 55 44 3D
DATA: String "BAUD=" for baud rate parameter.
4E9C
DEFB 00H 00
DATA: Null terminator for the string.
4E9D
DEFB C0H C0
DATA: Flags byte C0H (binary 11000000): bit 7=1 (valid keyword), bit 6=1 (16-bit numeric parameter).
4E9E
DEFW 4DA6H A6 4D
DATA: Handler address 4DA6H - points to the BAUD= parameter processing routine.

STOP= Keyword

4EA0
DEFM "STOP=" 53 54 4F 50 3D
DATA: String "STOP=" for stop bits parameter.
4EA5
DEFB 00H 00
DATA: Null terminator for the string.
4EA6
DEFB 80H 80
DATA: Flags byte 80H (binary 10000000): bit 7=1 (valid keyword).
4EA7
DEFW 4DC3H C3 4D
DATA: Handler address 4DC3H - points to the STOP= parameter processing routine.

PARITY= Keyword

4EA9
DEFM "PARITY=" 50 41 52 49 54 59 3D
DATA: String "PARITY=" for parity parameter.
4EB0
DEFB 00H 00
DATA: Null terminator for the string.
4EB1
DEFB 80H 80
DATA: Flags byte 80H (binary 10000000): bit 7=1 (valid keyword).
4EB2
DEFW 4DD1H D1 4D
DATA: Handler address 4DD1H - points to the PARITY= parameter processing routine.

WAIT Keyword

4EB4
DEFM "WAIT" 57 41 49 54
DATA: String "WAIT" for hardware handshaking enable.
4EB8
DEFB 00H,00H 00 00
DATA: Null terminator and unused byte.
4EBAH">
4EBA
DEFW 4DEAH EA 4D
DATA: Handler address 4DEAH - points to the WAIT mode handler.

NOWAIT Keyword

4EBC
DEFM "NOWAIT" 4E 4F 57 41 49 54
DATA: String "NOWAIT" for hardware handshaking disable.
4EC2
DEFB 00H,00H 00 00
DATA: Null terminator and unused byte.
4EC4
DEFW 4DEEH EE 4D
DATA: Handler address 4DEEH - points to the NOWAIT mode handler.
4EC6
DEFB 00H 00
DATA: Table terminator (null byte indicating end of RS-232 keyword table).

4EC7H - Baud Rate Lookup Table

This table contains 16 entries of 2-byte clock divisor values corresponding to different baud rates. The entries represent: 50, 110, 150, 300, 600, 1200, 2400, 4800, 9600 baud and additional rates. Each entry is the clock divisor value that produces the desired baud rate when loaded into the RS-232 hardware.

4EC7
DEFW 4B00H 32 00 4B
DATA: Baud rate entry 0: divisor 4B00H (19200 decimal) - 50 baud.
4ECAH">
4ECA
DEFW 6E00H 00 6E
DATA: Baud rate entry 1: divisor 6E00H (28160 decimal) - 110 baud.
4ECCH">
4ECC
DEFW 8600H 00 86
DATA: Baud rate entry 2: divisor 8600H (34304 decimal) - 150 baud.
4ECEH">
4ECE
DEFW 9600H 00 96
DATA: Baud rate entry 3: divisor 9600H (38400 decimal) - 300 baud.
4ED0H">
4ED0
DEFW 012CH 2C 01
DATA: Baud rate entry 4: divisor 012CH (300 decimal) - 600 baud.
4ED2H">
4ED2
DEFW 0258H 58 02
DATA: Baud rate entry 5: divisor 0258H (600 decimal) - 1200 baud.
4ED4H">
4ED4
DEFW 04B0H B0 04
DATA: Baud rate entry 6: divisor 04B0H (1200 decimal) - 2400 baud.
4ED6H">
4ED6
DEFW 0708H 08 07
DATA: Baud rate entry 7: divisor 0708H (1800 decimal) - 4800 baud.
4ED8H">
4ED8
DEFW 07D0H D0 07
DATA: Baud rate entry 8: divisor 07D0H (2000 decimal) - 9600 baud.
4EDAH">
4EDA
DEFW 0960H 60 09
DATA: Baud rate entry 9: divisor 0960H (2400 decimal).
4EDCH">
4EDC
DEFW 0E10H 10 0E
DATA: Baud rate entry 10: divisor 0E10H (3600 decimal).
4EDEH">
4EDE
DEFW 12C0H C0 12
DATA: Baud rate entry 11: divisor 12C0H (4800 decimal).
4EE0H">
4EE0
DEFW 1C20H 20 1C
DATA: Baud rate entry 12: divisor 1C20H (7200 decimal).
4EE2H">
4EE2
DEFW 2580H 80 25
DATA: Baud rate entry 13: divisor 2580H (9600 decimal).
4EE4H">
4EE4
DEFW 4B00H 00 4B
DATA: Baud rate entry 14: divisor 4B00H (19200 decimal) - duplicate entry.
4EE6H">
4EE6
DEFB 4BH 4B
DATA: High byte of final entry (incomplete - only 1 byte instead of 2).

4EE7H - Keyword Parser Main Loop

This routine is the main keyword parsing engine. It searches the command line (pointed to by HL) for keywords defined in a table (pointed to by BC). For each keyword found, it extracts numeric parameters if required and calls the associated handler routine.

4EE7
LD D,03H 1603
Load Register D with 03H (retry counter for parsing attempts).
4EE9
GOSUB to 4F0FH to validate command line and skip to next keyword in table.
4EEC
PUSH BC C5
Save Register Pair BC (keyword table pointer) onto the stack.
4EED
EX (SP),HL E3
EXchange the 16-bit value at the top of the stack with Register Pair HL. The keyword table pointer is now in HL, the command line pointer is on the stack.
4EEE
LD A,(HL) 7E
Fetch the flags byte from the keyword table entry at (HL) into Register A.
4EEF
INC HL 23
INCrement Register Pair HL by 1 to point to the handler address low byte.
4EF0
LD E,(HL) 5E
Fetch the handler address low byte from (HL) into Register E.
4EF1
INC HL 23
INCrement Register Pair HL by 1 to point to the handler address high byte.
4EF2
LD D,(HL) 56
Fetch the handler address high byte from (HL) into Register D. Register Pair DE now contains the complete handler address.
4EF3
POP HL E1
Restore Register Pair HL (command line pointer) from the stack.
4EF4
PUSH DE D5
Save Register Pair DE (handler address) onto the stack. This will be used as a return address.
4EF5
BIT 7,A CB7F
Test bit 7 of Register A (the flags byte). If bit 7 is clear, the Z FLAG is set (invalid/end of table).
4EF7
RET Z C8
RETurn if the Z FLAG (Zero) has been set (meaning bit 7 is clear, reached end of keyword table or invalid entry). The RET pops the handler address from stack and jumps there.

Bit 7 is set, valid keyword entry. Check if numeric parameter is required.

4EF8
PUSH AF F5
Save Register Pair AF (flags byte) onto the stack.
4EF9
GOSUB to 4F26H to parse numeric parameter if required by the flags. Returns with value in DE.
4EFC
POP BC C1
Restore the flags byte from the stack into Register Pair BC (specifically into B).
4EFD
BIT 5,B CB68
Test bit 5 of Register B (the flags byte). Bit 5=1 indicates numeric parameter is required.
4EFF
If the Z FLAG (Zero) has been set (meaning bit 5 is clear, no numeric parameter required), JUMP to 4F05H to skip validation.
4F01
LD A,D 7A
Copy Register D (high byte of parsed value) into Register A for validation.
4F02
OR E B3
Perform OR operation between Register A and Register E. If both D and E are zero, the Z FLAG will be set.
4F03
If the Z FLAG (Zero) has been set (meaning no numeric value was provided but one was required), JUMP to 4F44H to trigger error 2FH (invalid parameter).
4F05
BIT 6,B CB70
Test bit 6 of Register B (the flags byte). Bit 6=1 indicates 16-bit parameter allowed.
4F07
RET NZ C0
RETurn if the NZ FLAG (Not Zero) has been set (meaning bit 6 is set, 16-bit value is valid). The RET jumps to the handler with DE containing the parameter.

Bit 6 is clear, only 8-bit parameters allowed. Validate that high byte is zero.

4F08
LD A,D 7A
Copy Register D (high byte of parameter) into Register A for validation.
4F09
OR A B7
Perform OR operation on Register A with itself to test if it's zero. The Z FLAG will be set if A = 00H.
4F0A
If the NZ FLAG (Not Zero) has been set (meaning D is non-zero, value exceeds 8 bits), JUMP to 4F44H to trigger error 2FH (parameter out of range).
4F0C
LD A,E 7B
Copy Register E (low byte of parameter, the valid 8-bit value) into Register A for the handler.
4F0E
RET C9
RETurn to the handler (address was pushed at 4EF4H) with the 8-bit parameter in Register A.

4F0FH - Skip to Next Keyword Table Entry

This routine advances the keyword table pointer (BC) to the next entry by skipping past the current keyword string.

4F0F
GOSUB to 4C6AH (command line parser in SYS0 or this module) to validate command line state. Returns with Z FLAG set if error condition.
4F12
RET Z C8
RETurn if the Z FLAG (Zero) has been set (meaning error condition or end of command line).
4F13
LD A,(BC) 0A
[STRING SKIP LOOP] Fetch the byte from the keyword table at (BC) into Register A.
4F14
OR A B7
Perform OR operation on Register A with itself to test if it's zero (null terminator). The Z FLAG will be set if A = 00H.
4F15
INC BC 03
INCrement Register Pair BC by 1 to point to the next byte.
4F16
[LOOP] If the NZ FLAG (Not Zero) has been set (meaning not yet at null terminator), LOOP BACK to 4F13H to continue skipping string bytes.

Found null terminator. Now skip past the flags byte and 16-bit handler address (3 bytes total).

4F18
LD E,D 5A
Copy Register D into Register E. Register D was loaded with 03H at 4EE7H, representing 3 bytes to skip.
4F19
INC BC 03
[METADATA SKIP LOOP] INCrement Register Pair BC by 1 to advance past metadata bytes.
4F1A
DEC E 1D
DECrement Register E by 1. If E becomes zero, the Z FLAG is set.
4F1B
[LOOP] If the NZ FLAG (Not Zero) has been set (meaning more metadata bytes to skip), LOOP BACK to 4F19H.
4F1D
LD A,(BC) 0A
Fetch the first byte of the next keyword entry from (BC) into Register A.
4F1E
OR A B7
Perform OR operation on Register A with itself to test if it's zero (end of table marker). The Z FLAG will be set if A = 00H.
4F1F
If the NZ FLAG (Not Zero) has been set (meaning another keyword entry exists), LOOP BACK to 4F0FH to process it.

Reached end of keyword table (found 00H byte). Trigger parse error.

4F21
LD A,34H 3E34
Load Register A with 34H, the error code for "parse error" (unrecognized keyword on command line).

4F23H - Error Handler - Display Error and Return to DOS Ready

This routine displays an error message by calling the SYS0 error handler at 4409H and returns to DOS Ready.

4F23
JUMP to SYS0 error handler at 4409H. This routine displays the error message corresponding to the error code in Register A, then returns to DOS Ready prompt.

4F26H - Parse Numeric Parameter from Command Line

This routine parses a numeric parameter from the command line. It handles both decimal and hexadecimal numbers (hexadecimal if followed by 'H'). Returns the 16-bit value in Register Pair DE.

4F26
PUSH HL E5
Save Register Pair HL (command line pointer) onto the stack.
4F27
LD B,00H 0600
Load Register B with 00H to initialize the number base flag (00H = decimal, 01H = hexadecimal).
4F29
GOSUB to 4F49H to parse the number starting at (HL) as decimal, returns 16-bit result in DE.
4F2C
LD A,(HL) 7E
Fetch the character following the parsed number from (HL) into Register A.
4F2D
SUB 41H D641
SUBtract 41H (ASCII 'A') from Register A. This converts 'A'-'H' to range 00H-07H.
4F2F
CP 08H FE08
Compare Register A against 08H. If A < 08H (was 'A'-'H'), the CARRY FLAG is set.
4F31
If the NO CARRY FLAG has been set (meaning A >= 08H, character was not 'A'-'H'), JUMP to 4F40H to validate decimal parse.

Found a letter 'A'-'H' after the number. Check if it's 'H' to indicate hexadecimal.

4F33
POP HL E1
Restore Register Pair HL (original command line pointer) from the stack.
4F34
LD B,01H 0601
Load Register B with 01H to set the hexadecimal parsing flag.
4F36
PUSH HL E5
Save Register Pair HL back onto the stack.
4F37
GOSUB to 4F49H again to re-parse the number as hexadecimal this time, returns result in DE.
4F3A
LD A,(HL) 7E
Fetch the character following the hex number from (HL) into Register A.
4F3B
CP 48H FE48
Compare Register A against 48H (ASCII 'H', hexadecimal suffix). If Register A equals 48H, the Z FLAG is set.
4F3D
INC HL 23
INCrement Register Pair HL by 1 to skip past the 'H' suffix character.
4F3E
If the NZ FLAG (Not Zero) has been set (meaning character was not 'H', invalid hex format), JUMP to 4F44H to trigger error 2FH.
4F40
BIT 1,B CB48
Test bit 1 of Register B. This bit is set by the number parsing routine at 4F62H to indicate at least one valid digit was parsed. If bit 1 is clear, the Z FLAG is set.
4F42
POP BC C1
Restore Register Pair BC from the stack (this was the saved HL command line pointer).
4F43
RET NZ C0
RETurn if the NZ FLAG (Not Zero) has been set (meaning bit 1 is set, at least one digit was successfully parsed). DE contains the parsed numeric value.

4F44H - Invalid Parameter Error

This routine triggers error 2FH for invalid parameter format or value.

4F44
LD A,2FH 3E2F
Load Register A with 2FH, the error code for "invalid parameter" (bad format, out of range, or missing required value).
4F46
JUMP to SYS0 error handler at 4409H to display error 2FH and return to DOS Ready.

4F49H - Parse Multi-Digit Number (Decimal or Hexadecimal)

This routine parses a multi-digit number from the command line at (HL). The base is determined by Register B: if bit 0 of B is clear, parse as decimal (base 10); if bit 0 is set, parse as hexadecimal (base 16). Returns the 16-bit result in Register Pair DE. Sets bit 1 of B if at least one valid digit was parsed.

4F49
LD DE,0000H 110000
Load Register Pair DE with 0000H to initialize the accumulated numeric result to zero.
4F4C
LD A,(HL) 7E
[DIGIT PARSE LOOP START] Fetch the current character from the command line at (HL) into Register A.
4F4D
SUB 30H D630
SUBtract 30H (ASCII '0') from Register A. This converts ASCII digits '0'-'9' to binary values 0-9. If the character was less than '0', the result is negative (CARRY FLAG set).
4F4F
CP 0AH FE0A
Compare Register A against 0AH (10 decimal). If A < 0AH (was digit '0'-'9'), the CARRY FLAG is set.
4F51
If the CARRY FLAG has been set (meaning A is 00H-09H, valid decimal digit), JUMP to 4F5DH to accumulate this digit.

Character is not a decimal digit. Check if we're parsing hexadecimal and if it's 'A'-'F'.

4F53
BIT 0,B CB40
Test bit 0 of Register B (the base flag). If bit 0 is clear (decimal mode), the Z FLAG is set.
4F55
RET Z C8
RETurn if the Z FLAG (Zero) has been set (meaning decimal mode and character is not a digit, end of number). DE contains the accumulated value.
4F56
SUB 11H D611
SUBtract 11H from Register A. After the earlier SUB 30H, 'A' (41H) became 11H, so this converts 'A'-'F' (11H-16H) to 00H-05H.
4F58
CP 06H FE06
Compare Register A against 06H. If A < 06H (was 'A'-'F'), the CARRY FLAG is set.
4F5A
RET NC D0
RETurn if the NO CARRY FLAG has been set (meaning A >= 06H, character was not a valid hex digit). DE contains the accumulated value.
4F5C
ADD 0AH C60A
ADD 0AH (10 decimal) to Register A. This converts the 00H-05H values (from 'A'-'F') to 0AH-0FH (10-15 decimal).

Register A now contains a valid digit value (0-9 for decimal, 0-15 for hexadecimal). Accumulate it into DE.

4F5D
PUSH HL E5
Save Register Pair HL (command line pointer) onto the stack.
4F5E
LD H,D 62
Copy Register D into Register H.
4F5F
LD L,E 6B
Copy Register E into Register L. Register Pair HL now contains the accumulated value from DE.
4F60
LD C,A 4F
Copy Register A (the new digit value) into Register C for safekeeping during multiplication.
4F61
XOR A AF
Set Register A to ZERO by XORing it with itself. This will be used to accumulate overflow bits during the shift operations.
4F62
SET 1,B CBC8
SET bit 1 of Register B. This marks that at least one valid digit has been parsed.

Multiply the accumulated value (HL) by the base (10 or 16). For base 10: multiply by 2, then by 2 again (×4), then add original (×5), then by 2 (×10). For base 16: multiply by 2 four times (×16).

4F64
ADD HL,HL 29
ADD Register Pair HL to itself (shift left 1 bit = multiply by 2). If overflow occurs, the CARRY FLAG is set.
4F65
ADC A,A 8F
ADd with Carry: add Register A to itself plus the CARRY FLAG. This captures overflow bits from the HL shift.
4F66
ADD HL,HL 29
ADD Register Pair HL to itself again (shift left 1 bit = multiply by 2, total ×4). If overflow occurs, the CARRY FLAG is set.
4F67
ADC A,A 8F
ADd with Carry: add Register A to itself plus the CARRY FLAG. This captures overflow bits.
4F68
BIT 0,B CB40
Test bit 0 of Register B (the base flag). If bit 0 is clear (decimal mode), the Z FLAG is set.
4F6A
If the Z FLAG (Zero) has been set (meaning decimal mode, base 10), JUMP to 4F6FH to continue with decimal multiplication.

Hexadecimal mode (base 16): multiply by 2 two more times to get ×16 total.

4F6C
ADD HL,HL 29
ADD Register Pair HL to itself (shift left 1 bit = multiply by 2, total ×8). If overflow occurs, the CARRY FLAG is set.
4F6D
JUMP (unconditionally) to 4F70H to perform the final shift for ×16.

Decimal mode (base 10): add original value to get ×5, then multiply by 2 to get ×10.

4F6F
ADD HL,DE 19
ADD Register Pair DE (original value) to Register Pair HL (which is ×4). HL is now ×5 the original. If overflow occurs, the CARRY FLAG is set.
4F70
ADC A,A 8F
ADd with Carry: add Register A to itself plus the CARRY FLAG. This captures overflow bits.
4F71
ADD HL,HL 29
ADD Register Pair HL to itself (shift left 1 bit = multiply by 2). For decimal: ×5 becomes ×10. For hex: ×8 becomes ×16. If overflow occurs, the CARRY FLAG is set.
4F72
ADC A,A 8F
ADd with Carry: add Register A to itself plus the CARRY FLAG. This captures final overflow bits.

HL now contains the accumulated value multiplied by the base. Add the new digit value.

4F73
LD E,C 59
Copy Register C (the new digit value) into Register E.
4F74
LD D,00H 1600
Load Register D with 00H. Register Pair DE now contains the 16-bit digit value (00nn).
4F76
ADD HL,DE 19
ADD Register Pair DE (the new digit) to Register Pair HL (accumulated value × base). If overflow occurs, the CARRY FLAG is set.
4F77
ADC A,A 8F
ADd with Carry: add Register A to itself plus the CARRY FLAG. Register A now contains any overflow beyond 16 bits.
4F78
EX DE,HL EB
EXchange Register Pairs DE and HL. The new accumulated value is now in DE (the return register for the result).
4F79
POP HL E1
Restore Register Pair HL (command line pointer) from the stack.
4F7A
If the NZ FLAG (Not Zero) has been set (meaning Register A is non-zero, overflow occurred beyond 16 bits), JUMP to 4F44H to trigger error 2FH (number too large).
4F7C
INC HL 23
INCrement Register Pair HL by 1 to point to the next character on the command line.
4F7D
[LOOP] JUMP (unconditionally) BACK to 4F4CH to parse the next digit.

4F7FH - Display Null-Terminated String with Optional Comma Separator

This routine displays a null-terminated string at (HL). Before displaying the string, it checks a self-modifying code location at 4F81H to determine if a comma separator should be displayed first. After the first string is displayed, it modifies the code at 4F81H to display commas before subsequent strings.

4F7F
XOR A AF
Set Register A to ZERO by XORing it with itself. This prepares for the OR test.
4F80
OR 00H F600
Perform OR operation between Register A and 00H. This is self-modifying code - the operand byte at 4F81H is changed by instruction at 4F87H. First time: OR 00H (Z flag set). Subsequent times: OR 2CH (NZ flag set).
4F82
If the NZ FLAG (Not Zero) has been set (meaning operand at 4F81H is 2CH, not first string), GOSUB to 4FCBH to display a comma separator character first.
4F85
LD A,2CH 3E2C
Load Register A with 2CH (ASCII comma ',').
4F87
LD (4F81H),A 32814F
Store Register A (2CH) into memory location 4F81H. This modifies the operand of the OR instruction at 4F80H so that future calls to this routine will display a comma first.
4F8A
LD A,(HL) 7E
[STRING DISPLAY LOOP] Fetch the current character from the string at (HL) into Register A.
4F8B
OR A B7
Perform OR operation on Register A with itself to test if it's zero (null terminator). The Z FLAG will be set if A = 00H.
4F8C
INC HL 23
INCrement Register Pair HL by 1 to point to the next character.
4F8D
RET Z C8
RETurn if the Z FLAG (Zero) has been set (meaning null terminator reached, string display complete).
4F8E
GOSUB to 4FCBH to display the character in Register A.
4F91
[LOOP] JUMP (unconditionally) BACK to 4F8AH to display the next character.

4F93H - Display String with Decimal Value (8-bit)

This routine displays a null-terminated string at (HL) followed by an 8-bit decimal value from Register A. Entry point for displaying "KEYWORD=value" format.

4F93
LD E,A 5F
Copy Register A (the 8-bit value to display) into Register E.

4F94H - Display String with Decimal Value (16-bit from E)

This routine displays a null-terminated string at (HL) followed by a decimal value from Register E (extended to 16-bit in DE).

4F94
LD D,00H 1600
Load Register D with 00H. Register Pair DE now contains the 16-bit value to display (00nn where nn is from E).

4F96H - Display String with Decimal Value (16-bit from DE)

This routine displays a null-terminated string at (HL) followed by a 16-bit decimal value from Register Pair DE.

4F96
GOSUB to 4F7FH to display the null-terminated string at (HL) with optional comma separator.

Now convert the 16-bit value in DE to decimal ASCII and display it.

4F99
LD BC,0400H 010004
Load Register Pair BC with 0400H. B=04H is the number of decimal divisors to process (10000, 1000, 100, 10). C=00H is the leading zero suppression flag.
4F9C
LD HL,4FC3H 21C34F
Point Register Pair HL to 4FC3H, the start of the decimal divisor table.
4F9F
PUSH BC C5
[DIVISOR LOOP START] Save Register Pair BC (loop counter and leading zero flag) onto the stack.
4FA0
LD C,(HL) 4E
Fetch the low byte of the divisor from (HL) into Register C.
4FA1
INC HL 23
INCrement Register Pair HL by 1 to point to the high byte.
4FA2
LD B,(HL) 46
Fetch the high byte of the divisor from (HL) into Register B. Register Pair BC now contains the divisor.
4FA3
INC HL 23
INCrement Register Pair HL by 1 to point to the next divisor entry.
4FA4
EX DE,HL EB
EXchange Register Pairs DE and HL. The value to convert is now in HL, the divisor table pointer is in DE.
4FA5
LD A,2FH 3E2F
Load Register A with 2FH (ASCII '/' which is one less than '0'). This will be incremented to count divisions.
4FA7
INC A 3C
[DIVISION LOOP] INCrement Register A by 1. This counts how many times we can subtract the divisor.
4FA8
ADD HL,BC 09
ADD Register Pair BC (the divisor) to Register Pair HL. Wait, this should be subtract. This is adding to perform repeated subtraction by two's complement. Actually this appears to be a subtract loop using addition with negative numbers.
4FA9
[LOOP] If the CARRY FLAG has been set (meaning the addition wrapped around, indicating we can subtract more), LOOP BACK to 4FA7H.
4FAB
SBC HL,BC ED42
SuBtract with Carry: subtract BC from HL. This corrects for the last addition that caused overflow.
4FAD
POP BC C1
Restore Register Pair BC (loop counter in B, leading zero flag in C) from the stack.
4FAE
EX DE,HL EB
EXchange Register Pairs DE and HL. The remainder is now in DE, the divisor table pointer is back in HL.
4FAF
CP 30H FE30
Compare Register A against 30H (ASCII '0'). If Register A equals 30H (digit is zero), the Z FLAG is set.
4FB1
If the NZ FLAG (Not Zero) has been set (meaning digit is '1'-'9', not zero), JUMP to 4FB7H to display it.

Digit is '0'. Check leading zero suppression flag.

4FB3
INC C 0C
INCrement Register C (leading zero flag). If C was 00H, it becomes 01H.
4FB4
DEC C 0D
DECrement Register C back to its original value. This tests if C was zero without changing it permanently.
4FB5
If the Z FLAG (Zero) has been set (meaning C was 00H, still suppressing leading zeros), JUMP to 4FBBH to skip displaying this zero.
4FB7
INC C 0C
INCrement Register C to mark that we're no longer suppressing leading zeros (a non-zero digit has been encountered).
4FB8
GOSUB to 4FCBH to display the ASCII digit character in Register A.
4FBB
DJNZ 4F9FH 10E2
[LOOP] DECrement Register B and Jump if Not Zero. If B is not zero (more divisors to process), LOOP BACK to 4F9FH to process the next divisor.

All divisors (10000, 1000, 100, 10) processed. Display the final units digit (0-9).

4FBD
LD A,E 7B
Copy Register E (the remainder after all divisions, which is the units digit 0-9) into Register A for display.
4FBE
ADD 30H C630
ADD 30H (ASCII '0') to Register A. This converts the binary digit 0-9 to ASCII character '0'-'9'.
4FC0
JUMP to 4FCBH to display the units digit character and return to caller.

4FC3H - Decimal Divisor Lookup Table

This table contains four 16-bit divisor values used for decimal conversion: 10000, 1000, 100, 10. Each entry is stored in little-endian format (low byte first, high byte second).

4FC3
DEFW 2710H 10 27
DATA: Divisor 2710H (10000 decimal) - for extracting ten-thousands digit.
4FC5H">
4FC5
DEFW 03E8H E8 03
DATA: Divisor 03E8H (1000 decimal) - for extracting thousands digit.
4FC7H">
4FC7
DEFW 0064H 64 00
DATA: Divisor 0064H (100 decimal) - for extracting hundreds digit.
4FC9H">
4FC9
DEFW 000AH 0A 00
DATA: Divisor 000AH (10 decimal) - for extracting tens digit.

4FCBH - Display Single Character via ROM

This routine displays a single character by calling the ROM character output routine at 0033H. It preserves DE and AF registers across the call.

4FCB
PUSH DE D5
Save Register Pair DE onto the stack to preserve it across the ROM call.
4FCC
PUSH AF F5
Save Register Pair AF onto the stack to preserve it across the ROM call.
4FCD
GOSUB to ROM routine at 0033H to display the character in Register A at the current cursor position and advance the cursor.
4FD0
POP AF F1
Restore Register Pair AF from the stack.
4FD1
POP DE D1
Restore Register Pair DE from the stack.
4FD2
RET C9
RETurn to caller. The character has been displayed.

4FD3H - Unused Space / Padding

This section contains 533 bytes of unused space filled with 00H (NOP instructions). This padding extends from 4FD3H through 51E7H, bringing the module to its allocated size boundary.

4FD3-51E7
DEFB 00H (×533) 00 00 00...
DATA: Unused space - 533 bytes of 00H (NOP instructions). This padding ensures the module occupies its full allocated space in the NEWDOS/80 system file structure.