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

Page Customization

SYS11/SYS - BASIC RENUM Command Handler

SYS11 implements the BASIC RENUM (Renumber) command for NEWDOS/80 v2.0. This utility renumbers BASIC program lines and automatically updates all line number references in GOTO, GOSUB, ON...GOTO, ON...GOSUB, and similar statements. The command operates in two phases: Phase 1 scans the program building a table of old-to-new line number mappings, and Phase 2 performs the actual renumbering by updating all references throughout the program.

RENUM syntax: RENUM [new][,old[,increment]] where new is the starting line number for renumbering (default 10), old is the first line to begin renumbering from (default is start of program), and increment is the step between line numbers (default 10).

Variables:

AddressBytesPurpose
4D04H-4D05H2Starting old line number (RENUM from)
4D06H-4D07H2Ending old line number (RENUM to)
4D08H-4D09H2Maximum new line number limit
4D0AH1Flag: Non-zero if RENUM range specified
4D0BH1Flag: Non-zero if checking line bounds
4D4CH-4D4DH2Self-modifying: Line table pointer (scan address)
4DEDH-4DEEH2Current line number being parsed
4DE4H1Flag: DATA/REM skip mode
4E81H1Flag: Statement type indicator
4E8AH-4EC1H56Token dispatch table (token, handler address pairs)
4EF6H-4EF7H2Current BASIC program scan pointer
4F01H-4F02H2Current line start address
4FA6H1Bit flags: Bit 0 = first error displayed
5014H-5015H2Starting line address in program
5035H-5036H2Program expansion offset
50C0H-50C1H2Ending line number (high)
50C8H-50C9H2Last line address found
50F2H-50F3H2Program size adjustment
50F7H-50F8H2Available memory remaining
5121H1Phase flag: 0=Phase 1 (build table), 1=Phase 2 (renumber)
515AH-515BH2Line number difference (new - old)
515EH-515FH2Line count for current number parse
5168H-5169H2Memory expansion required
5170H-518BH28Error message: "FATAL ERROR. TEXT NOW BAD"
518CH-5197H12Error message: "ERROR LINES"
5198H-519CH5Completion message: "DONE"
51A2H-51F3H82Reserved/NOP area (workspace)
64CAH-654AH128Line number mapping table (64 entries × 2 bytes)

Key Routines:

AddressPurpose
4D0CH Entry point / store line number mapping
4D25H Phase 1 initialization
4D6AH Parse line content for tokens
4DADH Token dispatch loop
4E4CH Parse decimal line number (0-65529)
4E8AH Token dispatch table
4EC3H Binary search line lookup in mapping table
4F54H Display error with line number
4F97H Phase 1 complete / start Phase 2
4FFDH Phase 2 complete
5050H Fix next-line pointers after memory move
5063H Print "DONE" and return to BASIC
5120H Get next byte from program (phase-aware)
5147H Print message string

Self-Modifying Code Locations:

AddressSet ByPurpose
4D4CH4D65H, 4FEAHLine table pointer (in LD HL,nnnn)
4DEDH4D78HCurrent line number (in LD DE,nnnn)
4DE4H4DA8HDATA/REM skip flag (in LD A,nn)
4E81H4DA4H, 4DD1HStatement type flag (in OR nn)
4EF6H4D34H, 5007HScan pointer BC storage
4F01H4D38HCurrent line start (in LD HL,nnnn)
4FA6H4F65HError display flag (bit 0 = first shown)
5014H507BHStarting line address
5035H50CAHProgram expansion offset
50C0H5087HEnding line number (in LD DE,nnnn)
50C8H50AFHLast line address (in LD DE,nnnn)
50F2H50CDHProgram size adjustment (in LD DE,nnnn)
50F7H5117HRemaining memory (in LD DE,nnnn)
5121H4FDBHPhase flag: 0=Phase 1, non-zero=Phase 2
515AH5163HLine number difference storage
515EH4E73HDigit count storage (in LD DE,nnnn)
5168H516CHMemory expansion needed (in LD DE,nnnn)

Token Dispatch Table (4E8AH):

TokenHandlerMeaning
00H4D34HEnd of line - process next line
22H4D85HQuote - skip quoted string
3AH4DA3HColon - start new statement
88H4D9AHDATA - skip to end of statement
8DH4DD9HFOR - check for line numbers
8EH4DD9HNEXT - check for line numbers
91H4D7EHREM - skip to end of line
93H4DD4H(token) - parse line number
95H4DC5H(token) - check skip mode
9EH4DCFHRESTORE - parse line number
9FH4DC1H(token) - set skip mode
A1H4E23HRESUME - handle parentheses
A4H4E23HON - ON...GOTO/GOSUB handling
A5H4E12HON variant - same handling
B4H4E12HERL - error line handling
B5H4E03HELSE - check for line number
C2H4DD4HAUTO - parse line number
CAH4DADHDELETE - dispatch
FFH(end)End of table marker

Disassembly:

4D0CH - Entry Point / Store Line Number Mapping

This routine is called to store a line number mapping entry in the translation table. On entry, DE contains the old line number, BC contains the new line number, and HL points to the current position in the mapping table. The table stores pairs of (old, new) line numbers for Phase 2 reference lookup.

4D0C
EX DE,HL EB
Exchange DE and HL. Now HL = old line number, DE = table pointer
4D0D
LD (HL),E 73
Store low byte of table pointer at old line number address (this is swapped)
4D0E
INC HL 23
Advance to next byte
4D0F
LD (HL),D 72
Store high byte of table pointer
4D10
INC HL 23
Advance past the entry
4D11
PUSH HL E5
Save current table position
4D12
EX DE,HL EB
Restore: HL = table position, DE preserved
4D13
LD E,C 59
E = loop counter (number of lines to skip)
4D14
Jump into the line-skipping loop

[LOOP] Skip C lines in the BASIC program to find the next line to renumber

