4D00H - REF Command Entry Point and Parameter Type Detection
Entry point for the BASIC direct command REF. This section parses the REF command line to determine which reference format was requested: no argument (list all), a line number range (40H/60H tokens), a quoted filename (22H), a USR token (D5H), or a bare variable name. The result routes to the appropriate handler for cross-referencing variables, line numbers, or keywords in the currently loaded BASIC program.
4D00
GOSUB to 5D4FH in BASIC/CMD to display a carriage return followed by line feed output. This clears the current display line and positions the cursor at the start of a new line before processing the REF command. On return, HL points to the current position in the BASIC command line text.
4D03
LD A,(HL) 7E
Load Register A with the first character/token from the REF command line (pointed to by HL). This byte determines which REF format the user typed: 00H means no argument (REF with no parameters), 40H or 60H means a line number range expression, 22H means a quoted filespec, D5H means the USR token, or any other valid character means a bare variable name.
4D04
LD (5D45H),A 32 45 5D
Store the first command-line byte (Register A) to the display flag at 5D45H. This value controls how the REF output is formatted later. 00H means display all references; non-zero stores the first character for subsequent identification of the search target. [Self-Modifying Code]
5D45H is a code-embedded variable in BASIC/CMD that is written here and read by the output formatting routines.
4D07
OR A B7
Logical OR Register A with itself to set the CPU flags. If Register A is 00H (end-of-statement, meaning the user typed just REF with no arguments), the Z FLAG is set.
4D08
If the Z FLAG has been set (the first byte is 00H, meaning the user typed REF with no arguments), JUMP forward to 4D21H to proceed with an all-references listing (list every variable, line number, and keyword in the program).
4D0A
CP 40H FE 40
Compare Register A against 40H. In BASIC tokenized text, 40H is not a standard printable character in the command context; it represents a specific expression marker. If Register A equals 40H, the Z FLAG is set.
4D0C
If the Z FLAG has been set (the argument begins with 40H), JUMP forward to 4D12H to evaluate a numeric expression. This handles the case where the user typed a line number or numeric expression after REF.
4D0E
CP 60H FE 60
Compare Register A against 60H. This tests for another numeric expression marker. If Register A equals 60H, the Z FLAG is set.
4D10
If the NZ FLAG has been set (the first byte is not 00H, not 40H, and not 60H), JUMP forward to 4D24H to test for other argument types (quoted filespec, USR token, or variable name). If we fall through, the byte is 60H and we proceed to evaluate a numeric expression.
At this point, the argument begins with 40H or 60H, indicating a numeric expression (line number). The code calls the BASIC expression evaluator to parse it.
4D12
GOSUB to ROM routine at 1E5BH, the BASIC expression evaluator. This parses the numeric expression following the REF command and returns the result in DE as a 16-bit integer (the target line number). Register A holds 00H on success or a non-zero error code on failure.
4D15
OR A B7
Logical OR Register A with itself to test for an error from the expression evaluator. If A is non-zero, the evaluation produced an error.
4D16
If the NZ FLAG has been set (the expression evaluator returned an error), JUMP forward to 4D7FH to report a syntax error via JP 1997H.
4D18
LD A,D 7A
Load Register A with the high byte of Register Pair DE (the evaluated line number). This is the first step in checking whether the line number is zero.
4D19
OR E B3
Logical OR Register A (high byte of DE) with Register E (low byte of DE). If the entire 16-bit value DE is 0000H, the Z FLAG is set, meaning the user specified line number 0.
4D1A
If the Z FLAG has been set (the line number is zero), JUMP forward to 4D1DH to skip the DECrement. Line number 0 is not decremented because it already represents the start of the program.
4D1C
DEC DE 1B
DECrement Register Pair DE by 1. The user-supplied line number is decremented by 1 so that the subsequent search will find lines that have a line number greater than or equal to the user-specified value. For example, if the user types REF 100, DE becomes 99, so the search returns references starting at line 100.
4D1D
LD (4E76H),DE ED 53 76 4E
Store Register Pair DE (the adjusted line number threshold) to the line number limit variable at 4E76H. This value is used during the program scan to filter which line numbers are included in the REF output. If the user typed no line number argument, this location is not written here (the code jumped to 4D21H).
4D21
JUMP to 4F07H to begin the main REF program scan. This destination is the line-number REF handler which walks the BASIC program text and outputs cross-references for the specified line number range (or all lines if no argument was given).
4D24H - Quoted Filespec / USR Token / Variable Name Detection
Determines the REF argument type when it is not a line number range. Tests for a quoted filespec (22H = double-quote), the USR token (D5H), or falls through to parse a bare variable name.
4D24
CP 22H FE 22
Compare Register A (the first argument byte) against 22H (ASCII double-quote "). If the user typed a quoted filespec after REF (e.g., REF "MYPROG/BAS"), the Z FLAG is set.
4D26
If the Z FLAG has been set (the argument starts with a double-quote), JUMP forward to 4D2CH to process the quoted filespec. The filespec will be copied to the filename buffer at 51EFH for later matching.
4D28
CP D5H FE D5
Compare Register A against D5H, which is the BASIC token for the USR keyword. If the user typed REF USR, the Z FLAG is set.
4D2A
If the NZ FLAG has been set (the argument is neither a double-quote nor the USR token), JUMP forward to 4D49H to process a bare variable name (e.g., REF X or REF A$).
4D2CH - Quoted Filespec Handler (REF "filename")
Handles the case where the user typed REF followed by a quoted filespec. Copies up to 16 bytes of the filename string into the match buffer at 51EFH, then sets the comparison threshold to 3000H (a value that exceeds all valid line numbers, effectively meaning "match in all lines") and sets the scan mode to C3H (JP opcode) to signal filespec-matching mode.
4D2C
EX DE,HL EB
Exchange Register Pairs DE and HL. After this, DE points to the current position in the BASIC command line (the character after the opening double-quote) and HL is freed for use as the destination pointer.
4D2D
LD HL,51EFH 21 EF 51
Point Register Pair HL to 51EFH, the filename match buffer. The quoted filespec will be copied here for later comparison against filenames found in the BASIC program text.
4D30
LD B,10H 06 10
Load Register B with 10H (decimal 16), the maximum number of characters to copy from the quoted filespec into the match buffer. This limits filenames to 16 characters.
Filespec Copy Loop Start
The following loop copies characters from the command line into the match buffer at 51EFH, up to 16 bytes.
4D32
INC DE 13
INCrement Register Pair DE by 1 to advance to the next character in the command line text. On the first iteration, this skips past the opening double-quote character.
4D33
LD A,(DE) 1A
Load Register A with the next character from the command line (pointed to by DE). This is a filename character to be copied into the match buffer.
4D34
LD (HL),A 77
Store the character (Register A) to the match buffer (pointed to by HL at 51EFH and above). This copies one byte of the filename into the match buffer.
4D35
INC HL 23
INCrement Register Pair HL by 1 to advance to the next position in the match buffer.
4D36
DECrement Register B (character counter) and loop back to 4D32H if not zero. This loop copies up to 16 characters from the quoted filespec into the match buffer at 51EFH. [Loop End]
4D38
LD (HL),B 70
Store Register B (now 00H after the loop) to the byte following the last copied character in the match buffer. This writes a 00H null terminator after the filename string.
4D39
LD HL,3000H 21 00 30
Load Register Pair HL with 3000H (decimal 12288). This is a comparison threshold value that exceeds all valid BASIC line numbers (maximum 65529). Setting the threshold to 3000H means "match in all lines" — the filespec search will not be limited by line number.
4D3C
LD (51D3H),HL 22 D3 51
Store Register Pair HL (3000H) to the first comparison value at 51D3H. This is the lower bound of the line-number range; 3000H means no lower bound restriction (search all lines from the start of the program).
4D3F
LD (51D9H),HL 22 D9 51
Store Register Pair HL (3000H) to the second comparison value at 51D9H. This is the upper bound of the line-number range; 3000H means no upper bound restriction.
4D42
LD A,C3H 3E C3
Load Register A with C3H (the Z80 opcode for JP). This value will be stored as a mode flag to indicate that REF is operating in filespec-matching mode (as opposed to variable-name mode).
4D44
LD (4F7CH),A 32 7C 4F
Store C3H (Register A) to the scan mode flag at 4F7CH. This location is a self-modifying code target: when 4F7CH contains C3H, the code at 4F7CH executes as JP 512FH (filespec-matching mode). When it contains 21H, the code at 4F7CH executes as LD HL,512FH (variable-name mode). [Self-Modifying Code]
4D47
JUMP forward to 4D9AH to call the initialization routine at 5171H and then proceed to the main scan loop via JP 4E2FH.
4D49H - Bare Variable Name Parser (REF varname)
Handles the case where the user typed REF followed by a variable name (e.g., REF X, REF A$, REF NUM%). Parses up to 5 characters of the variable name, detects type suffixes ($ and the string token CFH), and validates that the name contains only legal alphanumeric characters. The parsed name is stored starting at 51DAH (or 51D4H for string variables) with a length byte preceding the name.
4D49
LD B,06H 06 06
Load Register B with 06H (decimal 6). This is not the variable name length limit directly; it is a counter for the character copy loop. The actual usable name is 5 characters because the counter is tested after the copy (giving 6 decrements, one extra for the loop termination test). Register B serves as a down-counter for the variable name character copy loop.
4D4B
LD A,21H 3E 21
Load Register A with 21H (the Z80 opcode for LD HL,nnnn). This value will be stored as the scan mode flag to indicate variable-name matching mode.
4D4D
LD (4F7CH),A 32 7C 4F
Store 21H (Register A) to the scan mode flag at 4F7CH. When 4F7CH contains 21H, the code at 4F7CH executes as LD HL,512FH followed by the variable-name comparison routine (as opposed to C3H which would make it JP 512FH for filespec mode). [Self-Modifying Code]
4D50
EX DE,HL EB
Exchange Register Pairs DE and HL. After this, DE points to the current position in the command line and HL is freed for use as the destination pointer.
4D51
LD HL,51DAH 21 DA 51
Point Register Pair HL to 51DAH, the variable name storage buffer. The parsed variable name will be stored here. The byte at 51D9H (one byte before) stores the name length, and 51DAH onward stores the actual characters.
4D54
LD C,00H 0E 00
Load Register C with 00H. Register C is a flag: 00H means no type suffix detected yet, 01H means a string-type suffix ($ or string token CFH) was found.
4D56
LD A,(DE) 1A
Load Register A with the current character from the command line (pointed to by DE). This is the first character of the variable name.
4D57
CP 24H FE 24
Compare Register A against 24H (ASCII $). The dollar sign is the string type suffix in BASIC (e.g., A$).
4D59
If the Z FLAG has been set (the character is a dollar sign $), JUMP forward to 4D5FH to handle the string type suffix.
4D5B
CP CFH FE CF
Compare Register A against CFH. Token CFH is the BASIC token for the string function marker (an alternate way that string-type variables are flagged in tokenized text).
4D5D
If the NZ FLAG has been set (the character is neither $ nor token CFH), JUMP forward to 4D68H to begin parsing the variable name characters. The variable has no string-type suffix so far.
String Type Suffix Handler
The character is either $ (24H) or token CFH. Advance past it, check if the next character is end-of-statement, and set the string flag.
4D5F
INC DE 13
INCrement Register Pair DE by 1 to advance past the type suffix character ($ or token CFH).
4D60
LD A,(DE) 1A
Load Register A with the character after the type suffix from the command line. This checks whether the type suffix was the entire argument (e.g., REF $, meaning search for all string variables).
4D61
OR A B7
Logical OR Register A with itself to set the CPU flags. If the byte after the suffix is 00H (end-of-statement), the Z FLAG is set, meaning the user typed just a type suffix with no variable name.
4D62
If the Z FLAG has been set (the argument is just a type suffix with no variable name, e.g., REF $), JUMP forward to 4DAAH. This handles the "search for all string variables" case by clearing the comparison values and proceeding to the scan loop.
4D64
INC C 0C
INCrement Register C from 00H to 01H, setting the string-type flag. This indicates that the variable being searched for has a $ or CFH type suffix.
4D65
LD HL,51D4H 21 D4 51
Point Register Pair HL to 51D4H. When a string type suffix is present, the variable name is stored at 51D4H (6 bytes earlier than the default 51DAH). This alternate buffer position allows the code to store both the length and the name in a different layout for string variables. The byte at 51D3H stores the length for string variables.
Variable Name Character Validation Loop
The following code validates and copies each character of the variable name, checking that it is either a digit (30H-39H) or a letter (41H-5AH after subtracting offsets).
4D68
PUSH HL E5
Save Register Pair HL (pointer to the name storage buffer, either 51DAH or 51D4H) onto the stack. This preserves the buffer base address while we parse characters.
4D69
LD A,(DE) 1A
Load Register A with the current character from the command line (pointed to by DE).
4D6A
SUB 30H D6 30
SUBtract 30H (ASCII 0) from Register A. If the character was a digit 30H-39H, the result is 00H-09H (less than 0AH). This is the first part of a range check: digits are valid variable name characters.
4D6C
CP 0AH FE 0A
Compare Register A against 0AH (decimal 10). If Register A < 0AH (the character was a digit 0-9), the CARRY FLAG is set, confirming a valid digit.
4D6E
If the CARRY FLAG has been set (the character is a valid digit), JUMP forward to 4D76H to copy it into the name buffer.
4D70
SUB 11H D6 11
SUBtract 11H from Register A. Combined with the previous SUB 30H, this is equivalent to subtracting 41H from the original character. If the original character was a letter A-Z (41H-5AH), the result is 00H-19H (less than 1AH).
4D72
CP 1AH FE 1A
Compare Register A against 1AH (decimal 26). If Register A < 1AH (the original character was a letter A-Z), the CARRY FLAG is set. If the NO CARRY FLAG is set, the character is neither a digit nor a letter — it is invalid.
4D74
If the NO CARRY FLAG has been set (the character is not a digit and not a letter), JUMP forward to 4D7FH to report a syntax error via JP 1997H. Invalid characters in a variable name are not allowed.
Valid Character Copy Loop
The character is valid (either a digit or a letter). Copy it into the name buffer and advance to the next character.
4D76
LD A,(DE) 1A
Load Register A with the original (unmodified) character from the command line (pointed to by DE). The earlier SUB instructions destroyed the original value, so it must be re-read.
4D77
OR A B7
Logical OR Register A with itself to set the CPU flags. If the character is 00H (end-of-statement), the Z FLAG is set, meaning the variable name is complete.
4D78
INC DE 13
INCrement Register Pair DE by 1 to advance to the next character in the command line. This is done before the branch so that DE always points past the last character read.
4D79
If the Z FLAG has been set (the character was 00H end-of-statement), JUMP forward to 4D82H to finalize the variable name. The name is complete.
4D7B
LD (HL),A 77
Store the valid character (Register A) to the name buffer (pointed to by HL).
4D7C
INC HL 23
INCrement Register Pair HL by 1 to advance to the next position in the name buffer.
4D7D
DECrement Register B (character counter) and loop back to 4D76H if not zero. Up to 6 characters are copied (B starts at 06H but only 5 characters are usable because the final iteration checks for end-of-name). [Loop End]
4D7FH - Syntax Error Exit
Reports a syntax error when the REF command argument is invalid. Jumps to the ROM error handler at 1997H.
4D7F
JUMP to ROM routine at 1997H, the BASIC syntax error handler. This displays a "?SN ERROR" message and returns to the BASIC READY prompt. This exit is taken whenever an invalid variable name character is found or the expression evaluator fails.
4D82H - Variable Name Length Calculation and Type Validation
After the variable name has been parsed, this section calculates the name length, validates it against the type suffix rules (string variables with a $ suffix must have 1 character, not 2+), stores the length byte, and routes to either the single-variable or multi-reference initialization path.
4D82
LD A,05H 3E 05
Load Register A with 05H (decimal 5). This is used with the remaining B counter to calculate the number of characters actually copied into the name buffer.
4D84
SUB B 90
SUBtract Register B (remaining counter) from Register A. The result is the number of characters copied: 05H minus the remaining count. For example, if B=03H (3 iterations left), then A=02H (2 characters were copied). Note: B started at 06H but one iteration was consumed by the end-of-name check, so the effective maximum is 5 characters.
4D85
EX DE,HL EB
Exchange Register Pairs DE and HL. After this, HL points to the position after the last character in the command line, and DE points to the position after the last character in the name buffer.
4D86
POP HL E1
Restore Register Pair HL from the stack. HL now points to the name buffer base (either 51DAH or 51D4H, as saved at 4D68H). This is the start of the name storage area.
4D87
BIT 6,(HL) CB 76
Test bit 6 of the byte at (HL). When HL points to 51DAH, this byte is the first character of the variable name. If it has bit 6 set, the character is in the 40H-7FH range (lowercase letter or special character). When HL points to 51D4H (string variable path), this tests a different byte. Bit 6 is used here as part of the string-type validation.
4D89
If the Z FLAG has been set (bit 6 is clear), JUMP forward to 4D94H to store the length and proceed. This is the normal path for non-string variable names.
4D8B
CP 02H FE 02
Compare Register A (the name length) against 02H. For string variables (identified by the $ suffix), the variable name must be exactly 1 character (A$ through Z$). A name length of 2 or more with a string suffix is invalid.
4D8D
If the NO CARRY FLAG has been set (the name length is 2 or more), JUMP back to 4D7FH to report a syntax error. String variables with a $ suffix cannot have multi-character names in NEWDOS/80 BASIC.
4D8F
LD A,20H 3E 20
Load Register A with 20H (ASCII space). For single-character string variables, a space is written after the variable name character in the name buffer. This pads the name to a consistent format for the comparison routines.
4D91
LD (DE),A 12
Store the space character (20H) to the position after the variable name character in the buffer (pointed to by DE). This pads the single-character name.
4D92
LD A,01H 3E 01
Load Register A with 01H, overriding the name length to 1. This is the correct length for a single-character string variable name.
4D94
DEC HL 2B
DECrement Register Pair HL by 1 to point to the length byte position, which is one byte before the name buffer start. For the default path (HL was 51DAH), this points to 51D9H. For the string path (HL was 51D4H), this points to 51D3H.
4D95
LD (HL),A 77
Store the name length (Register A) to the length byte position. For the default path, (51D9H) receives the name length. For the string path, (51D3H) receives the name length.
4D96
BIT 0,C CB 41
Test bit 0 of Register C (the string-type flag). If C is 01H (a $ or CFH type suffix was detected), bit 0 is set and the NZ FLAG results. If C is 00H (no type suffix), bit 0 is clear and the Z FLAG results.
4D98
If the NZ FLAG has been set (the variable has a string type suffix), JUMP forward to 4DA2H to handle the string-variable-specific path which adjusts the secondary length field.
Non-String Variable Path
No type suffix was present. Call the initialization routine and proceed to the main scan with mode 02H.
4D9A
GOSUB to 5171H, the REF scan initialization routine. This routine reads the first character of the variable name from 51DAH, determines the display column width based on whether the character is a letter (18H columns for A-Z) or a digit/special (38H columns for others), resets the PDRIVE table pointers at 4EEFH and 4EF2H to 4300H, and returns.
4D9D
LD A,02H 3E 02
Load Register A with 02H, the exit mode for a non-string variable name REF search. This value is passed to the main scan entry at 4E2FH to control the output format.
4D9F
JUMP to 4E2FH to begin the main REF program scan using the parsed variable name as the search target.
4DA2H - String Variable Length Adjustment
For string variables (those with a $ or CFH suffix), adjusts the secondary length field at 51D3H to include the total name length plus offset, then falls through to the BREAK-key check and main scan entry.
4DA2
LD B,00H 06 00
Load Register B with 00H, clearing the high byte of a 16-bit offset. Register C already holds the name length value from the length byte at (HL).
4DA4
LD C,(HL) 4E
Load Register C with the byte at (HL), which is the name length value just stored at 4D95H. HL points to either 51D9H or 51D3H (the length byte position). BC now holds the name length as a 16-bit value (B=00H, C=length).
4DA5
INC C 0C
INCrement Register C by 1. This adds 1 to the name length to account for the length byte itself, making BC the total size of the length-prefixed name record.
4DA6
ADD HL,BC 09
ADD Register Pair BC (length + 1) to Register Pair HL. This advances HL past the length byte and all name characters to point to the byte immediately after the name in the buffer.
4DA7
DEC (HL) 35
DECrement the byte at (HL) by 1. This adjusts the secondary comparison field that follows the name in the buffer. The decrement ensures that the comparison threshold is one less than the stored value, matching the "greater than" comparison logic used during the scan.
4DA8
JUMP forward to 4DB0H to set BC=FFFFH and call the initialization routine at 5168H, then continue to the BREAK-key polling loop.
4DAAH - Type-Suffix-Only Handler (REF $)
Handles the case where the user typed REF followed by only a type suffix (e.g., REF $) with no variable name. This means "list all string variables." Clears the comparison value at 51D3H to 0000H and falls through to the initialization.
4DAA
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H. This clears the comparison value so that no specific variable name is matched — only the type suffix will be used for filtering.
4DAD
LD (51D3H),HL 22 D3 51
Store 0000H (Register Pair HL) to the comparison value at 51D3H. This clears the lower-bound comparison, meaning all string variables will match regardless of name.
4DB0H - REF Initialization and BREAK Key Polling
Sets up the scan parameters by calling the initialization routine with BC=FFFFH, then enters a BREAK-key polling loop that waits for the user to press a key before starting the scan. The polling checks for the BREAK key (bit 2 of keyboard row 3840H), the @ key (bit 0), and the UP ARROW key (bit 3), using these to control whether to proceed, pause, or abort the REF listing.
4DB0
LD BC,FFFFH 01 FF FF
Load Register Pair BC with FFFFH (decimal 65535). This value is passed to the initialization routine at 5168H, where it is stored to 51DAH as the "all variables" wildcard marker.
4DB3
GOSUB to 5168H, the extended REF initialization routine. This stores BC (FFFFH) to 51DAH, writes 01H to 51D9H, reads the first byte from 51DAH, determines the column width (18H for letters, 38H for others), stores it to 5021H, and resets the PDRIVE table pointers at 4EEFH and 4EF2H to 4300H.
4DB6
LD HL,3840H 21 40 38
Point Register Pair HL to 3840H, the memory-mapped keyboard row 6 address. This row contains the ENTER, CLEAR, BREAK, UP, DOWN, LEFT, RIGHT, and SPACE keys.
Keyboard Polling Loop
Polls the keyboard to detect BREAK (bit 2), @ (bit 0 of next row), and UP ARROW (bit 3) keypresses. BREAK aborts, UP ARROW starts the scan after the user releases the key, and @ is used for an alternate entry.
4DB9
BIT 3,(HL) CB 5E
Test bit 3 of the byte at (HL) = keyboard row 3840H. Bit 3 corresponds to the UP ARROW key. If the UP ARROW key is pressed, bit 3 is active and the NZ FLAG is set.
4DBB
If the NZ FLAG has been set (the UP ARROW key is pressed), JUMP to ROM routine at 002BH to get a character from the keyboard (waits for keypress). This effectively pauses the REF output and waits for the user to press another key to continue.
4DBE
BIT 2,(HL) CB 56
Test bit 2 of the byte at (HL) = keyboard row 3840H. Bit 2 corresponds to the BREAK key. If BREAK is pressed, bit 2 is active and the NZ FLAG is set.
4DC0
If the Z FLAG has been set (the BREAK key is NOT pressed), JUMP forward to 4DCBH to exit the polling loop and begin the REF scan.
4DC2
BIT 3,(HL) CB 5E
Test bit 3 of keyboard row 3840H again (the UP ARROW key). This is a secondary check within the BREAK-held loop.
4DC4
If the NZ FLAG has been set (the UP ARROW key is pressed while BREAK is also held), JUMP back to 4DBBH. Holding BREAK + UP ARROW together triggers a keyboard input wait, effectively pausing.
4DC7
BIT 0,(HL) CB 46
Test bit 0 of keyboard row 3840H. Bit 0 corresponds to the @ key (ENTER key on row 6). If ENTER is pressed, bit 0 is active and the NZ FLAG is set.
4DC9
If the Z FLAG has been set (the @ key is NOT pressed), JUMP back to 4DC2H to continue polling. The loop waits for the user to press either ENTER (to abort) or release BREAK (to continue). [Loop End]
4DCBH - Scan Initialization and Self-Modifying Code Setup
After the keyboard polling, initializes the scan state variables. Clears Register A, loads the BASIC program start address, stores the initial iteration count, configures the conditional JP/JR instructions via self-modifying code based on the variable type being searched, and begins the main program scan by jumping to the scan loop entry at 4F6BH.
4DCB
XOR A AF
Set Register A to 00H and clear all flags. This initializes A to zero for use as a counter/flag reset.
4DCC
LD DE,(40A4H) ED 5B A4 40
Load Register Pair DE with the 16-bit value at 40A4H, the BASIC program start address. DE now points to the beginning of the BASIC program text in memory. The scan will walk forward through the program from this address.
4DD0
OR A B7
Logical OR Register A with itself to set the CPU flags based on the current value of A. On the first entry, A is 00H so the Z FLAG is set.
4DD1
LD (4E0CH),A 32 0C 4E
Store Register A to the iteration counter at 4E0CH. This is a self-modifying code target: the byte at 4E0CH is the operand of the LD A instruction at 4E0BH. When A=00H, this is the first iteration (scan pass). Non-zero values indicate subsequent passes. [Self-Modifying Code]
4DD4
LD A,DAH 3E DA
Load Register A with DAH (the Z80 opcode for JP C,nnnn). This is the default conditional-jump opcode that will be patched into the scan loop for the first-pass behavior.
4DD6
If the Z FLAG has been set (A was 00H at 4DD0H, meaning this is the first scan pass), JUMP forward to 4DDAH to store DAH as the conditional jump opcode. The first pass uses JP C (DAH) for one comparison mode.
4DD8
LD A,C2H 3E C2
Load Register A with C2H (the Z80 opcode for JP NZ,nnnn). On subsequent passes (non-zero iteration count), the conditional jump is changed to JP NZ. This switches the comparison logic for the second and later passes.
4DDA
LD (4FFCH),A 32 FC 4F
Store the conditional-jump opcode (DAH or C2H) to the self-modifying code target at 4FFCH. This patches the instruction at 4FFCH to be either JP C (first pass) or JP NZ (subsequent passes), controlling how comparison results branch. [Self-Modifying Code]
4DDD
LD (50A9H),A 32 A9 50
Store the same conditional-jump opcode to the self-modifying code target at 50A9H. This patches a second branch instruction at 50A9H to use the same comparison logic as 4FFCH. [Self-Modifying Code]
4DE0
LD A,(51D4H) 3A D4 51
Load Register A with the byte at 51D4H, the first character of the string-variable name buffer (or the first comparison byte for other modes). This character determines the column width for the output display.
4DE3
CP 3AH FE 3A
Compare Register A against 3AH (ASCII colon :). If the character is less than 3AH (a digit or other early ASCII character), the CARRY FLAG is set. Characters 3AH and above (colons, semicolons, letters, tokens) clear the CARRY FLAG.
4DE5
LD A,30H 3E 30
Load Register A with 30H (decimal 48). This is the column width for "narrow" display mode, used when the variable name starts with a character below 3AH.
4DE7
If the CARRY FLAG has been set (the first character is below 3AH), JUMP forward to 4DEBH to store the narrow column width 30H. [Success Path]
4DE9
LD A,18H 3E 18
Load Register A with 18H (decimal 24). This is the column width for "wide" display mode, used when the variable name starts with a character at 3AH or above (letters, tokens).
4DEB
LD (4FBEH),A 32 BE 4F
Store the column width (30H or 18H) to the self-modifying code target at 4FBEH. This patches the operand of a JR NC instruction at 4FBEH, controlling how many characters fit on one display line before wrapping. [Self-Modifying Code]
4DEE
LD A,CAH 3E CA
Load Register A with CAH (the Z80 opcode for JP Z,nnnn). This value will be stored to another self-modifying code location to configure the main loop's end-of-line detection.
4DF0
LD (4F6DH),A 32 6D 4F
Store CAH to the self-modifying code target at 4F6DH. This patches the instruction at 4F6DH to be JP Z,4DFCH, controlling how the scan loop handles end-of-line conditions. [Self-Modifying Code]
4DF3
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H. This clears the match counter or reference accumulator.
4DF6
LD (5085H),HL 22 85 50
Store 0000H to the match address storage at 5085H. This clears any previously stored match address before starting the new scan. [Self-Modifying Code]
4DF9
JUMP to 4F6BH to enter the main REF program scan loop. This is the top of the line-by-line scanner that walks through the BASIC program text.
4DFCH - End-of-Line Handler and Multi-Pass Controller
Called when the scan reaches the end of a BASIC line (the end-of-statement null byte at 4F6DH triggered a JP Z here). This routine checks the scan mode flag at 4F6DH. If C3H, all lines have been scanned and control passes to the display output at 4E80H. Otherwise, it checks whether the next line exists and routes to the line-number search at 4F07H or continues scanning. The multi-pass controller at 4E0BH dispatches based on the iteration counter: pass 0 goes to a fresh start, pass 1 re-enters the scan for additional variables, pass 2 returns to BASIC, and pass 3 exits with a formatted error message.
4DFC
LD A,(4F6DH) 3A 6D 4F
Load Register A with the byte at 4F6DH, the end-of-line detection flag. This is a self-modifying code location: it holds CAH (JP Z opcode) during the first scan, and is changed to C3H (JP opcode) when the scan is complete and all lines have been processed.
4DFF
CP C3H FE C3
Compare Register A against C3H (the JP opcode). If the flag has been changed to C3H, the scan is complete and the Z FLAG is set.
4E01
If the Z FLAG has been set (the scan mode flag is C3H, meaning the scan is complete), JUMP to 4E80H to enter the display output section that formats and prints the cross-reference results.
4E04
INC DE 13
INCrement Register Pair DE by 1 to advance past the current null byte to the next byte in the BASIC program text.
4E05
LD A,(DE) 1A
Load Register A with the byte at the new DE position. This reads the first byte of what should be the next BASIC line's link pointer. If the program has ended, this will be 00H.
4E06
OR A B7
Logical OR Register A with itself to test for 00H. If the byte is 00H (end of program), the Z FLAG is set.
4E07
DEC DE 1B
DECrement Register Pair DE by 1 to restore it to the null byte position. This undo the INC DE so that the line walker at 4F70H can correctly process the line header.
4E08
If the NZ FLAG has been set (the next byte is not 00H, meaning there are more BASIC lines to process), JUMP to 4F70H to store the current position as the line address and continue scanning the next line.
End of Program Reached
The BASIC program text has been fully scanned. The iteration counter at 4E0CH determines what happens next.
4E0B
LD A,00H 3E 00
Load Register A with the byte at 4E0CH (via self-modifying code). The operand byte at 4E0CH was written at 4DD1H with the iteration counter. 00H = first pass, 01H = second pass for single-variable mode, 02H = done, 03H = line-number mode complete. [Self-Modifying Code]
4E0CH is the operand of this LD A instruction, patched at runtime by the store at 4DD1H.
4E0D
OR A B7
Logical OR Register A with itself to set the CPU flags. If A is 00H (first pass), the Z FLAG is set.
4E0E
If the Z FLAG has been set (first pass complete), JUMP forward to 4E28H to check whether another pass is needed. The first pass collected variable references; now we may need to output them.
4E10
PUSH AF F5
Save Register A (the iteration counter) onto the stack for later retrieval after the carriage return output.
4E11
GOSUB to 5D52H, the carriage return output routine. This outputs a CR to end the current display line before beginning the next phase of output.
4E14
LD HL,FFFFH 21 FF FF
Load Register Pair HL with FFFFH (decimal 65535). This is the maximum possible line number value, used to reset the line number limit so that the next scan pass covers all lines.
4E17
LD (4E76H),HL 22 76 4E
Store FFFFH to the line number limit variable at 4E76H. This resets the limit to the maximum so that the next scan pass will match all line numbers.
4E1A
POP AF F1
Restore Register A (the iteration counter) from the stack.
4E1B
DEC A 3D
DECrement Register A by 1. If A was 01H (second pass), A becomes 00H and the Z FLAG is set.
4E1C
If the Z FLAG has been set (the counter was 01H, meaning the second pass is complete), JUMP back to 4DB0H to re-enter the initialization and BREAK-key polling. This allows the user to see the results of the current variable and then search for the next one.
4E1E
DEC A 3D
DECrement Register A by 1 again. If A was 02H (third state), A becomes 00H and the Z FLAG is set.
4E1F
RET Z C8
If the Z FLAG has been set (the counter was 02H), RETURN to the calling routine. This exits the REF command entirely, returning control to BASIC.
4E20
LD B,09H 06 09
Load Register B with 09H (decimal 9), the number of characters to display. This is the length of the " $EXT END" text at 51B6H.
4E22
LD HL,51B6H 21 B6 51
Point Register Pair HL to 51B6H, the text string "$EXT END" with a trailing 0DH. This message is displayed when the scan reaches the end of the BASIC program text.
4E25
JUMP to 5D70H, the digit/character display loop. This routine outputs B characters from the buffer at HL and then returns. The "$EXT END" message is displayed and the REF command terminates.
4E28H - First Pass Complete - Variable Scan Entry
After the first scan pass completes with iteration counter 00H, this section checks whether the search target is a wildcard (FFH at 51DAH). If so, the REF command returns to BASIC. Otherwise, it initializes the display header for the found variable and enters the output formatting section at 4E2FH.
4E28
LD A,(51DAH) 3A DA 51
Load Register A with the byte at 51DAH, the first byte of the variable name buffer. This byte was set to FFH if the search is a wildcard (all variables) or to the first character of the specific variable name being searched.
4E2B
INC A 3C
INCrement Register A by 1. If A was FFH (wildcard), it wraps to 00H and the Z FLAG is set. This tests for the "all variables" wildcard case.
4E2C
RET Z C8
If the Z FLAG has been set (the variable name is FFH = wildcard), RETURN to the calling routine. When REF was invoked with no variable name argument, the first pass scanned all variables and the command is now complete.
4E2D
LD A,01H 3E 01
Load Register A with 01H. This is the initial display mode code passed to the output formatter at 4E2FH, indicating that a variable header needs to be displayed before the line number list.
4E2FH - REF Output Header and Variable Display
Displays the variable name header for the REF output. This section outputs the variable name (from the buffer at 51DAH) with appropriate spacing, clears the 10-byte line-number accumulator at 51E5H, and then dispatches to the appropriate scan pass based on the mode value.
4E2F
PUSH AF F5
Save Register A (the display mode: 01H for first variable display, 02H for non-string variable entry) onto the stack.
4E30
LD HL,51D9H 21 D9 51
Point Register Pair HL to 51D9H, the name length byte. The byte at this address contains the number of characters in the variable name.
4E33
LD C,(HL) 4E
Load Register C with the name length from (51D9H). C now holds the number of characters in the variable name.
4E34
INC C 0C
INCrement Register C by 1 to include the length byte itself in the total count. C now holds the total size of the length-prefixed name record.
4E35
LD A,(4F7CH) 3A 7C 4F
Load Register A with the scan mode flag at 4F7CH. C3H = filespec mode, 21H = variable-name mode.
4E38
CP C3H FE C3
Compare Register A against C3H (filespec mode). If the mode is filespec, the Z FLAG is set.
4E3A
LD A,06H 3E 06
Load Register A with 06H (decimal 6). This is the number of leading spaces to output before the variable name in filespec mode.
4E3C
If the Z FLAG has been set (filespec mode), JUMP forward to 4E53H to output 6 leading spaces and then skip the variable name display. In filespec mode, the filename is not displayed in the header.
Variable Name Display
In variable-name mode, display the name with leading spaces to right-justify it within a 5-character field.
4E3E
PUSH HL E5
Save Register Pair HL (pointer to 51D9H, the name length byte) onto the stack.
4E3F
INC HL 23
INCrement Register Pair HL to point to 51DAH, the first character of the variable name.
4E40
LD A,05H 3E 05
Load Register A with 05H (decimal 5). This is the total field width for the variable name display.
4E42
SUB C 91
SUBtract Register C (name length + 1) from Register A (5). The result is the number of leading spaces needed to right-justify the variable name in a 5-character field. If the result is 00H (name fills the field), no spaces are needed.
4E43
If the NZ FLAG has been set (the result is non-zero, meaning leading spaces are needed), GOSUB to 5D30H to display A spaces. This right-justifies the variable name in the 5-character field.
4E46
LD B,C 41
Load Register B with Register C (the name length + 1). B is the loop counter for the character display loop.
4E47
GOSUB to 5D70H, the digit/character display loop. This outputs B characters from the buffer at HL (starting at 51DAH), displaying the variable name.
4E4A
POP HL E1
Restore Register Pair HL from the stack. HL points back to 51D9H (the name length byte).
4E4B
LD DE,51D3H 11 D3 51
Point Register Pair DE to 51D3H, the destination for the name copy. The variable name and length are copied from 51D9H to 51D3H so that 51D3H holds the active search pattern for the scan loop.
4E4E
INC C 0C
INCrement Register C by 1 to add one extra byte to the copy count. This ensures the copy includes the length byte plus all name characters plus the following byte.
4E4F
LDIR ED B0
Block copy C bytes from (HL) to (DE). This copies the length byte and variable name from 51D9H to 51D3H, with the copy count in BC (B=00H from earlier, C=length+2). After the copy, 51D3H contains the active search pattern used during the program scan.
4E51
LD A,01H 3E 01
Load Register A with 01H (decimal 1). This is the number of trailing spaces to display after the variable name header.
4E53
GOSUB to 5D30H to display A space characters. In variable mode this outputs 1 trailing space. In filespec mode this outputs 6 leading spaces.
4E56
LD HL,51E5H 21 E5 51
Point Register Pair HL to 51E5H, the 10-byte line-number accumulator buffer. This buffer stores the occurrence counts for each PDRIVE entry during the scan.
4E59
LD B,0AH 06 0A
Load Register B with 0AH (decimal 10), the number of bytes to clear in the accumulator buffer.
Clear Accumulator Buffer Loop
Zeros out 10 bytes at 51E5H-51EEH before starting the scan pass.
4E5B
LD (HL),00H 36 00
Store 00H to the current byte of the accumulator buffer (pointed to by HL).
4E5D
INC HL 23
INCrement Register Pair HL by 1 to advance to the next byte in the accumulator buffer.
4E5E
DECrement Register B and loop back to 4E5BH if not zero. This clears all 10 bytes of the accumulator buffer at 51E5H-51EEH. [Loop End]
4E60
POP AF F1
Restore Register A (the display mode saved at 4E2FH) from the stack. A is 01H for first-time variable display or 02H for non-string variable mode.
4E61
CP 01H FE 01
Compare Register A against 01H. If A is 01H (first-time variable display mode), the Z FLAG is set.
4E63
If the NZ FLAG has been set (the mode is not 01H, meaning this is a continuation pass), JUMP back to 4DCCH to reload the BASIC program start address and begin a new scan pass. This re-enters the scan at the point where DE is loaded from 40A4H.
PDRIVE Table Walk
Mode 01H: Walk through the PDRIVE entries at 4300H to find the first valid entry and use it as the starting point for the cross-reference scan.
4E66
LD HL,4300H 21 00 43
Point Register Pair HL to 4300H, the start of the PDRIVE table. Each PDRIVE entry is 16 bytes (10H), and the table contains entries for drives 0-3 starting at 4300H, 4310H, 4320H, and 4330H. The sentinel value at 4340H marks the end of the table.
4E69
LD E,(HL) 5E
Load Register E with the low byte of the 16-bit value at (HL). This reads the first word of the current PDRIVE entry, which is the link pointer to the next entry.
4E6A
INC HL 23
INCrement Register Pair HL by 1 to point to the high byte of the link pointer.
4E6B
LD D,(HL) 56
Load Register D with the high byte of the link pointer. DE now contains the 16-bit link pointer from the current PDRIVE entry.
4E6C
INC HL 23
INCrement Register Pair HL by 1 to point to the next field in the PDRIVE entry.
4E6D
LD (4EF2H),HL 22 F2 4E
Store Register Pair HL to the PDRIVE field pointer at 4EF2H. This saves the position within the current PDRIVE entry for later reference during the scan. [Self-Modifying Code]
4E70
JUMP back to 4DD0H to begin a new scan pass with the updated PDRIVE entry pointer. This re-enters the main scan initialization with the current iteration counter.
4E73H - Clean Stack Exit to BASIC
Performs a clean exit from the REF command by unwinding the stack and jumping to the ROM BASIC warm-restart point at 2B33H. This is used when the scan has completed all passes (iteration counter reached 03H).
4E73
POP AF F1
Discard the top value from the stack. This removes a saved register pair that was pushed earlier in the scan loop.
4E74
POP AF F1
Discard the second value from the stack. This further unwinds the stack to prepare for the jump to BASIC.
4E75
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H. This is the first parameter pushed for the ROM restart — it represents a null return address.
4E78
PUSH HL E5
Push 0000H onto the stack. This is the first of two null values pushed to set up the expected stack frame for the BASIC warm-restart.
4E79
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H again.
4E7C
PUSH HL E5
Push 0000H onto the stack again. The stack now has two 0000H entries, establishing the expected frame for the BASIC restart routine.
4E7D
JUMP to ROM routine at 2B33H, the BASIC warm-restart entry point. This returns control to the BASIC READY prompt with the stack properly cleaned up.
4E80H - Display Output Controller
The main display output controller. Called when the scan mode flag at 4F6DH has been set to C3H (scan complete). Checks the iteration counter at 4E0CH: if 03H, exits to BASIC via the stack cleanup at 4E73H. Otherwise, formats and displays the cross-reference results from the 10-byte accumulator buffer at 51E5H. Each byte in the buffer corresponds to a PDRIVE entry (drives 0-9), and non-zero values indicate that the variable was referenced in lines associated with that drive. The output format depends on whether the variable name starts with a letter (A-Z, using /nnnn format) or a digit/special character (using :n format).
4E80
LD A,(4E0CH) 3A 0C 4E
Load Register A with the iteration counter at 4E0CH (self-modifying code operand at 4E0BH+1). This value tracks which pass the scanner is on.
4E83
CP 03H FE 03
Compare Register A against 03H. If the counter has reached 03H (the final pass), the Z FLAG is set and the output is complete.
4E85
If the Z FLAG has been set (iteration counter is 03H), JUMP back to 4E73H to perform the clean stack exit to BASIC. All passes are complete.
4E87
PUSH AF F5
Save Register A (the iteration counter) onto the stack.
4E88
PUSH DE D5
Save Register Pair DE (the current program position) onto the stack.
4E89
LD A,(51DAH) 3A DA 51
Load Register A with the first byte of the variable name buffer at 51DAH. This determines the output format: letters (41H+) use a wider column with /nnnn formatting, while digits/specials use a narrower format.
4E8C
LD BC,0100H 01 00 01
Load Register Pair BC with 0100H: B=01H (number of PDRIVE entries to check), C=00H (starting PDRIVE index). This is the default for digits/specials — only 1 entry is checked.
4E8F
CP 41H FE 41
Compare Register A against 41H (ASCII A). If the variable name starts with a letter, the CARRY FLAG is clear (A ≥ 41H).
4E91
If the CARRY FLAG has been set (the first character is below 41H, a digit or special character), JUMP forward to 4E95H to use the narrow output format with only 1 PDRIVE entry.
4E93
LD B,0AH 06 0A
Load Register B with 0AH (decimal 10). When the variable name starts with a letter, all 10 PDRIVE entries are checked and displayed.
4E95
LD HL,51E5H 21 E5 51
Point Register Pair HL to 51E5H, the start of the 10-byte accumulator buffer. Each byte corresponds to a PDRIVE entry's occurrence count.
Accumulator Display Loop
Walks through the 10-byte accumulator buffer, displaying each non-zero entry with its associated PDRIVE drive number and occurrence count.
4E98
LD A,(HL) 7E
Load Register A with the current accumulator byte (pointed to by HL). A non-zero value means the variable was referenced at least once in lines associated with this PDRIVE entry.
4E99
OR A B7
Logical OR Register A with itself to test for zero. If the count is 00H (no references for this PDRIVE entry), the Z FLAG is set.
4E9A
If the Z FLAG has been set (no references for this entry), JUMP forward to 4EE3H to advance to the next accumulator byte and continue the loop.
4E9C
LD (4ED9H),A 32 D9 4E
Store the occurrence count (Register A) to the temporary storage at 4ED9H. This saves the count for later display after the cursor position check. [Self-Modifying Code]
4ED9H is the operand of the LD A instruction at 4ED8H.
4E9F
LD (HL),00H 36 00
Store 00H to the current accumulator byte, clearing it after reading. This prevents the same count from being displayed again on a subsequent pass.
4EA1
PUSH HL E5
Save Register Pair HL (pointer to the current accumulator byte) onto the stack.
4EA2
PUSH BC C5
Save Register Pair BC (B=remaining entries, C=current index) onto the stack.
4EA3
GOSUB to 519EH, the cursor position check and line-wrap routine. This checks whether the current cursor position on the display has enough room for the next reference output. If not, it outputs a carriage return and leading spaces to start a new line.
4EA6
LD DE,(4E76H) ED 5B 76 4E
Load Register Pair DE with the line number limit from 4E76H. This is the line number associated with the current reference being displayed.
4EAA
GOSUB to 5D67H, the convert-and-display-number routine. This converts the 16-bit value in DE to a decimal string and displays it. The line number is shown on the screen.
4EAD
POP BC C1
Restore Register Pair BC (B=remaining entries, C=current index) from the stack.
4EAE
LD A,C 79
Load Register A with Register C (the current PDRIVE index).
4EAF
OR A B7
Logical OR Register A with itself. If C is 00H (the first PDRIVE entry), the Z FLAG is set.
4EB0
PUSH BC C5
Save Register Pair BC onto the stack again for the inner display logic.
4EB1
If the NZ FLAG has been set (the PDRIVE index is not 00H), JUMP forward to 4EBBH to display the drive separator character. Drive 0 does not get a separator prefix.
4EB3
LD A,(4ED9H) 3A D9 4E
Load Register A with the occurrence count from the temporary storage at 4ED9H (saved earlier at 4E9CH). This reads back the count for the current entry.
4EB6
CP 02H FE 02
Compare Register A against 02H. If the count is less than 2 (only 1 reference), the CARRY FLAG is set and no count suffix is needed.
4EB8
If the CARRY FLAG has been set (only 1 reference), JUMP forward to 4EE1H to skip the count display and proceed to the next entry.
4EBA
LD A,C 79
Load Register A with Register C (the PDRIVE index) to prepare for the separator display.
4EBB
CP 05H FE 05
Compare Register A against 05H. If the PDRIVE index is less than 5, the CARRY FLAG is set and a / separator is used. If 5 or more, a ( separator is used.
4EBD
LD A,2FH 3E 2F
Load Register A with 2FH (ASCII /). This is the default separator character for PDRIVE indices 0-4.
4EBF
If the CARRY FLAG has been set (PDRIVE index < 5), JUMP forward to 4EC7H to display the / separator.
4EC1
LD A,C 79
Load Register A with Register C (the PDRIVE index).
4EC2
SUB 05H D6 05
SUBtract 05H from Register A. This converts PDRIVE indices 5-9 to 0-4 for the secondary separator lookup.
4EC4
LD C,A 4F
Load Register C with Register A (the adjusted index 0-4).
4EC5
LD A,28H 3E 28
Load Register A with 28H (ASCII (). This is the separator character for PDRIVE indices 5-9.
4EC7
GOSUB to 5D3FH to display the separator character (either / or ().
4ECA
LD A,C 79
Load Register A with Register C (the PDRIVE sub-index, 0-4).
4ECB
OR A B7
Logical OR Register A with itself to test for zero. If the sub-index is 00H, no additional suffix character is needed.
4ECC
If the Z FLAG has been set (sub-index is 0), JUMP forward to 4ED8H to skip the suffix character display.
4ECE
LD B,00H 06 00
Load Register B with 00H. BC now holds the sub-index as a 16-bit offset (B=00H, C=sub-index).
4ED0
LD HL,51B1H 21 B1 51
Point Register Pair HL to 51B1H, the type suffix lookup table. This table contains the characters $, %, !, # used as variable type indicators.
4ED3
ADD HL,BC 09
ADD Register Pair BC (sub-index) to Register Pair HL to index into the type suffix table. HL now points to the appropriate suffix character.
4ED4
LD A,(HL) 7E
Load Register A with the suffix character from the lookup table.
4ED5
GOSUB to 5D3FH to display the type suffix character.
4ED8
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H. The operand bytes at 4ED9H hold the occurrence count (written at 4E9CH via self-modifying code). [Self-Modifying Code]
4ED9H is the low byte, patched with the occurrence count at runtime. When this instruction executes, E holds the saved occurrence count and D holds 00H.
4EDB
LD A,E 7B
Load Register A with Register E (the occurrence count).
4EDC
CP 02H FE 02
Compare Register A against 02H. If the count is 2 or more, the NO CARRY FLAG is set and the count is displayed.
4EDE
If the NO CARRY FLAG has been set (the count is 2 or more), GOSUB to 5D67H to convert and display the count as a decimal number. A count of 1 is not displayed (implied).
4EE1
POP BC C1
Restore Register Pair BC from the stack (B=remaining entries, C=current index).
4EE2
POP HL E1
Restore Register Pair HL from the stack (pointer to the current accumulator byte).
4EE3
INC HL 23
INCrement Register Pair HL by 1 to advance to the next accumulator byte.
4EE4
INC C 0C
INCrement Register C (the PDRIVE index) by 1.
4EE5
DECrement Register B (remaining entries counter) and loop back to 4E98H if not zero. This processes all PDRIVE entries in the accumulator buffer. [Loop End]
4EE7
POP DE D1
Restore Register Pair DE (the program position) from the stack.
4EE8
POP AF F1
Restore Register A (the iteration counter) from the stack.
4EE9
CP 01H FE 01
Compare Register A against 01H. If the counter is 01H (first display pass), the Z FLAG is set and the scan should continue to the next variable.
4EEB
If the NZ FLAG has been set (the counter is not 01H), JUMP back to 4DD0H to re-enter the main scan with the updated counter. This continues scanning for additional variable references.
4EEEH - PDRIVE Table Iterator
After display output is complete for iteration counter 01H, this section walks through the PDRIVE table entries starting at 4300H. For each entry, it checks whether the link pointer is non-zero (indicating a valid drive). If valid, it loads the next PDRIVE entry address and re-enters the scan. When the end of the PDRIVE table is reached (4340H sentinel), it jumps to the end-of-program handler at 4E0BH.
4EEE
LD BC,0000H 01 00 00
Load Register Pair BC with 0000H. The operand bytes at 4EEFH are self-modifying: they hold the current PDRIVE table position, written by 5182H, 5185H, and 512AH. [Self-Modifying Code]
4EEFH holds the 16-bit PDRIVE table pointer.
4EF1
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H. The operand bytes at 4EF2H are self-modifying: they hold the second PDRIVE field pointer, written by 4E6DH and 5185H. [Self-Modifying Code]
4EF2H holds the 16-bit PDRIVE field pointer.
4EF4
OR A B7
Clear the CARRY FLAG (OR A clears carry). This prepares for the SBC comparison that follows.
4EF5
SBC HL,BC ED 42
SUBtract Register Pair BC (with borrow) from Register Pair HL. This compares HL against BC. If they are equal (both point to the same PDRIVE position), the Z FLAG is set.
4EF7
ADD HL,BC 09
ADD Register Pair BC back to HL to restore the original value of HL. The SBC was used only for comparison, not to modify HL.
4EF8
If the NZ FLAG has been set (HL and BC are different, meaning the PDRIVE pointers have not converged), JUMP back to 4E69H to read the next PDRIVE entry and continue the table walk.
4EFB
LD BC,4340H 01 40 43
Load Register Pair BC with 4340H, the PDRIVE table sentinel address. This marks the end of the 4-drive PDRIVE table (4300H + 4 × 10H = 4340H).
4EFE
OR A B7
Clear the CARRY FLAG for the SBC comparison.
4EFF
SBC HL,BC ED 42
SUBtract 4340H (with borrow) from HL. If HL equals 4340H (the sentinel), the Z FLAG is set, meaning all PDRIVE entries have been processed.
4F01
If the Z FLAG has been set (HL reached the sentinel at 4340H), JUMP back to 4DD0H to re-enter the main scan. All PDRIVE entries have been processed for this variable.
4F04
JUMP to 4E0BH, the multi-pass controller. This handles the transition between scan passes when the PDRIVE table walk is not yet complete.
4F07H - Line-Number REF Entry and Validation
Entry point for the line-number REF mode (REF with a numeric argument or no argument). Validates the search target, then walks through the BASIC program text line-by-line searching for the target line number. If the line number is found, sets the iteration counter to 03H and re-enters the scan to display references.
4F07
LD A,(4F7CH) 3A 7C 4F
Load Register A with the scan mode flag at 4F7CH. C3H = filespec mode, 21H = variable-name mode.
4F0A
CP C3H FE C3
Compare Register A against C3H (filespec mode). If filespec mode, the Z FLAG is set.
4F0C
LD A,(51DAH) 3A DA 51
Load Register A with the first byte of the variable name buffer at 51DAH. This will be tested for validity.
4F0F
If the NZ FLAG has been set (not filespec mode), JUMP forward to 4F15H to validate the variable name. In variable mode, the name at 51DAH is used directly.
4F11
LD A,(51EFH) 3A EF 51
Load Register A with the first byte of the filespec buffer at 51EFH. In filespec mode, the filename is stored here instead of at 51DAH.
4F14
DEC A 3D
DECrement Register A by 1. This adjusts the value for the INC A test that follows. If the original byte was 00H, DEC makes it FFH, and the subsequent INC brings it back to 00H (Z FLAG set = invalid).
4F15
INC A 3C
INCrement Register A by 1. For the variable-name path: if the byte at 51DAH was FFH (wildcard), INC wraps to 00H and the Z FLAG is set. For the filespec path: if the first filename byte was 00H (empty), the DEC/INC sequence produces 00H. A zero result means the target is invalid.
4F16
If the Z FLAG has been set (the search target is invalid — either FFH wildcard in variable mode or empty in filespec mode), JUMP to ROM routine at 1997H to display a syntax error.
4F19
LD BC,(4E76H) ED 4B 76 4E
Load Register Pair BC with the line number limit from 4E76H. This is the target line number (or adjusted threshold) for the search.
4F1D
LD DE,(40A4H) ED 5B A4 40
Load Register Pair DE with the BASIC program start address from 40A4H. The line search begins at the start of the program text.
4F21
LD A,B 78
Load Register A with Register B (high byte of the line number limit).
4F22
AND C A1
Logical AND Register A with Register C (low byte of the line number limit). If BC is FFFFH (no line number specified), the result is FFH.
4F23
INC A 3C
INCrement Register A by 1. If A was FFH (BC=FFFFH), A wraps to 00H and the Z FLAG is set. This tests for the "no line number limit" case.
4F24
If the Z FLAG has been set (no line number limit — BC=FFFFH), JUMP forward to 4F41H to set the iteration counter to 03H and proceed with a full scan. When no specific line is targeted, all lines are scanned.
Line Number Search Loop
Walks through the BASIC program lines comparing each line number against the target in BC. The BASIC line format is: 2-byte link pointer, 2-byte line number, then the tokenized text ending with 00H.
4F26
EX DE,HL EB
Exchange Register Pairs DE and HL. HL now points to the start of the current BASIC line (the link pointer).
4F27
PUSH HL E5
Save Register Pair HL (pointer to the current line) onto the stack.
4F28
LD A,(HL) 7E
Load Register A with the low byte of the link pointer at (HL). The link pointer points to the next BASIC line.
4F29
INC HL 23
INCrement Register Pair HL by 1 to point to the high byte of the link pointer.
4F2A
OR (HL) B6
Logical OR Register A with the high byte of the link pointer. If both bytes are 00H (end of program), the Z FLAG is set.
4F2B
If the Z FLAG has been set (end of program — the link pointer is 0000H), JUMP to 4E20H to display the "$EXT END" message and exit. The target line number was not found in the program.
4F2E
INC HL 23
INCrement HL to point to the low byte of the line number.
4F2F
LD E,(HL) 5E
Load Register E with the low byte of the line number.
4F30
INC HL 23
INCrement HL to point to the high byte of the line number.
4F31
LD D,(HL) 56
Load Register D with the high byte of the line number. DE now holds the 16-bit line number of the current BASIC line.
4F32
INC HL 23
INCrement HL to point to the first byte of the tokenized line text.
Skip to End of Line
Advances HL past the tokenized text to find the terminating 00H byte, then uses DE (the link pointer destination from the next line) as the next line address.
4F33
LD A,(HL) 7E
Load Register A with the current byte of the tokenized line text.
4F34
OR A B7
Logical OR Register A with itself to test for the 00H end-of-line marker.
4F35
INC HL 23
INCrement HL to advance to the next byte.
4F36
If the NZ FLAG has been set (the byte is not 00H), JUMP back to 4F33H to continue scanning. [Loop End]
4F38
EX DE,HL EB
Exchange DE and HL. HL now holds the line number of the current line, and DE points to the start of the next line (after the 00H terminator).
4F39
SBC HL,BC ED 42
SUBtract BC (the target line number) from HL (the current line number) with borrow. If HL equals BC, the Z FLAG is set (match found). If HL < BC, the CARRY FLAG is set (haven't reached the target yet).
4F3B
POP HL E1
Restore Register Pair HL (pointer to the current line's link field) from the stack.
4F3C
If the Z FLAG has been set (the current line number matches the target), JUMP forward to 4F41H to set up for the scan with counter 03H.
4F3E
EX DE,HL EB
Exchange DE and HL. HL now points to the next line start.
4F3F
If the CARRY FLAG has been set (the current line number is less than the target), JUMP back to 4F27H to continue searching the next line. [Loop End]
4F41
LD A,03H 3E 03
Load Register A with 03H. This sets the iteration counter to 03H, indicating line-number scan mode. Counter 03H triggers a different output format at 4E80H that displays all tokens and variables found on the specified line.
4F43
JUMP back to 4DD0H to enter the main scan with iteration counter 03H. The scan will process the specified line and output all cross-references found.
4F46H - Quoted String Skip Handler
When a double-quote (22H) is encountered in the BASIC program text during scanning, this routine skips over the quoted string content. It searches for the matching closing quote or end-of-line (00H), then returns to the main scan loop.
4F46
LD BC,4F77H 01 77 4F
Load Register Pair BC with 4F77H, the address of the token advance entry point. This will be pushed as a return address so that when the quote-skip routine returns, execution continues at the main scan loop.
4F49
PUSH BC C5
Push 4F77H onto the stack as a return address. The subsequent RET Z at 4F4EH will "return" to 4F77H when the closing quote is found.
4F4A
LD B,A 47
Load Register B with Register A (the opening quote character, 22H). B holds the target character to search for (the matching closing quote).
4F4B
INC DE 13
INCrement Register Pair DE by 1 to advance to the next character in the BASIC program text.
4F4C
LD A,(DE) 1A
Load Register A with the next character from the program text.
4F4D
CP B B8
Compare Register A against Register B (the closing quote character 22H). If the characters match, the Z FLAG is set.
4F4E
RET Z C8
If the Z FLAG has been set (the closing quote was found), RETURN. The return address on the stack is 4F77H, so execution continues at the main scan's token advance point.
4F4F
OR A B7
Logical OR Register A with itself to test for the 00H end-of-line marker.
4F50
If the NZ FLAG has been set (the character is not 00H and not the closing quote), JUMP back to 4F4BH to continue scanning. [Loop End]
4F52
POP AF F1
Discard the return address (4F77H) from the stack. The end-of-line was reached without finding a closing quote, so we take a different exit path.
4F53
JUMP forward to 4F6AH to advance DE past the current line and continue with the next line in the program.
4F55H - GOTO/GOSUB Statement Handler
When a GOTO token (88H) is encountered, this routine advances past the statement and scans for line number references, colons (statement separators), and quoted strings. This ensures the line numbers in GOTO/GOSUB targets are properly cross-referenced.
4F55
INC DE 13
INCrement Register Pair DE by 1 to advance past the GOTO/GOSUB token.
4F56
LD A,(DE) 1A
Load Register A with the next byte from the program text.
4F57
OR A B7
Logical OR Register A with itself to test for end-of-line (00H).
4F58
If the Z FLAG has been set (end of line), JUMP forward to 4F6AH to advance to the next line.
4F5A
CP 3AH FE 3A
Compare Register A against 3AH (ASCII colon :), the BASIC statement separator.
4F5C
If the Z FLAG has been set (the byte is a colon), JUMP forward to 4F77H to continue scanning the next statement on this line.
4F5E
CP 22H FE 22
Compare Register A against 22H (double-quote). A quoted string within a GOTO target needs to be skipped.
4F60
If the Z FLAG has been set (the byte is a double-quote), GOSUB to 4F4AH to skip over the quoted string content. On return, DE points past the closing quote.
4F63
JUMP back to 4F55H to continue scanning the GOTO statement. [Loop End]
4F65H - Token Skip to End-of-Line
Skips all remaining bytes on the current line until the 00H end-of-line marker is found. Used for tokens like REM (93H) and DATA (FBH) whose content should not be cross-referenced.
4F65
INC DE 13
INCrement Register Pair DE by 1 to advance to the next byte.
4F66
LD A,(DE) 1A
Load Register A with the current byte.
4F67
OR A B7
Test for 00H end-of-line.
4F68
If the NZ FLAG has been set (not end-of-line), JUMP back to 4F65H to continue skipping. [Loop End]
4F6AH - Advance to Next Line
Advances DE to the next byte after the current end-of-line marker and tests whether it is the start of a new line (non-zero) or the end of the program (00H). If end-of-program, jumps to the end-of-line handler at 4DFCH.
4F6A
INC DE 13
INCrement Register Pair DE by 1 to advance past the 00H end-of-line marker.
4F6B
LD A,(DE) 1A
Load Register A with the first byte of what should be the next line's link pointer.
4F6C
OR A B7
Test for 00H. If 00H, the program has ended.
4F6D
If the Z FLAG has been set (end of program), JUMP to 4DFCH, the end-of-line handler. [Self-Modifying Code]
The opcode at 4F6DH is patched: CAH (JP Z) during scanning, changed to C3H (JP unconditional) when the scan is complete. When C3H, every line boundary triggers the jump to 4DFCH regardless of whether there are more lines.
4F70H - Line Address Store and Header Skip
Stores the current program position (DE) as the line address at 4E7AH, then advances DE past the 4-byte line header (link pointer + line number) to point to the first tokenized byte of the line.
4F70
LD (4E7AH),DE ED 53 7A 4E
Store Register Pair DE to the current line address at 4E7AH. This saves the address of the current BASIC line's link pointer field for later reference when displaying line numbers. [Self-Modifying Code]
4F74
INC DE 13
INCrement DE to skip past byte 1 of the link pointer.
4F75
INC DE 13
INCrement DE to skip past byte 2 of the link pointer.
4F76
INC DE 13
INCrement DE to skip past byte 1 of the line number.
4F77
INC DE 13
INCrement DE to skip past byte 2 of the line number. DE now points to the first tokenized byte of the BASIC line.
4F78H - Main Token Scanner
The core token-scanning loop of the REF command. Reads each byte from the current BASIC line, classifies it (letter, digit, space, quote, special character, or token), and dispatches to the appropriate handler. This is where the actual cross-referencing occurs: variable names, filespecs, line numbers, and keywords are identified and matched against the search target.
4F78
LD A,(DE) 1A
Load Register A with the current byte from the BASIC program text (pointed to by DE).
4F79
OR A B7
Test for 00H end-of-line.
4F7A
If the Z FLAG has been set (end of line), JUMP back to 4F6AH to advance to the next line.
4F7C
LD HL,512FH 21 2F 51
Load Register Pair HL with 512FH, the address of the filespec comparison routine. [Self-Modifying Code]
The opcode byte at 4F7CH is patched: 21H (LD HL,nn) for variable-name mode, C3H (JP nn) for filespec mode. When C3H, this instruction becomes JP 512FH which jumps directly to the filespec comparison routine. When 21H, HL is loaded with 512FH but execution continues to the classification logic below.
4F7F
CP 41H FE 41
Compare Register A against 41H (ASCII A). Characters 41H and above are letters or tokens.
4F81
If the NO CARRY FLAG has been set (character is 41H or above — a letter, token, or extended byte), JUMP forward to 4F9BH to classify letters and tokens.
4F83
CP 30H FE 30
Compare Register A against 30H (ASCII 0). Characters 30H-39H are digits.
4F85
If the NO CARRY FLAG has been set (character is 30H or above but below 41H — a digit or colon/semicolon), JUMP forward to 4FBAH to handle digits and numeric content.
4F87
CP 20H FE 20
Compare Register A against 20H (ASCII space).
4F89
If the Z FLAG has been set (the byte is a space), JUMP back to 4F77H to skip the space and continue scanning the next byte.
4F8B
CP 22H FE 22
Compare Register A against 22H (double-quote). A quoted string in the program text.
4F8D
If the Z FLAG has been set (double-quote), JUMP back to 4F46H to skip the quoted string.
4F8F
CP 26H FE 26
Compare Register A against 26H (ASCII &). The ampersand introduces hex constants (&H) or octal constants (&O) in BASIC.
4F91
If the Z FLAG has been set (ampersand), JUMP to 504BH to handle the &H (hex) or &O (octal) constant prefix.
4F94
CP 2EH FE 2E
Compare Register A against 2EH (ASCII period .). A decimal point introduces a floating-point number.
4F96
If the Z FLAG has been set (period), JUMP to 4FE1H to skip past the numeric constant (digits after the decimal point).
4F99
JUMP back to 4F77H to advance past any other unrecognized character below 30H and continue scanning.
4F9BH - Letter and Token Classifier
Classifies bytes at 41H and above: letters (41H-5AH) route to the variable-name parser, tokens below 5BH route to the variable handler, and specific tokens (REM=93H, DATA=FBH, GOTO=88H, ON=A3H) have specialized handlers.
4F9B
LD C,A 4F
Load Register C with Register A (the current byte). C holds the byte for later comparison and storage.
4F9C
If the Z FLAG has been set (the byte is 41H, ASCII A, as tested by the CP 41H at 4F7FH — but note the Z FLAG was set from the preceding JR NC which doesn't set Z; this tests for the residual Z from a previous comparison), JUMP to 5073H to handle the special 'A' prefix. This routes to the AS keyword handler.
4F9F
CP 5BH FE 5B
Compare Register A against 5BH. Characters 41H-5AH are uppercase letters (valid variable name starters). Characters 5BH and above are tokens or special characters.
4FA1
If the CARRY FLAG has been set (the character is in the range 41H-5AH, a letter), JUMP to 5091H to begin parsing a variable name.
4FA4
CP 93H FE 93
Compare Register A against 93H, the BASIC token for REM. REM lines should be skipped entirely.
4FA6
If the Z FLAG has been set (REM token), JUMP back to 4F65H to skip to the end of the line.
4FA8
CP FBH FE FB
Compare Register A against FBH, the BASIC token for DATA. DATA lines should also be skipped.
4FAA
If the Z FLAG has been set (DATA token), JUMP back to 4F65H to skip to the end of the line.
4FAC
CP 88H FE 88
Compare Register A against 88H, the BASIC token for GOTO.
4FAE
If the Z FLAG has been set (GOTO token), JUMP back to 4F55H to scan the GOTO target for line number references.
4FB0
CP A3H FE A3
Compare Register A against A3H, the BASIC token for ON.
4FB2
If the NZ FLAG has been set (not the ON token), JUMP back to 4F77H to skip this token and continue scanning.
4FB4
LD (5085H),DE ED 53 85 50
Store Register Pair DE (the current program position) to the ON-statement address at 5085H. This saves the position of the ON keyword for reference when processing the ON...GOTO/GOSUB dispatch targets. [Self-Modifying Code]
4FB8
JUMP back to 4F77H to continue scanning. The ON keyword itself is noted but processing continues to find the GOTO/GOSUB that follows.
4FBAH - Digit and Numeric Constant Handler
Handles bytes in the range 30H-3FH (digits, colon, semicolons). A colon (3AH) is a statement separator; digits (30H-39H) introduce a numeric constant. Numeric constants are collected into the buffer at 51DFH for comparison against the search target.
4FBA
CP 3AH FE 3A
Compare Register A against 3AH (ASCII colon). A colon is a statement separator in BASIC.
4FBC
If the NO CARRY FLAG has been set (the character is 3AH or above — a colon, semicolons, or other punctuation), JUMP back to 4F77H to advance past the separator and continue scanning.
4FBE
This instruction is self-modifying. The operand byte at 4FBFH (currently 21H) is patched at 4DEBH with the column width (30H or 18H). [Self-Modifying Code]
When the operand is 30H: JR NC,4FF0H — long jump, numeric mode. When the operand is 18H: JR NC,4FD8H — short jump, letter mode. When the operand is 21H (initial value): JR NC,4FE1H. The carry flag was clear from the JR NC at 4FBCH that fell through, so this JR NC is taken. It routes to the numeric skip handler at 4FE1H.
4FC0
LD HL,51DFH 21 DF 51
Point Register Pair HL to 51DFH, the numeric constant collection buffer. Digits are stored here for comparison against the search target.
4FC3
LD B,06H 06 06
Load Register B with 06H (decimal 6), the maximum number of digits to collect.
4FC5
CP 30H FE 30
Compare Register A against 30H (ASCII 0). If the first digit is '0', the constant may have leading zeros.
4FC7
If the NZ FLAG has been set (the first digit is not '0'), JUMP forward to 4FD9H to store it in the buffer and continue collecting digits.
Leading Zero Skip Loop
Skips over leading zeros in the numeric constant (e.g., '007' is treated as '7').
4FC9
LD (HL),A 77
Store the '0' character to the buffer. This preserves the zero in case the entire number is zero.
4FCA
GOSUB to 514BH, the whitespace-skip routine. Advances DE past whitespace (spaces, tabs) and returns the next non-whitespace character in Register A.
4FCD
CP 30H FE 30
Compare Register A against 30H. If the next character is still '0', there are more leading zeros.
4FCF
If the Z FLAG has been set (another leading zero), JUMP back to 4FCAH to skip it and check the next character. [Loop End]
Digit Collection Loop
Collects up to 6 digits of the numeric constant into the buffer at 51DFH.
4FD1
CP 30H FE 30
Compare Register A against 30H (ASCII '0'). If below 30H, the character is not a digit.
4FD3
If the CARRY FLAG has been set (character below 30H, not a digit), JUMP forward to 4FEEH to check for a decimal point.
4FD5
CP 3AH FE 3A
Compare Register A against 3AH. Characters 3AH and above are not digits.
4FD7
If the NO CARRY FLAG has been set (character 3AH or above, not a digit), JUMP forward to 4FF2H to finalize the number and compare it against the search target.
4FD9
LD (HL),A 77
Store the digit character to the numeric buffer (pointed to by HL).
4FDA
INC HL 23
INCrement HL to the next buffer position.
4FDB
GOSUB to 514BH, the whitespace-skip routine, to get the next non-whitespace character.
4FDE
DECrement Register B and loop back to 4FD1H if not zero. Up to 6 digits are collected. [Loop End]
4FE0
DEC DE 1B
DECrement DE by 1 to back up to the last character read. This compensates for the fact that the whitespace-skip routine advanced DE past the final character.
4FE1
GOSUB to 514BH to skip whitespace and get the next character in Register A.
4FE4
CP 3AH FE 3A
Compare Register A against 3AH. If 3AH or above, the digit sequence is terminated.
4FE6
If the NO CARRY FLAG has been set (not a digit), JUMP forward to 4FECH to return to the main scanner.
4FE8
CP 30H FE 30
Compare Register A against 30H. If 30H or above (and below 3AH from the previous test), it is a digit.
4FEA
If the NO CARRY FLAG has been set (a digit), JUMP back to 4FE1H to continue skipping digits. [Loop End]
4FEC
JUMP back to 4F78H to return to the main token scanner with the current character in A.
4FEE
CP 2EH FE 2E
Compare Register A against 2EH (ASCII period .). A decimal point within a number (e.g., 3.14).
4FF0
If the Z FLAG has been set (decimal point), JUMP back to 4FE1H to continue skipping the fractional digits.
4FF2H - Numeric Constant Comparison
After collecting digits, calculates the digit count and compares the numeric constant against the search target. Compares both the digit count and the actual digits stored in the buffer at 51DFH against the target values at 51D3H/51D4H. If a match is found, the accumulator buffer entry is incremented.
4FF2
LD A,05H 3E 05
Load Register A with 05H, the base count value.
4FF4
SUB B 90
SUBtract Register B (remaining digit counter) from Register A. The result is the number of digits collected.
4FF5
ADC 00H CE 00
ADD 0 with carry to Register A. If the carry flag was set from the subtraction, this adds 1, adjusting the count.
4FF7
LD C,A 4F
Load Register C with Register A (the digit count).
4FF8
LD HL,(51D3H) 2A D3 51
Load Register Pair HL with the 16-bit value at 51D3H, the target comparison value (length + first digit of the search target).
4FFB
CP L BD
Compare Register A (digit count) against Register L (the target digit count from 51D3H). If they match, the Z FLAG is set.
4FFC
If the CARRY FLAG has been set (the collected digit count is less than the target), JUMP back to 4F78H. No match. [Self-Modifying Code]
The opcode at 4FFCH is patched at 4DDAH: DAH (JP C) for the first pass, C2H (JP NZ) for subsequent passes.
4FFF
If the NZ FLAG has been set (the digit counts do not match), JUMP forward to 501CH to check if this is a partial match using the alternate comparison path.
5001
LD A,(51DFH) 3A DF 51
Load Register A with the first collected digit from the buffer at 51DFH.
5004
CP H BC
Compare Register A against Register H (the second comparison byte from 51D4H). This compares the first digit of the collected number against the target.
5005
If the NZ FLAG has been set (the first digits do not match), JUMP back to 4FFCH to exit (the self-modified JP at 4FFCH handles the branch).
5007
LD IY,51D5H FD 21 D5 51
Point Index Register IY to 51D5H, the target name buffer starting at the second character. IY is used for the byte-by-byte comparison in the match subroutine.
500B
GOSUB to 5189H, the multi-byte comparison routine. Compares C bytes starting at 51E0H against C bytes starting at (IY). Returns Z if all bytes match, NZ if any differ.
500E
If the NZ FLAG has been set (the digits do not all match), JUMP back to 4FFCH to exit via the self-modified conditional jump.
5010
LD HL,51E5H 21 E5 51
Point Register Pair HL to 51E5H, the accumulator buffer. When a match is found, the appropriate entry in this buffer is incremented.
5013
LD A,(4E0CH) 3A 0C 4E
Load Register A with the iteration counter from 4E0CH.
5016
OR A B7
Test whether the iteration counter is zero (first pass).
5017
If the NZ FLAG has been set (not the first pass), JUMP to 50D9H to record the match in the accumulator and continue scanning.
501A
JUMP back to 4FECH to return to the main scanner. On the first pass, the match is noted but not yet recorded.
501CH - Alternate Comparison Path (Longer Name Match)
When the digit count exceeds the target, checks whether this is a longer variable name that starts with the same characters as the search target. Uses the alternate comparison values at 51D9H/51DBH and the multi-byte comparison at 5189H.
501C
LD HL,(51D9H) 2A D9 51
Load Register Pair HL with the 16-bit value at 51D9H (the alternate comparison value — length of the secondary pattern).
501F
LD A,C 79
Load Register A with Register C (the collected digit count).
5020
CP L BD
Compare Register A against Register L (the secondary length). [Self-Modifying Code]
The operand byte at 5021H is patched at 517CH with the column width (18H or 38H).
5021
If the CARRY FLAG has been set (the collected count is less than the secondary length), JUMP forward to 5037H to handle the shorter-than-expected case.
5023
If the NZ FLAG has been set (the counts do not match and the collected count is greater), JUMP back to 4F78H. No match possible.
5026
LD A,(51DFH) 3A DF 51
Load Register A with the first collected digit from the buffer at 51DFH.
5029
CP H BC
Compare Register A against Register H (the second byte of the comparison value at 51DAH).
502A
If the NZ FLAG has been set (the first characters do not match), JUMP back to 5021H to check the alternate path.
502C
LD IY,51DBH FD 21 DB 51
Point Index Register IY to 51DBH, the alternate name buffer for comparison.
5030
GOSUB to 5189H, the multi-byte comparison routine.
5033
If the NZ FLAG has been set (the names do not match), JUMP back to 5021H.
5035
JUMP forward to 5048H. The alternate comparison matched, so proceed to record it.
5037H - Copy Shorter Name to Active Buffer
When the collected name is shorter than the primary target but may match the secondary pattern, copies the collected name from 51DFH to 51DAH and calls the extended initialization at 516EH.
5037
LD A,C 79
Load Register A with Register C (the collected digit count).
5038
INC C 0C
INCrement Register C by 1 to include the length byte in the copy count.
5039
PUSH DE D5
Save Register Pair DE (the current program position) onto the stack.
503A
LD HL,51DFH 21 DF 51
Point HL to 51DFH, the source buffer (collected digits).
503D
LD DE,51DAH 11 DA 51
Point DE to 51DAH, the destination buffer (active variable name).
5040
LD B,00H 06 00
Load Register B with 00H. BC holds the copy count (B=00H, C=count+1).
5042
LDIR ED B0
Block copy BC bytes from (HL=51DFH) to (DE=51DAH). This copies the collected name into the active buffer.
5044
POP DE D1
Restore Register Pair DE (the program position) from the stack.
5045
GOSUB to 516EH, the extended initialization routine. This stores A (the digit count) to 51D9H and then falls into 5171H to reconfigure the display width and reset the PDRIVE pointers.
5048
JUMP to 5101H to enter the PDRIVE duplicate check and recording logic.
504BH - Ampersand Prefix Handler (&H / &O / &D)
Handles the ampersand prefix character (26H) which introduces hex (&H), octal (&O), or decimal (&D) constants in BASIC. Reads the character after the ampersand to determine the base, then skips past the constant's digits.
504B
GOSUB to 514BH to skip whitespace and get the next character in Register A.
504E
CP 44H FE 44
Compare Register A against 44H (ASCII D). If the character is 'D' (as in &D for decimal), the Z FLAG is set.
5050
If the Z FLAG has been set (the prefix is &D), JUMP to 4F6AH to skip the rest of the constant and advance to the next line.
5053
CP 4FH FE 4F
Compare Register A against 4FH (ASCII O). If the character is 'O' (as in &O for octal), the Z FLAG is set.
5055
If the Z FLAG has been set (the prefix is &O), JUMP to 4FE1H to skip the octal digits.
5058
CP 48H FE 48
Compare Register A against 48H (ASCII H). If the character is 'H' (as in &H for hexadecimal), the Z FLAG is set.
505A
If the NZ FLAG has been set (the character after & is not D, O, or H), JUMP forward to 5070H to return to the main scanner. The ampersand is treated as an unrecognized character.
Hex Digit Skip Loop
Skips hex digits (0-9, A-F) after the &H prefix.
505C
GOSUB to 514BH to skip whitespace and get the next character.
505F
CP 47H FE 47
Compare Register A against 47H (ASCII G). Hex digits go up to 'F' (46H). If the character is 47H or above, it is not a hex digit.
5061
If the NO CARRY FLAG has been set (character is 47H or above), JUMP to 5070H to exit the hex skip loop.
5063
CP 41H FE 41
Compare Register A against 41H (ASCII A). If 41H-46H, it is a hex letter digit.
5065
If the NO CARRY FLAG has been set (character is 41H-46H, a hex letter), JUMP back to 505CH to continue skipping. [Loop]
5067
CP 3AH FE 3A
Compare against 3AH. If 3AH or above (but below 41H from previous test), not a digit.
5069
If the NO CARRY FLAG has been set (3AH-40H, not a hex digit), JUMP to 5070H.
506C
CP 30H FE 30
Compare against 30H. If 30H-39H, it is a decimal/hex digit.
506E
If the NO CARRY FLAG has been set (digit 0-9), JUMP back to 505CH to continue skipping. [Loop End]
5070
JUMP back to 4F78H to return to the main token scanner.
5073H - 'A' Prefix Handler (AS Keyword Check)
When the character is 41H (ASCII 'A'), checks whether the next character forms the 'AS' keyword by looking for 'S' followed by a non-alphanumeric character. If 'AS' is detected, it is processed as a keyword. Otherwise, routes to the variable name parser at 5091H.
5073
GOSUB to 514BH to skip whitespace and get the next character in Register A.
5076
CP 53H FE 53
Compare Register A against 53H (ASCII S). If the next character is 'S', this may be the 'AS' keyword.
5078
If the NZ FLAG has been set (not 'S'), JUMP forward to 5094H to treat the 'A' as the start of a variable name.
507A
LD B,A 47
Load Register B with 'S' (53H). B preserves the second character of the potential 'AS' keyword.
507B
GOSUB to 514BH to get the character after 'S'.
507E
GOSUB to 5161H, the letter-range check routine. Returns CARRY set if the character is a letter (41H-5AH), meaning 'AS' is part of a longer variable name (e.g., 'ASK').
5081
If the CARRY FLAG has been set (the next character is a letter), JUMP forward to 509FH. 'AS' is part of a longer name, so treat 'A' as a variable name starter.
5083
PUSH DE D5
Save Register Pair DE (the program position) onto the stack.
5084
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H. The operand at 5085H is self-modifying: it holds the address of the ON keyword saved at 4FB4H. [Self-Modifying Code]
5087
LD HL,(4E7AH) 2A 7A 4E
Load Register Pair HL with the current line address from 4E7AH.
508A
OR A B7
Clear the CARRY FLAG for the SBC comparison.
508B
SBC HL,DE ED 52
SUBtract DE (the ON-keyword address) from HL (the current line address). If HL < DE (the ON keyword is on a later line), the result is negative.
508D
POP DE D1
Restore Register Pair DE from the stack.
508E
If the NO CARRY FLAG has been set (the current line is at or past the ON keyword), JUMP to 509FH. The 'AS' is not related to ON...AS, so treat it as a variable name.
5090
LD C,A 4F
Load Register C with Register A (the character after 'AS').
5091H - Variable Name Parser (from Program Text)
Parses a variable name from the BASIC program text. Reads characters, collecting letters and digits, and stores the first two significant characters for comparison against the search target. After the name is collected, compares it against the target variable name at 51D4H using the self-modifying conditional jump at 50A9H.
5091
GOSUB to 514BH to skip whitespace and get the next character from the program text.
5094
LD B,20H 06 20
Load Register B with 20H (ASCII space). B holds the default second character of the variable name (a space means the name is only 1 character long).
5096
GOSUB to 515AH, the alphanumeric range check. Returns CARRY set if the character is NOT alphanumeric (not a digit 30H-39H and not a letter 41H-5AH). This tests whether the second character of the variable name is valid.
5099
If the CARRY FLAG has been set (the character is not alphanumeric), JUMP forward to 50A4H. The variable name is only 1 character long (B remains as space).
509B
LD B,A 47
Load Register B with Register A (the second character of the variable name).
509C
GOSUB to 514BH to get the next character.
509F
GOSUB to 515AH to check if the character is alphanumeric.
50A2
If the NO CARRY FLAG has been set (the character is alphanumeric), JUMP back to 509CH to skip it and continue reading. Only the first two characters of the variable name are significant in BASIC; additional characters are consumed but ignored. [Loop End]
50A4
LD HL,(51D4H) 2A D4 51
Load Register Pair HL with the 16-bit value at 51D4H. This is the target variable name's first two characters (L=first char, H=second char).
50A7
LD A,C 79
Load Register A with Register C (the first character of the found variable name).
50A8
CP L BD
Compare Register A against Register L (the first character of the target). If they match, the Z FLAG is set.
50A9
If the CARRY FLAG has been set (the found character is less than the target), JUMP back to 4F78H. No match. [Self-Modifying Code]
The opcode at 50A9H is patched at 4DDDH: DAH (JP C) for the first pass, C2H (JP NZ) for subsequent passes.
50AC
If the NZ FLAG has been set (the first characters match but this is a different comparison outcome), JUMP forward to 50EEH for the alternate comparison path.
50AE
LD A,B 78
Load Register A with Register B (the second character of the found variable name).
50AF
CP H BC
Compare Register A against Register H (the second character of the target).
50B0
If the NZ FLAG has been set (the second characters do not match), JUMP back to 50A9H to exit via the self-modified conditional jump.
Both Characters Match
The found variable name matches the target's first two characters. Now check the type suffix and handle the match recording.
50B2
LD A,(4E0CH) 3A 0C 4E
Load Register A with the iteration counter from 4E0CH.
50B5
OR A B7
Test whether this is the first pass (A=00H).
50B6
If the Z FLAG has been set (first pass), JUMP forward to 50EBH. On the first pass, the match is noted but not yet recorded with type information.
Type Suffix Detection (Subsequent Passes)
On passes after the first, checks the character following the variable name for a type suffix ($, %, !, #) and records which type-slot the match belongs to.
50B8
LD A,(DE) 1A
Load Register A with the character immediately after the variable name (pointed to by DE). This may be a type suffix.
50B9
LD HL,51E9H 21 E9 51
Point Register Pair HL to 51E9H, the type suffix accumulator (within the 10-byte buffer at 51E5H, offset by 4 for type slots 4-7).
50BC
LD IY,51B5H FD 21 B5 51
Point Index Register IY to 51B5H, the type suffix lookup table. This table contains the characters for the 4 BASIC variable types in reverse order.
50C0
LD B,04H 06 04
Load Register B with 04H (decimal 4), the number of type suffixes to check ($, %, !, #).
50C2
CP (IY+00H) FD BE 00
Compare Register A (the character after the variable name) against the type suffix at (IY+0). This checks whether the character matches the current type suffix.
50C5
If the Z FLAG has been set (the type suffix matches), JUMP forward to 50CDH to process the match.
50C7
DEC HL 2B
DECrement HL to move to the previous accumulator slot.
50C8
DEC IY FD 2B
DECrement IY to move to the previous type suffix in the lookup table.
50CA
DECrement Register B and loop back to 50C2H if not zero. Checks all 4 type suffixes. [Loop End]
50CC
DEC DE 1B
DECrement DE by 1. If no type suffix was found, back up DE so that the character is re-read by the next scan iteration.
50CD
GOSUB to 514BH to skip whitespace and get the next character.
50D0
CP 28H FE 28
Compare Register A against 28H (ASCII (). An opening parenthesis after a variable name indicates an array variable (e.g., A(5)).
50D2
If the NZ FLAG has been set (not an opening parenthesis), JUMP forward to 50D9H to record the match without the array offset.
50D4
LD BC,0005H 01 05 00
Load Register Pair BC with 0005H (decimal 5). This offset is added to HL to advance to the array-variable accumulator slot (5 positions beyond the scalar slot).
50D7
ADD HL,BC 09
ADD 5 to HL. HL now points to the array-variable accumulator slot instead of the scalar-variable slot.
50D8
INC DE 13
INCrement DE to advance past the opening parenthesis.
50D9H - Record Match and Continue Scan
Records a match by incrementing the accumulator byte at (HL), resets the scan mode flag to C3H (enabling the end-of-scan jump), reads the line number from the current BASIC line header, stores it at 4E76H, and continues scanning.
50D9
INC (HL) 34
INCrement the byte at (HL) by 1. This increments the occurrence count in the appropriate accumulator buffer slot, recording that the current variable was found on this line.
50DA
LD HL,4F6DH 21 6D 4F
Point HL to 4F6DH, the end-of-line detection flag.
50DD
LD (HL),C3H 36 C3
Store C3H to (4F6DH). This changes the instruction at 4F6DH from JP Z (CAH) to JP (C3H), making the end-of-line jump unconditional. After a match is found, the scan should report the match by jumping to 4DFCH at the next end-of-line. [Self-Modifying Code]
50DF
LD HL,(4E7AH) 2A 7A 4E
Load Register Pair HL with the current line address from 4E7AH. This points to the start of the BASIC line's link pointer field.
50E2
INC HL 23
INCrement HL to skip past byte 1 of the link pointer.
50E3
INC HL 23
INCrement HL to skip past byte 2 of the link pointer, now pointing to the line number field.
50E4
LD C,(HL) 4E
Load Register C with the low byte of the current line number.
50E5
INC HL 23
INCrement HL to the high byte of the line number.
50E6
LD B,(HL) 46
Load Register B with the high byte of the current line number. BC now holds the 16-bit line number.
50E7
LD (4E76H),BC ED 43 76 4E
Store the current line number (BC) to the line number storage at 4E76H. This will be displayed when the match is output.
50EB
JUMP back to 4F78H to continue the main token scan loop.
50EEH - Alternate Variable Name Comparison
When the first character matches but the second does not (or the comparison mode differs), this section uses the alternate comparison values at 51DAH to check for a broader match.
50EE
LD HL,(51DAH) 2A DA 51
Load Register Pair HL with the 16-bit value at 51DAH (the alternate variable name comparison value).
50F1
LD A,C 79
Load Register A with Register C (the first character of the found variable).
50F2
CP L BD
Compare Register A against Register L (the first byte of the alternate pattern).
50F3
If the CARRY FLAG has been set (the found character is less than the alternate target), JUMP forward to 50FEH to handle the "new variable" case.
50F5
If the NZ FLAG has been set (no match), JUMP back to the main scanner.
50F8
LD A,B 78
Load Register A with Register B (the second character of the found variable).
50F9
CP H BC
Compare Register A against Register H (the second byte of the alternate pattern).
50FA
If the NZ FLAG has been set (second characters do not match), JUMP back to 50F3H to check the carry condition.
50FC
JUMP forward to 5101H. Both characters of the alternate pattern match.
50FE
GOSUB to 5168H, the extended initialization. This stores BC to 51DAH and reconfigures the scan parameters for a new variable target.
5101H - PDRIVE Table Duplicate Check
Checks the PDRIVE reference table at 4EEFH/4EF2H for duplicate entries before recording a new reference. Compares the current reference address against existing entries and either updates an existing entry or adds a new one.
5101
LD HL,(4EEFH) 2A EF 4E
Load Register Pair HL with the current PDRIVE table pointer from 4EEFH (self-modifying code target).
5104
LD BC,4340H 01 40 43
Load Register Pair BC with 4340H, the PDRIVE table sentinel.
5107
OR A B7
Clear the CARRY FLAG.
5108
SBC HL,BC ED 42
Compare HL against 4340H (the sentinel). If equal, the table is full and the pointer has reached the end.
510A
ADD HL,BC 09
Restore HL to its original value (the SBC was only for comparison).
510B
If the Z FLAG has been set (table pointer at sentinel), JUMP back to 50EBH to continue scanning. The table is full; no more entries can be recorded.
510D
LD BC,4300H 01 00 43
Load Register Pair BC with 4300H, the start of the PDRIVE table.
5110
OR A B7
Clear the CARRY FLAG.
5111
SBC HL,BC ED 42
Compare HL against 4300H. If equal, the pointer is at the table start (no entries yet).
5113
ADD HL,BC 09
Restore HL.
5114
LD BC,(4E7AH) ED 4B 7A 4E
Load Register Pair BC with the current line address from 4E7AH.
5118
If the Z FLAG has been set (pointer at table start), JUMP to 5126H to add the first entry directly.
Duplicate Check
Walks backward through existing entries to see if the current line address is already recorded.
511A
DEC HL 2B
DECrement HL to point to the high byte of the previous entry.
511B
LD A,B 78
Load Register A with Register B (high byte of the current line address).
511C
CP (HL) BE
Compare Register A against the high byte of the previous entry.
511D
If the NZ FLAG has been set (high bytes differ), JUMP to 5125H. No duplicate found at this position.
511F
DEC HL 2B
DECrement HL to point to the low byte of the previous entry.
5120
LD A,C 79
Load Register A with Register C (low byte of the current line address).
5121
CP (HL) BE
Compare Register A against the low byte of the previous entry.
5122
INC HL 23
INCrement HL back to the high byte position (restore position).
5123
If the Z FLAG has been set (both bytes match — duplicate found), JUMP to 50EBH. The entry already exists; skip recording.
5125
INC HL 23
INCrement HL to advance past the previous entry to the next available slot.
5126
LD (HL),C 71
Store Register C (low byte of the current line address) to the new table entry.
5127
INC HL 23
INCrement HL.
5128
LD (HL),B 70
Store Register B (high byte of the current line address) to the new table entry.
5129
INC HL 23
INCrement HL to point past the new entry.
512A
LD (4EEFH),HL 22 EF 4E
Store the updated table pointer to 4EEFH. [Self-Modifying Code]
512D
JUMP back to 50EBH to continue scanning.
512FH - Filespec Match Routine
Compares the current token in the BASIC program text against the filename stored at 51EFH. Called when the scan mode is C3H (filespec mode). Performs a byte-by-byte comparison of the program text against the match buffer. If a match is found, routes to the accumulator recording logic at 50D9H.
512F
LD HL,51EFH 21 EF 51
Point Register Pair HL to 51EFH, the filespec match buffer containing the user-specified filename.
5132
CP (HL) BE
Compare Register A (the current byte from the program text) against the first byte of the match buffer.
5133
If the NZ FLAG has been set (first bytes do not match), JUMP forward to 5148H to return to the main scan.
5135
PUSH DE D5
Save Register Pair DE (the current program position) onto the stack.
5136
INC DE 13
INCrement DE to advance to the next byte in the program text.
5137
INC HL 23
INCrement HL to advance to the next byte in the match buffer.
5138
LD A,(HL) 7E
Load Register A with the next byte from the match buffer.
5139
OR A B7
Test for 00H (end of the match buffer string).
513A
If the NZ FLAG has been set (more characters in the match buffer), JUMP forward to 5143H to continue comparing.
Full Match Found
The match buffer has been exhausted (null terminator reached). The entire filename matched. Route to the accumulator recording.
513C
POP HL E1
Discard the saved DE from the stack (we no longer need the original position; the match starts a new recording).
513D
LD HL,51E5H 21 E5 51
Point HL to 51E5H, the accumulator buffer.
5140
JUMP to 50D9H to record the match in the accumulator and continue scanning.
5143
LD A,(DE) 1A
Load Register A with the next byte from the program text.
5144
CP (HL) BE
Compare Register A against the next byte in the match buffer.
5145
If the Z FLAG has been set (bytes match), JUMP back to 5136H to continue comparing the next pair of bytes. [Loop End]
5147
POP DE D1
Restore Register Pair DE (the original program position) from the stack. The match failed partway through.
5148
JUMP back to 4F77H to advance past the current byte and continue scanning.
514BH - Whitespace Skip Utility
Advances DE past whitespace characters (space 20H, tab 09H, line-feed 0AH) and returns the next non-whitespace character in Register A. Returns NC for printable characters, CARRY for control characters below 09H.
514B
INC DE 13
INCrement Register Pair DE to advance to the next byte in the program text.
514C
LD A,(DE) 1A
Load Register A with the byte at (DE).
514D
CP 20H FE 20
Compare Register A against 20H (ASCII space).
514F
If the Z FLAG has been set (space), JUMP back to 514BH to skip it. [Loop]
5151
RET NC D0
If the NO CARRY FLAG has been set (character is 20H or above but not a space, i.e., a printable character above space), RETURN. Register A holds the non-whitespace character.
5152
CP 0BH FE 0B
Compare Register A against 0BH (vertical tab).
5154
RET NC D0
If the NO CARRY FLAG has been set (character is 0BH or above, below 20H), RETURN. Characters 0BH-1FH are control characters that are treated as whitespace terminators.
5155
CP 09H FE 09
Compare Register A against 09H (horizontal tab).
5157
RET C D8
If the CARRY FLAG has been set (character is below 09H), RETURN. Characters below 09H are non-whitespace control codes.
5158
JUMP back to 514BH to skip the tab character (09H or 0AH) and continue. [Loop End]
515AH - Alphanumeric Range Check
Tests whether Register A contains a digit (30H-39H) or a letter (41H-5AH). Returns CARRY set if the character is NOT alphanumeric, NO CARRY if it is.
515A
CP 30H FE 30
Compare Register A against 30H (ASCII '0'). If below 30H, not alphanumeric.
515C
RET C D8
RETURN with CARRY set if A < 30H (not a digit or letter).
515D
CP 3AH FE 3A
Compare against 3AH. If below 3AH (30H-39H), it is a digit.
515F
CCF 3F
Complement the CARRY FLAG. If the character was a digit (CARRY clear from CP 3AH since A < 3AH), CCF sets CARRY; but since we want NC for digits, this is combined with RET NC to return NC for digits. Actually: CP 3AH with A=35H gives NC (A<3AH is false, since 35H < 3AH means C is set). Wait — CP 3AH: if A < 3AH, CARRY is set. CCF inverts it to NC. So digits (30H-39H) return NC after this. Characters 3AH-40H: CP 3AH gives NC, CCF gives C.
5160
RET NC D0
RETURN with NO CARRY if the character is a digit (30H-39H). The CCF inverted the carry from the CP 3AH comparison.
5161
CP 41H FE 41
Compare Register A against 41H (ASCII 'A'). If below 41H, not a letter.
5163
RET C D8
RETURN with CARRY set if A < 41H (in the 3AH-40H range, not alphanumeric).
5164
CP 5BH FE 5B
Compare against 5BH. If below 5BH (41H-5AH), it is a letter.
5166
CCF 3F
Complement the CARRY FLAG. Letters (41H-5AH) had CARRY set from CP 5BH; CCF clears it to NC. Characters 5BH+ had NC; CCF sets CARRY.
5167
RET C9
RETURN. NO CARRY = alphanumeric (digit or letter), CARRY = not alphanumeric.
5168H - Extended Initialization Routine
Stores BC to the variable name buffer at 51DAH, writes 01H to the length byte at 51D9H, then falls through to 5171H to configure the display width and reset the PDRIVE table pointers.
5168
LD (51DAH),BC ED 43 DA 51
Store Register Pair BC to the variable name buffer at 51DAH. This sets the active search pattern.
516E
LD A,01H 3E 01
Load Register A with 01H.
516E
LD (51D9H),A 32 D9 51
Store 01H to the name length byte at 51D9H.
5171H - Display Width and PDRIVE Pointer Initialization
Reads the first byte of the variable name at 51DAH, determines the display column width (18H for letters, 38H for digits/specials), stores it to the self-modifying code target at 5021H, and resets the PDRIVE table pointers at 4EEFH and 4EF2H to 4300H.
5171
LD A,(51DAH) 3A DA 51
Load Register A with the first byte of the variable name buffer at 51DAH.
5174
CP 41H FE 41
Compare Register A against 41H (ASCII 'A'). Letters are at 41H and above.
5176
LD A,18H 3E 18
Load Register A with 18H (decimal 24), the column width for letter-based variable names.
5178
If the NO CARRY FLAG has been set (the first character is 41H or above, a letter), JUMP forward to 517CH to store 18H.
517A
LD A,38H 3E 38
Load Register A with 38H (decimal 56), the column width for digit/special-based names.
517C
LD (5021H),A 32 21 50
Store the column width (18H or 38H) to the self-modifying code target at 5021H. [Self-Modifying Code]
517F
LD HL,4300H 21 00 43
Load Register Pair HL with 4300H, the start of the PDRIVE table.
5182
LD (4EEFH),HL 22 EF 4E
Store 4300H to the PDRIVE table pointer at 4EEFH. This resets the pointer to the start of the table. [Self-Modifying Code]
5185
LD (4EF2H),HL 22 F2 4E
Store 4300H to the secondary PDRIVE pointer at 4EF2H. [Self-Modifying Code]
5188
RET C9
RETURN to the caller.
5189H - Multi-Byte Comparison Routine
Compares C bytes starting at 51E0H against C bytes starting at (IY). Returns Z if all bytes match, NZ if any differ. Register B is used as the loop counter (loaded from C). If C is 00H, returns immediately with Z set (empty comparison always matches).
5189
LD A,C 79
Load Register A with Register C (the comparison byte count).
518A
OR A B7
Test whether C is 00H (empty comparison).
518B
LD B,A 47
Load Register B with Register A (the byte count, also the loop counter).
518C
RET Z C8
If the Z FLAG has been set (C=00H, no bytes to compare), RETURN with Z set (match by default).
518D
LD HL,51E0H 21 E0 51
Point Register Pair HL to 51E0H, the source comparison buffer.
5190
LD A,(HL) 7E
Load Register A with the byte at (HL).
5191
CP (IY+00H) FD BE 00
Compare Register A against the byte at (IY+0). If the bytes differ, the NZ FLAG is set.
5194
INC HL 23
INCrement HL to advance to the next source byte.
5195
RET NZ C0
If the NZ FLAG has been set (bytes do not match), RETURN with NZ set (mismatch).
5196
INC IY FD 23
INCrement IY to advance to the next target byte.
5198
DECrement Register B and loop back to 5190H if not zero. [Loop End]
519A
RET C9
RETURN with Z set (all bytes matched).
519BH - Cursor Position Check and Line Wrap
Checks the current cursor position to determine whether there is enough room on the display line for the next reference output. If the cursor has reached column 53 (35H) or beyond, outputs a carriage return and leading spaces to start a new indented line. If there is room, outputs a space separator.
519B
GOSUB to 5D52H, the carriage return output routine.
519E
GOSUB to 5D3DH to display a space character followed by the cursor position.
51A1
LD A,(4020H) 3A 20 40
Load Register A with the current cursor position from 4020H. The low 6 bits (masked by AND 3FH) give the column number (0-63).
51A4
AND 3FH E6 3F
AND Register A with 3FH to mask out the row bits and keep only the column number (0-63).
51A6
CP 35H FE 35
Compare the column number against 35H (decimal 53). If the column is 53 or more, the line is nearly full.
51A8
If the NO CARRY FLAG has been set (column is 53 or more), JUMP back to 519BH to output a carriage return and restart the line with leading spaces. [Loop]
51AA
SUB 07H D6 07
SUBtract 07H from the column number. If the column is 7 or more, the NO CARRY FLAG is set (there is room for the next output).
51AC
RET NC D0
If the NO CARRY FLAG has been set (column is 7 or more), RETURN. There is enough room on the current line.
51AD
NEG ED 44
NEGate Register A. After the SUB 07H, A is negative (the column was less than 7). NEG makes it positive, giving the number of spaces needed to reach column 7.
51AF
JUMP to 5D30H to display A space characters, padding the output to column 7.
51B2H - Data Tables
Static data tables used by the REF command. These include the type suffix characters, the "$EXT END" display message, and the variable name work areas. The bytes from 51B2H through 51D2H are data, not executable code.
51B2
DEFB 24H,25H 24 25
Type Suffix Table (51B2H-51B5H)
Four bytes containing the BASIC variable type suffix characters: 24H = $ (string), 25H = % (integer).
51B4
DEFB 21H,23H 21 23
Continuation of the type suffix table: 21H = ! (single-precision), 23H = # (double-precision). The type suffix lookup at 50BCH/50C2H indexes into this table using IY.
51B6
DEFM "$EXT END" + 0DH 24 45 58 54 20 45 4E 44 0D
End-of-Program Message (51B6H-51BEH)
The 9-byte text string "$EXT END" followed by a carriage return (0DH). This is displayed at 4E25H when the REF scan reaches the end of the BASIC program. The decoded text is: $EXT ENDCR.
51BF-51D2
NOP × 20 00 × 20
Variable Name Work Area (51BFH-51D2H)
20 bytes of zeroed workspace used for storing parsed variable names, comparison buffers, and temporary data during the REF scan. Key sub-fields: 51D3H-51D4H = primary comparison value (length + first char); 51D9H = name length byte; 51DAH-51DFH = variable name characters; 51E0H-51E4H = digit collection buffer overflow; 51E5H-51EEH = 10-byte accumulator buffer; 51EFH-51FFH = filespec match buffer. These fields overlap the NOP padding and extend beyond the end of the loaded SYS12 overlay into the general work area.