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

Page Customization

Introduction/Summary

NEWDOS/80 v2.0 SYS15/SYS Disassembly - FORMS and SETCOM (Model III)

SYS15/SYS holds two library commands: FORMS, which sets the printer's line width and page length, and SETCOM, which sets the RS-232 interface. Both always show the values in force when they end. Its five load records fill 4D00H-51E7H of the overlay area (1,256 bytes) and its transfer address is 4D00H; the code ends at 4FD2H and 4FD3H-51E7H are 00H.

The page shows every byte of the file once, in address order.

Commands

SYS1/SYS's command table gives both commands the RST 28H code F1H (function 7 of directory slot 11H) with a sub-function in Register C; any other code or sub-function gives error 2AH.

Sub-FunctionCommand
1FORMS[,WIDTH=w][,LINES=l], 4D11H
2SETCOM[,OFF][,WORD=w][,BAUD=b][,STOP=s][,PARITY=p][,WAIT][,NOWAIT], 4D70H

Both commands look their options up in a table (word, 00H, attribute byte, handler address) through 4EE7H, which reads the option's number when attribute bit 7 is set (bit 6: 16 bits, else 0-255; bit 5: not 0) and RETURNs into the handler. Numbers are decimal, or hexadecimal ended by H. A bad number is error 2FH (BAD PARAMETER(S)); an unknown option or a bad separator is error 34H (ILLEGAL KEYWORD OR SEPARATOR OR TERMINATOR). The values are shown as WORD=value items separated by commas through 4F7FH.