4D16
Call BASIC/CMD routine to advance HL to next BASIC line (skips current line)
4D19
DEC E 1D
Decrement line counter
4D1A
If counter reached zero, exit loop
4D1C
LD A,(HL) 7E
Load low byte of next line address
4D1D
INC HL 23
Point to high byte
4D1E
OR (HL) B6
OR with high byte - tests if next line address is 0000H (end of program)
4D1F
If not end of program, continue skipping lines
4D21
DEC HL 2B
Back up to point at end marker
4D22
POP DE D1
Restore table position into DE
4D23
[LOOP END] Decrement B and loop back if more entries to store

4D25H - Phase 1 Initialization

Initialize for Phase 1 scanning. This sets up the program scan from the beginning and prepares to build the line number mapping table. Phase 1 scans through the BASIC program identifying which lines will be renumbered and what their new numbers will be.

4D25
Call subroutine to find starting/ending lines and calculate renumber range
4D28
LD HL,(40A4H) 2A A4 40
Load HL with TXTTAB (start of BASIC program text) from system variable
4D2B
LD B,H 44
Copy HL to BC (program start address)
4D2C
LD C,L 4D
BC now holds TXTTAB
4D2D
LD DE,0000H 11 00 00
DE = 0 (initial line number difference)
4D30
LD (515AH),DE ED 53 5A 51
Store 0 in line difference variable (new - old = 0 initially)
4D34
LD (4EF6H),BC ED 43 F6 4E
Store current scan pointer in 4EF6H
4D38
LD (4F01H),HL 22 01 4F
Store current line start address in 4F01H

[MAIN LOOP START] - Scan each BASIC line for line number references

4D3B
LD A,(HL) 7E
Load low byte of next line pointer
4D3C
INC HL 23
Point to high byte
4D3D
OR (HL) B6
OR with high byte to test for end of program (0000H)
4D3E
DEC HL 2B
Point back to line start
4D3F
If end of program reached, jump to Phase 1 completion
4D42
LD A,(5121H) 3A 21 51
Load phase flag (0 = Phase 1, non-zero = Phase 2)
4D45
OR A B7
Test phase flag
4D46
If Phase 1 (flag = 0), skip the line number update code

[PHASE 2 ONLY] - Update the line number in the current BASIC line

4D48
PUSH HL E5
Save current line address
4D49
PUSH DE D5
Save DE (line number difference)
4D4A
EX DE,HL EB
DE = current line address
4D4B
LD HL,0000H 21 00 00
[SELF-MODIFYING at 4D4CH] Load HL with line mapping table pointer (modified by code at 4D65H)
4D4E
INC HL 23
Point to high byte of old line number in table
4D4F
LD A,(HL) 7E
Load high byte of old line number from table
4D50
CP D BA
Compare with high byte of current line address
4D51
If no match, skip update for this line
4D53
DEC HL 2B
Point to low byte
4D54
LD A,(HL) 7E
Load low byte of old line number
4D55
CP E BB
Compare with low byte of current line address
4D56
If no match, skip update

Match found - update the line number in the BASIC program

4D58
LD (HL),C 71
Store low byte of new line number
4D59
INC HL 23
Point to high byte
4D5A
LD (HL),B 70
Store high byte of new line number
4D5B
INC HL 23
Point to next table entry
4D5C
LD DE,65CAH 11 CA 65
Load end of mapping table address
4D5F
OR A B7
Clear carry for subtraction
4D60
SBC HL,DE ED 52
Check if we've reached end of table
4D62
If at table end, skip update of table pointer
4D64
ADD HL,DE 19
Restore HL to current table position
4D65
LD (4D4CH),HL 22 4C 4D
[SELF-MODIFY] Update the table pointer operand at 4D4CH for next iteration
4D68
POP DE D1
Restore DE
4D69
POP HL E1
Restore current line address

4D6AH - Parse Line Content

Skip past the line header (next line pointer and line number) and begin parsing the line content for tokens that reference line numbers (GOTO, GOSUB, etc.).

4D6A
Get next byte from BASIC line (skip next-line pointer low byte)
4D6D
Get next byte (skip next-line pointer high byte)
4D70
Get next byte (skip line number low byte)
4D73
LD E,A 5F
Save line number low byte in E
4D74
Get next byte (line number high byte)
4D77
LD D,A 57
Save line number high byte in D. DE now = current line number
4D78
LD (4DEDH),DE ED 53 ED 4D
Store current line number at 4DEDH for later reference
4D7C
Jump to begin statement scanning

4D7EH - Skip to End of Line

Called when we need to skip to the end of the current BASIC line (e.g., after processing a REM or DATA statement).

4D7E
Get next byte from line
4D81
[LOOP] If not end of line (00H), keep reading bytes
4D83
End of line reached, jump back to process next line

4D85H - Handle Quoted Strings

When a quote character (22H) is encountered in the BASIC line, this routine skips past the entire quoted string since line numbers inside strings should not be renumbered.

4D85
LD DE,4DADH 11 AD 4D
Load return address for string skip completion
4D88
PUSH DE D5
Push return address on stack
4D89
LD E,A 5F
E = quote character (22H) we're looking for
4D8A
Get next byte from line
4D8D
CP E BB
Compare with target character (closing quote)
4D8E
RET Z C8
If found closing quote, return (to 4DADH)
4D8F
OR A B7
Test if end of line (00H)
4D90
[LOOP] If not end of line, keep scanning for closing quote
4D92
POP AF F1
Discard return address (hit end of line)
4D93
Jump to process next BASIC line

4D95H - Check for Quote or Colon

Part of the main parsing loop. This checks if the current character is a quote (start of string literal) or a colon (statement separator). Strings must be skipped entirely, and colons signal the start of a new statement.

4D95
CP 22H FE 22
Compare A with " (22H = quote character)
4D97
If quote found, call string-skip routine to find closing quote
4D9A
Get next byte from BASIC line
4D9D
If end of line (00H), jump to process next line
4D9F
CP 3AH FE 3A
Compare with : (3AH = colon, statement separator)
4DA1
[LOOP] If not colon, continue scanning for quote or colon

4DA3H - Begin Statement Scan

Reset statement flags and begin scanning a new BASIC statement. This is entered after processing each statement separator (colon) or at the start of a line. The flags track whether we're in a DATA/REM statement and the statement type.

