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

Page Customization

SYS13/SYS - NEWDOS/80 v2.0 BASIC Error Message Table and ERROR/RESUME Handler

SYS13/SYS is a BASIC/CMD overlay module that provides two major functions: (1) the complete BASIC error message lookup table containing 58 null-terminated ASCII strings covering ROM BASIC errors 0-22 and NEWDOS/80 DOS-specific errors 50-84, and (2) the ERROR/RESUME/ON ERROR GOTO statement handler at 50FEH. The error message table occupies the bulk of the overlay (4D47H-50FDH) and is accessed by the error display routine in SYS0 through an index-based lookup algorithm at 4D0CH. The overlay loads into memory at 4D00H-4D45H (the lookup dispatcher) and 4D47H-51E7H (error strings, handler code, and NOP padding).

Program Entry Point
4D0CH - Error message lookup dispatcher. Called with the error code in Register E and token 4FH in Register A when the error display routine needs to retrieve the text of an error message.

Secondary Entry Point
50FEH - ERROR/RESUME/ON ERROR GOTO statement handler. Jumped to when the BASIC interpreter encounters an ERROR statement token (4FH) during program execution.

SYS13 Variable and Data Area List

The following memory locations are used as working variables or parameters by SYS13.

Overlay Header Area (4D00H-4D0BH)

AddressVariableDescription
4D00H-4D01HStart line number parameterTwo-byte value loaded into the start line number register pair for the ERROR statement handler. Written by the error handler at 518BH and 519FH; read at 518BH and 5155H.
4D02H-4D03HIncrement value parameterTwo-byte value used as the increment for the ERROR statement line number calculation. Read at 519BH.
4D04H-4D05HRange start parameterTwo-byte value specifying the lower bound of the line number range for the ERROR statement handler. Read at 514BH and 517DH.
4D06H-4D07HRange end parameterTwo-byte value specifying the upper bound of the line number range for the ERROR statement handler. Read at 514FH and 5185H.
4D08H-4D09HSaved line number valueTwo-byte value used to store the current line number during ERROR handler processing. Written at 518EH.
4D0AHUSING flagSingle byte. When non-zero, signals that a USING modifier is active in the ERROR statement, causing the handler to skip the line number range check and proceed directly to the next-line scan. Read at 516BH.
4D0BHReserved / additional flagSingle byte. Used in conjunction with 4D0AH for secondary flag purposes. Written at 5141H.

External Variables Referenced

AddressVariableDescription
409AHError recovery flagSingle byte in the DOS work area. Cleared to 00H at 4D30H when the error index evaluates to 1 (specific error code 02H, SYNTAX ERROR). Used by the DOS to suppress error recovery when a syntax error is detected during tokenization.
4288HError state flagSingle byte in the DOS work area. Cleared to 00H at 50FFH when the ERROR/RESUME handler initializes. Indicates whether an error condition is currently active.
40A4HBASIC program start pointerTwo-byte pointer to the start of the BASIC program text in memory. Read at 515FH and 51C7H to begin scanning the line link chain.

SYS13 Major Routine List

The following major routines are defined within the SYS13 overlay.

AddressRoutineDescription
4D0CHError Message Lookup DispatcherEntry point for error message retrieval. Receives the error code in Register E, converts it to a table index using a three-range algorithm (0-46 direct, 47-98 clamped to “UNPRINTABLE ERROR”, 99+ offset), then walks the null-terminated string table at 4D47H counting entries to find the matching message. Returns with HL pointing to the error message string and the return address manipulated to vector through 1A01H for display.
4D47HError Message String TableData area containing 58 null-terminated ASCII error message strings. Entries 0-22 are ROM BASIC error messages (NEXT WITHOUT FOR through DISK BASIC FEATURE). Entries 23-57 are NEWDOS/80 DOS error messages (UNDEFINED USER FUNCTION through BAD FILE POSITIONING PARAM). The table is terminated by an additional 00H byte at 50FDH. Each entry is accessed by index; the lookup routine at 4D0CH walks the table counting null terminators to reach the desired entry.
50FEHERROR/RESUME/ON ERROR GOTO HandlerHandles the BASIC ERROR statement (token 4FH). Parses up to 4 comma-separated numeric parameters from the statement, validates line number ranges, walks the BASIC program line chain to locate target lines, updates line link pointers, and manages the cross-reference table at 64A3H. Uses RST 10H for expression evaluation and RST 18H for 16-bit unsigned comparison.

Disassembly

4D00H – Overlay Header and Error Message Lookup Dispatcher

This is the start of the SYS13 overlay. Addresses 4D00H–4D0BH serve as a parameter/variable area used by the ERROR statement handler at 50FEH. The executable code begins at 4D0CH, which is the program entry point. The dispatcher receives an error code in Register E, converts it to a zero-based table index, then walks the null-terminated error message table at 4D46H counting entries until the target index is reached. On exit, HL points to the first character of the error message string, and the return address is manipulated so that execution vectors through 1A01H (the ROM’s error message display continuation).

Parameter/Variable Area
The first 12 bytes (4D00H–4D0BH) are not executable code. They are used as a data area by the ERROR statement handler at 50FEH. The disassembler has misinterpreted these data bytes as instructions. See the Variable List above for the meaning of each location.

4D00
DEFW 000AH 0A 00
Start line number parameter (4D00H–4D01H), initialized to 000AH
4D02
DEFW 000AH 0A 00
Increment value parameter (4D02H–4D03H), initialized to 000AH
4D04
DEFW 0000H 00 00
Range start parameter (4D04H–4D05H), initialized to 0000H
4D06
DEFW FFF9H F9 FF
Range end parameter (4D06H–4D07H), initialized to FFF9H (65529 decimal, the maximum valid BASIC line number)
4D08
DEFW 0000H 00 00
Saved line number value (4D08H–4D09H), initialized to 0000H
4D0A
DEFB 00H 00
USING flag (4D0AH), initialized to 00H (inactive)
4D0B
DEFB 00H 00
Reserved flag (4D0BH), initialized to 00H

Error Message Lookup Entry Point
Execution enters here when the error display routine in SYS0 needs to retrieve the text of an error message. Register A contains 4FH (the ERROR statement token from the BASIC token table) and Register E contains the internal error code. The token is checked first to distinguish an error lookup call from an ERROR statement execution.