FORMS works on the printer control block 4025H-402CH: WIDTH (1-255) goes to 402BH, the most characters per line (255 means no limit to the ROM's printer driver), and 402AH, the characters printed on the line, is cleared; LINES (1-254; 255 keeps the current value) goes to 4028H as the lines per page plus 1, and 4029H, the lines printed, is cleared. FORMS shows WIDTH= and LINES= from 402BH and 4028H.

RS-232 Settings

SETCOM keeps the settings where the ROM's RS-232 initialization (005AH, through the control block at 41F5H) reads them: 41F8H the baud rate code (bits 7-4 sending, bits 3-0 receiving; SETCOM always sets both to the same code), 41F9H the configuration byte for the UART control port EAH, and 41FAH the wait switch. The options change copies of these in SYS15/SYS's own operands (4DF9H, 4DFAH and 4E02H); the result, with bits 1-0 cleared and bit 2 set in the configuration byte, is stored and the interface initialized (4E7EH). OFF, or a configuration byte of 00H when the state is shown, stores 0000H at 41F8H-41F9H and FFH at 41FAH and initializes the interface off (4E79H); the earlier settings are not kept.

OptionEffect on the settings
WORD=5-8Configuration bits 6-5: 00 for 5, 10 for 6, 01 for 7, 11 for 8 bits (a value of 9-13 also passes the check and sets other bits)
BAUD=One of 50, 75, 110, 134, 150, 300, 600, 1200, 1800, 2000, 2400, 3600, 4800, 7200, 9600, 19200 (codes 0-15, table 4EC7H)
STOP=1 or 2Configuration bit 4: set for two stop bits
PARITY=1, 2 or 3Odd (bit 3 clear, bit 7 clear), even (bit 3 clear, bit 7 set), none (bit 3 set)
WAIT, NOWAITWait switch FFH or 00H
OFFMust be the only option; turns the interface off

Variables

Memory Outside SYS15/SYS

Address
Size
Contents
4028H
1 byte
Printer Lines per Page
The printer control block's +3, the lines per page plus 1 (4D2AH, 4D3DH, 4D4FH).
4029H
1 byte
Printer Line Count
The printer control block's +4, the lines printed; set to 00H with a new page length (4D3DH).
402AH
1 byte
Printer Character Count
The printer control block's +5, the characters printed on the line; set to 00H by FORMS with options (4D43H).
402BH
1 byte
Printer Width
The printer control block's +6, the most characters per line, 255 for no limit (4D16H, 4D43H, 4D46H).
41F8H
1 byte
RS-232 Baud Rate Code
Bits 7-4 the sending rate, bits 3-0 the receiving rate, codes 0-15 (4D76H, 4E30H, 4E7EH).
41F9H
1 byte
RS-232 Configuration
The byte the ROM sends to the UART control port EAH: bit 7 even parity, bits 6-5 word length, bit 4 two stop bits, bit 3 no parity, bit 2 break, bits 1-0 RTS and DTR; 00H when off (4D76H, 4E0FH, 4E7EH).
41FAH
1 byte
RS-232 Wait Switch
Not 00H for WAIT, 00H for NOWAIT as SETCOM shows it (4D7EH, 4E6BH, 4E81H).

SYS15/SYS Tables

Address
Size
Contents
4D5BH-4D6FH
21 bytes
FORMS Option Table
WIDTH= and LINES=, also the texts shown.
4E87H-4EC6H
64 bytes
SETCOM Option Table
OFF, WORD=, BAUD=, STOP=, PARITY=, WAIT and NOWAIT, also the texts shown.
4EC7H-4EE6H
32 bytes
Baud Rate Table
The 16 rates in the order of their codes.
4FC3H-4FCAH
8 bytes
Powers of Ten
Minus 10000, 1000, 100 and 10 for the decimal display.

Operands Changed at Run Time

Address
Size
Contents
4D37H
1 byte
Page Length Plus 1
The operand of LD HL at 4D36H: 00H in the file (no LINES=), stored at 4D2DH.
4D42H
1 byte
Width
The operand of LD HL at 4D40H: stored at 4D19H (the current width) and 4D22H (WIDTH=).
4DF9H
1 byte
Baud Rate Code
The operand of LD HL at 4DF8H (Register L): copied from 41F8H at 4D7AH, changed by BAUD= at 4DBEH.
4DFAH
1 byte
Configuration
The operand of LD HL at 4DF8H (Register H): copied from 41F9H at 4D7AH, changed by WORD=, STOP= and PARITY=.
4E02H
1 byte
Wait Switch
The operand of LD A at 4E01H: copied from 41FAH at 4D81H, changed by WAIT and NOWAIT at 4DEFH.
4F81H
1 byte
Separator
The operand of OR at 4F80H: 00H in the file, 2CH (a comma) after the first item is shown (4F87H).

Outside Routines and Addresses

AddressContents
0033HROM: display a character (4FCDH).
005AHROM: initialize the RS-232 interface from the control block 41F5H (4E84H).
4409HSYS0/SYS: the DOS error exit (4F23H, 4F46H).
4C6AH, 4C7AHSYS0/SYS: compare a word (4F0FH), test for the end of the line or a separator (4D30H, 4DF2H, 4E08H).

Disassembly

4D00H - Function Dispatcher

SYS15/SYS (directory slot 11H) is loaded by the SYS0/SYS RST 28H dispatcher (4B67H) into 4D00H-51E7H and entered at 4D00H by the CALL at 4BC2H, with Register A = the RST 28H code, Register C = the sub-function, Register Pair HL = the command line after the command word, and 4BC5H (the dispatcher's tail) on top of the stack. The only code it accepts is F1H (function 7 of slot 11H), which SYS1/SYS's command table gives to FORMS (sub-function 1) and SETCOM (sub-function 2).

4D00
CP F1H FE F1
Compare Register A, the RST 28H code, against F1H, function 7 of directory slot 11H (SYS15/SYS). The Z FLAG is set if Register A = F1H.
4D02
If the NZ FLAG is set (Register A holds another code), JUMP to 4D0CH for error 2AH (ILLEGAL DOS FUNCTION).
4D04
DEC C 0D
DECrement Register C, the sub-function from SYS1/SYS's command table. The Z FLAG is set if Register C was 1 (FORMS).
4D05
If the Z FLAG is set (sub-function 1, the FORMS command), JUMP to 4D11H.
4D08
DEC C 0D
DECrement Register C, the sub-function. The Z FLAG is set if Register C was 2 (SETCOM).
4D09
If the Z FLAG is set (sub-function 2, the SETCOM command), JUMP to 4D70H.
4D0C
LD A,2AH 3E 2A
Load Register A with 2AH, the DOS error code ILLEGAL DOS FUNCTION, for any other code or sub-function. 4D02H comes here.
4D0E
JUMP to 4F23H, which leaves through the SYS0/SYS error exit 4409H with the error code in Register A.

4D11H - FORMS Command

FORMS[,WIDTH=w][,LINES=l] sets the printer's line width and page length in the printer control block at 4025H and always shows them. WIDTH and LINES must be 1-255; WIDTH goes to 402BH (the printer control block's +6, the most characters per line; 255 means no limit to the ROM's printer driver); LINES plus 1 goes to 4028H (+3), the line counter at 4029H (+4) and the character counter at 402AH (+5) are set to 00H; LINES=255 keeps the page length. The options store their values straight into the operands 4D42H and 4D37H.

4D11
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the first character of the command line after FORMS.
4D12
CP 0DH FE 0D
Compare Register A against 0DH, the carriage return that ends the command line. The Z FLAG is set for FORMS alone.
4D14
If the Z FLAG is set (no options), JUMP to 4D46H to show the current values only.
4D16
LD A,(402BH) 3A 2B 40
Load Register A with the byte at 402BH, the printer control block's +6: the current line width (the most characters per line).
4D19
LD (4D42H),A 32 42 4D
Self-Modifying Code
Store Register A (the current width) at 4D42H, the operand of the LD HL,0000H at 4D40H, so that the width is written back unchanged when no WIDTH= is given.

Option Loop
Register Pair HL = the command line at the next option.

4D1C
LD BC,4D5BH 01 5B 4D
Load Register Pair BC with 4D5BH, FORMS's option table: WIDTH= and LINES=. 4D34H comes back here.
4D1F
JUMP to 4EE7H, which looks the option at Register Pair HL up in the table at Register Pair BC, reads its number and jumps to its handler (4D22H or 4D27H) with the number in Register A and the command line pointer past it in Register Pair HL.
4D22
LD (4D42H),A 32 42 4D
WIDTH= (from 4EE7H with Register A = the width, 1-255): Self-Modifying Code
Store Register A at 4D42H, the operand of the LD HL,0000H at 4D40H.
4D25
JUMP to 4D30H to look at the separator after the number.
4D27
INC A 3C
LINES= (from 4EE7H with Register A = the lines per page, 1-255): INCrement Register A to the value the printer control block keeps at 4028H, the lines plus 1. The Z FLAG is set if the value was 255.
4D28
If the NZ FLAG is set (1-254), JUMP to 4D2DH to store it.
4D2A
LD A,(4028H) 3A 28 40
LINES=255: load Register A with the byte at 4028H, the printer control block's +3, the current page length plus 1, which is kept.
4D2D
LD (4D37H),A 32 37 4D
Self-Modifying Code
Store Register A (the page length plus 1) at 4D37H, the operand of the LD HL,0000H at 4D36H. 4D28H comes here.
4D30
GOSUB to SYS0/SYS 4C7AH, which looks at the character at Register Pair HL: the Z FLAG at the carriage return; a comma or spaces give the NZ FLAG with Register Pair HL past them; anything else gives the CARRY FLAG with Register A = 34H. 4D25H comes here.
4D33
RET C D8
If the CARRY FLAG is set (not a separator), RETURN to the dispatcher's tail 4BC5H with Register A = 34H (ILLEGAL KEYWORD OR SEPARATOR OR TERMINATOR).
4D34
If the NZ FLAG is set (another option follows), LOOP BACK to 4D1CH.
4D36
LD HL,0000H 21 00 00
Self-Modifying Code
Load Register Pair HL with 0000H in the file: the page length plus 1 in Register L (the operand 4D37H, 00H in the file, stored at 4D2DH) and 00H in Register H.
4D39
LD A,L 7D
Load Register A with Register L, the page length plus 1 (00H if no LINES= was given).
4D3A
OR A B7
OR Register A with itself to set the flags: the Z FLAG is set if no LINES= was given.
4D3B
If the Z FLAG is set (no LINES=), JUMP to 4D40H, leaving 4028H and 4029H unchanged.
4D3D
LD (4028H),HL 22 28 40
Store Register Pair HL at 4028H-4029H: Register L (the page length plus 1) at 4028H, the printer control block's +3, and Register H (00H) at 4029H, its +4, the count of lines printed.
4D40
LD HL,0000H 21 00 00
Self-Modifying Code
Load Register Pair HL with 0000H in the file: the width in Register L (the operand 4D42H, stored at 4D19H and by WIDTH= at 4D22H) and 00H in Register H. 4D3BH comes here.
4D43
LD (402AH),HL 22 2A 40
Store Register Pair HL at 402AH-402BH: Register H (00H) at 402AH, the printer control block's +5, the characters printed on the line, and Register L (the width) at 402BH, its +6.
4D46
LD A,(402BH) 3A 2B 40
Load Register A with the byte at 402BH, the printer control block's +6: the line width. 4D14H comes here.
4D49
LD HL,4D5BH 21 5B 4D
Point Register Pair HL to 4D5BH, the text WIDTH= (the first word of the option table).
4D4C
GOSUB to 4F93H, which shows the text at Register Pair HL (WIDTH=) and the number in Register A in decimal.
4D4F
LD A,(4028H) 3A 28 40
Load Register A with the byte at 4028H, the printer control block's +3: the page length plus 1.
4D52
LD HL,4D65H 21 65 4D
Point Register Pair HL to 4D65H, the text LINES= (the second word of the option table).
4D55
DEC A 3D
DECrement Register A, the page length plus 1 from 4028H: Register A = the lines per page.
4D56
GOSUB to 4F93H, which shows a comma, the text at Register Pair HL (LINES=) and the number in Register A in decimal.
4D59
XOR A AF
Load Register A with 00H (XOR A with itself), which also sets the Z FLAG: no error.
4D5A
RET C9
RETURN to the dispatcher's tail 4BC5H with Register A = 00H, no error.

4D5BH - FORMS Option Table (Data)

Read by 4EE7H from 4D1CH. Each entry: the option word with its = sign, 00H, an attribute byte and the handler's address. Attribute bits: 7 a number follows, 6 the number is 16 bits (else 0-255), 5 the number must not be 0. The words are also the texts shown by 4D49H and 4D52H.

4D5B-4D64
DEFM "WIDTH=" / DEFB 00H, A0H / DEFW 4D22H 57 49 44 54 48 3D 00 A0 22 4D
Option WIDTH=: attribute A0H (a number 1-255), handler 4D22H.
4D65-4D6E
DEFM "LINES=" / DEFB 00H, A0H / DEFW 4D27H 4C 49 4E 45 53 3D 00 A0 27 4D
Option LINES=: attribute A0H (a number 1-255), handler 4D27H.
4D6F
DEFB 00H 00
The 00H that ends FORMS's option table (4F1DH).

4D70H - SETCOM Command

SETCOM[,OFF][,WORD=w][,BAUD=b][,STOP=s][,PARITY=p][,WAIT][,NOWAIT] sets the RS-232 interface through the ROM's initialization routine 005AH and always shows its state. The ROM keeps the settings in the RS-232 initialization control block 41F5H-41FCH: 41F8H the baud rate code (bits 7-4 sending, 3-0 receiving), 41F9H the configuration byte the ROM sends to the UART control port EAH (bit 7 even parity, bits 6-5 word length, bit 4 two stop bits, bit 3 no parity, bit 2 break, bits 1-0 RTS and DTR; 00H means the interface is off), 41FAH the wait switch (not 00H = wait, 00H = no wait in this command's handling). The current values are copied into the operands 4DF9H, 4DFAH and 4E02H, each option changes them, and the result is stored and the interface initialized. OFF stores 0000H and FFH instead, which turns the interface off.

4D70
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the first character of the command line after SETCOM.
4D71
CP 0DH FE 0D
Compare Register A against 0DH, the carriage return that ends the command line. The Z FLAG is set for SETCOM alone.
4D73
If the Z FLAG is set (no options), JUMP to 4E0FH to show the current state only.
4D76
LD DE,(41F8H) ED 5B F8 41
Load Register Pair DE with the word at 41F8H: Register E = the baud rate code at 41F8H, Register D = the configuration byte at 41F9H.
4D7A
LD (4DF9H),DE ED 53 F9 4D
Self-Modifying Code
Store Register Pair DE at 4DF9H-4DFAH, the operand of the LD HL,0000H at 4DF8H: Register L will be the baud rate code and Register H the configuration byte, changed by the options.
4D7E
LD A,(41FAH) 3A FA 41
Load Register A with the byte at 41FAH, the RS-232 wait switch.
4D81
LD (4E02H),A 32 02 4E
Self-Modifying Code
Store Register A (the wait switch) at 4E02H, the operand of the LD A,00H at 4E01H, changed by WAIT and NOWAIT.

Option Loop
Register Pair HL = the command line at the next option.

4D84
LD BC,4E87H 01 87 4E
Load Register Pair BC with 4E87H, SETCOM's option table: OFF, WORD=, BAUD=, STOP=, PARITY=, WAIT and NOWAIT. 4DF6H comes back here.
4D87
JUMP to 4EE7H, which looks the option at Register Pair HL up in the table at Register Pair BC, reads its number if it takes one, and jumps to its handler with the number in Register A (or Register Pair DE for BAUD=).
4D8A
SUB 05H D6 05
WORD= (from 4EE7H with Register A = the bits per character): SUBtract 05H from Register A, so that 5, 6, 7 and 8 become 0, 1, 2 and 3.
4D8C
CP 09H FE 09
Compare Register A against 09H. The NO CARRY FLAG is set for 9 or more, which a word length below 5 (borrowed past 00H) or above 13 gives.
4D8E
If the NO CARRY FLAG is set, JUMP to 4F44H for error 2FH (BAD PARAMETER(S)). A word length of 9-13 passes this check and sets other configuration bits below.
4D91
OR A B7
OR Register A with itself to set the PARITY FLAG: P/V is set (PE) when Register A has an even number of 1 bits (0 for 5 bits, 3 for 8 bits).
4D92
If the PE FLAG is set (Register A = 0 or 3), JUMP to 4D97H: 5 bits and 8 bits keep their code.
4D95
XOR 03H EE 03
XOR Register A with 03H: 1 (6 bits) becomes 2, and 2 (7 bits) becomes 1, the order the UART's two word length bits use.
4D97
RRCA 0F
Rotate Register A right (RRCA): bit 0 of the word length code goes to bit 7. 4D92H comes here.
4D98
RRCA 0F
Rotate Register A right (RRCA) again: bit 0 of the code is now at bit 6.
4D99
RRCA 0F
Rotate Register A right (RRCA) a third time: the code is now in bits 5 and 6, the UART's word length bits (5 bits 00H, 6 bits 40H, 7 bits 20H, 8 bits 60H).
4D9A
LD C,A 4F
Load Register C with Register A, the word length bits.
4D9B
PUSH HL E5
Save Register Pair HL (the command line) onto the stack; 4DE7H takes it back.
4D9C
LD HL,4DFAH 21 FA 4D
Point Register Pair HL to 4DFAH, the configuration byte in the operand of the LD HL at 4DF8H.
4D9F
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the configuration byte.
4DA0
AND 9FH E6 9F
AND Register A with 9FH, clearing bits 6 and 5, the old word length.
4DA2
OR C B1
OR Register A with Register C, putting in the new word length bits.
4DA3
LD (HL),A 77
Store Register A at Register Pair HL (4DFAH), the new configuration byte.
4DA4
JUMP to 4DE7H to take the command line back and look at the next separator.
4DA6
PUSH HL E5
BAUD= (from 4EE7H with Register Pair DE = the baud rate): save Register Pair HL (the command line) onto the stack; 4DE7H takes it back.
4DA7
LD HL,4EC7H 21 C7 4E
Point Register Pair HL to 4EC7H, the table of the 16 baud rates in the order of their codes 0-15.
4DAA
XOR A AF
Load Register A with 00H (XOR A with itself), the code for the first rate in both nibbles.

Baud Rate Search
Register Pair HL = the table entry, Register A = its code in both nibbles.

4DAB
LD C,(HL) 4E
Load Register C with the byte at Register Pair HL, the low byte of the table's rate. 4DB9H comes back here.
4DAC
INC HL 23
INCrement Register Pair HL to the high byte of the table's rate.
4DAD
LD B,(HL) 46
Load Register B with the byte at Register Pair HL: Register Pair BC = the table's rate.
4DAE
INC HL 23
INCrement Register Pair HL to the next rate in the table.
4DAF
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the rate asked for, Register Pair DE = the table pointer.
4DB0
OR A B7
OR Register A with itself, which clears the CARRY FLAG for the SBC (Register A, the code, is not changed).
4DB1
SBC HL,BC ED 42
SUBtract Register Pair BC (the table's rate) from Register Pair HL (the rate asked for) with the CARRY FLAG: the Z FLAG is set if they are equal.
4DB3
ADD HL,BC 09
ADD Register Pair BC back to Register Pair HL, restoring the rate asked for. ADD HL,BC does not change the Z FLAG.
4DB4
EX DE,HL EB
Exchange Register Pairs DE and HL back: Register Pair DE = the rate asked for, Register Pair HL = the table pointer.
4DB5
If the Z FLAG is set (the rate is in the table), JUMP to 4DBEH with its code in Register A.
4DB7
ADD A,11H C6 11
ADD 11H to Register A: the next code, in both nibbles (00H, 11H, 22H ... FFH). The CARRY FLAG is set after the sixteenth rate.
4DB9
If the NO CARRY FLAG is set (rates left), LOOP BACK to 4DABH.
4DBB
JUMP to 4F44H for error 2FH (BAD PARAMETER(S)): the rate is not one of the 16. The STOP= and PARITY= handlers also come here from 4DE5H.
4DBE
LD (4DF9H),A 32 F9 4D
Self-Modifying Code
Store Register A (the code, the same in the sending and receiving nibbles) at 4DF9H, the baud rate code in the operand of the LD HL at 4DF8H. 4DB5H comes here.
4DC1
JUMP to 4DE7H to take the command line back and look at the next separator.
4DC3
PUSH HL E5
STOP= (from 4EE7H with Register A = the stop bits): save Register Pair HL (the command line) onto the stack; 4DE7H takes it back.
4DC4
LD HL,4DFAH 21 FA 4D
Point Register Pair HL to 4DFAH, the configuration byte in the operand of the LD HL at 4DF8H.
4DC7
RES 4,(HL) CB A6
Reset bit 4 of the byte at Register Pair HL (4DFAH): one stop bit.
4DC9
DEC A 3D
DECrement Register A, the stop bits. The Z FLAG is set for STOP=1.
4DCA
If the Z FLAG is set (one stop bit), JUMP to 4DE7H.
4DCC
SET 4,(HL) CB E6
Set bit 4 of the byte at Register Pair HL (4DFAH): two stop bits.
4DCE
DEC A 3D
DECrement Register A again. The Z FLAG is set for STOP=2.
4DCF
JUMP to 4DE5H, which gives error 2FH unless the Z FLAG is set.
4DD1
PUSH HL E5
PARITY= (from 4EE7H with Register A = 1 odd, 2 even or 3 none): save Register Pair HL (the command line) onto the stack; 4DE7H takes it back.
4DD2
LD HL,4DFAH 21 FA 4D
Point Register Pair HL to 4DFAH, the configuration byte in the operand of the LD HL at 4DF8H.
4DD5
SET 3,(HL) CB DE
Set bit 3 of the byte at Register Pair HL (4DFAH): no parity.
4DD7
SUB 03H D6 03
SUBtract 03H from Register A, the parity. The Z FLAG is set for PARITY=3.
4DD9
If the Z FLAG is set (no parity), JUMP to 4DE7H.
4DDB
RES 3,(HL) CB 9E
Reset bit 3 of the byte at Register Pair HL (4DFAH): parity is used.
4DDD
SET 7,(HL) CB FE
Set bit 7 of the byte at Register Pair HL (4DFAH): even parity.
4DDF
INC A 3C
INCrement Register A (the parity minus 3). The Z FLAG is set for PARITY=2.
4DE0
If the Z FLAG is set (even parity), JUMP to 4DE7H.
4DE2
RES 7,(HL) CB BE
Reset bit 7 of the byte at Register Pair HL (4DFAH): odd parity.
4DE4
INC A 3C
INCrement Register A again. The Z FLAG is set for PARITY=1.
4DE5
If the NZ FLAG is set (a stop bit count other than 1 or 2, or a parity other than 1-3), JUMP to 4DBBH for error 2FH. 4DCFH comes here.
4DE7
POP HL E1
Restore Register Pair HL from the stack: the command line after the option's number. 4DA4H, 4DC1H, 4DCAH, 4DD9H and 4DE0H come here.
4DE8
JUMP to 4DF2H to look at the separator after the option at Register Pair HL.
4DEA
LD A,FFH 3E FF
WAIT (from 4EE7H): load Register A with FFH, the wait switch value for waiting.
4DEC
JUMP to 4DEFH to store Register A (FFH) as the new wait switch.
4DEE
XOR A AF
NOWAIT (from 4EE7H): load Register A with 00H (XOR A with itself), the wait switch value for not waiting.
4DEF
LD (4E02H),A 32 02 4E
Self-Modifying Code
Store Register A (FFH for WAIT, 00H for NOWAIT) at 4E02H, the operand of the LD A,00H at 4E01H. 4DECH comes here.
4DF2
GOSUB to SYS0/SYS 4C7AH, which looks at the character at Register Pair HL: the Z FLAG at the carriage return; a comma or spaces give the NZ FLAG with Register Pair HL past them; anything else gives the CARRY FLAG with Register A = 34H. 4DE8H comes here.
4DF5
RET C D8
If the CARRY FLAG is set (not a separator), RETURN to the dispatcher's tail 4BC5H with Register A = 34H (ILLEGAL KEYWORD OR SEPARATOR OR TERMINATOR).
4DF6
If the NZ FLAG is set (another option follows), LOOP BACK to 4D84H.
4DF8
LD HL,0000H 21 00 00
Self-Modifying Code
Load Register Pair HL with 0000H in the file: the new settings: Register L = the baud rate code (operand 4DF9H) and Register H = the configuration byte (operand 4DFAH), copied from 41F8H-41F9H at 4D7AH and changed by the options.
4DFB
LD A,H 7C
Load Register A with Register H, the new configuration byte.
4DFC
AND FCH E6 FC
AND Register A with FCH, clearing bits 1 and 0 (RTS and DTR).
4DFE
OR 04H F6 04
OR Register A with 04H, setting bit 2 (break); the configuration byte is now never 00H, so the interface is on.
4E00
LD H,A 67
Load Register H with Register A, the configuration byte to store at 41F9H.
4E01
LD A,00H 3E 00
Self-Modifying Code
Load Register A with the new wait switch: the operand 4E02H was copied from 41FAH at 4D81H and changed by WAIT or NOWAIT.
4E03
GOSUB to 4E7EH, which stores Register Pair HL at 41F8H-41F9H and Register A at 41FAH and initializes the RS-232 interface through the ROM routine 005AH.
4E06
JUMP to 4E0FH to show the new state of the RS-232 interface from 41F8H-41FAH.
4E08
OFF (from 4EE7H): GOSUB to SYS0/SYS 4C7AH, which looks at the character at Register Pair HL: the Z FLAG only at the carriage return that ends the line.
4E0B
RET NZ C0
If the NZ FLAG is set (something follows OFF), RETURN to the dispatcher's tail 4BC5H with Register A = 34H (ILLEGAL KEYWORD OR SEPARATOR OR TERMINATOR).
4E0C
XOR A AF
Load Register A with 00H (XOR A with itself), which also sets the Z FLAG: the state to show is OFF.
4E0D
JUMP to 4E13H, which turns the interface off and shows OFF.

4E0FH - Show the RS-232 State

Shows OFF when the configuration byte at 41F9H is 00H (and then initializes the interface off again), otherwise WORD=w,BAUD=b,STOP=s,PARITY=p and WAIT or NOWAIT, all decoded from 41F8H-41FAH.

4E0F
LD A,(41F9H) 3A F9 41
Load Register A with the byte at 41F9H, the RS-232 configuration byte (00H while the interface is off). 4D73H and 4E06H come here.
4E12
OR A B7
OR Register A with itself to set the flags: the Z FLAG is set if the interface is off.
4E13
PUSH AF F5
Save Register Pair AF onto the stack: Register A = the configuration byte (00H for OFF) and its Z FLAG. 4E0DH comes here for OFF with Register A = 00H.
4E14
If the Z FLAG is set (off, or the OFF option), GOSUB to 4E79H, which stores 0000H at 41F8H-41F9H and FFH at 41FAH and calls the ROM's RS-232 initialization 005AH, which turns the interface off.
4E17
POP AF F1
Restore Register Pair AF from the stack: Register A = the configuration byte and its Z FLAG.
4E18
LD HL,4E87H 21 87 4E
Point Register Pair HL to 4E87H, the text OFF (the first word of SETCOM's option table). LD does not change the flags.
4E1B
If the Z FLAG is set (the interface is off), JUMP to 4E74H to show OFF and return.
4E1D
PUSH AF F5
Save Register Pair AF (Register A = the configuration byte) onto the stack; 4E48H and 4E57H take it back into Register Pair BC.
4E1E
AND 60H E6 60
AND Register A with 60H, keeping bits 6 and 5, the word length bits (00H 5 bits, 40H 6 bits, 20H 7 bits, 60H 8 bits).
4E20
If the PE FLAG is set (an even number of those bits: 00H or 60H), JUMP to 4E25H.
4E23
XOR 60H EE 60
XOR Register A with 60H: 40H (6 bits) becomes 20H and 20H (7 bits) becomes 40H.
4E25
RLCA 07
Rotate Register A left (RLCA): bit 6 goes to bit 7, bit 5 to bit 6. 4E20H comes here.
4E26
RLCA 07
Rotate Register A left (RLCA) again: the two bits are now in bits 7 and 0.
4E27
RLCA 07
Rotate Register A left (RLCA) a third time: Register A = 0, 1, 2 or 3.
4E28
ADD A,05H C6 05
ADD 05H to Register A (0-3): Register A = the word length in bits, 5-8.
4E2A
LD HL,4E8EH 21 8E 4E
Point Register Pair HL to 4E8EH, the text WORD= in SETCOM's option table.
4E2D
GOSUB to 4F93H, which shows the text at Register Pair HL (WORD=) and the number in Register A in decimal.
4E30
LD A,(41F8H) 3A F8 41
Load Register A with the byte at 41F8H, the baud rate code (bits 7-4 sending, bits 3-0 receiving).
4E33
AND 0FH E6 0F
AND Register A with 0FH, keeping the receiving rate's code, 0-15.
4E35
ADD A,A 87
ADD Register A to itself: the code times 2, the offset of its word in the baud rate table.
4E36
LD HL,4EC7H 21 C7 4E
Point Register Pair HL to 4EC7H, the table of the 16 baud rates.
4E39
LD E,A 5F
Load Register E with Register A, the offset in the table.
4E3A
LD D,00H 16 00
Load Register D with 00H: Register Pair DE = the offset.
4E3C
ADD HL,DE 19
ADD Register Pair DE (the offset) to Register Pair HL (4EC7H): Register Pair HL = the rate's entry.
4E3D
LD E,(HL) 5E
Load Register E with the byte at Register Pair HL, the low byte of the rate.
4E3E
INC HL 23
INCrement Register Pair HL to the high byte of the rate.
4E3F
LD D,(HL) 56
Load Register D with the byte at Register Pair HL: Register Pair DE = the baud rate.
4E40
LD HL,4E97H 21 97 4E
Point Register Pair HL to 4E97H, the text BAUD= in SETCOM's option table.
4E43
GOSUB to 4F96H, which shows a comma, the text at Register Pair HL (BAUD=) and the number in Register Pair DE in decimal.
4E46
LD E,01H 1E 01
Load Register E with 01H, one stop bit, the value shown unless bit 4 is set.
4E48
POP BC C1
Restore Register Pair BC from the stack: Register B = the configuration byte saved at 4E1DH.
4E49
BIT 4,B CB 60
Test bit 4 of Register B, the configuration byte: set for two stop bits.
4E4B
PUSH BC C5
Save Register Pair BC (Register B = the configuration byte) onto the stack again for 4E57H.
4E4C
If the Z FLAG is set (bit 4 clear), JUMP to 4E4FH with Register E = 1.
4E4E
INC E 1C
INCrement Register E from 1 to 2: the configuration byte asks for two stop bits.
4E4F
LD HL,4EA0H 21 A0 4E
Point Register Pair HL to 4EA0H, the text STOP= in SETCOM's option table. 4E4CH comes here.
4E52
GOSUB to 4F94H, which shows a comma, the text at Register Pair HL (STOP=) and Register E in decimal.
4E55
LD E,03H 1E 03
Load Register E with 03H, the PARITY= value for no parity, shown if bit 3 is set.
4E57
POP BC C1
Restore Register Pair BC from the stack: Register B = the configuration byte.
4E58
BIT 3,B CB 58
Test bit 3 of Register B, the configuration byte: set for no parity.
4E5A
If the NZ FLAG is set (no parity), JUMP to 4E62H with Register E = 3.
4E5C
DEC E 1D
DECrement Register E to 2, the PARITY= value for even parity, shown if bit 7 is set.
4E5D
BIT 7,B CB 78
Test bit 7 of Register B, the configuration byte: set for even parity.
4E5F
If the NZ FLAG is set (even parity), JUMP to 4E62H with Register E = 2.
4E61
DEC E 1D
DECrement Register E to 1, the PARITY= value for odd parity (bit 7 clear).
4E62
LD HL,4EA9H 21 A9 4E
Point Register Pair HL to 4EA9H, the text PARITY= in SETCOM's option table. 4E5AH and 4E5FH come here.
4E65
GOSUB to 4F94H, which shows a comma, the text at Register Pair HL (PARITY=) and Register E in decimal.
4E68
LD HL,4EB4H 21 B4 4E
Point Register Pair HL to 4EB4H, the text WAIT in SETCOM's option table.
4E6B
LD A,(41FAH) 3A FA 41
Load Register A with the byte at 41FAH, the RS-232 wait switch.
4E6E
OR A B7
OR Register A with itself to set the flags: the NZ FLAG is set if the switch is not 00H.
4E6F
If the NZ FLAG is set (wait), JUMP to 4E74H to show WAIT.
4E71
LD HL,4EBCH 21 BC 4E
Point Register Pair HL to 4EBCH, the text NOWAIT in SETCOM's option table.
4E74
GOSUB to 4F7FH, which shows a comma (none before the first item) and the text at Register Pair HL (OFF, WAIT or NOWAIT). 4E1BH and 4E6FH come here.
4E77
XOR A AF
Load Register A with 00H (XOR A with itself), which also sets the Z FLAG: no error.
4E78
RET C9
RETURN to the dispatcher's tail 4BC5H with Register A = 00H, no error.

4E79H - Set the RS-232 Control Block

4E79H turns the interface off: the baud rate code and the configuration byte become 00H and the wait switch FFH. 4E7EH stores Register Pair HL (Register L = the baud rate code, Register H = the configuration byte) at 41F8H-41F9H and Register A at 41FAH. Both then jump to the ROM routine 005AH, which loads Register Pair DE with 41F5H (the RS-232 initialization control block) and sends it through the ROM's output dispatcher; the ROM's driver programs the UART from 41F8H-41FAH, or turns it off for a configuration byte of 00H, and returns to the caller.

4E79
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H: the baud rate code 00H and the configuration byte 00H (off). 4E14H calls here.
4E7C
LD A,FFH 3E FF
Load Register A with FFH, the wait switch value.
4E7E
LD (41F8H),HL 22 F8 41
Store Register Pair HL at 41F8H-41F9H: Register L at 41F8H, the baud rate code, and Register H at 41F9H, the configuration byte. 4E03H calls here.
4E81
LD (41FAH),A 32 FA 41
Store Register A at 41FAH, the RS-232 wait switch.
4E84
JUMP to the ROM routine 005AH, which initializes the RS-232 interface from the control block at 41F5H and returns to the caller of 4E79H or 4E7EH.

4E87H - SETCOM Option Table (Data)

Read by 4EE7H from 4D84H. Each entry: the option word, 00H, an attribute byte (bit 7 a number follows, bit 6 the number is 16 bits, bit 5 the number must not be 0) and the handler's address. The words are also the texts 4E0FH shows.

4E87-4E8D
DEFM "OFF" / DEFB 00H, 00H / DEFW 4E08H 4F 46 46 00 00 08 4E
Option OFF: attribute 00H (no number), handler 4E08H. Also the text shown for an interface that is off (4E18H).
4E8E-4E96
DEFM "WORD=" / DEFB 00H, 80H / DEFW 4D8AH 57 4F 52 44 3D 00 80 8A 4D
Option WORD=: attribute 80H (a number 0-255), handler 4D8AH. Also the text shown by 4E2AH.
4E97-4E9F
DEFM "BAUD=" / DEFB 00H, C0H / DEFW 4DA6H 42 41 55 44 3D 00 C0 A6 4D
Option BAUD=: attribute C0H (a 16-bit number), handler 4DA6H. Also the text shown by 4E40H.
4EA0-4EA8
DEFM "STOP=" / DEFB 00H, 80H / DEFW 4DC3H 53 54 4F 50 3D 00 80 C3 4D
Option STOP=: attribute 80H (a number 0-255), handler 4DC3H. Also the text shown by 4E4FH.
4EA9-4EB3
DEFM "PARITY=" / DEFB 00H, 80H / DEFW 4DD1H 50 41 52 49 54 59 3D 00 80 D1 4D
Option PARITY=: attribute 80H (a number 0-255), handler 4DD1H. Also the text shown by 4E62H.
4EB4-4EBB
DEFM "WAIT" / DEFB 00H, 00H / DEFW 4DEAH 57 41 49 54 00 00 EA 4D
Option WAIT: attribute 00H (no number), handler 4DEAH. Also the text shown by 4E68H.
4EBC-4EC5
DEFM "NOWAIT" / DEFB 00H, 00H / DEFW 4DEEH 4E 4F 57 41 49 54 00 00 EE 4D
Option NOWAIT: attribute 00H (no number), handler 4DEEH. Also the text shown by 4E71H.
4EC6
DEFB 00H 00
The 00H that ends SETCOM's option table (4F1DH).

4EC7H - Baud Rate Table (Data)

The 16 baud rates as 16-bit numbers, in the order of the codes 0-15 that the ROM sends to the baud rate port. Searched by 4DA6H, indexed by 4E36H.

4EC7-4ECE
DEFW 0032H, 004BH, 006EH, 0086H 32 00 4B 00 6E 00 86 00
Codes 0-3 of the baud rate table: 50, 75, 110 and 134 baud.
4ECF-4ED6
DEFW 0096H, 012CH, 0258H, 04B0H 96 00 2C 01 58 02 B0 04
Codes 4-7 of the baud rate table: 150, 300, 600 and 1200 baud.
4ED7-4EDE
DEFW 0708H, 07D0H, 0960H, 0E10H 08 07 D0 07 60 09 10 0E
Codes 8-11 of the baud rate table: 1800, 2000, 2400 and 3600 baud.
4EDF-4EE6
DEFW 12C0H, 1C20H, 2580H, 4B00H C0 12 20 1C 80 25 00 4B
Codes 12-15 of the baud rate table: 4800, 7200, 9600 and 19200 baud.

4EE7H - Look Up an Option and Run Its Handler

Register Pair BC = an option table, Register Pair HL = the command line. The word at Register Pair HL is looked up (error 34H if it is not in the table); the handler's address is pushed and the routine RETURNs into it. An option without a number (attribute bit 7 clear) goes there at once. Otherwise the number after the word is read: with attribute bit 5 it must not be 0, with bit 6 it is passed in Register Pair DE, else it must be 0-255 and is passed in Register A. A bad number is error 2FH. Register Pair HL is past the option when the handler starts.

4EE7
LD D,03H 16 03
Load Register D with 03H, the number of bytes after the 00H of each table word (the attribute byte and the handler's address). 4D1FH and 4D87H jump here.
4EE9
GOSUB to 4F0FH, which finds the entry whose word matches the text at Register Pair HL; it returns with Register Pair BC at the byte after that word's 00H and Register Pair HL past the text.
4EEC
PUSH BC C5
Save Register Pair BC (the address of the entry's attribute byte) onto the stack.
4EED
EX (SP),HL E3
Exchange Register Pair HL with the word on top of the stack (at the Stack Pointer): Register Pair HL = the address of the attribute byte, and the command line pointer is kept on the stack.
4EEE
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the option's attribute byte.
4EEF
INC HL 23
INCrement Register Pair HL to the low byte of the handler's address.
4EF0
LD E,(HL) 5E
Load Register E with the byte at Register Pair HL, the low byte of the handler's address.
4EF1
INC HL 23
INCrement Register Pair HL to the high byte of the handler's address.
4EF2
LD D,(HL) 56
Load Register D with the byte at Register Pair HL: Register Pair DE = the handler's address.
4EF3
POP HL E1
Restore Register Pair HL from the stack: the command line past the option's word.
4EF4
PUSH DE D5
Save Register Pair DE (the handler's address) onto the stack, where the RETs below find it.
4EF5
BIT 7,A CB 7F
Test bit 7 of Register A, the attribute byte: set if a number follows the word.
4EF7
RET Z C8
If the Z FLAG is set (no number: OFF, WAIT, NOWAIT), RETURN into the handler with Register A = the attribute byte.
4EF8
PUSH AF F5
Save Register Pair AF (Register A = the attribute byte) onto the stack.
4EF9
GOSUB to 4F26H, which reads the decimal (or hexadecimal, ended by H) number at Register Pair HL into Register Pair DE.
4EFC
POP BC C1
Restore Register Pair BC from the stack: Register B = the attribute byte.
4EFD
BIT 5,B CB 68
Test bit 5 of Register B, the attribute byte: set if the number must not be 0.
4EFF
If the Z FLAG is set (0 is allowed), JUMP to 4F05H.
4F01
LD A,D 7A
Load Register A with Register D, the high byte of the number.
4F02
OR E B3
OR Register A with Register E: the Z FLAG is set if the number is 0.
4F03
If the Z FLAG is set (a number of 0), JUMP to 4F44H for error 2FH.
4F05
BIT 6,B CB 70
Test bit 6 of Register B, the attribute byte: set for a 16-bit number. 4EFFH comes here.
4F07
RET NZ C0
If the NZ FLAG is set (BAUD=), RETURN into the handler with the number in Register Pair DE.
4F08
LD A,D 7A
Load Register A with Register D, the high byte of the number.
4F09
OR A B7
OR Register A with itself to set the flags: the NZ FLAG is set for a number above 255.
4F0A
If the NZ FLAG is set (above 255), JUMP to 4F44H for error 2FH.
4F0C
LD A,E 7B
Load Register A with Register E, the number (0-255).
4F0D
OR A B7
OR Register A with itself to set the flags: the Z FLAG is set for 0.
4F0E
RET C9
RETURN into the handler with the number in Register A.

Search Loop
Register Pair BC = the table entry, Register Pair HL = the word in the command line, Register D = the bytes after each 00H.

4F0F
GOSUB to SYS0/SYS 4C6AH, which compares the 00H-ended word at Register Pair BC with the text at Register Pair HL: on a match the Z FLAG, Register Pair BC past the 00H and Register Pair HL past the text; otherwise the NZ FLAG with Register Pair HL unchanged and Register Pair BC inside the word. 4EE9H calls here; 4F1FH comes back here.
4F12
RET Z C8
If the Z FLAG is set (the word matches), RETURN to 4EECH with Register Pair BC at the attribute byte.
4F13
LD A,(BC) 0A
Load Register A with the byte at Register Pair BC, a character of the table word (00H at its end). 4F16H comes back here.
4F14
OR A B7
OR Register A with itself to set the flags: the Z FLAG is set at the 00H that ends the table word.
4F15
INC BC 03
INCrement Register Pair BC to the next byte of the table. INC BC does not change the flags.
4F16
If the NZ FLAG is set (still inside the word), LOOP BACK to 4F13H.
4F18
LD E,D 5A
Load Register E with Register D, the number of bytes to step over after the 00H (03H).
4F19
INC BC 03
INCrement Register Pair BC over one byte after the word's 00H. 4F1BH comes back here.
4F1A
DEC E 1D
DECrement Register E, the bytes still to step over. The Z FLAG is set when none are left.
4F1B
If the NZ FLAG is set (bytes left), LOOP BACK to 4F19H.
4F1D
LD A,(BC) 0A
Load Register A with the byte at Register Pair BC, the first byte of the next entry (00H at the end of the table).
4F1E
OR A B7
OR Register A with itself to set the flags: the Z FLAG is set at the end of the table.
4F1F
If the NZ FLAG is set (another entry), LOOP BACK to 4F0FH to compare it.
4F21
LD A,34H 3E 34
Load Register A with 34H, the DOS error code ILLEGAL KEYWORD OR SEPARATOR OR TERMINATOR: the word is not in the table.
4F23
JUMP to SYS0/SYS 4409H, the DOS error exit, with the error code in Register A. 4D0EH comes here with 2AH.

4F26H - Read a Number

Reads a number at Register Pair HL into Register Pair DE: decimal digits, or hexadecimal digits ended by H. The digits are first read as decimal; if a letter A-H follows them, the number is read again from its start as hexadecimal, and must then end with H. No digit, a missing H or a value above FFFFH is error 2FH. Register Pair HL returns past the number. Called by 4EF9H.

4F26
PUSH HL E5
Save Register Pair HL (the start of the number) onto the stack, in case it has to be read again as hexadecimal.
4F27
LD B,00H 06 00
Load Register B with 00H: bit 0 clear (decimal digits) and bit 1 clear (no digit read yet).
4F29
GOSUB to 4F49H, which reads the digits at Register Pair HL into Register Pair DE; Register Pair HL stops at the first character that is not a digit.
4F2C
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the character after the decimal digits.
4F2D
SUB 41H D6 41
SUBtract 41H (ASCII A) from Register A: the letters A-H become 00H-07H.
4F2F
CP 08H FE 08
Compare Register A against 08H. The CARRY FLAG is set for a letter A-H: a hexadecimal digit or the closing H follows.
4F31
If the NO CARRY FLAG is set (no letter A-H), JUMP to 4F40H: the number is decimal.
4F33
POP HL E1
Restore Register Pair HL from the stack: the start of the number, to read it again.
4F34
LD B,01H 06 01
Load Register B with 01H: bit 0 set, read hexadecimal digits; bit 1 clear, no digit read yet.
4F36
PUSH HL E5
Save Register Pair HL (the start of the number) onto the stack again, to be dropped at 4F42H.
4F37
GOSUB to 4F49H, which reads the hexadecimal digits at Register Pair HL into Register Pair DE.
4F3A
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the character after the hexadecimal digits.
4F3B
CP 48H FE 48
Compare Register A against 48H (ASCII H). The Z FLAG is set for the closing H.
4F3D
INC HL 23
INCrement Register Pair HL past the H. INC HL does not change the flags.
4F3E
If the NZ FLAG is set (no closing H), JUMP to 4F44H for error 2FH.
4F40
BIT 1,B CB 48
Test bit 1 of Register B: set by 4F62H once a digit has been read. 4F31H comes here.
4F42
POP BC C1
Restore Register Pair BC from the stack, dropping the saved start of the number. POP does not change the flags.
4F43
RET NZ C0
If the NZ FLAG is set (at least one digit), RETURN with the number in Register Pair DE and Register Pair HL past it.
4F44
LD A,2FH 3E 2F
Load Register A with 2FH, the DOS error code BAD PARAMETER(S). Every check of a value in SYS15/SYS comes here.
4F46
JUMP to SYS0/SYS 4409H, the DOS error exit, with the error code in Register A.

4F49H - Read Digits

Register Pair HL = the text, Register B bit 0 = hexadecimal. The digits are added up in Register Pair DE (times 10, or times 16, plus the digit); Register A collects every carry out of bit 15, and any carry is error 2FH. Bit 1 of Register B is set when a digit is read. Returns at the first character that is not a digit, with Register Pair HL pointing at it.

4F49
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H, the value before the first digit. 4F29H and 4F37H call here.

Digit Loop
Register Pair HL = the next character, Register Pair DE = the value so far.

4F4C
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the next character of the number. 4F7DH comes back here.
4F4D
SUB 30H D6 30
SUBtract 30H (ASCII 0) from Register A: the digits 0-9 become 00H-09H.
4F4F
CP 0AH FE 0A
Compare Register A against 0AH. The CARRY FLAG is set for a decimal digit.
4F51
If the CARRY FLAG is set (0-9), JUMP to 4F5DH with the digit's value in Register A.
4F53
BIT 0,B CB 40
Test bit 0 of Register B: set when hexadecimal digits are being read.
4F55
RET Z C8
If the Z FLAG is set (decimal), RETURN: the number ends at this character.
4F56
SUB 11H D6 11
SUBtract 11H more from Register A: the letters A-F (41H-46H, now 11H-16H) become 00H-05H.
4F58
CP 06H FE 06
Compare Register A against 06H. The NO CARRY FLAG is set for a character that is not A-F.
4F5A
RET NC D0
If the NO CARRY FLAG is set (not A-F), RETURN: the number ends at this character.
4F5B
ADD A,0AH C6 0A
ADD 0AH to Register A: the letters A-F become their values 0AH-0FH.
4F5D
PUSH HL E5
Save Register Pair HL (the position of the digit) onto the stack. 4F51H comes here with a decimal digit.
4F5E
LD H,D 62
Load Register H with Register D, the high byte of the value so far.
4F5F
LD L,E 6B
Load Register L with Register E: Register Pair HL = the value so far, and Register Pair DE keeps a copy for the times 5 of a decimal number.
4F60
LD C,A 4F
Load Register C with Register A, the value of the new digit.
4F61
XOR A AF
Load Register A with 00H (XOR A with itself): Register A collects the carries out of Register Pair HL for this digit.
4F62
SET 1,B CB C8
Set bit 1 of Register B: a digit has been read.
4F64
ADD HL,HL 29
ADD Register Pair HL to itself: the value times 2. A carry out of bit 15 sets the CARRY FLAG.
4F65
ADC A,A 8F
ADD Register A to itself with the CARRY FLAG (ADC): a carry makes Register A non-zero.
4F66
ADD HL,HL 29
ADD Register Pair HL to itself: the value times 4.
4F67
ADC A,A 8F
ADD Register A to itself with the CARRY FLAG (ADC), collecting the carry.
4F68
BIT 0,B CB 40
Test bit 0 of Register B: set for hexadecimal digits.
4F6A
If the Z FLAG is set (decimal), JUMP to 4F6FH to make times 5.
4F6C
ADD HL,HL 29
Hexadecimal: ADD Register Pair HL to itself, the value times 8.
4F6D
JUMP to 4F70H with Register Pair HL = the value times 8.
4F6F
ADD HL,DE 19
Decimal: ADD Register Pair DE (the value) to Register Pair HL (the value times 4): the value times 5.
4F70
ADC A,A 8F
ADD Register A to itself with the CARRY FLAG (ADC), collecting the carry. 4F6DH comes here.
4F71
ADD HL,HL 29
ADD Register Pair HL to itself: the value times 16 (hexadecimal) or times 10 (decimal).
4F72
ADC A,A 8F
ADD Register A to itself with the CARRY FLAG (ADC), collecting the carry.
4F73
LD E,C 59
Load Register E with Register C, the new digit's value.
4F74
LD D,00H 16 00
Load Register D with 00H: Register Pair DE = the new digit.
4F76
ADD HL,DE 19
ADD Register Pair DE (the digit) to Register Pair HL.
4F77
ADC A,A 8F
ADD Register A to itself with the CARRY FLAG (ADC): Register A is not 00H, and the NZ FLAG is set, if the value passed FFFFH at any step of this digit.
4F78
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the new value.
4F79
POP HL E1
Restore Register Pair HL from the stack: the position of the digit. POP does not change the flags.
4F7A
If the NZ FLAG is set (the value passed FFFFH), JUMP to 4F44H for error 2FH.
4F7C
INC HL 23
INCrement Register Pair HL to the next character.
4F7D
LOOP BACK to 4F4CH for the next digit at Register Pair HL.

4F7FH - Show an Item

4F7FH shows a comma before every item except the first (the operand 4F81H is 00H until the first item has been shown) and then the 00H-ended text at Register Pair HL. 4F93H takes the number in Register A, 4F94H in Register E, 4F96H in Register Pair DE, and shows it in decimal after the text, without leading zeros.

4F7F
XOR A AF
Load Register A with 00H (XOR A with itself). 4E74H calls here.
4F80
OR 00H F6 00
Self-Modifying Code
OR Register A with the operand 4F81H: 00H in the file, 2CH (a comma) after 4F87H has stored it. The NZ FLAG is set once an item has been shown.
4F82
If the NZ FLAG is set (not the first item), GOSUB to 4FCBH, which shows the comma in Register A.
4F85
LD A,2CH 3E 2C
Load Register A with 2CH, the ASCII comma that goes before every later item.
4F87
LD (4F81H),A 32 81 4F
Self-Modifying Code
Store Register A (2CH) at 4F81H, the operand of the OR at 4F80H, so that every later item is preceded by a comma.

Show the Text
Register Pair HL = the text, ended by 00H.

4F8A
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the next character of the text. 4F91H comes back here.
4F8B
OR A B7
OR Register A with itself to set the flags: the Z FLAG is set at the 00H that ends the text.
4F8C
INC HL 23
INCrement Register Pair HL to the following character. INC HL does not change the flags.
4F8D
RET Z C8
If the Z FLAG is set (the end of the text), RETURN with Register Pair HL past the 00H.
4F8E
GOSUB to 4FCBH, which shows the character in Register A.
4F91
LOOP BACK to 4F8AH for the next character of the text at Register Pair HL.
4F93
LD E,A 5F
Load Register E with Register A, the number to show (0-255). 4D4CH, 4D56H and 4E2DH call here.
4F94
LD D,00H 16 00
Load Register D with 00H: Register Pair DE = the number. 4E52H and 4E65H call here with the number in Register E.
4F96
GOSUB to 4F7FH, which shows the comma (if this is not the first item) and the text at Register Pair HL. 4E43H calls here with the number in Register Pair DE.
4F99
LD BC,0400H 01 00 04
Load Register Pair BC with 0400H: Register B = 4, the digits above the units; Register C = 00H, no digit shown yet (leading zeros are left out).
4F9C
LD HL,4FC3H 21 C3 4F
Point Register Pair HL to 4FC3H, the table of minus 10000, minus 1000, minus 100 and minus 10.

Digit Loop
Register Pair DE = what is left of the number, Register Pair HL = the next power of ten in the table.

4F9F
PUSH BC C5
Save Register Pair BC (the digit count and the digit-shown flag) onto the stack. 4FBBH comes back here.
4FA0
LD C,(HL) 4E
Load Register C with the byte at Register Pair HL, the low byte of the negative power of ten.
4FA1
INC HL 23
INCrement Register Pair HL to the high byte of the negative power of ten.
4FA2
LD B,(HL) 46
Load Register B with the byte at Register Pair HL: Register Pair BC = minus the power of ten.
4FA3
INC HL 23
INCrement Register Pair HL to the next table entry.
4FA4
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the number, Register Pair DE = the table pointer.
4FA5
LD A,2FH 3E 2F
Load Register A with 2FH, one below ASCII 0, the digit before the first count.
4FA7
INC A 3C
INCrement Register A, the digit. 4FA9H comes back here.
4FA8
ADD HL,BC 09
ADD Register Pair BC (minus the power of ten) to Register Pair HL (the number): the CARRY FLAG is set while the number was not below the power of ten.
4FA9
If the CARRY FLAG is set (the power fitted once more), LOOP BACK to 4FA7H.
4FAB
SBC HL,BC ED 42
SUBtract Register Pair BC (minus the power) from Register Pair HL with the CARRY FLAG (clear here): the last subtraction is undone.
4FAD
POP BC C1
Restore Register Pair BC from the stack: Register B = the digits left, Register C = the digit-shown flag.
4FAE
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the rest of the number, Register Pair HL = the table pointer.
4FAF
CP 30H FE 30
Compare Register A (the digit) against 30H, ASCII 0.
4FB1
If the NZ FLAG is set (the digit is not 0), JUMP to 4FB7H to show it.
4FB3
INC C 0C
INCrement Register C, the digit-shown flag, to test it for 00H without changing it.
4FB4
DEC C 0D
DECrement Register C back: the Z FLAG is set if no digit has been shown yet.
4FB5
If the Z FLAG is set (a leading zero), JUMP to 4FBBH without showing it.
4FB7
INC C 0C
INCrement Register C: a digit has been shown, so later zeros are shown. 4FB1H comes here.
4FB8
GOSUB to 4FCBH, which shows the digit in Register A.
4FBB
DECrement Register B and LOOP BACK to 4F9FH for the next power of ten. 4FB5H comes here.
4FBD
LD A,E 7B
Load Register A with Register E, the units left in the number (0-9).
4FBE
ADD A,30H C6 30
ADD 30H to Register A: the units digit in ASCII, always shown.
4FC0
JUMP to 4FCBH, which shows the units digit and returns to the caller.
4FC3-4FCA
DEFW D8F0H, FC18H, FF9CH, FFF6H F0 D8 18 FC 9C FF F6 FF
The negative powers of ten used by 4F9CH: minus 10000, minus 1000, minus 100 and minus 10.

4FCBH - Show a Character

Shows the character in Register A through the ROM routine 0033H, keeping Register Pairs AF and DE.

4FCB
PUSH DE D5
Save Register Pair DE onto the stack; the ROM display routine changes it. 4F82H, 4F8EH, 4FB8H and 4FC0H come here.
4FCC
PUSH AF F5
Save Register Pair AF (Register A = the character) onto the stack.
4FCD
GOSUB to the ROM routine at 0033H, which displays the character in Register A at the cursor.
4FD0
POP AF F1
Restore Register Pair AF from the stack: Register A = the character shown.
4FD1
POP DE D1
Restore Register Pair DE from the stack, as it was before the ROM call.
4FD2
RET C9
RETURN with Register A = the character and Register Pair DE unchanged.

4FD3H - End of the File

The rest of the five load records.

4FD3-51E7
DEFB 00H x 533 00 x 533
533 bytes of 00H at the end of the file (4FD3H-51E7H); no code of SYS15/SYS reads them.