4DA3
XOR A AF
A = 0
4DA4
LD (4E81H),A 32 81 4E
Clear statement type flag
4DA7
XOR A AF
A = 0
4DA8
LD (4DE4H),A 32 E4 4D
Clear DATA/REM skip flag
4DAB
PUSH HL E5
Save current position (for PUSH/POP balance)
4DAC
POP HL E1
Restore HL (effectively a NOP pair, placeholder)

[TOKEN DISPATCH LOOP] - Get next byte and dispatch to appropriate handler based on token

4DAD
Get next byte from BASIC line
4DB0
PUSH HL E5
Save current scan position
4DB1
LD HL,4E8AH 21 8A 4E
Point HL to token dispatch table
4DB4
LD E,(HL) 5E
Load handler address low byte
4DB5
INC HL 23
Point to high byte
4DB6
LD D,(HL) 56
Load handler address high byte. DE = handler address
4DB7
INC HL 23
Point to token byte
4DB8
CP (HL) BE
Compare current byte with token in table
4DB9
INC HL 23
Advance to next table entry
4DBA
If current byte < table token, no match - restore HL and get next byte
4DBC
If not equal (and not less), try next table entry

Token match found - dispatch to handler

4DBE
POP HL E1
Restore scan position
4DBF
PUSH DE D5
Push handler address onto stack
4DC0
RET C9
Return to handler address (dispatch)

4DC1H - Set DATA/REM Skip Mode

Called when a DATA or REM token is encountered. Sets a flag that causes subsequent bytes to be skipped until end of line, since DATA constants and REM comments should not have their contents parsed for line numbers.

4DC1
LD A,01H 3E 01
A = 1 (set flag)
4DC3
Jump to store in DATA/REM skip flag and continue

4DC5H - Check Skip Mode Active

Check if DATA/REM skip mode is active. If so, all bytes are ignored until end of line.

4DC5
LD A,(4DE4H) 3A E4 4D
Load DATA/REM skip flag
4DC8
OR A B7
Test if flag is set
4DC9
If flag clear, return to normal token dispatch
4DCB
LD A,01H 3E 01
A = 1
4DCD
Jump to set statement type flag and continue

4DCFH - Handle GOTO/GOSUB Tokens

Called when GOTO (token CEH) or GOSUB (token CDH) is encountered. These statements require line number arguments that must be renumbered. This routine parses the line number and records it for potential update.

4DCF
LD A,01H 3E 01
A = 1 (mark that we expect a line number)
4DD1
LD (4E81H),A 32 81 4E
Store in statement type flag (indicates line number expected)
4DD4
Call routine to check if next byte is a digit (0-9)
4DD7
If not a digit, go back to token dispatch (no line number here)

Digit found - parse the line number

4DD9
Parse line number into DE
4DDC
Skip whitespace after the line number
4DDF
CP 2CH FE 2C
Compare with , (comma - ON GOTO/GOSUB list separator)
4DE1
If not comma, done with this statement's line numbers

Comma found - check for more line numbers in ON...GOTO/GOSUB list

4DE3
LD A,00H 3E 00
[SELF-MODIFYING at 4DE4H] Load A with skip flag (modified by 4DA8H)
4DE5
OR A B7
Test skip flag
4DE6
If flag set, continue parsing more line numbers
4DE8
PUSH AF F5
Save AF (placeholder)
4DE9
POP AF F1
Restore AF (NOP sequence for timing/spacing)
4DEA
LD A,58H 3E 58
A = 58H ('X') - error code for undefined line
4DEC
LD DE,0000H 11 00 00
[SELF-MODIFYING at 4DEDH] Load DE with current line number (stored at 4D78H)
4DEF
Call error/warning display routine with line number
4DF2
DEC BC 0B
Decrement BC (undo last increment)
4DF3
DEC HL 2B
Back up scan position
4DF4
Get next byte, checking for end of line/statement
4DF7
[LOOP] Continue skipping until end of statement

4DF9H - Line Number Overflow Error Handler

Called when a line number exceeds the maximum valid value (65529). Displays error and aborts operation.

4DF9
POP HL E1
Clean up stack - pop saved address
4DFA
POP BC C1
Pop BC
4DFB
POP AF F1
Pop AF
4DFC
LD A,53H 3E 53
A = 53H ('S') - error code for syntax/overflow error
4DFE
Jump to load current line number and display error

4E00H - Handle THEN Token

Handle the THEN token (D2H). THEN can be followed by a line number (for implied GOTO) or by statements. This checks if a digit follows.

4E00
Attempt to parse line number
4E03
Check if next character is a digit
4E06
If digit found, parse another line number (multiple targets)
4E08
CP D2H FE D2
Compare with THEN token (D2H)
4E0A
If less than THEN token, not a keyword needing line numbers
4E0C
CP D7H FE D7
Compare with token range upper bound (D7H)
4E0E
If within range (THEN-D6H), check for more digits
4E10
Return to main token dispatch loop

4E12H - Handle ON Token

Handle the ON token (A4H/A5H). ON...GOTO and ON...GOSUB statements have lists of line numbers that need renumbering. This scans for the GOTO or GOSUB token that follows the numeric expression.

4E12
Check if current character is a digit
4E15
If not a digit, check for GOTO/GOSUB token
4E17
Parse the line number (skip it - this is the selector expression)
4E1A
Skip whitespace
4E1D
CP CEH FE CE
Compare with GOTO token (CEH)
4E1F
If GOTO found, jump to parse line number list
4E21
Otherwise continue normal parsing

4E23H - Handle Function with Parentheses

Handle tokens that can have parenthesized arguments containing commas. This tracks parenthesis nesting so that commas inside parentheses are not mistaken for ON...GOTO/GOSUB separators.