4D0C
CP 4FH FE 4F
Compare Register A against 4FH (the ERROR statement token). If Register A equals 4FH, the Z FLAG is set, indicating this is an ERROR statement execution rather than an error message lookup. If Register A does not equal 4FH, the NZ FLAG is set, indicating an error message lookup request.
4D0E
If the Z FLAG has been set (Register A equals 4FH, meaning this is an ERROR statement), JUMP to 50FEH to execute the ERROR/RESUME/ON ERROR GOTO handler.

Error Code Preprocessing
At this point, Register A does not equal 4FH, so this is an error message lookup call. Register E holds the internal error code. The code saves the error code, checks for a special range of error codes (9CH–A1H) that require additional handling, then converts the error code to a table index.

4D11
LD A,E 7B
Load Register A with the contents of Register E (the internal error code to look up).
4D12
PUSH AF F5
Save Register A (the error code) and the flags onto the stack. The error code will be restored later for the return sequence.
4D13
SUB 9CH D6 9C
SUBtract 9CH (156 decimal) from Register A. This tests whether the error code is in the range 9CH–A1H. If the original error code was 9CH, Register A becomes 00H. If it was A1H, Register A becomes 05H. The CARRY FLAG is set if the original value was less than 9CH.
4D15
CP 06H FE 06
Compare Register A against 06H. After the SUB 9CH above, if the original error code was in the range 9CH–A1H (6 values), Register A is 00H–05H and the CARRY FLAG is set. If the original code was outside that range, the CARRY FLAG is not set.
4D17
If the CARRY FLAG has been set (the error code is in the range 9CH–A1H), GOSUB to 5D37H in the BASIC/CMD module. This routine performs special handling for error codes in this range, which correspond to DOS-specific I/O errors that need additional translation before the message lookup can proceed.
4D1A
POP AF F1
Restore Register A (the original error code) and the flags from the stack.

Error Code to Table Index Conversion
The error code in Register A is now converted to a zero-based table index. The algorithm has three ranges:
1. Error codes 00H–2EH (0–46 decimal): Index = error_code / 2 (via RRCA). These are ROM BASIC errors and the first DOS error.
2. Error codes 2FH–62H (47–98 decimal): Clamped to index 19, which maps to “UNPRINTABLE ERROR”.
3. Error codes 63H+ (99+ decimal): Index = (error_code − 34H) / 2. These are NEWDOS/80 DOS-specific errors.

4D1B
CP 63H FE 63
Compare Register A (the error code) against 63H (99 decimal). If the error code is 63H or greater, the NO CARRY FLAG is set, indicating a NEWDOS/80 DOS error that uses the offset formula. If less than 63H, the CARRY FLAG is set.
4D1D
If the NO CARRY FLAG has been set (error code ≥ 99 decimal), JUMP forward to 4D25H to apply the offset formula: SUB 34H then RRCA.
4D1F
CP 2FH FE 2F
Compare Register A against 2FH (47 decimal). If the error code is less than 2FH, the CARRY FLAG is set, indicating a ROM BASIC error or the first DOS error that uses direct division. If 2FH or greater (but less than 63H), the NO CARRY FLAG is set.
4D21
If the CARRY FLAG has been set (error code < 47 decimal), JUMP forward to 4D27H to apply direct division: RRCA converts the even error code to a table index by dividing by 2.
4D23
LD A,5AH 3E 5A
Load Register A with 5AH (90 decimal). This clamps all error codes in the range 47–98 decimal to the value 90, which after the SUB 34H and RRCA below produces index 19 (“UNPRINTABLE ERROR”). This catch-all handles undefined error codes in the gap between ROM BASIC and NEWDOS/80 errors.
4D25
SUB 34H D6 34
SUBtract 34H (52 decimal) from Register A. For DOS errors (≥ 99 decimal), this offsets the error code so that error code 64H (100 decimal) becomes 30H (48 decimal), which after RRCA produces index 24. For clamped codes (A = 5AH), 5AH − 34H = 26H (38 decimal).
4D27
RRCA 0F
Rotate Register A Right Circular. Bit 0 moves to both the Carry flag and bit 7. For even error codes, this is equivalent to dividing by 2, producing the zero-based table index. For example: error code 00H → index 0, error code 02H → index 1, error code 64H after SUB 34H = 30H → index 24.
4D28
LD B,A 47
Load Register B with the table index from Register A. Register B will serve as the countdown counter for walking through the error message table.
4D29
LD HL,4D46H 21 46 4D
Point Register Pair HL to 4D46H, which is one byte before the first error message string at 4D47H. The table walk loop below will increment past the 00H byte at 4D46H to reach the first string.
4D2C
INC B 04
INCrement Register B by 1. This adjusts the counter so that a DJNZ loop will execute the correct number of iterations. Since the loop decrements before testing, incrementing B ensures the walk counts exactly B null terminators before stopping at the target string.

Special Case: Error Index 1 (Syntax Error)
If the computed table index is 1 (SYNTAX ERROR), the code clears the error recovery flag at 409AH. This prevents the DOS from attempting error recovery when a syntax error occurs during BASIC tokenization, because the program text is in an inconsistent state.

4D2D
DEC A 3D
DECrement Register A by 1. If the original table index was 1, Register A becomes 0 and the Z FLAG is set. If the index was 0 (NEXT WITHOUT FOR), Register A wraps to FFH and the NZ FLAG is set. For all other indices, NZ is set.
4D2E
If the NZ FLAG has been set (the table index is not 1), JUMP forward to 4D33H to begin the table walk loop, skipping the 409AH clear.
4D30
Store Register A (which is 00H since the Z FLAG was set) to memory location 409AH (the error recovery flag in the DOS work area). Clearing this flag to 00H disables error recovery for SYNTAX ERROR conditions.

Error Message Table Walk Loop
This loop walks through the null-terminated string table at 4D47H. Each error message is terminated by 00H. The loop counts past B null terminators to reach the target entry. On exit, HL points to the first character of the target error message string. [LOOP START]