4E23
LD D,02H 16 02
D = 2 (looking for 2 commas outside parentheses)
4E25
LD E,FFH 1E FF
E = FFH (-1, parenthesis depth counter starting value)
4E27
INC E 1C
Increment depth (E = 0 initially after first INC)
4E28
Get next byte from line
4E2B
CP 28H FE 28
Compare with ( (open parenthesis)
4E2D
If open paren, increment depth and continue
4E2F
DEC E 1D
Decrement depth (assume close paren)
4E30
CP 29H FE 29
Compare with ) (close parenthesis)
4E32
If close paren, continue (depth already decremented)
4E34
INC E 1C
Not close paren, restore depth
4E35
If depth non-zero (inside parens), continue scanning
4E37
CP 2CH FE 2C
Compare with , (comma)
4E39
If not comma, continue scanning
4E3B
DEC D 15
Found comma outside parens - decrement comma counter
4E3C
If more commas needed, continue scanning
4E3E
Found all expected commas, process as line number list

4E40H - Get Next Byte with End Check

Get next byte from the BASIC line, but check for end of line or statement separator. If either is found, pop return address and go to next statement.

4E40
Get next byte from line into A
4E43
OR A B7
Test for end of line (00H)
4E44
If end of line, clean up and exit
4E46
CP 3AH FE 3A
Compare with : (colon, statement separator)
4E48
RET NZ C0
If not colon, return with byte in A
4E49
POP DE D1
Discard return address from stack
4E4A
Jump to continue with next statement

4E4CH - Parse Line Number

Parse a decimal line number from the BASIC program text. Converts ASCII digits to binary and validates the result is within range (0-65529). Returns the line number in DE. If in Phase 2, also looks up the new line number from the mapping table.

4E4C
Check if current char is digit, get next if whitespace
4E4F
If not a digit, skip this (no line number)
4E51
PUSH BC C5
Save BC (output buffer pointer)
4E52
LD DE,0000H 11 00 00
DE = 0 (accumulator for line number)
4E55
LD B,D 42
B = 0
4E56
LD C,E 4B
C = 0. BC = 0 (digit counter)

[LOOP] Parse decimal digits, building line number in DE

4E57
PUSH HL E5
Save current scan position
4E58
INC BC 03
Increment digit count
4E59
LD HL,1998H 21 98 19
HL = 6552 (65520 / 10, max line number check)
4E5C
OR A B7
Clear carry
4E5D
SBC HL,DE ED 52
Check if DE > 6552 (would overflow on multiply by 10)
4E5F
If overflow, jump to error handler
4E61
LD H,D 62
HL = DE (copy current value)
4E62
LD L,E 6B
HL now = current accumulated value
4E63
ADD HL,HL 29
HL = 2 * value
4E64
ADD HL,HL 29
HL = 4 * value
4E65
ADD HL,DE 19
HL = 5 * value
4E66
ADD HL,HL 29
HL = 10 * value
4E67
SUB 30H D6 30
Convert ASCII digit to binary (A = A - '0')
4E69
LD E,A 5F
E = digit value
4E6A
LD D,B 50
D = 0. DE = digit (0-9)
4E6B
ADD HL,DE 19
HL = 10 * oldvalue + digit
4E6C
EX DE,HL EB
DE = new accumulated value
4E6D
POP HL E1
Restore scan position
4E6E
PUSH HL E5
Save it again
4E6F
RST 10H D7
Get next character (ROM routine)
4E70
EX (SP),HL E3
Swap HL with stack (update saved position)
4E71
If digit (carry set), continue parsing

Parsing complete - DE contains the line number

4E73
LD (515EH),BC ED 43 5E 51
Store digit count at 515EH
4E77
POP BC C1
Pop saved HL into BC (for stack balance)
4E78
INC HL 23
Advance past last digit
4E79
EX (SP),HL E3
Restore original BC from stack
4E7A
PUSH HL E5
Save current position
4E7B
LD A,D 7A
A = high byte of line number
4E7C
OR E B3
OR with low byte
4E7D
If line number non-zero, jump to lookup in table
4E80
OR 00H F6 00
[SELF-MODIFYING at 4E81H] OR with statement type flag
4E82
If flag set (line number expected), jump to handle special case
4E85
LD A,53H 3E 53
A = 53H ('S') - syntax error code
4E87
Jump to error display routine

4E8AH - Token Dispatch Table

This table maps BASIC tokens to handler addresses. Format: handler_low, handler_high, token. Searched linearly until token matches or FFH end marker.

4E8A
DEFB 34H,4DH,00H 34 4D 00
Token 00H (EOL): Handler 4D34H - Next line
4E8D
DEFB 85H,4DH,22H 85 4D 22
Token 22H (quote): Handler 4D85H - Skip string
4E90
DEFB A3H,4DH,3AH A3 4D 3A
Token 3AH (colon): Handler 4DA3H - New statement
4E93
DEFB 9AH,4DH,88H 9A 4D 88
Token 88H (DATA): Handler 4D9AH - Skip data
4E96
DEFB D9H,4DH,8DH D9 4D 8D
Token 8DH (FOR): Handler 4DD9H
4E99
DEFB 8EH,D9H,4DH 8E D9 4D
Token 8EH (NEXT): Handler 4DD9H
4E9C
DEFB 91H,7EH,4DH 91 7E 4D
Token 91H (REM): Handler 4D7EH - Skip to EOL
4E9F
DEFB 93H,D4H,4DH 93 D4 4D
Token 93H: Handler 4DD4H - Parse line#
4EA2
DEFB 95H,C5H,4DH 95 C5 4D
Token 95H: Handler 4DC5H - Check skip
4EA5
DEFB 9EH,CFH,4DH 9E CF 4D
Token 9EH (RESTORE): Handler 4DCFH
4EA8
DEFB 9FH,C1H,4DH 9F C1 4D
Token 9FH: Handler 4DC1H - Set skip
4EAB
DEFB A1H,23H,4EH A1 23 4E
Token A1H (RESUME): Handler 4E23H
4EAE
DEFB A4H,23H,4EH A4 23 4E
Token A4H (ON): Handler 4E23H
4EB1
DEFB A5H,12H,4EH A5 12 4E
Token A5H: Handler 4E12H
4EB4
DEFB B4H,12H,4EH B4 12 4E
Token B4H (ERL): Handler 4E12H
4EB7
DEFB B5H,03H,4EH B5 03 4E
Token B5H (ELSE): Handler 4E03H
4EBA
DEFB C2H,D4H,4DH C2 D4 4D
Token C2H (AUTO): Handler 4DD4H
4EBD
DEFB CAH,ADH,4DH CA AD 4D
Token CAH (DELETE): Handler 4DADH
4EC0
DEFB FFH FF
End of table marker

4EC3H - Binary Search Line Lookup

Binary search through the line mapping table at 64CAH to find a line number. Returns pointer to the line in BASIC program. Table has 64 two-byte entries (128 bytes total).

4EC3
LD HL,64CAH 21 CA 64
HL = line mapping table base
4EC6
LD BC,0080H 01 80 00
BC = 128 (initial search range)
4EC9
ADD HL,BC 09
HL = middle of current range
4ECA
PUSH HL E5
Save search position
4ECB
LD A,(HL) 7E
Load pointer low byte
4ECC
INC HL 23
Point to high byte
4ECD
LD H,(HL) 66
H = pointer high byte
4ECE
LD L,A 6F
HL = pointer to BASIC line
4ECF
LD A,(HL) 7E
Load next-line pointer low
4ED0
INC HL 23
Point to high byte
4ED1
OR (HL) B6
Test for end marker (0000H)
4ED2
INC HL 23
Point to line number
4ED3
SCF 37
Set carry (search lower)
4ED4
If end marker, exit search
4ED6
INC HL 23
Point to line# high byte
4ED7
LD A,D 7A
A = target line# high
4ED8
CP (HL) BE
Compare high bytes
4ED9
DEC HL 2B
Point to low byte
4EDA
If different, done comparing
4EDC
LD A,E 7B
A = target line# low
4EDD
CP (HL) BE
Compare low bytes
4EDE
POP HL E1
Restore search position
4EDF
If target >= entry, search higher
4EE1
OR A B7
Clear carry
4EE2
SBC HL,BC ED 42
Move search lower
4EE4
SRL C CB 39
Halve search range
4EE6
LD A,C 79
A = new range
4EE7
CP 02H FE 02
Minimum range check
4EE9
Continue binary search if range >= 2
4EEB
LD A,(HL) 7E
Load result pointer low
4EEC
INC HL 23
Point to high byte
4EED
LD H,(HL) 66
H = pointer high
4EEE
LD L,A 6F
HL = result line pointer
4EEF
LD A,(5121H) 3A 21 51
Load phase flag
4EF2
OR A B7
Test phase
4EF3
If Phase 1, skip check
4EF5
LD BC,0000H 01 00 00
[SELF-MOD 4EF6H] BC = scan start ptr
4EF8
LD A,H 7C
Compare found line with
4EF9
CP B B8
scan start pointer
4EFA
If different, continue
4EFC
LD A,L 7D
Compare low bytes
4EFD
CP C B9
Check match
4EFE
If different, continue
4F00
LD HL,0000H 21 00 00
[SELF-MOD 4F01H] HL = current line start
4F03
LD A,(HL) 7E
Load next-line ptr low
4F04
INC HL 23
Point to high byte
4F05
OR (HL) B6
Test for end (0000H)
4F06
If end, not found
4F08
INC HL 23
Point to line# low
4F09
LD C,(HL) 4E
C = line# low
4F0A
INC HL 23
Point to line# high
4F0B
LD A,(HL) 7E
A = line# high
4F0C
CP D BA
Compare with target high
4F0D
If different, check direction
4F0F
LD A,C 79
A = line# low
4F10
CP E BB
Compare with target low
4F11
If line >= target, found it
4F13
Advance to next BASIC line
4F16
Continue search
4F18
INC HL 23
Point past end marker
4F19
INC HL 23
HL at line# position
4F1A
INC A 3C
A = 1 (not found flag)
4F1B
SCF 37
Set carry (error)
4F1C
DEC HL 2B
Back to line# high
4F1D
DEC HL 2B
Back to line# low
4F1E
LD D,(HL) 56
D = line# high
4F1F
DEC HL 2B
Back to next-ptr high
4F20
LD E,(HL) 5E
E = line# low. DE = line number
4F21
RET C9
Return with line in DE

4F22H - Lookup Old Line Number

Called when a non-zero line number was parsed. Looks up the old line number in the mapping table to find its new value.

4F22
PUSH DE D5
Save parsed line number
4F23
Binary search for line in table
4F26
POP BC C1
BC = original parsed line#
4F27
If found (Z), handle it
4F29
LD D,B 50
DE = original line# (not found)
4F2A
LD E,C 59
Prepare for error display
4F2B
LD A,55H 3E 55
A = 55H ('U') - Undefined line error
4F2D
PUSH AF F5
Save error code
4F2E
LD A,(4D0BH) 3A 0B 4D
Load bounds check flag
4F31
OR A B7
Test flag
4F32
If not checking bounds, display error
4F34
LD HL,(4D06H) 2A 06 4D
HL = upper bound line#
4F37
RST 18H DF
Compare HL with DE (ROM compare)
4F38
If DE > upper, error
4F3A
LD HL,(4D04H) 2A 04 4D
HL = lower bound line#
4F3D
EX DE,HL EB
Swap for compare
4F3E
RST 18H DF
Compare
4F3F
EX DE,HL EB
Restore
4F40
If in range, show error
4F42
POP AF F1
Discard error code (line out of range OK)
4F43
POP BC C1
Restore BC
4F44
LD A,(5121H) 3A 21 51
Load phase flag
4F47
OR A B7
Test phase
4F48
If Phase 1, skip Phase 2 code
4F4A
Phase 2: Update line# in program
4F4D
Jump to cleanup
4F4F
Phase 1: Calculate memory needed
4F52
POP HL E1
Restore scan position
4F53
RET C9
Return to caller

4F54H - Display Error with Line Number

Display an error message with the offending line number. A = error code character, DE = line number.