4D33
LD A,(HL) 7E
Load Register A with the byte at the address pointed to by Register Pair HL (the current position in the error message table).
4D34
OR A B7
OR Register A with itself. This sets the Z FLAG if Register A is 00H (a null terminator), or the NZ FLAG if it is a non-zero character byte.
4D35
INC HL 23
INCrement Register Pair HL by 1 to advance the pointer to the next byte in the error message table.
4D36
If the NZ FLAG has been set (the current byte is not a null terminator), JUMP back to 4D33H to continue scanning through the current string. [LOOP — skip non-null characters]

At this point, a null terminator has been found. HL now points to the byte after the null (the first character of the next message, or another null if at the end of the table).

4D38
OR (HL) B6
OR Register A (which is 00H from the null terminator) with the byte at (HL). If the next byte is also 00H (end of the entire table), the Z FLAG is set. If the next byte is non-zero (start of another error message), the NZ FLAG is set.
4D39
If the Z FLAG has been set (the table has been exhausted before the target index was reached), JUMP back to 4D23H to clamp to “UNPRINTABLE ERROR” (index 19). This is a safety fallback for error codes that index beyond the end of the table.
4D3B
DECrement Register B (the remaining entry count) by 1. If B is not zero, JUMP back to 4D33H to scan past the next error message string. If B reaches zero, fall through: HL now points to the first character of the target error message. [LOOP END]

Return Sequence
The target error message has been located. HL points to its first character. The code now manipulates the return address stack so that execution continues at the ROM’s error message display routine at 1A01H, which will print the error message string pointed to by HL.

4D3D
EX DE,HL EB
Exchange Register Pairs DE and HL. Now DE points to the error message string, and HL holds the previous contents of DE.
4D3E
POP AF F1
Restore Register A (the original error code saved at 4D12H) and flags from the stack. This also removes the stacked error code, leaving the caller’s return address at the top of the stack.
4D3F
LD HL,1A01H 21 01 1A
Point Register Pair HL to 1A01H, the ROM’s error message display continuation address. This is the address where the error display routine expects to resume after the error message string has been located.
4D42
EX (SP),HL E3
Exchange the top-of-stack value with Register Pair HL. This replaces the caller’s return address on the stack with 1A01H, so the upcoming RET will jump to the ROM’s error display routine instead of returning to the original caller. HL now holds the original return address (which is discarded).
4D43
EX DE,HL EB
Exchange Register Pairs DE and HL. Now HL points to the error message string (restored from DE where it was placed at 4D3DH). The ROM routine at 1A01H expects HL to point to the message text.
4D44
PUSH AF F5
Save Register A (the original error code) and flags onto the stack. The ROM error display routine at 1A01H expects the error code on the stack for error number output.
4D45
RET C9
RETurn. Pops the address 1A01H from the stack (placed there by the EX (SP),HL at 4D42H) and jumps to it. Execution continues in the ROM error message display routine with HL pointing to the error message string and Register A containing the error code.

4D46H – Sentinel Byte

This null byte precedes the error message table and serves as the starting point for the table walk loop. The loop at 4D33H scans forward from 4D46H, and the INC HL at 4D35H advances past this byte to reach the first message at 4D47H

4D46
DEFB 00H 00
Null byte.

4D47H – Error Message String Table (ROM BASIC Errors 0–22)

This is the beginning of the error message string table. Each entry is a null-terminated ASCII string. The first 23 entries (indices 0–22) correspond to ROM BASIC error messages. These are the same error texts used by Level II BASIC, duplicated here in the SYS13 overlay because the overlay replaces the ROM’s built-in error table when NEWDOS/80 is active. The error code displayed to the user is the table index (0–22).

4D47
DEFM "NEXT WITHOUT FOR" + 00H
ROM BASIC error 0 (internal code 00H). Triggered when a NEXT statement is encountered without a matching FOR loop on the control stack.
4D58
DEFM "SYNTAX ERROR" + 00H
ROM BASIC error 1 (internal code 02H). Triggered when the BASIC interpreter encounters an unrecognizable statement, missing punctuation, or invalid syntax.
4D65
DEFM "RETURN WITHOUT GOSUB" + 00H
ROM BASIC error 2 (internal code 04H). Triggered when a RETURN statement is encountered without a prior GOSUB having been executed.
4D7A
DEFM "OUT OF DATA" + 00H
ROM BASIC error 3 (internal code 06H). Triggered when a READ statement requests data but all DATA statements have been exhausted.
4D86
DEFM "ILLEGAL FUNCTION CALL" + 00H
ROM BASIC error 4 (internal code 08H). Triggered when a function receives an argument outside its valid domain (e.g., negative SQRT, invalid MID$ index).
4D9C
DEFM "OVERFLOW" + 00H
ROM BASIC error 5 (internal code 0AH). Triggered when a numeric calculation produces a result that exceeds the floating-point range.
4DA5
DEFM "OUT OF MEMORY" + 00H
ROM BASIC error 6 (internal code 0CH). Triggered when the program runs out of available RAM for variables, strings, arrays, or program text.
4DB3
DEFM "UNDEFINED LINE #" + 00H
ROM BASIC error 7 (internal code 0EH). Triggered when a GOTO or GOSUB references a line number that does not exist in the program.
4DC4
DEFM "SUBSCRIPT OUT OF RANGE" + 00H
ROM BASIC error 8 (internal code 10H). Triggered when an array subscript is outside the declared bounds of the array.
4DDB
DEFM "REDIMENSIONED ARRAY" + 00H
ROM BASIC error 9 (internal code 12H). Triggered when a DIM statement attempts to re-dimension an array that has already been dimensioned.
4DEF
DEFM "DIVISION BY ZERO" + 00H
ROM BASIC error 10 (internal code 14H). Triggered when a division or MOD operation attempts to divide by zero.
4E00
DEFM "ILLEGAL DIRECT" + 00H
ROM BASIC error 11 (internal code 16H). Triggered when a statement that is only valid inside a program is entered in direct mode (e.g., INPUT, DEF FN).
4E0F
DEFM "TYPE MISMATCH" + 00H
ROM BASIC error 12 (internal code 18H). Triggered when an operation attempts to use a string value where a numeric value is required, or vice versa.
4E1D
DEFM "OUT OF STRING SPACE" + 00H
ROM BASIC error 13 (internal code 1AH). Triggered when the string storage area is exhausted and garbage collection cannot reclaim enough space.
4E31
DEFM "STRING TOO LONG" + 00H
ROM BASIC error 14 (internal code 1CH). Triggered when a string operation produces a result longer than 255 characters.
4E41
DEFM "STRING FORMULA TOO COMPLEX" + 00H
ROM BASIC error 15 (internal code 1EH). Triggered when a string expression contains too many nested operations for the expression evaluator stack.
4E5C
DEFM "CAN'T CONTINUE" + 00H
ROM BASIC error 16 (internal code 20H). Triggered when a CONT command is issued but the program cannot be continued (e.g., after editing, CLEAR, or NEW).
4E6B
DEFM "NO RESUME" + 00H
ROM BASIC error 17 (internal code 22H). Triggered when an error-handling routine ends without a RESUME statement to return control.
4E75
DEFM "RESUME WITHOUT ERROR" + 00H
ROM BASIC error 18 (internal code 24H). Triggered when a RESUME statement is executed but no error condition is pending.
4E8A
DEFM "UNPRINTABLE ERROR" + 00H
ROM BASIC error 19 (internal code 26H). Used as a fallback for error codes in the range 47-98 decimal that have no defined message. Displayed as ? followed by the error number.
4E9C
DEFM "MISSING OPERAND" + 00H
ROM BASIC error 20 (internal code 28H). Triggered when an expression is incomplete or an operator has no right-hand operand.
4EAC
DEFM "BAD FILE DATA" + 00H
ROM BASIC error 21 (internal code 2AH). Triggered when an INPUT# or GET statement reads data from a file that does not match the expected type.
4EBA
DEFM "DISK BASIC FEATURE" + 00H
ROM BASIC error 22 (internal code 2CH). Triggered when a Disk BASIC command (such as OPEN, CLOSE, GET, PUT) is used but the DOS overlay for that feature is not loaded.