4F54
PUSH HL E5
Save HL
4F55
PUSH BC C5
Save BC
4F56
PUSH AF F5
Save error code
4F57
LD A,(5121H) 3A 21 51
Load phase flag
4F5A
OR A B7
Test phase
4F5B
If Phase 2, fatal error
4F5E
LD HL,4FA6H 21 A6 4F
HL = error display flag address
4F61
BIT 0,(HL) CB 46
Test if first error already shown
4F63
If already shown, skip header
4F65
SET 0,(HL) CB C6
Set first-error flag
4F67
Print newline
4F6A
LD HL,518CH 21 8C 51
HL = "ERROR LINES" message
4F6D
Print message
4F70
LD A,(4020H) 3A 20 40
Load cursor column
4F73
AND 3FHAND 00111111 E6 3F
Mask to column (0-63)
4F75
CP 38H FE 38
Check if past column 56
4F77
If so, print newline
4F7A
LD BC,(4020H) ED 4B 20 40
BC = cursor position
4F7E
Print line number (DE)
4F81
LD (4020H),BC ED 43 20 40
Restore cursor
4F85
LD A,2FH 3E 2F
A = '/' separator
4F87
Print '/'
4F8A
POP AF F1
Restore error code
4F8B
Print error character
4F8E
Print space
4F91
Print space
4F94
POP BC C1
Restore BC
4F95
POP HL E1
Restore HL
4F96
RET C9
Return

4F97H - Phase 1 Complete / Start Phase 2

Called when Phase 1 scan reaches end of program. Checks if memory expansion is needed, expands program if necessary, then starts Phase 2 to actually update line numbers.

4F97
LD A,(5121H) 3A 21 51
Load phase flag
4F9A
OR A B7
Test phase
4F9B
If Phase 2, go to final completion
4F9E
LD A,(4D0AH) 3A 0A 4D
Load range-specified flag
4FA1
OR A B7
Test flag
4FA2
If range specified, skip to completion
4FA5
LD A,00H 3E 00
[SELF-MOD 4FA6H] Error display flag (bit 0 = shown)
4FA7
OR A B7
Test if errors were displayed
4FA8
If errors, abort with message
4FAB
LD HL,(40F9H) 2A F9 40
HL = string space boundary
4FAE
LD DE,(40A4H) ED 5B A4 40
DE = TXTTAB (program start)
4FB2
OR A B7
Clear carry
4FB3
SBC HL,DE ED 52
HL = program size
4FB5
LD B,H 44
BC = program size
4FB6
LD C,L 4D
For memory move
4FB7
LD HL,(5168H) 2A 68 51
HL = expansion needed
4FBA
BIT 7,H CB 7C
Check if negative (shrinking)
4FBC
If positive, continue
4FBE
LD HL,0000H 21 00 00
No expansion needed
4FC1
INC H 24
Add 256 bytes safety margin
4FC2
PUSH HL E5
Save expansion amount
4FC3
ADD HL,DE 19
HL = new program start
4FC4
ADD HL,BC 09
HL = new program end
4FC5
If overflow, out of memory
4FC7
EX DE,HL EB
DE = new end
4FC8
ADD HL,BC 09
HL = current end
4FC9
PUSH DE D5
Save new end
4FCA
EXX D9
Switch to alt registers
4FCB
POP DE D1
DE' = new end
4FCC
LD HL,(40B1H) 2A B1 40
HL' = STREND
4FCF
DEC H 25
Safety margin
4FD0
RST 18H DF
Compare HL' with DE'
4FD1
If insufficient memory, error
4FD4
INC H 24
Restore STREND
4FD5
POP BC C1
BC = expansion amount
4FD6
LD SP,HL F9
Set SP to safe location
4FD7
PUSH BC C5
Save expansion
4FD8
EXX D9
Back to main registers
4FD9
LD A,01H 3E 01
A = 1 (Phase 2)
4FDB
LD (5121H),A 32 21 51
Set phase flag to Phase 2
4FDE
LDDR ED B8
Move program up in memory
4FE0
LD A,(HL) 7E
Copy last byte
4FE1
LD (DE),A 12
To new location
4FE2
POP BC C1
BC = expansion amount
4FE3
PUSH DE D5
Save new TXTTAB
4FE4
LD E,80H 1E 80
E = 128 (table entries)
4FE6
PUSH HL E5
Save old TXTTAB
4FE7
LD HL,64CAH 21 CA 64
HL = mapping table
4FEA
LD (4D4CH),HL 22 4C 4D
Initialize table pointer

[LOOP] Update all pointers in mapping table by expansion offset

4FED
LD A,(HL) 7E
Load pointer low byte
4FEE
ADD A,C 81
Add offset low
4FEF
LD (HL),A 77
Store updated low
4FF0
INC HL 23
Point to high byte
4FF1
LD A,(HL) 7E
Load pointer high byte
4FF2
ADC A,B 88
Add offset high with carry
4FF3
LD (HL),A 77
Store updated high
4FF4
INC HL 23
Next entry
4FF5
DEC E 1D
Decrement counter
4FF6
Continue until all updated
4FF8
POP BC C1
BC = old TXTTAB
4FF9
POP HL E1
HL = new TXTTAB
4FFA
Start Phase 2 scan

4FFDH - Phase 2 Complete

Called when Phase 2 finishes. Skip past line header bytes, update string boundary, then compact the program back down.

4FFD
Skip next-line pointer bytes
5000
Skip line number bytes
5003
LD (40F9H),BC ED 43 F9 40
Update string boundary
5007
LD (4EF6H),BC ED 43 F6 4E
Update scan pointer
500B
Recalculate line ranges
500E
Calculate memory needed
5011
If no adjustment, done

[LOOP] Compact program - move data up if needed

5013
LD HL,0000H 21 00 00
[SELF-MOD 5014H] HL = start line address
5016
PUSH HL E5
Save start
5017
LD DE,(40F9H) ED 5B F9 40
DE = string boundary
501B
LDIR ED B0
Move block
501D
EX DE,HL EB
HL = new end
501E
OR A B7
Clear carry
501F
SBC HL,DE ED 52
Calculate difference
5021
LD B,H 44
BC = difference
5022
LD C,L 4D
For adjustment
5023
EX DE,HL EB
HL = destination
5024
POP DE D1
DE = start
5025
LDIR ED B0
Move remaining
5027
Recalculate
502A
Continue if more needed
502C
Final calculation
502F
LD HL,(40F9H) 2A F9 40
HL = string boundary
5032
PUSH HL E5
Save it
5033
PUSH BC C5
Save count
5034
LD DE,0000H 11 00 00
[SELF-MOD 5035H] DE = offset
5037
PUSH DE D5
Save offset
5038
PUSH HL E5
Save boundary
5039
PUSH BC C5
Save count
503A
OR A B7
Clear carry
503B
SBC HL,DE ED 52
Calc move size
503D
LD B,H 44
BC = size
503E
LD C,L 4D
For LDDR
503F
POP HL E1
HL = source end
5040
POP DE D1
DE = destination
5041
DEC DE 1B
Adjust for LDDR
5042
ADD HL,DE 19
HL = end address
5043
EX DE,HL EB
Swap for LDDR
5044
LDDR ED B8
Move block down
5046
POP DE D1
DE = offset
5047
POP BC C1
BC = count
5048
POP HL E1
HL = boundary
5049
LDIR ED B0
Copy remaining
504B
Recalculate
504E
Continue if needed

5050H - Fix Line Pointers

After moving program in memory, fix all the next-line pointers throughout the program.

5050
LD HL,(40A4H) 2A A4 40
HL = TXTTAB
5053
LD E,(HL) 5E
E = next-line low
5054
INC HL 23
Point to high
5055
LD D,(HL) 56
D = next-line high
5056
LD A,D 7A
Test for end
5057
OR E B3
DE = 0?
5058
If end, done
505A
INC HL 23
Point to line#
505B
LD (HL),E 73
Store updated ptr low
505C
INC HL 23
Point to high
505D
LD (HL),D 72
Store updated ptr high
505E
Advance to next line
5061
Continue loop

5063H - Print Done Message

Print "DONE" message and return to BASIC.

5063
LD HL,5198H 21 98 51
HL = "DONE" message
5066
Print message
5069
Print newline
506C
LD DE,(40A4H) ED 5B A4 40
DE = TXTTAB
5070
Return to BASIC (ROM re-link routine)

5073H - Calculate Line Ranges

Calculate the starting and ending line addresses for the renumber operation based on user-specified range.

5073
LD DE,(4D04H) ED 5B 04 4D
DE = start line number
5077
Find start line in program
507A
PUSH DE D5
Save result
507B
LD (5014H),HL 22 14 50
Store start address
507E
PUSH HL E5
Save HL
507F
LD DE,(4D06H) ED 5B 06 4D
DE = end line number
5083
INC DE 13
Include end line
5084
Find end line
5087
LD (50C0H),DE ED 53 C0 50
Store end line number
508B
POP BC C1
BC = start address
508C
OR A B7
Clear carry
508D
SBC HL,BC ED 42
HL = range size
508F
POP DE D1
DE = start line#
5090
PUSH BC C5
Save start addr
5091
PUSH HL E5
Save range size
5092
LD HL,(40A4H) 2A A4 40
HL = TXTTAB

[LOOP] Scan program to find last line before range

5095
LD A,(HL) 7E
Load next-line low
5096
INC HL 23
Point to high
5097
OR (HL) B6
Test for end
5098
If end, done
509A
INC HL 23
Point to line# low
509B
LD C,(HL) 4E
C = line# low
509C
INC HL 23
Point to high
509D
LD A,(HL) 7E
A = line# high
509E
CP D BA
Compare with target
509F
If different, check
50A1
LD A,C 79
Compare low bytes
50A2
CP E BB
Check match
50A3
If >= target, done
50A5
Advance to next line
50A8
Continue loop
50AA
DEC HL 2B
Back up
50AB
DEC HL 2B
To line start
50AC
LD D,(HL) 56
D = ptr high
50AD
DEC HL 2B
Point to low
50AE
LD E,(HL) 5E
E = ptr low
50AF
LD (50C8H),DE ED 53 C8 50
Store last line addr
50B3
POP BC C1
BC = range size
50B4
POP DE D1
DE = start addr
50B5
RST 18H DF
Compare DE, HL
50B6
If DE < HL, error
50B8
Additional check
50BB
If carry, adjust
50BD
If not zero, use BC
50BF
LD DE,0000H 11 00 00
[SELF-MOD 50C0H] DE = end line#
50C2
LD BC,0000H 01 00 00
BC = 0
50C5
Skip to store
50C7
LD DE,0000H 11 00 00
[SELF-MOD 50C8H] DE = last line addr
50CA
LD (5035H),HL 22 35 50
Store offset
50CD
LD (50F2H),BC ED 43 F2 50
Store size
50D1
LD HL,(4D08H) 2A 08 4D
HL = max new line#
50D4
RST 18H DF
Compare with DE
50D5
RET C D8
If max < end, return
50D6
LD A,D 7A
Test if DE = 0
50D7
OR E B3
Check zero
50D8
RET Z C8
If zero, return
50D9
LD A,8CH 3E 8C
A = error code (out of memory)
50DB
LD B,A 47
B = error code
50DC
LD A,(5121H) 3A 21 51
Load phase flag
50DF
OR A B7
Test phase
50E0
LD A,B 78
Restore error code
50E1
If Phase 1, display error
50E4
LD HL,5170H 21 70 51
HL = "FATAL ERROR" message
50E7
Print message
50EA
Jump to system reset

50EDH - Out of Memory Error

Called when there isn't enough memory to expand the program for renumbering.

50ED
LD A,0CH 3E 0C
A = 0CH (Out of Memory error code)
50EF
Jump to error handler

50F1H - Calculate Memory Adjustment (Shrink Path)

Calculate how much memory needs to be adjusted. Entry with DE=0 for shrinking path.

50F1
LD DE,0000H 11 00 00
[SELF-MOD 50F2H] DE = size adjustment value
50F4
Jump to common calculation code

50F6H - Calculate Memory Adjustment (Expand Path)

Calculate memory adjustment with stored offset value for expansion.