4ECDH – Error Message String Table (NEWDOS/80 DOS Errors 50–84)

Continuing the error message string table, entries 23–57 (indices 23–57) correspond to NEWDOS/80 DOS-specific error messages. These errors are unique to Disk BASIC and the NEWDOS/80 operating system. The displayed error number is the table index plus 27 (e.g., index 23 = error 50, index 24 = error 51, through index 57 = error 84). Five entries contain only “?” and serve as placeholders for undefined error numbers (57, 60, 61, 74, and 81). The table ends with a final 00H terminator at 50FDH that marks the absolute end of the error list.

4ECD
DEFM "UNDEFINED USER FUNCTION" + 00H
NEWDOS/80 DOS error 50. Triggered when a user-defined function (DEF FN) is called but has not been defined.
4EE5
DEFM "FIELD OVERFLOW" + 00H
NEWDOS/80 DOS error 51. Triggered when a FIELD statement attempts to allocate more bytes than the record length of the file.
4EF4
DEFM "INTERNAL ERROR" + 00H
NEWDOS/80 DOS error 52. Triggered when an unexpected internal inconsistency is detected within the BASIC runtime.
4F03
DEFM "BAD FILE #" + 00H
NEWDOS/80 DOS error 53. Triggered when an invalid file number (outside the range 1 to the maximum configured files) is used in a file I/O statement.
4F0E
DEFM "FILE NOT FOUND" + 00H
NEWDOS/80 DOS error 54. Triggered when an OPEN, KILL, or NAME statement references a file that does not exist on disk.
4F1D
DEFM "BAD FILE MODE" + 00H
NEWDOS/80 DOS error 55. Triggered when a file I/O operation is incompatible with the mode in which the file was opened (e.g., writing to an input-only file).
4F2B
DEFM "FILE ALREADY OPEN" + 00H
NEWDOS/80 DOS error 56. Triggered when an OPEN statement attempts to open a file that is already open on another file number.
4F3D
DEFM "?" + 00H
NEWDOS/80 DOS error 57. Placeholder entry for an undefined error number. Displays as ?.
4F3F
DEFM "DOS ERROR" + 00H
NEWDOS/80 DOS error 58. Triggered when a DOS-level error occurs during a file operation. The underlying DOS error code is reported separately.
4F49
DEFM "FILE ALREADY EXISTS" + 00H
NEWDOS/80 DOS error 59. Triggered when a NAME statement attempts to rename a file to a name that already exists on disk.
4F5D
DEFM "?" + 00H
NEWDOS/80 DOS error 60. Placeholder entry for an undefined error number. Displays as ?.
4F5F
DEFM "?" + 00H
NEWDOS/80 DOS error 61. Placeholder entry for an undefined error number. Displays as ?.
4F61
DEFM "DISK FULL" + 00H
NEWDOS/80 DOS error 62. Triggered when a write operation cannot complete because the disk has no free granules remaining.
4F6B
DEFM "INPUT PAST END" + 00H
NEWDOS/80 DOS error 63. Triggered when a GET or INPUT# statement attempts to read past the end of the file.
4F7A
DEFM "BAD RECORD #" + 00H
NEWDOS/80 DOS error 64. Triggered when a record number specified in a GET or PUT statement is zero or exceeds the maximum valid record number (32767).
4F87
DEFM "BAD FILE NAME" + 00H
NEWDOS/80 DOS error 65. Triggered when a filespec contains invalid characters or does not conform to the 8.3 filename format.
4F95
DEFM "MODE MISMATCH" + 00H
NEWDOS/80 DOS error 66. Triggered when a file I/O statement (GET, PUT, PRINT#, INPUT#) is used with a file opened in an incompatible mode.
4FA3
DEFM "DIRECT STATEMENT IN FILE" + 00H
NEWDOS/80 DOS error 67. Triggered when a file being loaded with LOAD or MERGE contains a direct-mode statement (a line without a line number).
4FBC
DEFM "TOO MANY FILES" + 00H
NEWDOS/80 DOS error 68. Triggered when the maximum number of simultaneously open files (as configured in NEWDOS/80) has been reached.
4FCB
DEFM "DISK WRITE PROTECTED" + 00H
NEWDOS/80 DOS error 69. Triggered when a write operation is attempted on a disk that has its write-protect tab enabled.
4FE0
DEFM "FILE ACCESS DENIED" + 00H
NEWDOS/80 DOS error 70. Triggered when a file operation is denied because the file has access restrictions set in its directory entry.
4FF3
DEFM "SEQ # OVERFLOW" + 00H
NEWDOS/80 DOS error 71. Triggered when a sequential file record number overflows the maximum allowable value.
5002
DEFM "RECORD OVERFLOW" + 00H
NEWDOS/80 DOS error 72. Triggered when a record written to a random-access file exceeds the declared record length.
5012
DEFM "ILLEGAL TO EXTEND FILE" + 00H
NEWDOS/80 DOS error 73. Triggered when a write operation attempts to extend a file beyond its allocated space and extension is not permitted.
5029
DEFM "?" + 00H
NEWDOS/80 DOS error 74. Placeholder entry for an undefined error number. Displays as ?.
502B
DEFM "PREVIOUSLY DISPLAYED ERROR" + 00H
NEWDOS/80 DOS error 75. This error code indicates that the error message has already been displayed by a lower-level routine. The BASIC error handler suppresses duplicate display.
5046
DEFM "CAN'T PROCESS LINE 0" + 00H
NEWDOS/80 DOS error 76. Triggered when the RENUM command or an error handler encounters a reference to line 0, which is invalid in NEWDOS/80 BASIC.
505B
DEFM "BAD FILE TYPE" + 00H
NEWDOS/80 DOS error 77. Triggered when a file operation encounters a file whose type code does not match the expected type for the operation.
5069
DEFM "IGEL SYNTAX ERROR" + 00H
NEWDOS/80 DOS error 78. Triggered by the IGEL (Interactive Game/Education Language) processor when the IGEL command syntax is invalid.
507B
DEFM "IGEL ITEM SYNTAX ERROR" + 00H
NEWDOS/80 DOS error 79. Triggered by the IGEL processor when an individual item within an IGEL command has invalid syntax.
5092
DEFM "BAD/ILLEGAL/MISSING IGEL ITEM PREFIX" + 00H
NEWDOS/80 DOS error 80. Triggered by the IGEL processor when an item is missing its required prefix character or uses an invalid/illegal prefix.
50B7
DEFM "?" + 00H
NEWDOS/80 DOS error 81. Placeholder entry for an undefined error number. Displays as ?.
50B9
DEFM "BAD RECORD LENGTH" + 00H
NEWDOS/80 DOS error 82. Triggered when a random-access file is opened with an invalid record length (zero or exceeding the sector size).
50CB
DEFM "STMT USES 2 FILE AREAS" + 00H
NEWDOS/80 DOS error 83. Triggered when a statement (such as NAME) requires two filespecs but encounters an error in parsing the second filename.
50E2
DEFM "BAD FILE POSITIONING PARAM" + 00H
NEWDOS/80 DOS error 84. Triggered when a file positioning operation (such as a FIELD or record seek) receives an invalid parameter value.
50FD
DEFB 00H
End-of-error-list delimiter. This final 00H byte follows the last error message string and marks the absolute end of the error message table. When the table walk loop at 4D38H encounters two consecutive 00H bytes (the last message’s terminator followed by this byte), it recognizes that the table has been exhausted.

50FEH – ERROR/RESUME/ON ERROR GOTO Statement Handler

This routine handles the BASIC ERROR statement (token 4FH). When the BASIC interpreter encounters the ERROR token during program execution, it jumps here from 4D0EH. The handler clears the error state flag at 4288H, then parses up to 4 comma-separated numeric parameters from the ERROR statement. These parameters specify: the start line number (stored at 4D00H), the end line number (stored at 4D02H), and optionally USING/XREF modifiers (stored at 4D0AH/4D0BH). The routine validates line number ranges against the bounds stored at 4D04H–4D07H, walks the BASIC program line chain via the pointer at 40A4H, updates line link addresses, and manages the cross-reference table at 64A3H. RST 10H is used for expression evaluation and RST 18H for 16-bit unsigned comparison.

50FE
XOR A AF
Set Register A to 00H and clear all flags. This zero value will be used to initialize the error state flag.
50FF
Store 00H (Register A) to memory location 4288H (the error state flag in the DOS work area). This clears any pending error condition, initializing the handler for fresh parameter parsing.
5102
LD BC,4D00H 01 00 4D
Point Register Pair BC to 4D00H (the start of the SYS13 parameter area). Register Pair BC will be used as a destination pointer for storing the parsed parameter values. The first parameter (start line number) will be stored at 4D00H–4D01H.
5105
LD A,(HL) 7E
Load Register A with the byte at the address pointed to by Register Pair HL (the current position in the BASIC program text being executed). This fetches the next token or character after the ERROR keyword.
5106
OR A B7
OR Register A with itself. Sets the Z FLAG if the byte is 00H (end of statement), or NZ FLAG if there are parameters following the ERROR keyword.
5107
If the Z FLAG has been set (end of statement, no parameters), JUMP to 5130H. An ERROR statement with no parameters triggers an “Undefined Line Number” error via JP 1997H.
5109
LD A,04H 3E 04
Load Register A with 04H (decimal 4). This is the maximum number of comma-separated parameters the ERROR statement accepts.

Top of Loop
Parameter Parsing Loop

510B
EX AF,AF’ 08
Exchange Register A and flags with the alternate Register A’ and flags’. This saves the parameter counter (4, then 3, 2, 1) in the alternate register set, freeing Register A for expression evaluation.
510C
DEC HL 2B
DECrement Register Pair HL by 1. This backs up the program text pointer by one position so that RST 10H (the expression evaluator) can re-read the current token as the start of the numeric expression.
510D
RST 10H D7
GOSUB to the RST 10H vector (the BASIC expression evaluator). This evaluates the numeric expression starting at (HL) and returns the result in Register Pair DE. The CARRY FLAG is set if a valid numeric result was obtained; NO CARRY if the expression is not numeric (e.g., a keyword like USING or XREF).
510E
If the CARRY FLAG has been set (a valid numeric expression was evaluated), JUMP to 5116H to convert the result and store it in the parameter area.
5110
CP 2CH FE 2C
Compare Register A against 2CH (ASCII comma ,). If the expression evaluator did not find a number, check whether the next character is a comma (indicating an omitted parameter).
5112
If the Z FLAG has been set (the character is a comma, meaning the parameter was omitted), JUMP to 5126H to skip this parameter and advance to the next one, leaving the default value in place.
5114
Unconditional JUMP to 5139H. The expression was not numeric and not a comma, so it must be a keyword modifier (USING or XREF). Jump to the modifier detection code.
5116
GOSUB to ROM routine at 1E5AH. This routine converts the floating-point result of the expression evaluation into a 16-bit unsigned integer in Register Pair DE. If the value is out of range (negative or > 65535), an error is generated.
5119
LD A,E 7B
Load Register A with the low byte of the result (Register E).
511A
LD (BC),A 02
Store the low byte (Register A) to the address pointed to by Register Pair BC (the current parameter position in the 4D00H area).
511B
INC BC 03
INCrement Register Pair BC by 1 to advance the parameter pointer to the high byte position.
511C
LD A,D 7A
Load Register A with the high byte of the result (Register D).
511D
LD (BC),A 02
Store the high byte (Register A) to the address pointed to by Register Pair BC.
511E
DEC BC 0B
DECrement Register Pair BC by 1 to point back to the low byte position. The parameter has been stored as a 16-bit little-endian value at (BC) and (BC+1).
511F
OR E B3
OR Register A (high byte D) with Register E (low byte). If both bytes are zero (the parameter value is 0000H), the Z FLAG is set.
5120
If the Z FLAG has been set (the parameter value is zero), JUMP to 5130H. A zero value for the first parameter (start line number) triggers an “Undefined Line Number” error.
5122
DEC HL 2B
DECrement Register Pair HL by 1 to back up the program text pointer for the next RST 10H call.
5123
RST 10H D7
GOSUB to the RST 10H vector to advance the program text pointer past any whitespace and fetch the next token.
5124
If the Z FLAG has been set (end of statement reached after the parameter), JUMP to 5148H to finalize parameter parsing and begin the line scan.
5126
RST 08H ⇒ 2CH CF 2C
RST 08H with inline byte 2CH (ASCII comma ,). This checks that the next character in the program text is a comma separator between parameters. If the character is not a comma, a SYNTAX ERROR is generated.
5128
INC BC 03
INCrement Register Pair BC by 1 to advance the parameter pointer past the low byte.
5129
INC BC 03
INCrement Register Pair BC by 1 again to advance past the high byte. BC now points to the next 2-byte parameter slot in the 4D00H area.
512A
EX AF,AF’ 08
Exchange Register A with the alternate A’ to retrieve the parameter counter.
512B
DEC A 3D
DECrement Register A (the parameter counter) by 1. When the counter reaches zero, all 4 parameters have been processed.
512C
If the NZ FLAG has been set (the parameter counter has not reached zero, more parameters remain), JUMP back to 510BH to parse the next parameter.

End of Loop
Parameter Parsing Loop

512E
Unconditional JUMP to 5139H. All 4 numeric parameters have been parsed; proceed to check for USING/XREF keyword modifiers.

Error Exit for Invalid Parameters

5130
JUMP to ROM routine at 1997H. This is the “Undefined Line Number” error exit (error code 0EH). Triggered when the ERROR statement has no parameters or when a line number parameter is zero.

USING/XREF Modifier Detection
After numeric parameters have been parsed, the code checks for the optional USING keyword (token 55H) or XREF keyword (token 58H). These keywords modify the behavior of the ERROR statement to control output formatting or cross-reference generation.

5133
LD (DE),A 12
Store Register A to the address pointed to by Register Pair DE. DE points to either 4D0AH (USING flag) or 4D0BH (XREF flag). The value stored is the token byte (55H for USING, 58H for XREF), which serves as a non-zero flag indicating the modifier is active.
5134
RST 10H D7
GOSUB to the RST 10H vector to advance the program text pointer past the keyword token and fetch the next token.
5135
If the Z FLAG has been set (end of statement), JUMP to 5148H to finalize parsing and begin the line scan.
5137
RST 08H ⇒ 2CH CF 2C
RST 08H with inline byte 2CH (ASCII comma ,). Verify that the next character is a comma. If not, SYNTAX ERROR.
5139
LD DE,4D0AH 11 0A 4D
Point Register Pair DE to 4D0AH (the USING flag location in the parameter area). If the next token is the USING keyword, the token value will be stored here.
513C
LD A,(HL) 7E
Load Register A with the current byte from the program text pointed to by HL.
513D
CP 55H FE 55
Compare Register A against 55H (the USING keyword token). If Register A equals 55H, the Z FLAG is set.
513F
If the Z FLAG has been set (the token is USING), JUMP back to 5133H to store the USING flag at (DE) = 4D0AH and continue parsing.
5141
LD DE,4D0BH 11 0B 4D
Point Register Pair DE to 4D0BH (the XREF/secondary flag location in the parameter area).
5144
CP 58H FE 58
Compare Register A against 58H (the XREF keyword token). If Register A equals 58H, the Z FLAG is set.
5146
If the Z FLAG has been set (the token is XREF), JUMP back to 5133H to store the XREF flag at (DE) = 4D0BH and continue parsing.

Parameter Validation and Line Scan Initialization
All parameters and modifiers have been parsed. The code validates the start and end line numbers against the configured range bounds, then begins scanning the BASIC program line chain.

5148
OR A B7
OR Register A with itself to set flags based on the last parsed byte. If Register A is 00H (end of statement), the Z FLAG is set. If non-zero (unexpected token), the NZ FLAG is set.
5149
If the NZ FLAG has been set (unexpected token at end of parameter list), JUMP to 5130H to generate an “Undefined Line Number” error.
514B
LD DE,(4D04H) ED 5B 04 4D
Load Register Pair DE with the 16-bit value at 4D04H–4D05H (the range start parameter). This is the lower bound of valid line numbers for the operation.
514F
LD HL,(4D06H) 2A 06 4D
Load Register Pair HL with the 16-bit value at 4D06H–4D07H (the range end parameter, initialized to FFF9H = 65529 decimal, the maximum valid BASIC line number).
5152
RST 18H DF
GOSUB to the RST 18H vector (16-bit unsigned comparison). Compares HL against DE. If HL < DE (the end line number is less than the start line number), the CARRY FLAG is set.
5153
If the CARRY FLAG has been set (end < start, an invalid range), JUMP to 5130H to generate an “Undefined Line Number” error.
5155
EX DE,HL EB
Exchange Register Pairs DE and HL. Now HL = range start (from 4D04H), DE = range end (from 4D06H).
5156
LD HL,FFF9H 21 F9 FF
Point Register Pair HL to FFF9H (65529 decimal), the maximum valid BASIC line number in NEWDOS/80.
5159
RST 18H DF
GOSUB to the RST 18H vector. Compares HL (FFF9H) against DE (range end). If FFF9H < range end, the range end exceeds the maximum valid line number and the CARRY FLAG is set.
515A
If the CARRY FLAG has been set (range end exceeds 65529), JUMP to 5130H to generate an “Undefined Line Number” error.

BASIC Program Line Scan
The parameters are valid. The code now scans the BASIC program’s linked-list line chain starting from the program start pointer at 40A4H. Register Pair BC is initialized to 0000H as a line counter. Each line link is a 2-byte pointer to the next line; a link of 0000H marks the end of the program. [LOOP START — main line scan]

515C
LD BC,0000H 01 00 00
Load Register Pair BC with 0000H, initializing the line counter to zero.
515F
Load Register Pair HL with the 16-bit value at 40A4H (the BASIC program start pointer). HL now points to the first byte of the first line’s link field in the program text.
5162
LD E,(HL) 5E
Load Register E with the low byte of the line link at (HL). This is the low byte of the address of the next line in the program.
5163
INC HL 23
INCrement Register Pair HL by 1 to point to the high byte of the line link.
5164
LD D,(HL) 56
Load Register D with the high byte of the line link at (HL). Register Pair DE now holds the complete 16-bit line link (the address of the next line).
5165
LD A,D 7A
Load Register A with Register D (the high byte of the line link).
5166
OR E B3
OR Register A (high byte) with Register E (low byte). If both are zero (the line link is 0000H), the Z FLAG is set, indicating the end of the BASIC program has been reached.
5167
If the Z FLAG has been set (end of program), JUMP to 51B5H to finalize the line count and set up the cross-reference table.
5169
PUSH DE D5
Save Register Pair DE (the next line address) onto the stack. This value will be used later as the starting point for scanning the next line.
516A
INC BC 03
INCrement Register Pair BC by 1 to count this line.
516B
LD A,(4D0AH) 3A 0A 4D
Load Register A with the byte at 4D0AH (the USING flag). If non-zero, the USING modifier is active.
516E
OR A B7
OR Register A with itself to set flags. Z FLAG is set if the USING flag is 00H (inactive); NZ FLAG is set if the USING flag is non-zero (active).
516F
If the NZ FLAG has been set (USING is active), JUMP to 51A9H to skip the line number range check and proceed directly to the next-line scan routine at 5CCCH.

Line Number Range Check
The USING modifier is not active, so the code reads the current line’s line number and checks whether it falls within the specified range (4D04H to 4D06H). If within range, the line is processed; if outside the range, the line is skipped.

5171
PUSH HL E5
Save Register Pair HL (the current position in the line link field) onto the stack.
5172
INC HL 23
INCrement Register Pair HL to skip past the high byte of the line link, advancing to the line number field.
5173
LD E,(HL) 5E
Load Register E with the low byte of the line number at (HL).
5174
INC HL 23
INCrement Register Pair HL to point to the high byte of the line number.
5175
LD D,(HL) 56
Load Register D with the high byte of the line number at (HL). Register Pair DE now holds the current line’s 16-bit line number.
5176
LD A,D 7A
Load Register A with Register D (high byte of the line number).
5177
OR E B3
OR Register A with Register E. If both are zero (line number is 0), the Z FLAG is set. A line number of zero is invalid.
5178
LD A,96H 3E 96
Load Register A with 96H (150 decimal). This is the internal error code for a line-number-zero error, which corresponds to displayed error 76 (“CAN’T PROCESS LINE 0”). Note: (96H − 34H) / 2 = 49, and table index 49 + 27 = displayed error 76.
517A
If the Z FLAG has been set (line number is 0000H), JUMP to 5DE2H in the BASIC/CMD module, the error dispatch routine. Register A contains the error code 96H, which will produce displayed error 76 (“CAN’T PROCESS LINE 0”).
517D
LD HL,(4D04H) 2A 04 4D
Load Register Pair HL with the 16-bit value at 4D04H (the range start parameter).
5180
EX DE,HL EB
Exchange Register Pairs DE and HL. Now HL = current line number, DE = range start.
5181
RST 18H DF
GOSUB to the RST 18H vector. Compares HL (line number) against DE (range start). If the line number is less than the range start, the CARRY FLAG is set.
5182
EX DE,HL EB
Exchange Register Pairs DE and HL back. HL = range start, DE = line number.
5183
If the CARRY FLAG has been set (line number < range start), JUMP to 51A4H to skip this line (it is below the specified range).
5185
LD HL,(4D06H) 2A 06 4D
Load Register Pair HL with the 16-bit value at 4D06H (the range end parameter).
5188
RST 18H DF
GOSUB to the RST 18H vector. Compares HL (range end) against DE (line number). If the range end is less than the line number, the CARRY FLAG is set (line is beyond the range).
5189
If the CARRY FLAG has been set (line number > range end), JUMP to 51A4H to skip this line (it is above the specified range).

Line Within Range — Process It
The current line number falls within the specified range. The code saves the current start line number from 4D00H, stores the current line number, and calculates the next start value by adding the increment from 4D02H.

518B
LD HL,(4D00H) 2A 00 4D
Load Register Pair HL with the 16-bit value at 4D00H (the current start line number parameter).
518E
LD (4D08H),HL 22 08 4D
Store Register Pair HL to 4D08H (the saved line number value). This preserves the current start line number for reference during this iteration.
5191
EX DE,HL EB
Exchange Register Pairs DE and HL. Now HL = current line number (from DE), DE = saved start value.
5192
LD HL,FFF9H 21 F9 FF
Point Register Pair HL to FFF9H (65529 decimal), the maximum valid BASIC line number.
5195
RST 18H DF
GOSUB to the RST 18H vector. Compares HL (FFF9H) against DE (the current line number from the saved value). If FFF9H < DE, the value is invalid.
5196
LD A,8CH 3E 8C
Load Register A with 8CH (140 decimal). This is the internal error code for a bad record number error, corresponding to displayed error 64 (“BAD RECORD #”). Note: (8CH − 34H) / 2 = 44, but since the error code lookup uses the 99+ range: (8CH − 34H) / 2 = 2CH / 2 = 22H = 44. Table index 44 − 27 does not map correctly. The actual mapping: 8CH = 140 decimal, which is ≥ 99, so index = (140 − 52) / 2 = 44, and displayed = 44 + 27 = 71 (“SEQ # OVERFLOW”). This error is raised when the calculated line number exceeds the maximum.
5198
If the CARRY FLAG has been set (the line number exceeds 65529), JUMP to 5DE2H in the BASIC/CMD module, the error dispatch routine. Register A contains error code 8CH.
519B
LD HL,(4D02H) 2A 02 4D
Load Register Pair HL with the 16-bit value at 4D02H (the increment value parameter).
519E
ADD HL,DE 19
ADD Register Pair DE (the current start line number) to Register Pair HL (the increment). HL now contains the next start line number value (current + increment).
519F
LD (4D00H),HL 22 00 4D
Store the updated start line number (Register Pair HL) back to 4D00H, advancing the parameter for the next iteration.
51A2
If the CARRY FLAG has been set (the addition overflowed past FFFFH), JUMP back to 5196H to load error code 8CH and generate an overflow error.

Update Line Link and Continue Scan
The line has been processed and the start line number advanced. The code now updates the line link pointer and proceeds to the next line in the chain.

51A4
POP HL E1
Restore Register Pair HL from the stack (the saved position in the line link field, pushed at 5171H).
51A5
LD (HL),D 72
Store Register D (the high byte of the updated line address) to (HL), the high byte position of the line link field.
51A6
DEC HL 2B
DECrement Register Pair HL to point to the low byte of the line link field.
51A7
LD (HL),E 73
Store Register E (the low byte of the updated line address) to (HL), the low byte position of the line link field.
51A8
INC HL 23
INCrement Register Pair HL to restore it to the high byte position for subsequent operations.
51A9
GOSUB to 5CCCH in the BASIC/CMD module. This routine performs the per-line processing (scanning the line body for tokens, handling USING formatting, or collecting cross-reference data).
51AC
POP DE D1
Restore Register Pair DE from the stack (the next line address, saved at 5169H). DE now points to the start of the next line in the BASIC program.
51AD
RST 18H DF
GOSUB to the RST 18H vector. Compares the current address against DE (the next line start). If they are equal (Z FLAG set), the scan has reached the next line’s link field correctly.
51AE
If the Z FLAG has been set (next line reached successfully), JUMP back to 5162H to process the next line. [LOOP — continue scanning program lines]
51B0
LD A,72H 3E 72
Load Register A with 72H (114 decimal). This is the internal error code which via the 99+ path: (114 − 52) / 2 = 31, table index 31 + 27 = displayed error 58 (“DOS ERROR”). This error indicates an internal inconsistency in the line chain.
51B2
JUMP to 5DE2H in the BASIC/CMD module, the error dispatch routine. Register A contains error code 72H (“DOS ERROR”). [LOOP END — main line scan]

End of Program — Cross-Reference Table Setup
The scan has reached the end of the BASIC program (a line link of 0000H was found at 5167H). Register Pair BC holds the total line count. The code now calculates which page of the cross-reference table at 64A3H to populate, determines the number of entries (up to 128), and calls the SVC routine to initialize the table.

51B5
LD H,B 60
Load Register H with Register B (the high byte of the line count from BC).
51B6
LD L,C 69
Load Register L with Register C (the low byte of the line count). Register Pair HL now holds the total line count.
51B7
LD C,A 4F
Load Register C with Register A (which is 00H from the OR E at 5166H that set the Z FLAG). Register C is initialized to 00H as a page counter.
51B8
LD DE,0080H 11 80 00
Load Register Pair DE with 0080H (128 decimal). This is the maximum number of entries per page in the cross-reference table at 64A3H.

Top of Loop
Page Count Calculation

51BB
INC C 0C
INCrement Register C (the page counter) by 1.
51BC
SBC HL,DE ED 52
SUBtract with Carry: HL = HL − DE − Carry. Subtract 128 from the remaining line count. If the result is zero, the lines fit exactly into this page. If the result goes negative, the CARRY FLAG is set.
51BE
If the Z FLAG has been set (the remaining count is exactly zero), JUMP to 51C2H to proceed with C pages of 128 entries each.
51C0
If the NO CARRY FLAG has been set (there are still more than 128 lines remaining), JUMP back to 51BBH to increment the page counter and subtract another 128.

End of Loop

51C2
LD DE,64A3H 11 A3 64
Point Register Pair DE to 64A3H, the base address of the cross-reference table in memory. This table stores 2-byte line address entries used by the RENUM command and the error handler.
51C5
LD B,80H 06 80
Load Register B with 80H (128 decimal), the number of entries to initialize in the cross-reference table.
51C7
Load Register Pair HL with the 16-bit value at 40A4H (the BASIC program start pointer). HL points to the beginning of the program text for the cross-reference table initialization.
51CA
LD A,2DH 3E 2D
Load Register A with 2DH (45 decimal). This is an SVC (Supervisor Call) function code used to invoke a DOS service for cross-reference table initialization.
51CC
RST 28H EF
GOSUB to the RST 28H vector, the SVC dispatcher. Invokes SVC function 2DH with DE pointing to the cross-reference table at 64A3H, B = 80H (128 entries), and HL pointing to the BASIC program start. This SVC populates the cross-reference table with the addresses of the first 128 BASIC lines.
51CD-51E7
NOP × 27 00 × 27
NOP padding. 27 bytes of 00H fill the remainder of the SYS13 overlay from 51CDH through 51E7H. This unused space pads the overlay to its required file size.