50F6
LD DE,0000H 11 00 00
[SELF-MOD 50F7H] DE = remaining memory to process
50F9
LD HL,(40B1H) 2A B1 40
HL = STREND (end of string storage)
50FC
DEC H 25
Subtract 256 bytes safety margin
50FD
LD BC,(40F9H) ED 4B F9 40
BC = string space boundary
5101
SBC HL,BC ED 42
HL = available memory space
5103
LD B,H 44
BC = available space
5104
LD C,L 4D
Copy for comparison
5105
EX DE,HL EB
HL = offset needed, DE = available
5106
LD A,D 7A
A = high byte of available
5107
DEC A 3D
Decrement for range check
5108
CP F0H FE F0
Check if within valid range
510A
If out of range, memory error
510D
OR A B7
Clear carry for subtraction
510E
SBC HL,BC ED 42
Compare offset with available
5110
If offset >= available, done
5112
ADD HL,BC 09
Restore HL value
5113
LD B,H 44
BC = updated remaining
5114
LD C,L 4D
For next iteration
5115
Continue loop
5117
LD (50F7H),HL 22 F7 50
Store remaining memory value
511A
LD A,B 78
A = BC high byte
511B
OR C B1
Test if BC = 0 (sets Z flag)
511C
RET C9
Return with Z flag indicating completion

511DH - Skip Whitespace

Skip any whitespace characters (spaces, tabs) and return the next significant byte in A.

511D
Get current byte and check for whitespace

5120H - Get Next Byte from Program

Fetch the next byte from the BASIC program being scanned. Updates scan position and optionally copies byte to output buffer. Self-modifying code controls copy behavior.

5120
LD A,00H 3E 00
[SELF-MOD 5121H] Phase flag: 0=Phase 1, non-zero=Phase 2
5122
OR A B7
Test phase flag
5123
LD A,(HL) 7E
Load byte from current position
5124
INC HL 23
Advance scan pointer
5125
If Phase 1, skip copy to output
5127
LD (BC),A 02
Phase 2: Copy byte to output buffer (BC)
5128
INC BC 03
Advance output pointer
5129
OR A B7
Set flags based on byte value (Z if 00H = end of line)
512A
RET C9
Return with byte in A, flags set

512BH - Skip Whitespace Loop

Loop entry for whitespace skipping. Continues fetching bytes until non-whitespace found.

512B
Get next byte
512E
LD A,(HL) 7E
Peek at current byte
512F
CP 20H FE 20
Compare with space (20H)
5131
If space, skip it and continue
5133
CP 0BH FE 0BH
Compare with vertical tab (0BH)
5135
RET NC D0
If >= 0BH (not control), return
5136
CP 09H FE 09
Compare with tab (09H)
5138
RET C D8
If < 09H (control char), return
5139
Tab or 0AH - skip and continue

513BH - Check for Digit

Check if current byte is a decimal digit (0-9). Returns with carry set if digit found.

513B
Skip whitespace and get byte
513E
CP 30H FE 30
Compare with '0' (30H)
5140
If < '0', not a digit
5142
CP 3AH FE 3A
Compare with ':' (one past '9')
5144
RET C D8
If < ':' then it is a digit - return with carry set
5145
Not a digit - get next byte and return

5147H - Print Message String

Print a null-terminated or 03H-terminated message string pointed to by HL.

5147
LD A,(HL) 7E
Load character from message
5148
CP 03H FE 03
Compare with ETX (end of text marker)
514A
INC HL 23
Advance to next character
514B
If end marker, print newline and return
514E
Print character in A
5151
Continue with next character

5153H - Phase 1: Calculate Memory Expansion

During Phase 1, calculate how much memory expansion is needed based on the difference between old and new line number digit counts.

5153
LD BC,5D51H 01 51 5D
BC = address of digit count routine in BASIC/CMD
5156
Convert DE to decimal string, get digit count
5159
LD HL,0000H 21 00 00
HL = 0
515C
ADD HL,DE 19
HL = new line number digit count
515D
LD DE,0000H 11 00 00
[SELF-MOD 515EH] DE = old line number digit count (stored by 4E73H)
5160
OR A B7
Clear carry
5161
SBC HL,DE ED 52
HL = difference (new digits - old digits)
5163
LD (515AH),HL 22 5A 51
Store difference at 515AH
5166
RET M F8
If negative (shrinking), return
5167
LD DE,0000H 11 00 00
[SELF-MOD 5168H] DE = current expansion total
516A
RST 18H DF
Compare HL with DE (ROM routine)
516B
RET C D8
If new diff < current, return (no update needed)
516C
LD (5168H),HL 22 68 51
Update maximum expansion needed
516F
RET C9
Return

5170H - Error Message: "FATAL ERROR. TEXT NOW BAD"

ASCII message displayed when a fatal error occurs during Phase 2 renumbering.

5170
DEFM "FATAL ERROR. TEXT NOW BAD" 46 41 54 41 4C...
ASCII: "FATAL ERROR. TEXT NOW BAD" (28 bytes with terminator)

518CH - Error Message: "ERROR LINES"

ASCII message header displayed before listing lines with errors.

518C
DEFM "ERROR LINES" 45 52 52 4F 52...
ASCII: "ERROR LINES" followed by 03H terminator

5198H - Completion Message: "DONE"

ASCII message displayed when renumbering completes successfully.

5198
DEFM "DONE" 44 4F 4E 45 03
ASCII: "DONE" followed by 03H terminator

519DH - Additional Range Validation

Perform additional validation of the renumber range parameters.

519D
SBC HL,BC ED 42
Calculate HL - BC
519F
RET C D8
Return if carry (underflow)
51A0
RST 18H DF
Compare HL with DE
51A1
RET C9
Return with comparison result

51A2H - Reserved/Workspace Area

Reserved area filled with NOPs (00H bytes). May be used as workspace during renumbering operations or reserved for future expansion. Extends from 51A2H to 51F3H (82 bytes).

51A2-51F3
DEFS 82,00H 00 00 00...
Reserved workspace area (82 bytes of 00H/NOP)