5700H-572DH — FCB / Runtime Work Area
This block of 46 bytes (5700H-572DH) is initialized to 00H in the /CMD file image. At runtime, various BASIC/CMD routines and SYS overlay modules write structured data into this area. The addresses within this block serve as an FCB (File Control Block) template and general-purpose workspace for disk BASIC file operations. The data stored here includes drive numbers, filename pointers, FCB flags, and file positioning information used by SYS10 (GET/PUT), SYS19 (LOAD/SAVE), SYS20, and other overlay modules. Because the /CMD loader places zeroes here, the disassembler shows NOP instructions; these are NOT executable code.
5700
DEFB 00H 00
Runtime variable. Written to by code at 60E1H (within BASIC/CMD) and by SYS20 at 55CDH. Read by SYS10 at 4D09H, 4D41H, and 4D68H. This byte holds an FCB status or drive-related flag set during file open/init operations.
5701
DEFB 00H 00
Runtime variable. Part of the FCB work area; exact purpose determined by runtime context with surrounding bytes.
5702
DEFB 00H 00
Runtime variable. Written to by SYS20 at 55C9H.
5703
DEFB 00H 00
Runtime variable. FCB work area byte.
5704
DEFB 00H 00
Runtime variable. FCB work area byte.
5705
DEFB 00H 00
Runtime variable. Written to by code at 6113H (within BASIC/CMD file setup routine).
5706
DEFB 00H 00
Runtime variable. FCB work area byte.
5707
DEFB 00H 00
Runtime variable. FCB work area byte.
5708
DEFB 00H 00
Runtime variable. Written to by code at 611AH (within BASIC/CMD file setup routine).
5709
DEFB 00H 00
Runtime variable. FCB work area byte.
570A
DEFB 00H 00
Runtime variable. FCB work area byte.
570B
DEFB 00H 00
Runtime variable. Written to by SYS10 at 4D4BH and read back by SYS10 at 4D88H. Used as a GET/PUT operation parameter.
570C
DEFB 00H 00
Runtime variable. FCB work area byte.
There is a gap in the disassembly from 570DH to 572CH. The address 570DH is referenced by SYS19 at 5279H, 54B3H, and 55FFH as a DE source (a pointer loaded with LD DE,(570DH) or LD DE,570DH). Addresses 5710H (written by SYS19 at 55D5H and 55EDH), 5712H (written at 60DAH), 5715H (written at 60EEH), 5716H (written at 621BH), 5717H (written at 60D7H), and 5719H (written at 60EBH) are all runtime variables within this work area. The gap contains no executable code; it is contiguous workspace.
572D
DEFB 00H 00
Runtime variable. Last byte of the FCB/runtime work area before executable code begins at 572EH.
572EH-5754H — SVC Dispatch Entry Points (Jump Table Stubs)
This section contains a series of compact entry points that are reached via the jump table at 67BBH-684BH (which is copied to 4152H during initialization). Each entry point loads Register Pair BC with an address (typically a routine in the SYS overlay area at 5200H-56FFH or higher) and loads Register A with an SVC function code, then falls through or jumps to the common SVC dispatcher at 576CH. The pattern is: LD BC,nnnn / JR 5752H (or JR 576CH), where BC holds a “return-to” or parameter address and A holds the SVC function number. Some entry points first CALL 6073H or 6076H to perform setup operations before dispatching. The SVC function codes observed are 34H, 35H, 36H, and 37H, corresponding to NEWDOS/80 Supervisor Call functions for BASIC disk operations.
572E
PUBLIC ENTRY - called via jump table
GOSUB to 6073H to perform file operation setup. This routine (at 6073H) initializes file control structures and prepares for the SVC call.
5731
LD BC,5334H 01 34 53
Load Register Pair BC with 5334H. This address (5334H) is in the SYS overlay area and will be used as a parameter or callback address by the SVC dispatcher.
5734
JUMP forward to 5752H to load SVC function code 35H into Register A and continue to the common dispatcher at 576CH.
5736
LD BC,559CH 01 9C 55
PUBLIC ENTRY — CMD"F"
Load Register Pair BC with 559CH (SYS overlay area address). This is the entry point for the CMD"F" handler (file operations), reached when the CMD dispatcher at 57C3H identifies character ‘F’ (46H).
5739
JUMP forward to 5752H to load SVC function code 35H and dispatch.
573B
LD BC,8440H 01 40 84
Load Register Pair BC with 8440H. This address is above the normal BASIC/CMD and DOS range, suggesting it is a high-memory routine or buffer address used during this particular SVC operation.
573E
GOSUB to 6076H to perform an alternate file operation setup (different entry point from 6073H, may skip certain initialization steps).
5741
LD BC,55C5H 01 C5 55
Load Register Pair BC with 55C5H (SYS overlay area address), the parameter/callback for this SVC function.
5744
JUMP forward to 5752H to load SVC function code 35H and dispatch.
5746
RET C D8
If the CARRY FLAG is set (indicating an error or special condition from a prior operation), RETurn immediately to the caller without proceeding further. This is a conditional bail-out entry point.
5747
LD A,01H 3E 01
Load Register A with 01H. This value serves as a flag or mode indicator (01H = file open for read, per FCB status byte bit 0).
5749
LD B,AFH 06 AF
Load Register B with AFH (decimal 175). This value is a parameter passed to the routine called next — it may represent a buffer size or character count limit.
574B
PUSH AF F5
Save Register A (01H, the mode flag) and the current FLAGS onto the stack for later retrieval.
574C
GOSUB to 6073H to perform file operation setup, same setup routine as at 572EH.
574F
LD BC,5202H 01 02 52
Load Register Pair BC with 5202H (SYS overlay area address). 5202H is the start+2 of the BASIC overlay area (5200H), used as a callback for this operation.
5752
LD A,35H 3E 35
Common Merge Point for SVC 35H dispatch
Load Register A with 35H (SVC function code 35H). This is one of the NEWDOS/80 BASIC disk SVC functions. Multiple entry points converge here to use function 35H.
5754
JUMP forward to 576CH, the common SVC dispatcher, which will push BC, test A, and execute RST 28H with the function code in A.
5756H-576AH — Additional SVC Dispatch Entry Points (Function 34H)
More entry points that dispatch through the common SVC handler at 576CH. These use SVC function code 34H instead of 35H. Entry at 575DH performs a comparison check before dispatching.
5756
PUSH AF F5
Save Register A and FLAGS onto the stack. Register A holds a value set by the caller (entry comes from a jump table stub).
5757
PUSH BC C5
Save Register Pair BC onto the stack. BC holds parameters from the calling context.
5758
LD BC,54FAH 01 FA 54
Load Register Pair BC with 54FAH (SYS overlay area address), the parameter/callback for this dispatch.
575B
JUMP forward to 576AH to load SVC function code 34H and continue to dispatcher.
575D
POP HL E1
Restore the top-of-stack value into Register Pair HL. This pops a return address or parameter that was pushed by the caller.
575E
POP HL E1
Pop the NEXT stack value into Register Pair HL, discarding the first popped value (it was consumed as a throwaway). HL now holds the second item from the stack.
575F
PUSH HL E5
Save Register Pair HL (the value just retrieved) back onto the stack to preserve it for later use.
5760
LD DE,1A7EH 11 7E 1A
Load Register Pair DE with 1A7EH. This is a ROM address used as a comparison value — it represents a boundary or limit address within the Model III ROM.
5763
RST 18H DF
Execute RST 18H (CPDEHL): Compare Register Pair DE (1A7EH) with Register Pair HL. Sets Z FLAG if DE = HL, CARRY FLAG if DE < HL.
5764
If the NZ FLAG is set (DE ≠ HL, meaning the address in HL does not match the ROM boundary at 1A7EH), JUMP to ROM routine at 036BH. This is an error or alternate path handler in the ROM.
5767
LD BC,5202H 01 02 52
Load Register Pair BC with 5202H (SYS overlay area callback address), same as used at 574FH.
576A
LD A,34H 3E 34
COMMON MERGE POINT for SVC 34H dispatch
Load Register A with 34H (SVC function code 34H). This is the NEWDOS/80 BASIC disk SVC function 34H.
576CH-577EH — Common SVC Dispatcher and File Open Wrapper
This is the central dispatcher that all SVC entry points converge to. It pushes BC (the callback/parameter address), checks if Register A is zero (a no-op sentinel), and then executes the SVC call via RST 28H. After the SVC returns, it calls 57B5H (which itself executes RST 28H with function 37H) to perform a follow-up operation. If the follow-up fails (NZ), it jumps to the error translator at 5DEFH. On success, it stores the result and returns.
576C
PUSH BC C5
Save Register Pair BC (the callback/parameter address loaded by the entry point stub) onto the stack. The SVC handler will use this as a return or continuation address.
576D
CP 00H FE 00
Compare Register A against 00H. If A is zero, this is a “no operation” sentinel indicating no SVC should be executed.
576F
RET Z C8
If the Z FLAG is set (A = 00H, no SVC function to execute), RETurn immediately. The return address is the BC value just pushed, so execution continues at the callback address loaded by the entry point stub.
SVC CALL SEQUENCE
At this point, Register A holds a non-zero SVC function code (34H, 35H, 36H, or 37H). The PUSH BC above placed the callback address on the stack, so when the RET at 577EH executes, control will pass to that callback address. The code now saves HL, clears the variable at 576EH, executes the SVC, checks the result, and returns.
5770
PUSH HL E5
Save Register Pair HL (the current BASIC text pointer or file pointer) onto the stack for preservation across the SVC call.
5771
SELF-MODIFYING CODE TARGET: 576EH
Point Register Pair HL to 576EH, a single-byte runtime variable within BASIC/CMD. This variable is used to store the result of the SVC operation.
5774
LD (HL),00H 36 00
SELF-MODIFYING CODE — writes to 576EH
Store 00H into the byte at (HL) = 576EH, clearing the result variable before the SVC call.
5776
GOSUB to 57B5H, which executes RST 28H (SVC call) with the function code currently in Register A. On entry to 57B5H, A still holds the SVC function code (34H/35H/36H). The RST 28H at 57B5H dispatches to the NEWDOS/80 supervisor, which loads and executes the appropriate SYS overlay module. On return, the Z FLAG indicates success (Z) or failure (NZ).
5779
If the NZ FLAG is set (the SVC call at 57B5H returned an error), JUMP to 5DEFH, the DOS-to-BASIC error translation routine. That routine converts the DOS error code into a BASIC error code and invokes the BASIC error handler.
577C
LD (HL),A 77
Store Register A (the SVC return value, which is 00H on success) into (HL) = 576EH, recording the result of the operation. Since we reached here on Z FLAG (success), A is 00H, confirming the cleared state.
577D
POP HL E1
Restore Register Pair HL (the BASIC text pointer or file pointer saved at 5770H) from the stack.
577E
RET C9
RETurn to the caller. The return address on the stack is the BC callback address pushed at 576CH, so execution continues at the SYS overlay callback routine.
577FH-57A8H — SVC Function 36H Dispatch Entry Points
This block contains a series of entry points that load Register Pair BC with various SYS overlay callback addresses and all converge on 5782H, which loads SVC function code 36H into Register A and then jumps to the common dispatcher at 576CH. These entry points are reached from the jump table at 67BBH (copied to 4152H during initialization) and implement different BASIC disk statements (OPEN, CLOSE, field access, etc.) that use SVC function 36H.
577F
LD BC,534AH 01 4A 53
Load Register Pair BC with 534AH (SYS overlay area callback). This entry point dispatches a disk BASIC operation via SVC 36H with callback to 534AH.
5782
LD A,36H 3E 36
COMMON MERGE POINT for SVC 36H dispatch
Load Register A with 36H (SVC function code 36H).
5784
PUBLIC ENTRY — called by SYS17 at 5033H
JUMP back to 576CH, the common SVC dispatcher, to push BC, test A, and execute the SVC call.
5786
LD BC,53F2H 01 F2 53
Load Register Pair BC with 53F2H (SYS overlay area callback).
5789
JUMP back to 5782H to load SVC function code 36H and dispatch.
578B
LD BC,5462H 01 62 54
Load Register Pair BC with 5462H (SYS overlay area callback).
578E
JUMP back to 5782H to load SVC function code 36H and dispatch.
5790
LD BC,54C5H 01 C5 54
Load Register Pair BC with 54C5H (SYS overlay area callback).
5793
JUMP back to 5782H to load SVC function code 36H and dispatch.
5795
LD BC,5504H 01 04 55
Load Register Pair BC with 5504H (SYS overlay area callback).
5798
JUMP back to 5782H to load SVC function code 36H and dispatch.
579A
LD BC,55D4H 01 D4 55
Load Register Pair BC with 55D4H (SYS overlay area callback).
579D
JUMP back to 5782H to load SVC function code 36H and dispatch.
579F
LD BC,55E8H 01 E8 55
Load Register Pair BC with 55E8H (SYS overlay area callback).
57A2
JUMP back to 5782H to load SVC function code 36H and dispatch.
57A4
PUSH BC C5
Save Register Pair BC onto the stack. BC was set by the caller and holds a context value. This entry point is reached from 581CH when a filename does not end with ‘$’ (24H).
57A5
LD BC,5202H 01 02 52
Load Register Pair BC with 5202H (SYS overlay area callback, same as used at 574FH and 5767H).
57A8
JUMP back to 5782H to load SVC function code 36H and dispatch.
57AAH-57C2H — SVC Function 57H/37H Calls and Lowercase-to-Uppercase Converter
This section contains two small entry points that set Register B to a parameter value and then execute SVC function 57H via RST 28H, followed by the lowercase-to-uppercase ASCII converter routine at 57BAH. The converter is used throughout BASIC/CMD to normalize user input to uppercase before keyword matching and filename processing.
57AA
LD B,28H 06 28
Load Register B with 28H (decimal 40). This sets a parameter value (record length or field width of 40 bytes) before the SVC call.
57AC
JUMP forward to 57B0H to load SVC function code 57H and execute.
57AE
LD B,20H 06 20
Load Register B with 20H (decimal 32). This sets a different parameter value (record length or field width of 32 bytes) before the SVC call.
57B0
LD A,57H 3E 57
Load Register A with 57H (SVC function code 57H). This NEWDOS/80 supervisor call function is dispatched via the RST 28H instruction that follows.
57B2
RST 28H EF
Execute RST 28H (NEWDOS/80 Supervisor Call). The function code in Register A (57H) selects the operation; Register B holds the parameter value (28H or 20H). The SVC dispatcher transfers control to the appropriate SYS module handler.
57B3
LD A,37H 3E 37
Load Register A with 37H (SVC function code 37H). This entry point is reached from the CMD ‘O’ dispatcher at 57DDH and from the common SVC wrapper at 5776H. SVC 37H is a BASIC disk support function.
57B5
RST 28H EF
PUBLIC ENTRY — called by SYS17 at 5093H
Execute RST 28H (NEWDOS/80 Supervisor Call) with function code 37H in Register A. This is a public entry point called from 5776H and by SYS17 at 5093H. On return, the Z FLAG indicates success (Z) or failure (NZ).
DATA AREA
Bytes 57B6H-57B9H are four 00H bytes. 57B8H is a runtime variable written to by code at 5D86H and read by SYS19 at 5322H. The other bytes (57B6H, 57B7H, 57B9H) serve as padding or unused workspace.
57B6
DEFB 00H 00
Data byte (padding or workspace).
57B7
DEFB 00H 00
Data byte (padding or workspace).
57B8
DEFB 00H 00
SELF-MODIFYING CODE TARGET: 57B8H
Runtime variable. Written to by code at 5D86H; read by SYS19 at 5322H. Stores a state flag or intermediate result used during BASIC file LOAD/SAVE operations.
57B9
DEFB 00H 00
Data byte (padding or workspace).
SUBROUTINE: UPPERCASE CONVERTER
This small routine converts a lowercase ASCII letter (61H-7AH, ‘a’-‘z’) to its uppercase equivalent (41H-5AH, ‘A’-‘Z’) by subtracting 20H. If the character in Register A is not a lowercase letter, it is returned unchanged. Called from the filename copy loop at 5806H and other input processing routines.
57BA
CP 61H FE 61
Compare Register A against 61H (ASCII ‘a’). If A < 61H (not a lowercase letter and not a letter at all in the lowercase range), the CARRY FLAG is set.
57BC
RET C D8
If the CARRY FLAG is set (A < 61H, the character is not lowercase), RETurn immediately with A unchanged. The character is already uppercase, a digit, or a special character.
57BD
CP 7BH FE 7B
Compare Register A against 7BH (one past ASCII ‘z’). If A ≥ 7BH (character is above the lowercase range), the NO CARRY FLAG is set.
57BF
RET NC D0
If the NO CARRY FLAG is set (A ≥ 7BH, the character is above ‘z’), RETurn immediately with A unchanged. The character is not a lowercase letter.
57C0
SUB 20H D6 20
SUBtract 20H from Register A, converting the lowercase ASCII letter to its uppercase equivalent (e.g., 61H ‘a’ becomes 41H ‘A’).
57C2
RET C9
RETurn with the now-uppercase character in Register A.
57C3H-57E9H — CMD Statement Device Code Dispatcher
This routine is the main dispatcher for the BASIC CMD statement. It reads the first character of the CMD argument (a single-letter device/option code) from the BASIC text pointed to by HL, then dispatches to the appropriate handler based on the character. Supported CMD codes are: ‘S’ (53H) for SYSTEM command via SYS0, ‘F’ (46H) for file operations, ‘C’ (43H) for cassette operations, ‘J’ (4AH) for JKL operations, ‘O’ (4FH) for SVC 37H call, and ‘E’ (45H) for video enable. If the character matches none of these, control falls through to a JP to ROM at 1E4AH which generates an "Illegal Function Call" error.
57C3
LD A,(HL) 7E
Load Register A with the byte at (HL), the current character from the BASIC text. HL points to the CMD argument string. This character is the single-letter device code that determines which CMD sub-function to execute.
57C4
CP 53H FE 53
Compare Register A against 53H (ASCII ‘S’). If the CMD argument is ‘S’ (SYSTEM command), the Z FLAG is set.
57C6
POP HL E1
Restore Register Pair HL from the stack. This pops a return address that was pushed by the caller, setting up HL for use by the dispatched handler.
57C7
If the NZ FLAG is set (the character is NOT ‘S’), JUMP forward to 57CCH to test the next character option.
57C9
JUMP to 402DH in the SYS0 resident DOS module. This is the SYSTEM command entry point in the DOS. CMD“S” hands control directly to DOS to execute the SYSTEM command.
57CC
CP 46H FE 46
Compare Register A against 46H (ASCII ‘F’). If the CMD argument is ‘F’ (file operations), the Z FLAG is set.
57CE
If the Z FLAG is set (character is ‘F’), JUMP to 5736H, the CMD“F” file operations entry point, which loads BC with 559CH and dispatches SVC 35H.
57D1
CP 43H FE 43
Compare Register A against 43H (ASCII ‘C’). If the CMD argument is ‘C’ (cassette operations), the Z FLAG is set.
57D3
If the Z FLAG is set (character is ‘C’), JUMP to 5986H, the cassette operations handler.
57D6
CP 4AH FE 4A
Compare Register A against 4AH (ASCII ‘J’). If the CMD argument is ‘J’ (JKL system handler), the Z FLAG is set.
57D8
If the Z FLAG is set (character is ‘J’), JUMP to 5A76H, the JKL operations handler.
57DB
CP 4FH FE 4F
Compare Register A against 4FH (ASCII ‘O’). If the CMD argument is ‘O’ (execute SVC function 37H), the Z FLAG is set.
57DD
If the Z FLAG is set (character is ‘O’), JUMP to 57B3H, which loads Register A with SVC function code 37H and executes RST 28H.
57E0
CP 45H FE 45
Compare Register A against 45H (ASCII ‘E’). If the CMD argument is ‘E’ (video enable), the Z FLAG is set.
57E2
If the NZ FLAG is set (character is NOT ‘E’ and none of the above matched), JUMP forward to 57E9H which generates a syntax error via ROM.
57E4
LD A,C0H 3E C0
Load Register A with C0H. This is the CMD“E” handler: C0H is a control value for the video enable function.
57E6
JUMP to 4409H in SYS0 to execute the video enable operation with parameter C0H in Register A.
57E9
ERROR PATH
JUMP to ROM routine at 1E4AH. This is the Model III ROM "Illegal Function Call" handler. No valid CMD device code was found, so a syntax error is generated.
57ECH-5822H — Filename Extraction and Directory Lookup
This routine evaluates a string expression from the BASIC text to extract a filename, converts it to uppercase, copies it into the directory match buffer at 4225H, and then checks for a ‘$’ suffix indicating a special file type. If the filename length is exactly 1 character, it is treated as a single-letter CMD code and re-dispatched through 57C3H. The routine includes a character copy loop that converts lowercase to uppercase via the 57BAH subroutine, and a trailing-space stripping loop that replaces spaces with a 0DH (carriage return) terminator.
57EC
GOSUB to ROM routine at 2337H to evaluate a string expression from the BASIC text. On return, DE points to the string data and A holds the string length.
57EF
PUSH HL E5
Save Register Pair HL (the BASIC text pointer, now advanced past the string expression) onto the stack.
57F0
LD DE,(4121H) ED 5B 21 41
Load Register Pair DE with the 16-bit value stored at 4121H. This BASIC system variable holds the pointer to the current string data (the result of the string expression evaluation at 2337H).
57F4
GOSUB to 5CA4H to validate and process the filename string. This routine checks the string length and returns the length in Register A.
57F7
DEC A 3D
DECrement Register A by 1 (adjust the filename length for zero-based counting or to test for maximum length).
57F8
CP 4FH FE 4F
Compare Register A against 4FH (decimal 79). This checks if the filename length exceeds 80 characters (after the DEC, 4FH = original length of 80). If A ≥ 4FH, the filename is too long.
57FA
If the NO CARRY FLAG is set (A ≥ 4FH, the filename exceeds 79 characters after DEC), JUMP to 1E4AH (ROM "Illegal Function Call" error handler). The filename is too long.
57FD
INC A 3C
INCrement Register A by 1, restoring the original filename length after the comparison.
57FE
LD HL,4225H 21 25 42
Point Register Pair HL to 4225H, the directory filename match buffer in the DOS data area. The filename will be copied here for directory lookup operations.
5801
LD B,A 47
Load Register B with Register A (the filename length). B will serve as the loop counter for the character copy loop.
5802
LD C,A 4F
Load Register C with Register A (the filename length). C preserves the original length for later comparison at 5816H to detect single-character filenames.
5803
PUSH HL E5
Save Register Pair HL (pointer to 4225H, the directory buffer start) onto the stack for later retrieval after the copy loop.
LOOP START — Copy filename characters, converting to uppercase
This loop reads each character from the source string at (DE), converts it to uppercase via the 57BAH subroutine, stores it in the directory buffer at (HL), and repeats for B characters.
5804
LD A,(DE) 1A
Load Register A with the next character from the source string at (DE).
5805
INC DE 13
INCrement Register Pair DE by 1 to advance to the next source character.
5806
GOSUB to 57BAH, the lowercase-to-uppercase converter. If Register A holds a lowercase letter (61H-7AH), it is converted to uppercase (41H-5AH). Otherwise A is returned unchanged.
5809
LD (HL),A 77
Store the uppercase character (Register A) into the directory buffer at (HL).
580A
INC HL 23
INCrement Register Pair HL by 1 to advance to the next position in the directory buffer.
580B
LOOP END when B = 0
DECrement Register B (the remaining character count) and JUMP back to 5804H if B is not zero (more characters to copy).
TRAILING SPACE STRIP
After copying all characters, this code works backward from the end of the copied string, replacing trailing spaces (20H) with a 0DH carriage return terminator.
580D
LD (HL),0DH 36 0D
Store 0DH (carriage return, the string terminator) at the current position in the directory buffer. This marks the end of the filename.
580F
DEC HL 2B
DECrement Register Pair HL by 1 to move one position backward in the directory buffer.
5810
LD A,(HL) 7E
Load Register A with the character at (HL), the last non-terminator character in the buffer.
5811
CP 20H FE 20
Compare Register A against 20H (ASCII space). If the character is a trailing space, the Z FLAG is set.
5813
LOOP — strip trailing spaces
If the Z FLAG is set (character is a space), JUMP back to 580FH to overwrite this space with 0DH and check the next character backward.
5815
POP HL E1
Restore Register Pair HL from the stack. HL now points back to 4225H (the start of the directory buffer, saved at 5803H).
5816
DEC C 0D
DECrement Register C (the original filename length) by 1. If the original length was 1 (a single character), C becomes 0 and the Z FLAG is set.
5817
If the Z FLAG is set (the filename was exactly 1 character long), JUMP to 57C3H to re-dispatch through the CMD character handler. A single-character “filename” is treated as a CMD device code rather than an actual file name.
581A
CP 24H FE 24
Compare Register A (the last non-space character of the filename) against 24H (ASCII ‘$’). A ‘$’ suffix indicates a special file type (string variable file or system extension).
581C
If the NZ FLAG is set (the last character is NOT ‘$’), JUMP to 57A4H to dispatch as a normal filename through SVC 36H with callback 5202H.
581F
GOSUB to ROM routine at 2611H. This ROM routine handles the ‘$’ suffix processing, advancing the BASIC text pointer past the ‘$’ character.
5822
JUMP back to 57F4H to continue filename processing with the updated pointer after the ‘$’ suffix was consumed.
5824H-583EH — File Number Evaluation and Mode Setup
These routines evaluate a BASIC file number expression and set up the file mode byte at 40DCH. Entry at 5824H is a public entry point called by SYS20 and is used when a file number prefixed with ‘>’ (BEH token) needs the “output mode” flag (80H) set. Entry at 5831H is an alternate that uses a different ROM call. Both paths converge at 5839H which reads the file access mode byte from 40AFH and compares it against 03H.
5824
RST 10H D7
PUBLIC ENTRY — called by SYS20
Execute RST 10H (CHRGET): Get the next non-space character from the BASIC text, advancing the text pointer. The character is returned in Register A with flags set (Z if end-of-statement, C if numeric digit).
5825
LD A,80H 3E 80
Load Register A with 80H. This is the “output mode” flag bit that will be written to the file mode byte at 40DCH.
5827
LD (40DCH),A 32 DC 40
Store 80H (Register A) into the BASIC system variable at 40DCH. This variable holds the current file access mode flag: 80H indicates output mode.
582A
OR (HL) B6
OR the byte at (HL) (the current BASIC text character) with Register A (80H). This combines the file mode flag with the current text byte, setting the high bit.
582B
LD B,A 47
Load Register B with Register A (the combined mode/character byte). B is passed as a parameter to the ROM routine called next.
582C
GOSUB to ROM routine at 2612H. This ROM routine processes the file number expression with the mode byte in B.
582F
JUMP forward to 5839H to read the file mode result from 40AFH and compare against 03H.
5831
LD A,80H 3E 80
PUBLIC ENTRY — called by SYS20
Load Register A with 80H (output mode flag), same as 5825H.
5833
LD (40DCH),A 32 DC 40
Store 80H (Register A) into the file access mode variable at 40DCH.
5836
GOSUB to ROM routine at 260DH. This is an alternate file number evaluation entry point that processes the file number expression differently from 2612H (does not require the mode byte in B).
5839
LD A,(40AFH) 3A AF 40
Load Register A with the byte at 40AFH. This BASIC system variable holds the file access mode result after the file number evaluation (01H = input, 02H = output, 03H = random access).
583C
CP 03H FE 03
Compare Register A against 03H (random access mode). If A = 03H, the Z FLAG is set (file is open for random access); if A ≠ 03H, the NZ FLAG is set. The caller uses this flag to determine subsequent processing.
583E
RET C9
RETurn to the caller with the Z FLAG reflecting whether the file is in random access mode (Z = random access, NZ = sequential input or output).
583FH-586FH — PRINT# Position and DEF USR Address Handlers
This section handles two distinct BASIC features that share common infrastructure. The code at 583FH checks for the ‘>’ token (BEH, indicating PRINT# position/field output). The code at 585CH handles the token C1H. Both paths interact with file number evaluation (5824H/5870H), ROM expression evaluators, and the data area at 589DH.
583F
CP BEH FE BE
Compare Register A against BEH (the BASIC token for ‘>’, the “greater than” or print-position operator). If the current token is BEH, the Z FLAG is set.
5841
If the NZ FLAG is set (current token is NOT BEH), JUMP forward to 585CH to check for token C1H instead.
5843
GOSUB to 5824H, the file number evaluation and mode setup routine. This advances past the file number token, sets 40DCH to 80H (output mode), and evaluates the file number expression.
5846
GOSUB to ROM routine at 2828H. This ROM routine evaluates a numeric expression and returns the 16-bit result in Register Pair HL (the print position value).
5849
LD A,L 7D
Load Register A with Register L (the low byte of the evaluated expression result from 2828H). This is the print position value.
584A
LD (DE),A 12
Store Register A (low byte of position) into the memory location pointed to by DE. DE was set up by prior code to point to a field in the file control structure.
584B
INC DE 13
INCrement Register Pair DE by 1 to point to the next byte in the file control structure.
584C
LD A,H 7C
Load Register A with Register H (the high byte of the evaluated expression result).
584D
LD (DE),A 12
Store Register A (high byte of position) into (DE), completing the 16-bit position storage in the file control structure.
584E
LD A,28H 3E 28
Load Register A with 28H (ASCII ‘(’, the opening parenthesis token). This prepares to check that the expression was properly parenthesized.
5850
CP (HL) BE
Compare Register A (28H, ‘(’) against the byte at (HL) (the current BASIC text character). If the character is ‘(’, the Z FLAG is set.
5851
ERROR PATH
If the NZ FLAG is set (the expected ‘(’ was not found in the BASIC text), JUMP to ROM routine at 1F05H, which generates a syntax error.
5854
RST 10H D7
Execute RST 10H (CHRGET): Get the next non-space character from the BASIC text, advancing past the ‘(’.
5855
GOSUB to ROM routine at 260DH to evaluate the file number expression within the parentheses.
5858
LD A,2CH 3E 2C
Load Register A with 2CH (ASCII ‘,’, the comma separator). This prepares to check for a comma delimiter after the file number.
585A
JUMP back to 5850H to compare Register A (2CH, comma) against the current BASIC text character at (HL). If a comma is found, processing continues; if not, a syntax error is generated.
585C
CP C1H FE C1
Compare Register A against C1H (a BASIC token, possibly the DEF USR token). If the current token matches, the Z FLAG is set.
585E
FALL-THROUGH TO ROM
If the NZ FLAG is set (the token does NOT match C1H), JUMP to ROM routine at 1997H. This is the ROM’s default statement dispatcher for unrecognized tokens.
5861
GOSUB to 5870H, the numeric digit parser that reads a single digit (0-9) from the BASIC text and computes a table offset in DE from the base table at 589DH.
5864
PUSH DE D5
Save Register Pair DE (the computed table entry address from 5870H) onto the stack.
5865
RST 08H ⇒ D5HCF D5
Execute RST 08H (SYNCHR): Verify that the next character in the BASIC text matches the inline byte that follows this instruction. If the character does not match, a syntax error (FC error) is generated. D5H is the BASIC token that must appear at this point in the statement for correct syntax. RST 08H verifies this token is present and advances the text pointer past it.
5867
GOSUB to ROM routine at 2B02H to evaluate a numeric expression. The result is returned as a 16-bit value in Register Pair DE.
586A
EX (SP),HL E3
Exchange the top-of-stack value with Register Pair HL. HL had the BASIC text pointer; now HL holds the table entry address (pushed at 5864H), and the BASIC text pointer goes onto the stack.
586B
LD (HL),E 73
Store Register E (low byte of the evaluated expression result) into the table entry at (HL).
586C
INC HL 23
INCrement Register Pair HL by 1 to point to the high byte of the table entry.
586D
LD (HL),D 72
Store Register D (high byte of the evaluated expression result) into (HL), completing the 16-bit address write to the table.
586E
POP HL E1
Restore Register Pair HL (the BASIC text pointer) from the stack.
586F
RET C9
RETurn to the caller. The table entry has been updated with the address from the evaluated expression.
5870H-587EH — Single-Digit Numeric Parser with Table Offset
This small subroutine reads a single decimal digit (0-9) from the BASIC text and computes a table offset into the address table at 589DH. The digit is doubled (since each table entry is 2 bytes) and added to the base address in DE. On return, DE points to the corresponding 2-byte entry in the table.
5870
Point Register Pair DE to 589DH, the base of the address lookup table. Each table entry is 2 bytes (a 16-bit address).
5873
RST 10H D7
Execute RST 10H (CHRGET): Get the next non-space character from the BASIC text. Register A receives the character; CARRY FLAG is set if the character is a numeric digit (30H-39H).
5874
RET NC D0
If the NO CARRY FLAG is set (the character is NOT a numeric digit), RETurn immediately. DE still points to the base of the table (entry 0), which serves as the default.
5875
SUB 30H D6 30
SUBtract 30H from Register A, converting the ASCII digit character (‘0’-‘9’) to its binary value (0-9).
5877
ADD A,A 87
Double Register A (multiply by 2) because each table entry is 2 bytes. A now holds the byte offset into the table.
5878
ADD A,E 83
ADD Register A (the byte offset) to Register E (low byte of the table base address 589DH). This computes the low byte of the target entry address.
5879
LD E,A 5F
Load Register E with the computed low byte. DE now has the correct low byte for the table entry.
587A
If the NO CARRY FLAG is set (no overflow from the ADD A,E), JUMP forward to 587DH, skipping the high byte adjustment. The entry is within the same 256-byte page.
587C
INC D 14
INCrement Register D by 1 to account for the carry from the addition that crossed a page boundary.
587D
RST 10H D7
Execute RST 10H (CHRGET): Advance the BASIC text pointer past the digit character that was just consumed.
587E
RET C9
RETurn with DE pointing to the selected 2-byte entry in the table at 589DH.
587FH-589CH — File Number Setup with Random Access Check
This routine retrieves a file number parameter, evaluates the file access mode, and sets up a return path through 586EH. If the file is in random access mode (mode 03H), it calls ROM routine 29DAH to perform random access initialization. On return, DE holds the BASIC text pointer and HL points to the string descriptor area at 4121H.
587F
POP AF F1
Restore Register A and FLAGS from the stack. Register A holds a parameter value set by the caller before this routine was entered.
5880
GOSUB to 5870H, the single-digit parser. Reads a digit from the BASIC text and computes the table offset in DE from the base at 589DH.
5883
PUSH DE D5
Save Register Pair DE (the table entry address computed by 5870H) onto the stack.
5884
GOSUB to ROM routine at 252CH to evaluate a file number expression from the BASIC text.
5887
EX (SP),HL E3
Exchange the top-of-stack value with HL. HL now holds the table entry address (from 5883H), and the BASIC text pointer goes onto the stack.
5888
LD C,(HL) 4E
Load Register C with the low byte of the 2-byte address stored at the table entry (HL).
5889
INC HL 23
INCrement Register Pair HL by 1 to point to the high byte of the table entry.
588A
LD B,(HL) 46
Load Register B with the high byte of the table entry. BC now holds the 16-bit address read from the table.
588B
Point Register Pair HL to 586EH (the POP HL / RET sequence at the end of the PRINT# handler). This address is pushed as a return address so that when this routine’s RET executes, control passes through 586EH to clean up the stack.
588E
PUSH HL E5
Save 586EH (the cleanup return address) onto the stack.
588F
PUSH BC C5
Save Register Pair BC (the 16-bit address read from the table) onto the stack. This will serve as a return address for the RET at 589CH.
5890
GOSUB to 5839H to read the file access mode from 40AFH and compare against 03H (random access). Returns with Z FLAG set if random access mode.
5893
PUSH AF F5
Save Register A (the file access mode value) and FLAGS (Z if random access) onto the stack.
5894
If the Z FLAG is set (file is in random access mode, mode = 03H), GOSUB to ROM routine at 29DAH to perform random access record initialization.
5897
EX DE,HL EB
Exchange Register Pairs DE and HL. DE now holds the BASIC text pointer; HL is freed for the next load.
5898
LD HL,4121H 21 21 41
Point Register Pair HL to 4121H, the BASIC string descriptor pointer. This system variable holds the address of the most recently evaluated string’s data.
589B
POP AF F1
Restore Register A and FLAGS from the stack (the file access mode and Z/NZ flag saved at 5893H).
589C
RET C9
RETurn. The return address on the stack is the BC value pushed at 588FH (the table-derived address), so execution continues at that address. After that routine returns, the return address will be 586EH (pushed at 588EH), which performs the final POP HL / RET cleanup.
589DH-58B8H — DEF USR Address Table and OPEN/CLOSE Entry Points
This area contains two distinct data structures. The first part (589DH-58B1H) is a table of 10 two-byte address entries, each initialized to 1E4AH (the ROM "Illegal Function Call" handler), except the first entry at 589DH which is initialized to 4A1EH. These are the DEF USR address slots (USR0 through USR9). When the user executes DEF USR<n>=address, the code at 586BH-586DH writes the new address into the corresponding table entry. The second part (58B2H-58B8H) contains entry points for OPEN and CLOSE statement handlers.
[DATA TABLE: DEF USR Address Slots] 10 entries of 2 bytes each (20 bytes total). Default value 1E4AH = ROM "Illegal Function Call" handler, so calling an undefined USR function generates an "Illegal Function Call" error. The entries have initial bytes 4A 1E which is address 1E4AH in little-endian byte order.
589D
USR0 address slot. Default: 1E4AH (ROM "Illegal Function Call" error). Written to by code at 586BH-586DH when DEF USR0=nnnn is executed.
589F
USRUSR1 address slot. Default: 1E4AH.
58A1
USRUSR2 address slot. Default: 1E4AH.
58A3
USRUSR3 address slot. Default: 1E4AH.
58A5
USRUSR4 address slot. Default: 1E4AH.
58A7
USRUSR5 address slot. Default: 1E4AH.
58A9
USRUSR6 address slot. Default: 1E4AH.
58AB
USRUSR7 address slot. Default: 1E4AH.
58AD
USRUSR8 address slot. Default: 1E4AH.
58AF
USRUSR9 address slot. Default: 1E4AH.
[OPEN/CLOSE STATEMENT ENTRY POINTS] The following entries use the “LD BC eats next byte” pattern. Execution enters at the LD A,xxH instruction (offset +1); the LD BC opcode (01H) at the entry before it serves as a “skip” when falling through from the previous path. Register A receives a file access mode value.
58B0
DEFB 1EH,3EH 1E 3E
Bytes 1EH 3EH: The 1EH at 58B0H is the tail of the last USR address (part of 1E4AH in the USR9 entry). The 3EH at 58B1H is the “LD A,” opcode that, when jumped to at 58B1H, begins loading the OPEN mode byte. This overlaps the end of the USR table.
58B2
DEFB 08H 08
ENTRY POINT: OPEN for APPEND via JP to 58B1H
LD A,08H when entered at 58B1H (3E 08). 08H is the file mode for OPEN: mode 8 = append mode.
58B3
DEFB 01H,3EH,04H 01 3E 04
ENTRY POINT: OPEN for RANDOM via JP to 58B4H
LD BC,043EH when falling through (01H eats the next 2 bytes as a dummy LD BC). When entered at 58B4H, executes LD A,04H. 04H is the file mode for OPEN: mode 4 = random access.
58B6
DEFB 01H,3EH,02H 01 3E 02
ENTRY POINT: OPEN for OUTPUT via JP to 58B7H
LD BC,023EH when falling through (01H eats 2 bytes). When entered at 58B7H, executes LD A,02H. 02H is the file mode for OPEN: mode 2 = output.
58B9H-58C5H — OPEN Statement Handler
This is the OPEN statement execution entry point. Register A holds the file access mode value (02H for output, 04H for random, 08H for append) set by one of the “LD BC eats next byte” entry points at 58B2H-58B8H. The code evaluates the filename expression via ROM routines, converts the file number, and then jumps to ROM to complete the OPEN operation.
58B9
PUSH AF F5
Save Register A (the file access mode: 02H=output, 04H=random, 08H=append) and FLAGS onto the stack for later retrieval after the filename evaluation.
58BA
GOSUB to ROM routine at 2819H. This ROM routine evaluates the OPEN statement’s filename string expression and sets up internal parameters for the file open operation.
58BD
POP AF F1
Restore Register A (the file access mode value) and FLAGS from the stack.
58BE
GOSUB to ROM routine at 2857H. This ROM routine processes the file number, access mode, and record length parameters. Register A contains the mode value.
58C1
EX DE,HL EB
Exchange Register Pairs DE and HL. After the ROM call, DE held the filename pointer; it is now in HL. The BASIC text pointer moves to DE.
58C2
GOSUB to ROM routine at 09FFH. This ROM routine performs the actual file open operation, creating or finding the FCB entry and associating it with the specified file number.
58C5
JUMP to ROM routine at 2A2BH to finalize the OPEN operation and return to the BASIC interpreter loop.
58C8H-58DEH — CLOSE/FIELD Statement Handler
This section handles CLOSE and FIELD-related statement setup. It uses the same “LD BC eats next byte” pattern for mode selection and calls the file number validation routine at 5C99H. The file access mode is stored to 40AFH and validated against the current file state before jumping to the ROM handler.
58C8
LD A,08H 3E 08
ENTRY POINT via jump table
Load Register A with 08H (file mode for append/special). This is an entry point reached via the jump table.
58CA
DEFB 01H,3EH,04H 01 3E 04
ENTRY POINT: mode 04H via JP to 58CBH
LD BC,043EH when falling through (01H eats next 2 bytes). When entered at 58CBH, executes LD A,04H (random access mode).
58CD
DEFB 01H,3EH,02H 01 3E 02
ENTRY POINT: mode 02H via JP to 58CEH
LD BC,023EH when falling through. When entered at 58CEH, executes LD A,02H (output mode).
58D0
PUSH AF F5
Save Register A (the file access mode) and FLAGS onto the stack.
58D1
GOSUB to 5C99H, a file number validation routine that checks the file number from the BASIC text and returns with the file number in A and DE pointing to the FCB.
58D4
POP AF F1
Restore Register A (the file access mode) from the stack.
58D5
LD (40AFH),A 32 AF 40
Store Register A (the file access mode) into the BASIC system variable at 40AFH, which tracks the current file access mode.
58D8
DEC A 3D
DECrement Register A by 1. This adjusts the mode value for the comparison that follows (converting mode 1-based to 0-based).
58D9
CP (HL) BE
Compare Register A (decremented mode) against the byte at (HL). This validates the mode against the file’s current state.
58DA
ERROR PATH
If the NO CARRY FLAG is set (mode value is too large or mismatched), JUMP to 1E4AH (ROM "Illegal Function Call" error handler).
58DD
EX DE,HL EB
Exchange Register Pairs DE and HL, moving the BASIC text pointer to HL and the FCB pointer to DE.
58DE
JUMP to ROM routine at 09F7H to complete the CLOSE/FIELD operation with the FCB in DE and the validated mode.
58E1H-592AH — FIELD Definition and String Copy Handler
This routine handles FIELD statement definitions for random access files. It evaluates field variable expressions, checks memory boundaries against the BASIC string area and program limits, copies string data into field buffers, and manages the stack of field definitions. The routine makes extensive use of RST 08H (SYNCHR) for syntax verification and RST 18H (CPDEHL) for address comparisons.
58E1
OR AFH F6 AF
OR Register A with AFH (1010 1111). This turns on bits 7, 5, 3, 2, 1, and 0, producing a non-zero value of one of four possibilities: AFH, BFH, EFH, and FFH
58E3
PUSH AF F5
Save Register A (the field operation flag) and FLAGS onto the stack.
58E4
GOSUB to 5E7BH. This routine evaluates a string expression and returns with DE pointing to the string data and HL pointing to the string descriptor.
58E7
PUSH HL E5
Save Register Pair HL (the string descriptor pointer returned by 5E7BH) onto the stack.
58E8
PUSH DE D5
Save Register Pair DE (the string data pointer returned by 5E7BH) onto the stack.
58E9
EX DE,HL EB
Exchange DE and HL. HL now points to the string data; DE points to the string descriptor.
58EA
INC HL 23
INCrement HL by 1 to advance past the first byte of the string descriptor (the length byte), pointing to the string data address within the descriptor.
58EB
LD E,(HL) 5E
Load Register E with the low byte of the string data address from the descriptor.
58EC
INC HL 23
INCrement HL by 1 to point to the high byte of the string data address in the descriptor.
58ED
LD D,(HL) 56
Load Register D with the high byte of the string data address. DE now holds the address where the string data is stored in memory.
58EE
LD HL,(40F9H) 2A F9 40
Load Register Pair HL with the 16-bit value at 40F9H. This BASIC system variable holds the top of the string area (the highest address available for string storage).
58F1
RST 18H DF
Execute RST 18H (CPDEHL): Compare Register Pair DE (string data address) with Register Pair HL (top of string area at 40F9H). CARRY is set if DE < HL.
58F2
If the CARRY FLAG is set (string data address is below the string area top, meaning it is within the string area), JUMP forward to 58FDH to continue processing.
58F4
LD HL,(40A4H) 2A A4 40
Load Register Pair HL with the 16-bit value at 40A4H. This BASIC system variable holds the start of the BASIC program area (or the current BASIC text pointer limit).
58F7
RST 18H DF
Execute RST 18H (CPDEHL): Compare DE (string address) against HL (program area start). CARRY is set if DE < HL.
58F8
POP HL E1
Restore Register Pair HL from the stack (the string data pointer saved at 58E8H).
58F9
PUSH HL E5
Save HL back onto the stack (it was popped temporarily to access flags).
58FA
If the CARRY FLAG is set (string address is below the program area, meaning it needs to be relocated), GOSUB to 5CC4H to copy the string data to a safe location within the string area.
58FD
POP HL E1
Restore Register Pair HL from the stack (the string data pointer).
58FE
EX (SP),HL E3
Exchange the top-of-stack value with HL. HL now holds the string descriptor pointer (saved at 58E7H); the string data pointer goes back onto the stack.
58FF
RST 08H ⇒ D5H CF
Execute RST 08H (SYNCHR): Verify the next character in the BASIC text matches D5H (the BASIC token that must appear at this point for correct syntax, likely the ‘=’ token in a FIELD assignment).
5901
GOSUB to ROM routine at 2337H to evaluate a string expression (the right-hand side of the FIELD assignment).
5904
POP BC C1
Restore Register Pair BC from the stack (the string data pointer that was exchanged onto the stack at 58FEH).
5905
EX (SP),HL E3
Exchange top-of-stack with HL. HL now holds the previous context value; the BASIC text pointer goes onto the stack.
5906
PUSH HL E5
Save HL onto the stack.
5907
PUSH BC C5
Save BC (the string data pointer) onto the stack.
5908
GOSUB to 5C99H, the file number validation routine. Returns with A holding the file number and DE pointing to the appropriate FCB.
590B
LD C,A 4F
Load Register C with Register A (the validated file number from 5C99H).
590C
POP HL E1
Restore Register Pair HL from the stack (the string data pointer saved at 5907H).
590D
PUSH DE D5
Save Register Pair DE (the FCB pointer from 5C99H) onto the stack.
590E
LD B,(HL) 46
Load Register B with the byte at (HL), the string length from the string descriptor.
590F
INC HL 23
INCrement HL to point to the low byte of the string data address in the descriptor.
5910
LD E,(HL) 5E
Load Register E with the low byte of the string data address.
5911
INC HL 23
INCrement HL to point to the high byte of the string data address.
5912
LD D,(HL) 56
Load Register D with the high byte. DE now points to the source string data.
5913
EX DE,HL EB
Exchange DE and HL. HL now points to the source string data; DE is freed.
5914
POP DE D1
Restore Register Pair DE from the stack (the FCB pointer saved at 590DH).
5915
LD A,B 78
Load Register A with Register B (the source string length).
5916
SUB C 91
SUBtract Register C (the file number / field position offset) from Register A. This computes the difference between the source string length and the target field length.
5917
If the CARRY FLAG is set (source string is shorter than the field), JUMP to 591DH to handle the short-string case by padding.
5919
LD B,C 41
Load Register B with Register C (the field length). B will be the copy count: only copy as many bytes as the field can hold (truncate the source).
591A
LD C,A 4F
Load Register C with Register A (the excess bytes count: source length minus field length). C holds the number of bytes to skip or pad.
591B
JUMP forward to 591FH to continue with the copy operation.
591D
LD C,00H 0E 00
Load Register C with 00H. When the source string is shorter than the field, C = 00H means no padding bytes need to be skipped (the entire source is used and the remainder is space-padded).
591F
POP AF F1
Restore Register A and FLAGS from the stack (the field operation flag saved at 58E3H). The Z FLAG state determines whether this is an LSET (Z) or RSET (NZ) operation.
5920
If the Z FLAG is set (this is an LSET operation), GOSUB to 5CBCH. This routine copies B bytes from (HL) to (DE) for left-justified string assignment.
5923
GOSUB to 5CB6H. This routine pads or fills the remaining field space (C bytes of spaces) to complete the field assignment.
5926
GOSUB to 5CBCH. For RSET operations (where the Z FLAG was not set at 591FH and the first CALL was skipped), this copies the string data right-justified. For LSET, this is a no-op or finalizer.
5929
POP HL E1
Restore Register Pair HL (the BASIC text pointer) from the stack.
592A
RET C9
RETurn to the BASIC interpreter loop.
592BH-5962H — CMD“F=” Keyword Dispatch Table
This area is a keyword lookup table used by the CMD“F” file operations handler. The disassembler has misinterpreted these bytes as executable code, but they are DATA: a series of entries in the format [length-prefix] [keyword-ASCII-bytes] [dispatch-address-low] [dispatch-address-high]. Each entry encodes a CMD“F=keyword” command with its length, the ASCII keyword text, and the 16-bit address of the handler routine. Some dispatch addresses have high bits set in certain bytes, which serve as flags. The table is terminated by a 00H byte at 5962H.
[DATA TABLE: CMD"F=" Keywords] Each entry format is: 1 byte length, N bytes keyword, 2 bytes dispatch address. These implement the NEWDOS/80 extended CMD"F=" commands documented in the NEWDOS/80 manual: POPS, POPR, POPN (stack management), ERASE, KEEP (variable management), SASZ (string area sizing), SWAP (variable exchange), and SS (single-step debugging).
592B
DEFB 04H 04
Length prefix: 4 characters follow for keyword “POPS”.
592C
DEFM "POPS" 50 4F 50 53
Keyword text: “POPS” — CMD“F=POPS” purges all active GOSUB returns and FOR-NEXT controls from the BASIC control stack, resetting to the first (top) level.
5930
DEFW 5316H 16 53
Dispatch address: 5316H. The handler routine for CMD“F=POPS” is located at 5316H in the SYS overlay area.
5932
DEFB 04H 04
Length prefix: 4 characters follow for keyword “POPR”.
5933
DEFM "POPR" 50 4F 50 52
Keyword text: “POPR” — CMD“F=POPR” purges the current GOSUB level and any FOR-NEXT loops within it. Similar to RETURN but continues at the next statement instead of returning to the caller.
5937
DEFW 5324H 24 53
Dispatch address: 5324H. The handler routine for CMD“F=POPR”.
5939
DEFB 04H 04
Length prefix: 4 characters follow for keyword “POPN”.
593A
DEFM "POPN" 50 4F 50 4E
Keyword text: “POPN” — CMD“F=POPN” purges the most recently established FOR-NEXT loop. With an optional variable name parameter, purges the loop for that variable and any loops nested inside it.
593E
DEFW 5334H 34 53
Dispatch address: 5334H. The handler routine for CMD“F=POPN”.
5940
DEFB 05H 05
Length prefix: 5 characters follow for keyword “ERASE”.
5941
DEFM "ERASE" 45 52 41 53 45
Keyword text: “ERASE” — CMD“F=ERASE” deletes specific variables from BASIC’s variable table, freeing memory. If an array element is specified, the entire array is cleared.
5946
DEFW 57AAH AA 57
Dispatch address: 57AAH. The handler for CMD“F=ERASE” — this is the entry point at 57AAH which loads B=28H and calls SVC 57H.
5948
DEFB 04H 04
Length prefix: 4 characters follow for keyword “KEEP”.
5949
DEFM "KEEP" 4B 45 45 50
Keyword text: “KEEP” — CMD“F=KEEP” clears all variables EXCEPT those listed. DEFFN variables are always preserved. If no variables are listed, all standard variables are cleared.
594D
Dispatch address: 57AEH. The handler for CMD“F=KEEP” — entry point at 57AEH which loads B=20H and calls SVC 57H.
594F
DEFB 04H 04
Length prefix: 4 characters follow for keyword “SASZ”.
5950
DEFM "SASZ" 53 41 53 5A
Keyword text: “SASZ” — CMD“F=SASZ” dynamically changes the size of BASIC’s string storage area without clearing variables. The new size must accommodate existing strings.
5954
Dispatch address: 5C34H. The handler for CMD“F=SASZ”.
5956
DEFB 04H 04
Length prefix: 4 characters follow for keyword “SWAP”.
5957
DEFM "SWAP" 53 57 41 50
Keyword text: “SWAP” — CMD“F=SWAP” exchanges the values of two variables. Both variables must be the same type (both strings, both integers, etc.).
595B
Dispatch address: 5963H. The handler for CMD“F=SWAP”.
595D
DEFB 02H 02
Length prefix: 2 characters follow for keyword “SS”.
595E
DEFM "SS" 53 53
Keyword text: “SS” — CMD“F=SS” enables or disables single-step execution mode. CMD“F=SS” enables, CMD“F=SS”,N disables, and CMD“F=SS”,line starts stepping at the specified line.
5960
Dispatch address: 5B8FH. The handler for CMD“F=SS” (single-step mode).
5962
DEFB 00H 00
Table terminator. A length prefix of 00H signals the end of the keyword table. If the scanner reaches this byte without finding a match, the CMD“F=” command is not recognized.
5963H-5985H — CMD“F=SWAP” Handler (Variable Exchange)
This routine implements the CMD“F=SWAP” command, which exchanges the values of two BASIC variables. It first parses both variable references (separated by a comma), validates that they are the same type (string, integer, single-precision, or double-precision), and then performs a byte-by-byte swap of their internal representations. RST 08H with inline byte 2CH verifies the comma separator. The ROM routine at 260DH evaluates variable references and returns pointers to the variable storage in DE.
5963
RST 08H ⇒ 2CH CF 2C
Execute RST 08H (SYNCHR): Verify the next character in the BASIC text matches the inline byte that follows which is 2CH (ASCII comma). The SWAP command requires a comma before the first variable name: CMD“F=SWAP”,var1,var2.
5965
GOSUB to ROM routine at 260DH to evaluate the first variable reference from the BASIC text. On return, DE points to the variable’s storage location in memory, and 40AFH holds the variable type code.
5968
PUSH DE D5
Save Register Pair DE (pointer to the first variable’s storage) onto the stack.
5969
LD A,(40AFH) 3A AF 40
Load Register A with the byte at 40AFH, the BASIC system variable that holds the type code of the most recently evaluated variable (02H=integer, 03H=string, 04H=single-precision, 08H=double-precision).
596C
PUSH AF F5
Save Register A (the type code of the first variable) onto the stack for later comparison with the second variable’s type.
596D
RST 08H ⇒ 2CH CF 2C
Execute RST 08H (SYNCHR): Verify the next character matches a "," to continue honoring the forced syntax.
596F
GOSUB to ROM routine at 260DH to evaluate the second variable reference. On return, DE points to the second variable’s storage.
5972
POP BC C1
Restore Register Pair BC from the stack. B now holds the first variable’s type code (saved as A at 596CH, now in B because POP BC pops into B from the high byte of the AF pair pushed).
5973
LD A,(40AFH) 3A AF 40
Load Register A with the type code of the second variable from 40AFH.
5976
CP B B8
Compare Register A (second variable’s type) against Register B (first variable’s type). If both types match, the Z FLAG is set; if they differ, the NZ FLAG is set.
5977
If the NZ FLAG is set (the two variables are different types), JUMP to 1E4AH (ROM "Illegal Function Call" error handler). SWAP requires both variables to be the same type.
Swap Loop
At this point, both variables are confirmed to be the same type. Register A = B = the byte count for this variable type (the type code doubles as the storage size: 2 bytes for integer, 3 for string descriptor, 4 for single-precision, 8 for double-precision). The loop exchanges bytes one at a time between (HL) and (DE) using C as a temporary register.
597A
EX (SP),HL E3
Exchange the top-of-stack with HL. HL now holds the pointer to the first variable (saved at 5968H); the BASIC text pointer goes onto the stack.
597B
LD C,(HL) 4E
LOOP START
Load Register C with the byte at (HL) — save the current byte from the first variable into C as a temporary.
597C
LD A,(DE) 1A
Load Register A with the byte at (DE) — read the current byte from the second variable.
597D
LD (HL),A 77
Store Register A (byte from second variable) into (HL) (first variable’s location). The first variable now has the second’s byte value.
597E
LD A,C 79
Load Register A with Register C (the saved byte from the first variable).
597F
LD (DE),A 12
Store Register A (byte from first variable) into (DE) (second variable’s location). The second variable now has the first’s byte value. The swap of this byte position is complete.
5980
INC HL 23
INCrement HL by 1 to advance to the next byte of the first variable.
5981
INC DE 13
INCrement DE by 1 to advance to the next byte of the second variable.
5982
LOOP END when B = 0
DECrement Register B (the byte count) and JUMP back to 597BH if B is not zero (more bytes to swap).
5984
POP HL E1
Restore Register Pair HL (the BASIC text pointer) from the stack.
5985
RET C9
RETurn to the BASIC interpreter loop. Both variables have been fully swapped.
5986H - CMD"C" Cassette Operations Handler
This routine handles the CMD"C" cassette operations command. It first checks whether the cassette interface is available by reading the system variable at 40A2H (which holds FFFFH if no cassette is present). If no cassette, it falls through to ROM at 1997H. Otherwise, it parses the cassette command parameters: an optional baud rate value in B (default 28H = 2400 baud) and a mode flag in C (00H for read, other values for write). The parameters ‘R’ sets C=00H (read), ‘S’ with B=28H sets a different mode. After parsing, the routine stores B to 5A4BH and C to 5A6EH, sets bit 6 of the flag byte at 4289H, clears 4288H, and then enters the main cassette program load/save loop starting at 59C4H which processes BASIC program lines from/to cassette.
5986
LD DE,(40A2H) ED 5B A2 40
Load Register Pair DE with the 16-bit value stored at 40A2H. This BASIC system variable holds the cassette interface status word. A value of FFFFH indicates no cassette hardware is available.
598A
LD A,D 7A
Load Register A with Register D (the high byte of the cassette status word from 40A2H).
598B
AND E A3
AND Register A with Register E (the low byte). If both bytes are FFH (no cassette), the result is FFH. If either byte is not FFH, the result will have some zero bits.
598C
INC A 3C
INCrement Register A by 1. If A was FFH (both bytes were FFH, no cassette), it wraps to 00H and the Z FLAG is set. If A was anything else, the result is non-zero and NZ is set.
598D
NOTE: This logic appears inverted — NZ means cassette IS present, so this may be a pass-through to ROM’s own cassette handler
If the NZ FLAG is set (cassette hardware IS available, meaning 40A2H did NOT contain FFFFH), JUMP to ROM routine at 1997H, the default statement dispatcher. This handles the case where the cassette interface exists but the CMD“C” command should be processed by ROM instead.
5990
LD BC,2800H 01 00 28
Load Register Pair BC with 2800H. B = 28H (decimal 40, the default baud rate parameter representing 2400 baud); C = 00H (default cassette mode = read).
5993
DEC HL 2B
DECrement Register Pair HL by 1 to back up the BASIC text pointer one position, preparing for the CHRGET at the next instruction to re-read the current character.
5994
RST 10H D7
Execute RST 10H (CHRGET): Get the next non-space character from the BASIC text. Returns character in A with Z FLAG set if end-of-statement.
5995
If the Z FLAG is set (end of statement reached, no parameters specified), JUMP forward to 59ACH to use the default values in BC (B=28H, C=00H) and proceed with the cassette operation.
Parameter Parsing Loop
The code now parses comma-separated cassette parameters. Each parameter is either ‘R’ (52H, read mode), ‘S’ (53H, with B=28H), or a numeric baud rate value. RST 08H with inline byte 2CH enforces comma separators between parameters.
5997
LD BC,FE13H 01 13 FE
Load Register Pair BC with FE13H. B = 13H (decimal 19); C = FEH. These are alternate cassette operation parameters — B sets a different timing constant and C sets a mode flag for the cassette read/write routines.
599A
RST 08H ⇒ 2CH CF 2C
LOOP START — parse next parameter
Execute RST 08H (SYNCHR): Verify the next BASIC text character matches a ",".
599C
CP 52H FE 52
Compare Register A (the current BASIC text character after the comma) against 52H (ASCII ‘R’). If the parameter is ‘R’ (cassette Read mode), the Z FLAG is set.
599E
If the NZ FLAG is set (character is NOT ‘R’), JUMP forward to 59A4H to check for the ‘S’ parameter instead.
59A0
LD C,00H 0E 00
Load Register C with 00H. This sets the cassette mode to “read” (C = 00H indicates read mode for the cassette transfer routines).
59A2
JUMP forward to 59A9H to advance the text pointer past this parameter and check for more parameters.
59A4
LD B,28H 06 28
Load Register B with 28H (decimal 40, the 2400 baud timing constant). This is the ‘S’ parameter handler — it sets the baud rate for cassette save operations.
59A6
RST 08H ⇒ 53H CF 53
Execute RST 08H (SYNCHR): Verify the next character matches 53H (ASCII ‘S’). If the character is not ‘S’, RST 08H generates a syntax error.
59A8
DEC HL 2B
DECrement Register Pair HL by 1 to back up the text pointer, so the following CHRGET will re-read the character after ‘S’.
59A9
RST 10H D7
Execute RST 10H (CHRGET): Get the next non-space character from the BASIC text, advancing past the parameter just processed.
59AA
LOOP END when Z FLAG is set (end of statement)
If the NZ FLAG is set (not end of statement, more parameters follow), JUMP back to 599AH to parse the next comma-separated parameter.
Parameter Storage
All parameters have been parsed. B holds the baud rate constant and C holds the read/write mode flag. These are stored to self-modifying code locations for use by the cassette transfer routines that follow.
59AC
LD A,B 78
Load Register A with Register B (the baud rate constant, default 28H or modified by parameter parsing).
59AD
LD (5A4BH),A 32 4B 5A
SELF-MODIFYING CODE — writes to 5A4BH
Store Register A (the baud rate constant) into the self-modifying code location at 5A4BH. This value is read later during cassette I/O to configure the transfer timing.
59B0
LD A,C 79
Load Register A with Register C (the cassette mode flag: 00H = read, FEH = write).
59B1
LD (5A6EH),A 32 6E 5A
SELF-MODIFYING CODE — writes to 5A6EH
Store Register A (the cassette mode flag) into the self-modifying code location at 5A6EH. This value is tested later to determine whether to read from or write to cassette.
59B4
LD HL,4289H 21 89 42
Point Register Pair HL to 4289H, a BASIC system flag byte.
59B7
SET 6,(HL) CB F6
SET bit 6 of the byte at (HL) = 4289H. This flag bit signals to the BASIC interpreter that a cassette operation is in progress.
59B9
XOR A AF
Set Register A to 00H and clear all arithmetic flags.
59BA
LD (4288H),A 32 88 42
Store 00H (Register A) into the BASIC system flag byte at 4288H, clearing it in preparation for the cassette operation.
59BD
LD HL,(40A4H) 2A A4 40
Load Register Pair HL with the 16-bit value at 40A4H, the start address of the BASIC program area. HL now points to the beginning of the BASIC program in memory.
59C0
LD D,H 54
Load Register D with Register H (high byte of the BASIC program start address).
59C1
LD E,L 5D
Load Register E with Register L (low byte). DE now equals HL, both pointing to the BASIC program start. DE will serve as the destination pointer for building the cassette image.
59C2
JUMP forward to 5A0AH to enter the main BASIC program line processing loop. This is the first entry into the loop, starting at the beginning of the program.
59C4H - Cassette Program Line Copy and Token Expansion Loop
This is the main processing loop for the CMD“C” cassette operation. It walks through the BASIC program line by line, comparing the link pointer against BC, expanding tokenized keywords by copying from the token expansion area at 4D00H, and building a cassette-ready image of the program. The loop processes each line’s link pointer, line number, and tokenized body, calling subroutines at 5A48H and 5A4DH to copy characters with special handling for quoted strings, colons, and the REM token (93H).
59C4
EX DE,HL EB
LOOP START — process next BASIC program line
Exchange Register Pairs DE and HL. DE had the destination pointer; HL had the source pointer. Now HL = destination, DE = source.
59C5
OR A B7
Clear the CARRY FLAG by ORing A with itself (flags are set based on A, but CARRY is always cleared).
59C6
SBC HL,BC ED 42
SUBtract Register Pair BC (with borrow) from HL. This compares the current destination pointer (HL) against BC (a limit or reference address). If HL < BC, CARRY is set.
59C8
ADD HL,BC 09
ADD BC back to HL, restoring HL to its original value. The SBC/ADD pair was used solely to set the flags for the comparison without changing HL.
59C9
EX DE,HL EB
Exchange DE and HL back to their original roles: HL = source pointer, DE = destination pointer.
59CA
INC DE 13
INCrement Register Pair DE by 1, advancing the destination pointer past the current position.
59CB
INC HL 23
INCrement Register Pair HL by 1, advancing the source pointer past the current position.
59CC
If the NZ FLAG is set (HL did NOT equal BC in the comparison at 59C6H, meaning the destination has not reached the limit), JUMP forward to 59D5H to continue processing this line.
Destination Reached Limit
The destination pointer has reached the reference address in BC. Back up DE by 5 positions to overwrite the last incomplete entry, then jump to 5A0AH to advance to the next program line.
59CE
DEC DE 1B
DECrement DE by 1 (back up destination pointer, step 1 of 5).
59CF
DEC DE 1B
DECrement DE by 1 (step 2 of 5).
59D0
DEC DE 1B
DECrement DE by 1 (step 3 of 5).
59D1
DEC DE 1B
DECrement DE by 1 (step 4 of 5).
59D2
DEC DE 1B
DECrement DE by 1 (step 5 of 5). DE has been backed up by 5 bytes to discard the partially-written line entry.
59D3
JUMP forward to 5A0AH to process the next source line (or end the loop if the source is exhausted).
Continue Line Processing
The destination has not reached the limit. Save the current source position on the stack and call ROM routines to process the tokenized BASIC line, expanding keywords and copying data.
59D5
PUSH HL E5
Save Register Pair HL (the current source pointer within the BASIC program) onto the stack.
59D6
LD H,B 60
Load Register H with Register B (high byte of BC). HL is being set to BC, the limit/reference address.
59D7
LD L,C 69
Load Register L with Register C (low byte). HL now equals BC.
59D8
PUSH HL E5
Save Register Pair HL (which now holds BC, the limit address) onto the stack.
59D9
GOSUB to ROM routine at 2B7EH. This ROM routine performs token expansion or string processing for BASIC program listing operations.
59DC
XOR A AF
Set Register A to 00H and clear all flags. This prepares a null terminator byte.
59DD
LD (BC),A 02
Store 00H (Register A) at the address pointed to by BC, writing a null terminator at the end of the expanded token text.
59DE
LD HL,(40A7H) 2A A7 40
Load Register Pair HL with the 16-bit value at 40A7H. This BASIC system variable holds a pointer related to the token expansion buffer or the current output position.
59E1
GOSUB to ROM routine at 1BC0H. This routine performs further processing of the expanded BASIC line, setting up the output for cassette writing.
59E4
POP BC C1
Restore Register Pair BC from the stack (the limit address saved at 59D8H).
59E5
LD D,B 50
Load Register D with Register B. DE is being set to BC (the limit address).
59E6
LD E,C 59
Load Register E with Register C. DE now equals BC, pointing to the limit address which serves as the destination for the expanded text comparison.
Compare Expanded Line with Original
The loop at 59E7H compares the expanded (detokenized) line against the original source, byte by byte. If a mismatch is found, the token table at 4D00H is searched for the keyword.
59E7
INC HL 23
LOOP START — compare bytes
INCrement HL by 1, advancing the expanded text pointer.
59E8
LD A,(DE) 1A
Load Register A with the byte at (DE), the current byte from the original source.
59E9
CP (HL) BE
Compare Register A (original byte) against the byte at (HL) (expanded byte). If they match, the Z FLAG is set.
59EA
INC DE 13
INCrement DE by 1, advancing the original source pointer.
59EB
MATCH — continue comparison
If the Z FLAG is set (bytes match), JUMP forward to 5A06H to continue checking or finish this line.
Mismatch — Token Expansion
The bytes do not match, indicating a tokenized keyword in the original that was expanded. Copy from the token table at 4D00H to the output.
59ED
LD HL,4D00H 21 00 4D
Point Register Pair HL to 4D00H, the start of the DOS overlay area which contains the BASIC keyword token table during this operation.
59F0
LD A,(HL) 7E
LOOP START — copy token text
Load Register A with the byte at (HL), the current byte from the token table.
59F1
OR A B7
Set flags based on Register A. If A = 00H (null terminator, end of token text), the Z FLAG is set.
59F2
LD (BC),A 02
Store Register A (the token text byte) at the address pointed to by BC (the output buffer).
59F3
INC HL 23
INCrement HL by 1, advancing the token table pointer.
59F4
INC BC 03
INCrement BC by 1, advancing the output buffer pointer.
59F5
LOOP END when null terminator found
If the NZ FLAG is set (A was not the null terminator, more token text bytes remain), JUMP back to 59F0H to copy the next byte.
59F7
PUSH BC C5
Save Register Pair BC (the current output buffer position after the token text) onto the stack.
59F8
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H. DE = 0 is passed as a parameter to the routine at 5D67H.
59FB
GOSUB to 5D67H, a REF data processor utility (public entry, called by SYS12). This routine processes data related to the token expansion and returns a value in Register E.
59FE
LD A,08H 3E 08
Load Register A with 08H (decimal 8).
5A00
SUB E 93
SUBtract Register E (the value returned by 5D67H) from Register A. A = 08H − E, computing a spacing or padding count.
5A01
GOSUB to 5D30H, a RENUM/REF utility routine (public entry, called by SYS12). This routine uses the computed value in A for formatting or padding the output.
5A04
XOR A AF
Set Register A to 00H and clear all flags.
5A05
POP DE D1
Restore Register Pair DE from the stack (the output buffer position saved at 59F7H).
5A06
OR A B7
Set flags based on Register A. If A = 00H (the comparison byte was null or the XOR A cleared it), the Z FLAG is set.
5A07
LOOP END when A = 00H
If the NZ FLAG is set (the byte was not null, more bytes to compare in this line), JUMP back to 59E7H to continue the byte-by-byte comparison.
5A09
POP HL E1
Restore Register Pair HL from the stack (the source pointer saved at 59D5H).
5A0AH - BASIC Program Line Link Pointer Processor
This section reads the 2-byte link pointer from the current BASIC program line, copies it to the destination buffer, then checks if the link is 0000H (end of program). If not end-of-program, it reads the 2-byte line number, stores it, saves the value at 59F9H, and then enters the character copy loops at 5A39H/5A40H to process the tokenized line body. If the link is 0000H, it calls ROM error routines and the RENUM support routine at 5D52H before jumping to ROM at 1A19H for re-entry.
5A0A
LD C,(HL) 4E
Load Register C with the byte at (HL), the low byte of the BASIC program line’s link pointer (the address of the next line).
5A0B
INC HL 23
INCrement HL by 1 to point to the high byte of the link pointer.
5A0C
LD B,(HL) 46
Load Register B with the high byte of the link pointer. BC now holds the full 16-bit link address to the next BASIC program line.
5A0D
LD A,C 79
Load Register A with Register C (low byte of the link pointer).
5A0E
LD (DE),A 12
Store Register A (low byte of link) into the destination buffer at (DE).
5A0F
INC DE 13
INCrement DE by 1, advancing the destination pointer.
5A10
LD A,B 78
Load Register A with Register B (high byte of the link pointer).
5A11
LD (DE),A 12
Store Register A (high byte of link) into the destination buffer at (DE).
5A12
INC DE 13
INCrement DE by 1, advancing the destination pointer.
5A13
INC HL 23
INCrement HL by 1, advancing the source pointer past the link pointer to the line number field.
5A14
LD A,B 78
Load Register A with Register B (high byte of link).
5A15
OR C B1
OR Register A with Register C (low byte of link). If BC = 0000H (end of BASIC program), the Z FLAG is set; otherwise NZ is set.
5A16
If the NZ FLAG is set (link pointer is NOT 0000H, more program lines follow), JUMP forward to 5A24H to process the line number and line body.
End of Program
The link pointer is 0000H, indicating the end of the BASIC program. Call ROM error processing routines and the RENUM support utility, then return to the BASIC interpreter via ROM at 1A19H.
5A18
GOSUB to ROM routine at 1AF8H, an error processing or cleanup routine.
5A1B
GOSUB to ROM routine at 1B59H, another error processing or cleanup routine.
5A1E
GOSUB to 5D52H, a RENUM support utility (public entry, called by SYS11 and SYS12). This routine performs final cleanup or variable adjustment after the cassette operation completes.
5A21
JUMP to ROM routine at 1A19H, the BASIC interpreter re-entry point. Control returns to BASIC after the cassette operation is complete.
Process Line Number and Body
The link pointer is non-zero, so this is a valid BASIC program line. Read the 2-byte line number, copy it to the destination, save BC at 59F9H, then enter the character copy loops.
5A24
LD C,(HL) 4E
Load Register C with the byte at (HL), the low byte of the BASIC line number.
5A25
INC HL 23
INCrement HL by 1 to point to the high byte of the line number.
5A26
LD B,(HL) 46
Load Register B with the high byte of the line number. BC now holds the 16-bit BASIC line number.
5A27
LD A,C 79
Load Register A with Register C (low byte of line number).
5A28
LD (DE),A 12
Store the low byte of the line number into the destination buffer at (DE).
5A29
INC DE 13
INCrement DE by 1.
5A2A
LD A,B 78
Load Register A with Register B (high byte of line number).
5A2B
LD (DE),A 12
Store the high byte of the line number into the destination buffer at (DE).
5A2C
LD (59F9H),BC ED 43 F9 59
SELF-MODIFYING CODE — writes to 59F9H
Store Register Pair BC (the BASIC line number) into the self-modifying code location at 59F9H. This saves the current line number for use during token expansion processing.
5A30
INC DE 13
INCrement DE by 1, advancing the destination pointer past the line number.
5A31
INC HL 23
INCrement HL by 1, advancing the source pointer past the line number to the start of the tokenized line body.
5A32
PUSH HL E5
Save Register Pair HL (the source pointer to the tokenized line body) onto the stack.
5A33
LD B,D 42
Load Register B with Register D (high byte of DE). BC is being set to DE (the destination pointer).
5A34
LD C,E 4B
Load Register C with Register E. BC now equals DE, pointing to the destination buffer position.
5A35
PUSH DE D5
Save Register Pair DE (the destination pointer) onto the stack.
5A36
LD DE,4D00H 11 00 4D
Point Register Pair DE to 4D00H, the DOS overlay area. During this operation, 4D00H is used as a temporary buffer for token expansion output.
5A39
LOOP START — copy from source to token buffer
GOSUB to 5A4DH, the character copy routine that processes the tokenized line body. It copies characters from (HL) to (DE) with special handling for quoted strings (22H), colons (3AH), and the REM token (93H). Returns NZ if more data remains.
5A3C
LOOP END when Z (null terminator reached)
If the NZ FLAG is set (more characters remain in the tokenized line), JUMP back to 5A39H to process the next character.
5A3E
POP DE D1
Restore Register Pair DE from the stack (the destination buffer position saved at 5A35H).
5A3F
POP HL E1
Restore Register Pair HL from the stack (the source pointer saved at 5A32H).
5A40
LOOP START — copy from source to destination
GOSUB to 5A48H, a character copy routine that copies characters from (HL) to (DE) with space-handling. Returns NZ if more characters remain.
5A43
LOOP END when Z (null terminator reached)
If the NZ FLAG is set (more characters remain), JUMP back to 5A40H to copy the next character.
5A45
OUTER LOOP — next line
JUMP back to 59C4H to process the next BASIC program line.
5A48H - Character Copy with Space Handling
This small subroutine copies a single character from (HL) to (DE), with special handling: if the character is a space (20H), it jumps to 5A6BH (which advances pointers without copying). Returns Z if the character was a null terminator (00H), NZ otherwise.
5A48
LD A,(HL) 7E
Load Register A with the byte at (HL), the current source character.
5A49
CP 20H FE 20
Compare Register A against 20H (ASCII space). If the character is a space, the Z FLAG is set.
5A4B
NOTE: 5A4BH is also a self-modifying code target (written at 59ADH with the baud rate constant)
If the Z FLAG is set (character is a space), JUMP to 5A6BH which advances HL and DE without storing the space, effectively skipping spaces in the output.
5A4DH - Character Copy with Token and String Handling
This subroutine copies a single byte from (HL) to (DE) with special handling for several character types. It recognizes null terminators (00H, returns Z), quoted strings (22H, copies all characters within quotes), colons (3AH, advances BASIC text pointer via CHRGET), and the REM token (93H, copies remaining bytes verbatim until null). Returns Z if the null terminator was reached, NZ if more data remains.
5A4D
LD A,(HL) 7E
Load Register A with the byte at (HL), the current source byte from the tokenized BASIC line.
5A4E
OR A B7
Set flags based on Register A. If A = 00H (null terminator marking the end of the tokenized line), the Z FLAG is set.
5A4F
LD (DE),A 12
Store Register A into the destination at (DE), copying the byte regardless of whether it is a terminator (the caller checks the Z FLAG after return).
5A50
RET Z C8
If the Z FLAG is set (A = 00H, null terminator), RETurn to the caller with Z FLAG set indicating end of the tokenized line.
5A51
CP 22H FE 22
Compare Register A against 22H (ASCII double-quote). If the character is a quote, the Z FLAG is set, indicating the start of a quoted string literal.
5A53
If the NZ FLAG is set (character is NOT a quote), JUMP forward to 5A5FH to check for colon and REM token.
Quoted String Copy Loop
A double-quote was found. Copy all characters within the quoted string until the closing quote or null terminator is reached.
5A55
INC HL 23
LOOP START
INCrement HL by 1 to advance to the next source character within the quoted string.
5A56
INC DE 13
INCrement DE by 1 to advance the destination pointer.
5A57
LD A,(HL) 7E
Load Register A with the next source character.
5A58
OR A B7
Set flags based on A. Z FLAG set if null terminator.
5A59
LD (DE),A 12
Store the character into the destination at (DE).
5A5A
RET Z C8
If the Z FLAG is set (null terminator within the quoted string — unterminated string), RETurn with Z set.
5A5B
CP 22H FE 22
Compare Register A against 22H (closing double-quote). Z FLAG set if the closing quote is found.
5A5D
LOOP END when closing quote found
If the NZ FLAG is set (not the closing quote, still inside the string), JUMP back to 5A55H to copy the next character.
5A5F
CP 3AH FE 3A
Compare Register A against 3AH (ASCII colon, the BASIC statement separator). Z FLAG set if colon.
5A61
If the NZ FLAG is set (character is NOT a colon), JUMP forward to 5A66H to check for the REM token.
5A63
PUSH HL E5
Save Register Pair HL (the source pointer) onto the stack before calling CHRGET.
5A64
RST 10H D7
Execute RST 10H (CHRGET): Advance the BASIC text pointer past the colon to peek at the next statement. This is done to detect if the next statement after the colon is significant for the cassette operation.
5A65
POP HL E1
Restore Register Pair HL (the source pointer) from the stack.
5A66
CP 93H FE 93
Compare Register A against 93H (the BASIC token for the REM statement). Z FLAG set if this is a REM token.
5A68
If the Z FLAG is set (REM token found), JUMP to 5A6EH to enter the verbatim copy mode, which copies all remaining bytes in the line without further token processing.
5A6A
INC DE 13
INCrement DE by 1, advancing the destination pointer.
5A6B
INC HL 23
INCrement HL by 1, advancing the source pointer to the next byte.
5A6C
OR D B2
OR Register A with Register D. Since D is a non-zero high byte of an address in the 5xxxH-6xxxH range, this always produces a non-zero result, setting the NZ FLAG. This is a trick to force NZ return (indicating “more data”) without an additional comparison instruction.
5A6D
RET C9
RETurn with NZ FLAG set (more data to process in this line).
5A6EH - REM Statement Verbatim Copy
When a REM token (93H) is encountered in the tokenized BASIC line, this routine copies all remaining bytes in the line verbatim (without token processing) until the null terminator (00H) is found. The byte at 5A6EH is also a self-modifying code target (written at 59B1H with the cassette mode flag), so its initial value (00H in the /CMD image) is overwritten at runtime before this code executes.
5A6E
DEFB 00H 00
SELF-MODIFYING CODE TARGET: 5A6EH
Runtime variable / NOP. This byte is the self-modifying code target written at 59B1H with the cassette mode flag. When executed as code, 00H is a NOP.
5A6F
INC HL 23
LOOP START — verbatim copy
INCrement HL by 1, advancing the source pointer to the next byte in the REM text.
5A70
LD A,(HL) 7E
Load Register A with the next byte from the source (the REM comment text).
5A71
OR A B7
Set flags based on A. Z FLAG set if null terminator (00H, end of the line).
5A72
LD (DE),A 12
Store Register A into the destination at (DE), copying the byte unconditionally.
5A73
LOOP END when null terminator found
If the NZ FLAG is set (not null terminator, more REM text remains), JUMP back to 5A6EH to copy the next byte.
5A75
RET C9
RETurn with Z FLAG set (null terminator reached, end of the REM line). The caller will proceed to the next BASIC program line.
5A76H - CMD"J" JKL Statement Handler
This routine handles the CMD“J” statement, which provides the JKL (Jump/Key/Line) system for NEWDOS/80 BASIC. JKL allows BASIC programs to define computed branches based on variable values and day-of-month tables. The routine first verifies the comma separator, calls the file positioning routine at 6190H, checks for a ‘-’ (2DH) separator, validates parameters against ranges, and then builds or looks up entries in the JKL tables stored in the data area at 5B7AH-5B8EH. The handler calls several utility subroutines at 5B3FH, 5B47H, 5B59H, and 5B6EH for parameter validation, day-count computation, and numeric parsing.
5A76
RST 08H ⇒ 2CH CF 2C
Execute RST 08H (SYNCHR): Verify the next BASIC text character matches a ",". The CMD“J” command requires a comma after the “J”.
5A78
PUBLIC ENTRY POINT
GOSUB to 6190H, a file position routine (public entry, called by SYS10 and SYS20). This routine evaluates a date or position parameter from the BASIC text and returns a value in Register B with the Z FLAG indicating validity.
5A7B
ERROR PATH
If the NZ FLAG is set (the parameter is invalid), JUMP to 5AE7H which jumps to 5B44H ("Illegal Function Call" error via 1E4AH).
5A7D
LD A,(HL) 7E
Load Register A with the byte at (HL), the current BASIC text character after the date parameter.
5A7E
CP 2DH FE 2D
Compare Register A against 2DH (ASCII ‘-’, the hyphen/minus separator). If a hyphen is present, the Z FLAG is set, indicating a date range (e.g., J,1-15 for days 1 through 15).
5A80
LD A,B 78
Load Register A with Register B (the first date/parameter value returned by 6190H).
5A81
If the Z FLAG is set (hyphen found, this is a date range specification), JUMP to 5AE9H to handle the range with start value in A.
5A83
CP 08H FE 08
Compare Register A against 08H (decimal 8). If A < 08H, the CARRY FLAG is set, indicating the parameter is below the minimum valid value.
5A85
ERROR PATH
If the CARRY FLAG is set (parameter < 8), JUMP to 5AE7H for syntax error. The JKL system requires a minimum parameter value of 8.
Main JKL Table Build
The parameter is valid (≥ 8) and is not a range. Set up table building with BC=010CH (B=01H entry count, C=0CH offset), validate month and day values, compute the day-of-year index, and build the JKL entry.
5A87
LD BC,010CH 01 0C 01
Load Register Pair BC with 010CH. B = 01H (minimum value for the month range check); C = 0CH (12 decimal, maximum month value).
5A8A
GOSUB to 5B47H, the range-validated numeric parser. This routine reads a 2-digit numeric value from the BASIC text, validates it is within the range B-C (1-12 for months), and returns the value in Register A. If out of range, it jumps to 5B44H (syntax error).
5A8D
PUSH AF F5
Save Register A (the validated month value, 1-12) onto the stack.
5A8E
GOSUB to 5B3FH, the ‘/’ separator checker. This routine reads the next character from (HL), verifies it is 2FH (ASCII ‘/’), and advances HL past it. If not ‘/’, it jumps to 5B44H (syntax error).
5A91
LD BC,011FH 01 1F 01
Load Register Pair BC with 011FH. B = 01H (minimum day value); C = 1FH (31 decimal, maximum day value).
5A94
GOSUB to 5B47H to read and validate the day value (1-31). Returns day in Register A.
5A97
POP BC C1
Restore Register Pair BC from the stack. B now holds the month value (saved at 5A8DH as the A byte of the AF pair).
5A98
DEC A 3D
DECrement Register A by 1, converting the day from 1-based (1-31) to 0-based (0-30) for table indexing.
5A99
LD C,A 4F
Load Register C with Register A (the 0-based day value). B = month, C = 0-based day.
5A9A
PUSH BC C5
Save Register Pair BC (B = month, C = 0-based day) onto the stack for later use.
5A9B
GOSUB to 5B3FH to verify the next ‘/’ separator.
5A9E
GOSUB to 5B59H, a year/leap-year calculator. This routine reads the year value from the BASIC text, determines the days-per-month value based on whether it is a leap year, and stores the result at 5B7CH.
Compute Day-of-Year Index
Walk through the month-length table at 5B7AH, accumulating day counts for each complete month before the target month. The result in DE is the day-of-year offset for the start of the target month, plus the day within the month (in C).
5AA1
Point Register Pair HL to 5B7AH, the days-per-month table. Each byte holds the number of days in the corresponding month (January=31, February=28 or 29, etc.).
5AA4
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H. DE will accumulate the total day count as months are summed.
5AA7
POP BC C1
Restore Register Pair BC from the stack (B = month, C = 0-based day, saved at 5A9AH).
5AA8
LD A,(HL) 7E
LOOP START — sum days for each month
Load Register A with the byte at (HL), the number of days in the current month from the table.
5AA9
ADD A,E 83
ADD Register A (days in this month) to Register E (accumulated day count low byte).
5AAA
LD E,A 5F
Load Register E with the new accumulated low byte.
5AAB
INC HL 23
INCrement HL by 1 to advance to the next month in the table.
5AAC
If the NO CARRY FLAG is set (no overflow from the ADD), JUMP forward to 5AAFH to skip the high-byte increment.
5AAE
INC D 14
INCrement Register D by 1 to account for the carry from the low-byte addition.
5AAF
LOOP END when B = 0
DECrement Register B (the month counter) and JUMP back to 5AA8H if B is not zero (more months to sum).
5AB1
LD A,C 79
Load Register A with Register C (the 0-based day within the target month).
5AB2
CP (HL) BE
Compare Register A (0-based day) against the byte at (HL), which is the number of days in the target month. If A ≥ (HL), the day exceeds the month’s length (NO CARRY).
5AB3
ERROR PATH — day exceeds month length
If the NO CARRY FLAG is set (day ≥ month length, invalid day for this month), JUMP to 5AE7H for syntax error.
5AB5
EX DE,HL EB
Exchange DE and HL. HL now holds the accumulated day-of-year count; DE holds the table pointer.
5AB6
INC BC 03
INCrement BC by 1 (adjusting the day value from 0-based back to 1-based for the final calculation).
5AB7
ADD HL,BC 09
ADD BC to HL, adding the (now 1-based) day-within-month to the accumulated day-of-year total. HL now holds the complete day-of-year index.
5AB8
EX DE,HL EB
Exchange DE and HL back. DE now holds the day-of-year index.
5AB9
GOSUB to 5D0BH. This utility routine processes the computed day-of-year index in DE for further JKL table operations.
5ABC
Point Register Pair HL to 5D2CH, a 3-byte result buffer written by the routine at 5D0BH.
5ABF
Point Register Pair DE to 5B87H, a runtime data area within BASIC/CMD (in the NOP fill region) used for JKL working storage.
5AC2
LD BC,0003H 01 03 00
Load Register Pair BC with 0003H (3 bytes to copy).
5AC5
LDIR ED B0
Block copy 3 bytes from (HL) = 5D2CH to (DE) = 5B87H. This transfers the computed JKL result into the working storage area.
5AC7
LD A,03H 3E 03
Load Register A with 03H (the byte count for the JKL data that was just copied, or a parameter for the ROM calls that follow).
5AC9
POP HL E1
COMMON MERGE POINT for JKL write path
Restore Register Pair HL from the stack (the BASIC text pointer saved earlier).
5ACA
PUSH AF F5
Save Register A (the data byte count) and FLAGS onto the stack.
5ACB
RST 08H ⇒ 2CH CF 2C
Execute RST 08H (SYNCHR): Verify comma separator.
5ACD
GOSUB to ROM routine at 260DH to evaluate a variable reference from the BASIC text. On return, DE points to the variable’s storage.
5AD0
GOSUB to ROM routine at 0AF4H. This routine performs numeric conversion or validation on the variable value.
5AD3
POP AF F1
Restore Register A (the data byte count) from the stack.
5AD4
PUSH HL E5
Save Register Pair HL (the BASIC text pointer) onto the stack.
5AD5
PUSH DE D5
Save Register Pair DE (the variable pointer) onto the stack.
5AD6
GOSUB to ROM routine at 28BFH. This ROM routine performs a numeric operation (copy or convert) related to the variable value for the JKL assignment.
5AD9
POP HL E1
Restore Register Pair HL from the stack (the variable pointer saved at 5AD5H).
5ADA
GOSUB to ROM routine at 285DH. This routine completes the variable assignment, copying the computed JKL value into the target variable.
5ADD
Point Register Pair HL to 5B87H, the JKL working storage area. This is the source for the final LDIR copy.
5AE0
LD C,A 4F
Load Register C with Register A (the byte count returned from the ROM calls).
5AE1
LD B,00H 06 00
Load Register B with 00H. BC now holds the byte count as a 16-bit value for LDIR.
5AE3
LDIR ED B0
Block copy BC bytes from (HL) = 5B87H to (DE) = the variable storage location. This writes the JKL-computed value into the BASIC variable.
5AE5
POP HL E1
Restore Register Pair HL (the BASIC text pointer saved at 5AD4H) from the stack.
5AE6
RET C9
RETurn to the BASIC interpreter. The JKL operation is complete.
5AE7
JUMP to 5B44H which executes JP 1E4AH (ROM "Illegal Function Call" handler).
5AE9H - JKL Date Range Handler
This section handles the JKL date range syntax (e.g., CMD“J”,7-15). It validates the start value, reads the end value from the BASIC text (including a 2-byte address at the hyphen position), calls the date calculator subroutines, and builds a multi-byte JKL range entry in the working storage at 5B87H-5B8EH.
5AE9
CP 07H FE 07
Compare Register A (the first parameter value) against 07H (decimal 7). If A < 07H, the CARRY FLAG is set.
5AEB
ERROR PATH
If the CARRY FLAG is set (parameter < 7), JUMP to 5AE7H for syntax error. The minimum range start value for JKL is 7.
5AED
INC HL 23
INCrement HL by 1 to advance past the ‘-’ separator to the address field.
5AEE
LD E,(HL) 5E
Load Register E with the low byte at (HL), the low byte of the end-range address or value.
5AEF
INC HL 23
INCrement HL to point to the high byte.
5AF0
LD D,(HL) 56
Load Register D with the high byte. DE now holds the 16-bit value from the BASIC text after the hyphen.
5AF1
LD (5B8DH),DE ED 53 8D 5B
SELF-MODIFYING CODE — writes to 5B8DH
Store Register Pair DE into the self-modifying code location at 5B8DH. This saves the end-range value for later use by the JKL range builder.
5AF5
DEC HL 2B
DECrement HL by 1, backing up the text pointer to before the high byte (preparing for the next CHRGET sequence).
5AF6
GOSUB to 5B59H, the year/leap-year calculator, to determine days-per-month for the date range computation.
5AF9
GOSUB to 5B3FH to verify the ‘/’ separator.
5AFC
LD B,03H 06 03
Load Register B with 03H (the number of digits to parse for the year value).
5AFE
GOSUB to 5B6EH, a multi-digit numeric parser that reads B digits from the BASIC text and returns the value in DE (via 5CD7H).
5B01
Point Register Pair HL to 5B7BH, the second entry in the days-per-month table (February).
5B04
LD B,00H 06 00
Load Register B with 00H, initializing a counter or accumulator for the backward search loop that follows.
5B06
DEC DE 1B
LOOP START — backward month search
DECrement DE by 1 (counting down the remaining value).
5B07
LD A,L 7D
Load Register A with Register L (the low byte of the table pointer). This is used to check if HL has reached the end of the table (5B87H).
5B08
CP 87H FE 87
Compare Register A against 87H. If L = 87H, HL points to 5B87H (past the end of the 13-byte days-per-month table), indicating all months have been processed.
5B0A
ERROR PATH
If the Z FLAG is set (past end of table), JUMP to 5AE7H for syntax error. The date range exceeds the calendar year.
5B0C
LD C,(HL) 4E
Load Register C with the byte at (HL), the number of days in the current month from the table.
5B0D
EX DE,HL EB
Exchange DE and HL. HL now holds the remaining count; DE holds the table pointer.
5B0E
OR A B7
Clear the CARRY FLAG.
5B0F
SBC HL,BC ED 42
SUBtract BC (days in this month, with C in low byte and B=00H in high byte) from HL. If HL < BC, CARRY is set (the remaining count is within this month).
5B11
EX DE,HL EB
Exchange back: HL = table pointer, DE = remaining count (after subtraction).
5B12
INC HL 23
INCrement HL to advance to the next month in the table.
5B13
LOOP END when CARRY set (remaining < month days)
If the NO CARRY FLAG is set (remaining count ≥ days in this month, more months to subtract), JUMP back to 5B07H to continue the backward search.
5B15
EX DE,HL EB
Exchange DE and HL. HL now holds the remaining day count (a negative offset after the over-subtraction).
5B16
ADD HL,BC 09
ADD BC back to HL, restoring the day-within-month value (undoing the over-subtraction).
5B17
PUSH HL E5
Save HL (the day-within-month offset) onto the stack.
5B18
LD A,E 7B
Load Register A with Register E (the low byte of the table pointer, which now indicates the month).
5B19
SUB 7BH D6 7B
SUBtract 7BH from Register A. Since the table starts at 5B7BH, this converts the table pointer offset to a 0-based month index.
5B1B
LD E,A 5F
Load Register E with the month index.
5B1C
LD D,H 54
Load Register D with Register H (for alignment with the following CALL parameter).
5B1D
GOSUB to 5D0BH to process the month/day index for the JKL range.
5B20
LD HL,(5D2DH) 2A 2D 5D
Load Register Pair HL with the 16-bit value at 5D2DH, a result from the 5D0BH computation.
5B23
LD (5B87H),HL 22 87 5B
SELF-MODIFYING CODE — writes to 5B87H
Store Register Pair HL into the JKL working storage at 5B87H.
5B26
POP DE D1
Restore Register Pair DE from the stack (the day-within-month offset saved at 5B17H).
5B27
INC DE 13
INCrement DE by 1 (convert from 0-based to 1-based day).
5B28
GOSUB to 5D0BH again with the adjusted day value in DE.
5B2B
Point HL to 5B89H (offset +2 in the JKL working storage area).
5B2E
LD A,2FH 3E 2F
Load Register A with 2FH (ASCII ‘/’, the date separator character for the formatted JKL result).
5B30
LD (HL),A 77
Store ‘/’ at 5B89H (the separator between month and day in the result string).
5B31
INC HL 23
INCrement HL to 5B8AH.
5B32
LD DE,(5D2DH) ED 5B 2D 5D
Load DE with the result from 5D2DH (the day value computed by 5D0BH).
5B36
LD (HL),E 73
Store the low byte of the day value at 5B8AH.
5B37
INC HL 23
INCrement HL to 5B8BH.
5B38
LD (HL),D 72
Store the high byte of the day value at 5B8BH.
5B39
INC HL 23
INCrement HL to 5B8CH.
5B3A
LD (HL),A 77
Store ‘/’ (Register A, still 2FH) at 5B8CH (the separator after the day field).
5B3B
LD A,08H 3E 08
Load Register A with 08H (the total byte count of the JKL range result string: 8 bytes).
5B3D
JUMP back to 5AC9H, the common merge point, to complete the JKL operation by assigning the 8-byte result to the target BASIC variable.
5B3FH - Slash Separator Checker
Reads the current character from (HL), verifies it is 2FH (ASCII ‘/’), and advances HL past it. If the character is not ‘/’, falls through to 5B44H which generates a syntax error.
5B3F
LD A,(HL) 7E
Load Register A with the byte at (HL), the current BASIC text character.
5B40
CP 2FH FE 2F
Compare Register A against 2FH (ASCII ‘/’). Z FLAG set if the character is a slash.
5B42
INC HL 23
INCrement HL by 1 to advance past this character (regardless of whether it matched).
5B43
RET Z C8
If the Z FLAG is set (character was ‘/’), RETurn successfully. HL now points past the separator.
5B44
ERROR EXIT — used by multiple JKL routines
JUMP to ROM routine at 1E4AH ("Illegal Function Call" error handler). The expected ‘/’ separator was not found.
5B47H - Range-Validated Numeric Parser
Reads a 2-digit decimal number from the BASIC text, validates it falls within the range B (minimum) to C (maximum), and returns the value in Register A. If the value is out of range or the high byte is non-zero, jumps to 5B44H (syntax error).
5B47
PUSH BC C5
Save Register Pair BC (B = minimum, C = maximum of the valid range) onto the stack.
5B48
LD B,02H 06 02
Load Register B with 02H (2 digits to parse).
5B4A
GOSUB to 5B6EH, the multi-digit numeric parser. Returns the parsed value in DE (D = high byte, E = low byte).
5B4D
LD A,D 7A
Load Register A with Register D (the high byte of the parsed value).
5B4E
OR A B7
Set flags from A. If D is non-zero (value > 255), the NZ FLAG is set.
5B4F
ERROR PATH
If the NZ FLAG is set (value exceeds 255), JUMP to 5B44H for syntax error. JKL date values must be single-byte.
5B51
POP BC C1
Restore Register Pair BC (B = minimum, C = maximum) from the stack.
5B52
LD A,E 7B
Load Register A with Register E (the parsed value, confirmed to fit in a single byte).
5B53
SUB B 90
SUBtract Register B (minimum) from A. If A < B (value below minimum), the CARRY FLAG is set.
5B54
CP C B9
Compare the adjusted value (A = original − minimum) against Register C (maximum). If the adjusted value ≥ C, it exceeds the range (NO CARRY).
5B55
ERROR PATH
If the NO CARRY FLAG is set (value out of range), JUMP to 5B44H for syntax error.
5B57
LD A,E 7B
Load Register A with Register E (the original parsed value, before range adjustment). This restores the actual value for the caller.
5B58
RET C9
RETurn with A = the validated numeric value.
5B59H - Year / Leap Year Calculator
Reads a year value from the BASIC text, validates it within the range 0-99, determines whether the year is a leap year, and stores the February days-per-month value (1CH = 28 for non-leap, 1DH = 29 for leap) at 5B7CH in the days-per-month table.
5B59
LD BC,0064H 01 64 00
Load Register Pair BC with 0064H. B = 00H (minimum); C = 64H (100 decimal, one past the maximum valid year value 99).
5B5C
GOSUB to 5B47H to read and validate the 2-digit year value (range 0-99). Returns value in A.
5B5F
LD B,1CH 06 1C
Load Register B with 1CH (decimal 28). This is the default February day count for a non-leap year.
5B61
OR A B7
Set flags based on A (the year value). Z FLAG set if year = 0.
5B62
If the Z FLAG is set (year = 0), JUMP to 5B69H. Year 0 is treated as a non-leap year (February = 28 days).
5B64
AND 03H E6 03
AND Register A with 03H, isolating the lowest 2 bits. If the result is 00H, the year is divisible by 4 (a leap year candidate).
5B66
If the NZ FLAG is set (year is NOT divisible by 4, not a leap year), JUMP to 5B69H with B = 1CH (28 days for February).
5B68
INC B 04
INCrement Register B by 1, changing it from 1CH (28) to 1DH (29). This is a leap year, so February has 29 days.
5B69
LD A,B 78
Load Register A with Register B (1CH = 28 for non-leap, or 1DH = 29 for leap year).
5B6A
LD (5B7CH),A 32 7C 5B
SELF-MODIFYING CODE — writes to 5B7CH
Store the February day count into the days-per-month table at 5B7CH. This is the February entry in the table at 5B7AH.
5B6D
RET C9
RETurn with the days-per-month table updated for the correct year.
5B6EH - Multi-Digit Numeric Parser
Reads B digits from the BASIC text and returns the decimal value in DE. Calls 5CD7H for each digit and validates that exactly the expected number of digits are present.
5B6E
PUSH BC C5
Save Register Pair BC (B = digit count to parse) onto the stack.
5B6F
GOSUB to 5CD7H, a single-digit parser that reads one decimal digit from the BASIC text and accumulates it into a value. Returns the running value in DE and the CARRY FLAG set if a valid digit was found.
5B72
LD A,C 79
Load Register A with Register C (a count or status value returned by 5CD7H).
5B73
POP BC C1
Restore Register Pair BC (B = expected digit count) from the stack.
5B74
ERROR PATH
If the CARRY FLAG is set (an error occurred during digit parsing), JUMP to 5B44H for syntax error.
5B76
CP B B8
Compare Register A (the number of digits actually parsed) against Register B (the expected digit count).
5B77
ERROR PATH
If the NZ FLAG is set (wrong number of digits), JUMP to 5B44H for syntax error.
5B79
RET C9
RETurn with DE = the parsed numeric value.
5B7AH - Days-Per-Month Table and JKL Working Storage
This area contains a 13-byte days-per-month table (5B7AH-5B86H) followed by 8 bytes of NOP-initialized working storage (5B87H-5B8EH) used by the JKL handler. The table holds the number of days in each month, with the entry at 5B7CH (February) being self-modified at runtime by the leap year calculator at 5B6AH to reflect 28 or 29 days. Bytes 5B87H and 5B8DH are runtime variable locations written to during JKL operations.
[DATA TABLE: Days per month] 13 entries starting at 5B7AH. Entry 0 is unused (or represents a base offset), entries 1-12 correspond to January through December. Values are in hex: 1FH=31, 1CH=28, 1EH=30.
5B7A
DEFB 00H 00
Entry 0: base offset (unused or placeholder).
5B7B
DEFB 1FH 1F
January: 1FH (31 days).
5B7C
DEFB 1CH 1C
SELF-MODIFYING CODE TARGET: 5B7CH
February: 1CH (28 days, default non-leap). This byte is overwritten at runtime by the leap year calculator at 5B6AH: 1CH for non-leap years, 1DH (29) for leap years.
5B7D
DEFB 1FH 1F
March: 1FH (31 days).
5B7E
DEFB 1EH 1E
April: 1EH (30 days).
5B7F
DEFB 1FH 1F
May: 1FH (31 days).
5B80
DEFB 1EH 1E
June: 1EH (30 days).
5B81
DEFB 1FH 1F
July: 1FH (31 days).
5B82
DEFB 1EH 1E
August: note byte is 1EH (30) but August has 31 days. This may be intentional for the JKL algorithm’s specific date computation, or it could reflect a different calendar convention used by NEWDOS/80.
5B83
DEFB 1FH 1F
September: 1FH (31 days).
5B84
DEFB 1EH 1E
October: 1EH (30 days).
5B85
DEFB 1FH 1F
November: 1FH (31 days).
5B86
DEFB 1FH 1F
December: 1FH (31 days).
JKL WORKING STORAGE
8 bytes of NOP-initialized space used for building JKL result strings. Written by LDIR at 5AC5H and by direct stores at 5B23H and 5AF1H.
5B87
DEFB 00H 00
SELF-MODIFYING CODE TARGET: 5B87H
JKL working byte 0. Written by code at 5B23H (LD (5B87H),HL).
5B88
DEFB 00H 00
JKL working byte 1 (high byte of the value stored at 5B87H).
5B89
DEFB 00H 00
JKL working byte 2 (date separator ‘/’ written at 5B30H).
5B8A
DEFB 00H 00
JKL working byte 3 (day low byte written at 5B36H).
5B8B
DEFB 00H 00
JKL working byte 4 (day high byte written at 5B38H).
5B8C
DEFB 00H 00
JKL working byte 5 (second separator ‘/’ written at 5B3AH).
5B8D
DEFB 00H 00
SELF-MODIFYING CODE TARGET: 5B8DH
JKL working byte 6. Written by code at 5AF1H (LD (5B8DH),DE).
5B8E
DEFB 00H 00
JKL working byte 7 (high byte of the value stored at 5B8DH).
5B8FH - CMD"F=SS" Handler (Single-Step Mode Configuration)
This routine handles the CMD"F=SS" command, which configures single-step mode for BASIC program execution. The command syntax is: CMD"F=SS" [,count] [N]. If a numeric count is provided, it sets the single-step interval stored at 63C4H. If the letter "N" is specified, the step mode byte at 63B4H is set to 18H (indicating "N" mode); otherwise it defaults to 20H (space character, indicating normal step mode). This is a PUBLIC entry point called from the CMD"F=" keyword dispatch table at 592BH.
5B8F
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H, initializing the step count to zero. DE will hold the numeric parameter value if one is provided on the command line.
5B92
DEC HL 2B
DECrement HL (the BASIC text pointer) by 1, backing up one position so that the next RST 10H (CHRGET) call will re-read the current character.
5B93
RST 10H D7
Call the CHRGET routine to get the next non-space character from the BASIC text. Returns the character in Register A with Z FLAG set if end-of-statement (00H or 3AH colon).
5B94
NO PARAMETERS - use defaults
If the Z FLAG has been set (end of statement reached, meaning no parameters were provided after CMD"F=SS"), JUMP forward to 5BA4H to store the default values.
Parameter Parsing
If we reach here, there are parameters after the "SS" keyword. The code expects a comma separator followed by either a numeric count, the letter "N", or both.
5B96
RST 08H ⇒ 2CH CF 2C
Call the SYNCHR routine to verify that the next character in the BASIC text is a ",". If the character does not match, a Syntax Error is generated. This enforces that a comma must follow the "SS" keyword before any parameters.
5B98
CP 4EH FE 4E
Compare Register A (the character after the comma, returned by SYNCHR which advances the text pointer past the comma and fetches the next non-space character) against 4EH (ASCII: N). If Register A equals 4EH, the Z FLAG is set.
5B9A
N MODE selected
If the Z FLAG has been set (the character is "N"), JUMP forward to 5BADH to set the "N" step mode (18H).
Numeric Count Parameter
The character is not "N", so it is expected to be a numeric digit. The code calls the multi-digit numeric parser at 5CD5H (which presets B=FFH for unlimited digit count) to read the decimal number into DE.
5B9C
GOSUB to 5CD5H, the multi-digit numeric parser with unlimited digit count. On entry, HL points to the first digit character in the BASIC text. On return, DE holds the parsed binary value, C holds the digit count, and HL points past the last digit.
5B9F
LD A,C 79
Load Register A with Register C (the digit count returned by the parser at 5CD5H). If C=0, no valid digits were found.
5BA0
OR A B7
OR Register A with itself. This sets the Z FLAG if A=0 (no digits were parsed), or NZ FLAG if A is nonzero (digits were successfully found).
5BA1
If the Z FLAG has been set (no digits were found - the parameter after the comma was not a number and not "N"), JUMP to ROM routine 1997H, the default statement dispatcher, which returns to the BASIC command loop without further processing.
Store Step Count and Mode
At this point, DE holds the parsed numeric step count. The code stores DE to 63C4H (the step interval counter) and sets the default step mode byte (20H = space, meaning normal step mode).
5BA4
DEC HL 2B
DECrement HL by 1, backing up the BASIC text pointer so the last-read character can be re-examined by the caller after this routine returns.
5BA5
LD (63C4H),DE ED 53 C4 63
SELF-MODIFYING CODE] - 63C4H holds the single-step interval counter used during BASIC program execution.
Store Register Pair DE (the step count: 0000H if no count given, or the parsed value) to memory location 63C4H.
5BA9
LD A,20H 3E 20
Load Register A with 20H (ASCII: space). This is the default step mode byte, indicating normal single-step mode (as opposed to "N" mode).
5BAB
JUMP forward unconditionally to 5BAFH to store the mode byte and return. This skips over the "N" mode entry below.
"N" Mode Entry
This entry point is reached when the character after the comma was "N". It sets the step mode byte to 18H instead of the default 20H.
5BAD
LD A,18H 3E 18
Load Register A with 18H. This is the "N" step mode byte, which selects a different single-step behavior during program execution (step without pausing for keypress).
5BAF
LD (63B4H),A 32 B4 63
SELF-MODIFYING CODE] - 63B4H holds the step mode flag read during BASIC program single-step execution.
Store Register A (the step mode byte: 20H for normal or 18H for "N" mode) to memory location 63B4H.
5BB2
RST 10H D7
Call the CHRGET routine to advance the BASIC text pointer past any remaining characters, preparing for the next statement.
5BB3
RET C9
RETurn to the CMD"F=" dispatcher. The single-step configuration is complete.
5BB4H - Variable Type and Suffix Parser
This routine parses a BASIC variable name at the current BASIC text pointer position (HL) and determines its data size based on a trailing suffix character. It is a PUBLIC entry point called by SYS21. On entry, HL points to the BASIC text. The routine reads the first character, validates it as alphabetic via ROM 1E3DH, then scans subsequent characters (letters and digits) until a non-alphanumeric character is found. The non-alphanumeric character is tested for four recognized suffixes: % (integer, 2 bytes), $ (string descriptor, 3 bytes), ! (single precision, 4 bytes), # (double precision, 8 bytes). If no suffix is found, the per-variable default type is looked up from the DEFINT/DEFSNG/DEFDBL/DEFSTR table at 4100H+offset using the first letter as an index. The results are stored as self-modifying code: the data size goes to 5BFEH, the trailing character count goes to 5C03H, and the variable name character goes to 5C09H. The routine returns with the Z FLAG reflecting whether the next character is an open parenthesis (28H), indicating an array reference.
5BB4
DEC HL 2B
DECrement HL (the BASIC text pointer) by 1, backing up so the next CHRGET call will re-read the current character.
5BB5
RST 10H D7
Call the CHRGET routine to get the next non-space character from the BASIC text into Register A.
5BB6
LD B,A 47
Load Register B with the character from Register A. Register B preserves the variable's first character (the letter name) throughout this routine.
5BB7
GOSUB to ROM routine 1E3DH to test whether the character in Register A is alphabetic (A-Z). On return, Register A is preserved (unchanged). The CARRY FLAG is set if the character is NOT alphabetic; NO CARRY FLAG if it IS alphabetic (A-Z).
5BBA
If the CARRY FLAG has been set (the first character is not a letter - invalid variable name), JUMP to ROM routine 1997H, the default statement dispatcher, which returns to the READY prompt without further processing.
Variable Name Scanning Loop
The variable name starts with a valid letter (saved in B). Now scan all subsequent letters and digits, counting them in Register C. Register A is cleared to zero as an initializer. C starts at 0 and tracks the total character count beyond the first letter.
5BBD
XOR A AF
XOR Register A with itself, setting A to 00H and clearing all flags.
5BBE
LD C,A 4F
Load Register C with Register A (00H). Register C is the character counter, initialized to zero.
Character Count Loop
This loop reads characters from the BASIC text. For each digit (CARRY set by CHRGET) or letter (NO CARRY from 1E3DH), it increments C and loops back. When a non-alphanumeric character is found, the loop exits to the type suffix detection chain.
5BBF
INC C 0C
LOOP START - character counting
INCrement Register C (the character counter) by 1.
5BC0
DEC C 0D
DECrement Register C by 1, restoring it. The INC/DEC pair tests the current value of C: it sets the Z FLAG if C was 0 before the INC (restoring 0 after INC/DEC), or NZ if C was nonzero. This determines whether any trailing characters have been counted yet.
5BC1
If the NZ FLAG has been set (C was nonzero, meaning at least one extra character has been counted already), JUMP forward to 5BC4H to skip the LD C,A below.
5BC3
LD C,A 4F
Load Register C with Register A. On the first pass (C was 0), this stores the current value of A into C. This instruction is only executed on the first iteration of the loop.
5BC4
RST 10H D7
Call the CHRGET routine to get the next character from the BASIC text into Register A. CARRY FLAG is set if the character is a numeric digit (0-9).
5BC5
LOOP - digit found, continue
If the CARRY FLAG has been set (the character is a numeric digit), JUMP back to 5BBFH to increment the counter and continue scanning.
5BC7
GOSUB to ROM routine 1E3DH to test whether Register A holds an alphabetic character (A-Z). Register A is preserved. CARRY FLAG set if NOT alphabetic; NO CARRY if alphabetic.
5BCA
LOOP - letter found, continue
If the NO CARRY FLAG has been set (the character IS alphabetic), JUMP back to 5BBFH to increment the counter and continue scanning.
Type Suffix Detection Chain
Register A holds the raw non-alphanumeric character (preserved by 1E3DH). The code tests for the four BASIC type suffix characters by subtracting 25H (ASCII "%") and using a chain of INC A / CP instructions to check for each suffix in order. Register D holds the byte size for the detected type: % (25H) → D=02H (integer, 2 bytes), $ (24H) → D=03H (string descriptor, 3 bytes), ! (21H) → D=04H (single precision, 4 bytes), # (23H) → D=08H (double precision, 8 bytes).
5BCC
LD D,02H 16 02
Load Register D with 02H. This is the byte size for integer type (% suffix = 2 bytes per variable).
5BCE
SUB 25H D6 25
SUBtract 25H (ASCII: %) from Register A. If the suffix character was %, the result is zero and the Z FLAG is set. After this instruction, A = (original_char − 25H).
5BD0
% INTEGER SUFFIX
If the Z FLAG has been set (the suffix character was %), JUMP forward to 5BEAH to store the type size D=02H (integer, 2 bytes).
5BD2
INC D 14
INCrement Register D from 02H to 03H. D=03H is the byte size for string descriptor type ($ suffix = 3 bytes).
5BD3
INC A 3C
INCrement Register A by 1. After SUB 25H, if the original character was $ (ASCII 24H), then A was FFH (24H−25H wraps to FFH); INC A produces 00H and sets the Z FLAG.
5BD4
$ STRING SUFFIX
If the Z FLAG has been set (the suffix character was $), JUMP forward to 5BEAH to store the type size D=03H (string descriptor, 3 bytes).
5BD6
INC D 14
INCrement Register D from 03H to 04H. D=04H is the byte size for single precision type (! suffix = 4 bytes).
5BD7
CP FDH FE FD
Compare Register A against FDH. After SUB 25H and INC A, if the original character was ! (ASCII 21H), then A = 21H−25H+1 = FDH (unsigned: FCH+1). If A equals FDH, the Z FLAG is set.
5BD9
! SINGLE PRECISION SUFFIX
If the Z FLAG has been set (the suffix character was !), JUMP forward to 5BEAH to store the type size D=04H (single precision, 4 bytes).
5BDB
LD D,08H 16 08
Load Register D with 08H. D=08H is the byte size for double precision type (# suffix = 8 bytes). The value is loaded directly rather than incrementing because there is a gap from 04H to 08H.
5BDD
INC A 3C
INCrement Register A by 1. After SUB 25H and the first INC A, if the original character was # (ASCII 23H), then A = 23H−25H+1 = FFH (unsigned: FEH+1). This second INC A produces 00H and sets the Z FLAG.
5BDE
# DOUBLE PRECISION SUFFIX
If the Z FLAG has been set (the suffix character was #), JUMP forward to 5BEAH to store the type size D=08H (double precision, 8 bytes).
No Recognized Suffix - Default Type Lookup
The character was not %, $, !, or #. This means either it was a statement separator (colon, end of line) or some other non-suffix character. The code looks up the default type for this variable's letter from the BASIC DEFINT/DEFSNG/DEFDBL/DEFSTR type table. Register D=41H and Register E=(letter−41H+1), forming an address into the type table where each letter A-Z has a 1-byte entry holding the default byte size for untyped variables starting with that letter.
5BE0
LD A,B 78
Load Register A with Register B (the first letter of the variable name, saved at 5BB6H).
5BE1
SUB 41H D6 41
SUBtract 41H (ASCII: A) from Register A, converting the letter to a zero-based index (A=0, B=1, ... Z=25).
5BE3
LD E,A 5F
Load Register E with the zero-based letter index.
5BE4
INC E 1C
INCrement Register E by 1, making the index 1-based (A=1, B=2, ... Z=26). The table has an extra byte at offset 0 before the per-letter entries.
5BE5
LD D,41H 16 41
Load Register D with 41H. Register Pair DE now holds the address 41xxH where xx is the 1-based letter index. For letter "A": DE=4101H. For "Z": DE=411AH. This indexes into the BASIC variable type default table maintained by DEFINT/DEFSNG/DEFDBL/DEFSTR statements.
5BE7
LD A,(DE) 1A
Load Register A with the byte at the memory location pointed to by DE (the default type table entry for this variable's starting letter). The value is the default byte size (02H=integer, 03H=string, 04H=single, 08H=double).
5BE8
LD D,A 57
Load Register D with Register A (the default byte size from the table). D now holds the type size, same as if a suffix had been found.
5BE9
DEC HL 2B
DECrement HL by 1, backing up the BASIC text pointer past the non-suffix character so it can be re-read by the caller. When a suffix was found, the pointer had already advanced past it; when no suffix was found, we need to back up so the caller sees the separator character.
Store Results
The type size is in D, the character count is in C, and the variable's first letter is in B. Store these three values to self-modifying code locations for use by the caller (routines in SYS21 and elsewhere that read back 5BFEH, 5C03H, and 5C09H).
5BEA
LD A,D 7A
Load Register A with Register D (the type byte size: 02H, 03H, 04H, or 08H).
5BEB
LD (5BFEH),A 32 FE 5B
SELF-MODIFYING CODE] - 5BFEH holds the parsed variable's data size, read back by SYS21 and other callers. This writes the immediate operand of the CP instruction at 5BFDH.
Store Register A (the type byte size) to memory location 5BFEH.
5BEE
LD A,C 79
Load Register A with Register C (the character count of trailing characters in the variable name after the first letter).
5BEF
LD (5C03H),A 32 03 5C
SELF-MODIFYING CODE] - 5C03H holds the variable name trailing character count. This writes the immediate operand of the CP instruction at 5C02H.
Store Register A (the character count) to memory location 5C03H.
5BF2
LD A,B 78
Load Register A with Register B (the first letter of the variable name).
5BF3
LD (5C09H),A 32 09 5C
SELF-MODIFYING CODE] - 5C09H holds the variable's first letter character. This writes the immediate operand of the CP instruction at 5C08H.
Store Register A (the first letter) to memory location 5C09H.
5BF6
RST 10H D7
Call the CHRGET routine to advance the BASIC text pointer and get the next non-space character into Register A.
5BF7
CP 28H FE 28
Compare Register A against 28H (ASCII: open parenthesis (). If the next character is "(", this variable is an array reference. The Z FLAG is set if A=28H (array), NZ if not (simple variable).
5BF9
RET C9
RETurn to the caller. The Z FLAG indicates whether the variable is an array (Z=array, NZ=simple variable). The type size is stored at 5BFEH, character count at 5C03H, and first letter at 5C09H.
5BFAH - BASIC Line Type Byte and End-of-Program Checker
This routine examines the type nibble of the byte at (HL) in a BASIC program line link structure. It serves dual purposes: when called directly, it checks if a BASIC line entry has a zero type nibble and whether the following bytes indicate the end-of-program marker (0000H). But the three CP instructions at 5BFDH, 5C02H, and 5C08H are also self-modifying code targets - their immediate operands are overwritten by the variable parser at 5BB4H with the type size, character count, and letter name respectively. When the routine is accessed through those specific bytes (rather than called from the top), the CP instructions serve as data storage locations. This is a PUBLIC entry point called by SYS21.
5BFA
LD A,(HL) 7E
Load Register A with the byte at the memory location pointed to by HL (the first byte of a BASIC line link structure).
5BFB
AND 0FH E6 0F
AND Register A with 0FH, masking off the high nibble and keeping only the low nibble. This extracts the line type indicator from the link byte.
5BFD
CP 00H FE 00
SELF-MODIFYING CODE TARGET at 5BFEH] - The immediate byte 00H at 5BFEH is overwritten by 5BEBH with the variable type byte size (02H/03H/04H/08H).
Compare Register A against 00H. If the low nibble is 00H, this is a normal BASIC line (or the end-of-program marker).
5BFF
RET NZ C0
If the NZ FLAG has been set (low nibble is not 00H - this is a special line type), RETurn immediately to the caller with NZ status.
Check For End-of-Program Marker
The low nibble was 00H, indicating a normal line or the end marker. Now check the full 2-byte link pointer: if both subsequent bytes are 00H, this is the end-of-program double-zero marker (0000H link = no more lines).
5C00
INC HL 23
INCrement HL to point to the second byte of the link pointer.
5C01
LD A,(HL) 7E
Load Register A with the second byte of the link pointer.
5C02
CP 00H FE 00
SELF-MODIFYING CODE TARGET at 5C03H] - The immediate byte 00H at 5C03H is overwritten by 5BEFH with the variable name trailing character count.
Compare Register A against 00H.
5C04
If the NZ FLAG has been set (the second byte is nonzero - this is a valid link, not end-of-program), JUMP forward to 5C0BH to restore HL and return.
5C06
INC HL 23
INCrement HL to point to the third byte.
5C07
LD A,(HL) 7E
Load Register A with the third byte.
5C08
CP 00H FE 00
SELF-MODIFYING CODE TARGET at 5C09H] - The immediate byte 00H at 5C09H is overwritten by 5BF3H with the variable name first letter.
Compare Register A against 00H. The Z FLAG reflects whether this byte is also zero (complete end-of-program triple-zero marker).
5C0A
DEC HL 2B
DECrement HL by 1, backing up one position.
5C0B
DEC HL 2B
DECrement HL by 1, restoring HL to its original position (the first byte of the link structure).
5C0C
RET C9
RETurn to the caller. The Z FLAG indicates whether the program end was found (Z=end marker, NZ=valid line or special type).
5C0DH - BASIC Line Entry Length Calculator
This routine calculates the total length of a BASIC line entry and advances HL past it. It reads the low nibble of (HL) to get a data size value, adds 3 for the overhead bytes (2-byte link pointer + 1 type byte), and adds the result to HL. The OR H at the end serves as a nonzero test to confirm the pointer is in a valid memory range. Used to traverse BASIC program data structures of varying element sizes.
5C0D
LD A,(HL) 7E
Load Register A with the byte at the memory location pointed to by HL (the type/size byte of the current entry).
5C0E
AND 0FH E6 0F
AND Register A with 0FH, masking the low nibble to extract the element's data size value.
5C10
ADD 03H C6 03
ADD 03H to Register A. The 3-byte overhead covers the link pointer (2 bytes) plus the type byte itself, giving the total entry length in bytes.
5C12
LD C,A 4F
Load Register C with Register A (the total entry length).
5C13
LD B,00H 06 00
Load Register B with 00H. Register Pair BC now holds the 16-bit entry length (00:length).
5C15
ADD HL,BC 09
ADD Register Pair BC (the entry length) to HL, advancing HL past this entry to the start of the next one.
5C16
OR H B4
OR Register A with Register H. This sets NZ if H is nonzero (HL is in a valid memory range above 00FFH). Used as a quick validity check by the caller.
5C17
RET C9
RETurn to the caller. HL now points to the next entry. NZ indicates valid data remains.
5C18H - BASIC Line Link Chain Follower
This routine follows a link chain embedded within a BASIC program data structure. It skips 3 overhead bytes, reads a 2-byte address from the current position into BC, advances HL, and then falls into 5C15H to add BC to HL and return. This is used to traverse linked BASIC structures where entries contain embedded forward-offset addresses. It is a PUBLIC entry point called by SYS21.
5C18
INC HL 23
INCrement HL by 1 (skip first overhead byte).
5C19
INC HL 23
INCrement HL by 1 (skip second overhead byte).
5C1A
INC HL 23
INCrement HL by 1 (skip third overhead byte). HL now points to the first byte of the embedded 2-byte address.
5C1B
LD C,(HL) 4E
Load Register C with the low byte of the address stored at (HL).
5C1C
INC HL 23
INCrement HL to point to the high byte of the embedded address.
5C1D
LD B,(HL) 46
Load Register B with the high byte of the address. Register Pair BC now holds the complete 16-bit address from the link structure.
5C1E
INC HL 23
INCrement HL past the address field, pointing to the data beyond it.
5C1F
JUMP back to 5C15H to execute ADD HL,BC / OR H / RET. This adds the address in BC as an offset to HL and returns with the validity check.
5C21H - Parenthesis Nesting Depth Counter
This routine scans BASIC text from the current position (HL) and tracks parenthesis nesting depth. Register B counts nesting: it increments for each open parenthesis "(" and decrements for each close parenthesis ")". When B reaches zero (all parentheses balanced), it advances past the closing ")" with CHRGET and returns with the CARRY FLAG clear. If end-of-statement is reached before parentheses are balanced, it returns with the CARRY FLAG set to signal an error. This is a PUBLIC entry point called by SYS21.
5C21
LD B,00H 06 00
Load Register B with 00H, initializing the parenthesis nesting depth counter to zero.
5C23
INC B 04
OPEN PAREN - increase nesting depth
INCrement Register B by 1, counting an open parenthesis. On first entry, this sets B=1 to account for the expected opening parenthesis.
5C24
RST 10H D7
LOOP START - scan characters
Call the CHRGET routine to get the next non-space character from the BASIC text into Register A. Z FLAG set if end-of-statement.
5C25
SCF 37
Set the CARRY FLAG. This pre-sets CARRY so that if the next instruction returns (end-of-statement found), the caller knows the parentheses were unbalanced.
5C26
RET Z C8
ERROR - premature end of statement
If the Z FLAG has been set (end of statement reached with parentheses still unbalanced), RETurn with CARRY FLAG set indicating an error condition (unmatched parentheses).
5C27
CP 28H FE 28
Compare Register A against 28H (ASCII: open parenthesis (). Z FLAG set if the character is "(".
5C29
OPEN PAREN - increase depth
If the Z FLAG has been set (found an open parenthesis), JUMP back to 5C23H to increment the nesting counter and continue scanning.
5C2B
CP 29H FE 29
Compare Register A against 29H (ASCII: close parenthesis )). Z FLAG set if the character is ")".
5C2D
LOOP - skip non-parenthesis characters
If the NZ FLAG has been set (the character is neither "(" nor ")"), JUMP back to 5C24H to skip this character and continue scanning.
5C2F
CLOSE PAREN - decrease depth, loop if unbalanced
DECrement Register B (the nesting counter) by 1 for the close parenthesis. If B is not yet zero (parentheses not fully balanced), JUMP back to 5C24H to continue scanning. If B reaches zero, fall through.
Balanced Parentheses - Return Success
All parentheses are balanced (B decremented to zero). Advance the text pointer past the final closing parenthesis and return with CARRY clear to indicate success.
5C31
RST 10H D7
Call the CHRGET routine to advance the BASIC text pointer past the closing parenthesis and get the next character into Register A.
5C32
OR A B7
OR Register A with itself. This clears the CARRY FLAG (the OR instruction always resets carry) and sets the Z FLAG based on whether the next character is 00H (end of line).
5C33
RET C9
RETurn to the caller. CARRY FLAG is clear (success - parentheses balanced). Z FLAG indicates whether end-of-statement was reached.
5C34H - CMD"F=SASZ" Handler (Set Array Size / Memory Resize)
This routine handles the CMD"F=SASZ,expr" command, which resizes the BASIC string/array area. The expression is evaluated as a 16-bit integer specifying the new desired size. The routine calculates the difference between the current top-of-arrays pointer (40B1H) and the requested size, verifies there is enough room by checking against the current stack and the BASIC string space pointer (40FDH), then relocates the existing data either upward (using LDDR) or downward (using LDIR) while interrupts are disabled. The stack pointer is also adjusted to maintain proper alignment. This is a PUBLIC entry point called from the CMD"F=" keyword dispatch table at 592BH.
5C34
RST 08H ⇒ 2CH CF
Call the SYNCHR routine to verify that the next character in the BASIC text matches a ",". Enforces that SASZ is followed by a comma before the size expression.
5C36
GOSUB to ROM routine 2B02H to evaluate the numeric expression in the BASIC text and convert it to a 16-bit integer. On return, DE holds the evaluated value (the requested new array/string area size) and HL points past the expression.
5C39
PUSH HL E5
Save HL (the BASIC text pointer after the expression) onto the stack for later restoration.
Calculate Size Difference
Compute the difference between the current top-of-arrays (40B1H) and the requested size (DE). The result indicates how much memory needs to be allocated or freed.
5C3A
LD HL,(40B1H) 2A B1 40
Load Register Pair HL with the value at memory location 40B1H, the current top-of-arrays pointer. This is the upper boundary of the BASIC variable/array storage area.
5C3D
OR A B7
OR Register A with itself to clear the CARRY FLAG, preparing for the SBC instruction.
5C3E
SBC HL,DE ED 52
SUBtract with Carry Register Pair DE (the requested size) from HL (top-of-arrays). The result HL = (top_of_arrays − requested_size) represents the size difference. If positive, the area is shrinking; if negative (carry set), it is growing.
5C40
LD (5C77H),HL 22 77 5C
SELF-MODIFYING CODE] - 5C77H holds the calculated size delta, used later as an operand in the LD DE instruction at 5C76H.
Store the size difference (HL) to memory location 5C77H.
5C43
PUSH HL E5
Save the size difference (HL) onto the stack.
5C44
GOSUB to ROM routine 28E6H to perform a memory availability check. This routine verifies that enough free memory exists for the requested operation.
5C47
POP DE D1
Restore the size difference from the stack into Register Pair DE.
Verify Stack Clearance
Check that the new memory layout does not collide with the current stack area. Compare the proposed new boundary against the string area top pointer (40D6H).
5C48
LD HL,(40D6H) 2A D6 40
Load Register Pair HL with the value at 40D6H, the top-of-string-space pointer (the highest address used by string data, growing downward).
5C4B
RST 18H DF
Call the CPDEHL routine (RST 18H) to compare DE against HL. Z FLAG set if equal; CARRY set if DE < HL.
5C4C
EX DE,HL EB
EXchange Register Pair DE with HL. DE now holds the string space top, HL holds the size difference.
5C4D
LD E,1AH 1E 1A
Load Register E with error code 1AH (decimal 26). This is the "Out of String Space" error code, prepared in case the check fails.
5C4F
ERROR - Out of String Space
If the CARRY FLAG has been set (the size difference exceeds available string space - insufficient memory), JUMP to ROM error handler at 19A2H with error code 1AH in E.
Calculate New Stack Position
The memory resize is feasible. Now compute the new adjusted stack pointer position. The stack must be moved by the same amount as the data to maintain proper alignment.
5C52
LD DE,(40A0H) ED 5B A0 40
Load Register Pair DE with the value at 40A0H, the BASIC program start pointer (bottom of the BASIC program area).
5C56
OR A B7
Clear the CARRY FLAG for the following SBC instruction.
5C57
SBC HL,DE ED 52
SUBtract DE (program start) from HL (the size difference). The result represents the offset needed for the stack adjustment.
5C59
ADD HL,SP 39
ADD the current Stack Pointer to HL. This calculates the new stack position after the memory shift.
5C5A
LD (5C8DH),HL 22 8D 5C
SELF-MODIFYING CODE] - 5C8DH holds the computed new stack pointer, used later as the operand of the LD SP instruction at 5C8CH.
Store the new stack position to memory location 5C8DH.
5C5D
DEC H 25
DECrement Register H by 1. This subtracts 100H (256 bytes) from HL as a safety margin to ensure the new stack does not collide with other data areas.
Verify Free Memory Margin
Check that the new layout leaves enough room between the top of BASIC storage and the string free pointer (40FDH).
5C5E
LD DE,(40FDH) ED 5B FD 40
Load Register Pair DE with the value at 40FDH, the string free space pointer (the current lowest address of free string space).
5C62
RST 18H DF
Call the CPDEHL routine (RST 18H) to compare DE against HL. CARRY set if DE < HL (not enough room).
5C63
ERROR - Out of Memory
If the CARRY FLAG has been set (the new layout does not leave enough free memory), JUMP to ROM routine 197AH to display an "Out of Memory" error and return to READY.
Prepare Block Move
All checks passed. Now set up the block move to relocate the existing data. The code captures the current stack pointer, computes the byte count from the program area, and determines whether to move upward (LDDR) or downward (LDIR).
5C66
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H. This will be used with ADD HL,SP to capture the current stack pointer value (since there is no direct LD HL,SP instruction on the Z80).
5C69
ADD HL,SP 39
ADD the Stack Pointer to HL. HL now holds the current value of SP (the top of the stack).
5C6A
PUSH HL E5
Save the current stack pointer value (HL) onto the stack. This will be the source address for one of the block move directions.
5C6B
EX DE,HL EB
EXchange DE and HL. DE now holds the current stack pointer; HL holds the previous value of DE (the string free pointer from 40FDH).
5C6C
LD HL,(40A0H) 2A A0 40
Load Register Pair HL with the value at 40A0H (program start pointer) again.
5C6F
OR A B7
Clear the CARRY FLAG for the SBC instruction.
5C70
SBC HL,DE ED 52
SUBtract DE (current stack pointer) from HL (program start). The result is the byte count of the data block that needs to be moved (the distance from the stack to the program start).
5C72
LD B,H 44
Load Register B with Register H (high byte of the byte count).
5C73
LD C,L 4D
Load Register C with Register L (low byte of the byte count). BC now holds the number of bytes to move.
5C74
INC BC 03
INCrement BC by 1 to include the boundary byte in the move count.
5C75
ADD HL,DE 19
ADD DE (stack pointer) back to HL, restoring HL to the program start address.
5C76
LD DE,0000H 11 00 00
SELF-MODIFYING CODE TARGET at 5C77H] - The operand bytes at 5C77H-5C78H were overwritten at 5C40H with the size difference. DE is loaded with the amount to shift the data.
Load Register Pair DE with 0000H.
5C79
LD (40A0H),DE ED 53 A0 40
Store Register Pair DE (the size difference, which represents the new program start offset) to 40A0H, updating the BASIC program start pointer to reflect the resize.
5C7D
RST 18H DF
Call the CPDEHL routine (RST 18H) to compare DE against HL. This determines the direction of the block move: if DE < HL (carry set), move downward using LDDR; if DE >= HL (no carry), move upward using LDIR.
5C7E
DI F3
Disable Interrupts. The block move must not be interrupted because both the stack pointer and memory contents are being relocated simultaneously.
5C7F
UPWARD MOVE
If the NO CARRY FLAG has been set (DE >= HL - the data needs to move upward), JUMP to 5C85H to use the LDIR copy path.
Downward Move (LDDR PATH)
The data moves to a lower address. LDDR copies from high to low, preventing overlap corruption when shifting data downward.
5C81
LDDR ED B8
Execute block move: copy BC bytes from (HL) to (DE), decrementing HL and DE after each byte. This moves the data block downward in memory.
5C83
JUMP forward to 5C8CH to restore the stack pointer and re-enable interrupts.
Upward Move (LDIR PATH)
The data moves to a higher address. LDIR copies from low to high.
5C85
POP HL E1
Restore the original stack pointer value from the stack into HL (the source address for the upward move).
5C86
LD DE,(5C8DH) ED 5B 8D 5C
Load Register Pair DE with the value at 5C8DH (the pre-computed new stack position, stored at 5C5AH). This is the destination address for the upward move.
5C8A
LDIR ED B0
Execute block move: copy BC bytes from (HL) to (DE), incrementing HL and DE after each byte. This moves the data block upward in memory.
5C8C
LD SP,0000H 31 00 00
SELF-MODIFYING CODE TARGET at 5C8DH] - The operand bytes at 5C8DH-5C8EH were overwritten at 5C5AH with the new stack pointer value. This sets SP to the relocated stack position.
Load the Stack Pointer with 0000H.
5C8F
EI FB
Enable Interrupts. The block move and stack relocation are complete; interrupts can safely resume.
5C90
POP HL E1
Restore HL from the (now-relocated) stack. This recovers the BASIC text pointer that was saved at 5C39H.
5C91
RET C9
RETurn to the CMD"F=" dispatcher. The memory resize is complete, the stack pointer has been adjusted, and the BASIC text pointer is restored.
5C92H - String Variable Descriptor Fetcher
This routine synchronizes on a comma, evaluates a string expression, and retrieves the string descriptor. It calls ROM 2337H (string expression evaluator) to parse the string, then exchanges the return address with HL and calls ROM 29D7H to locate the string descriptor. On return, A holds the string length, DE holds the string data address, and HL points to the descriptor. This routine is used by SYS10 and other callers that need to access string variable data.
5C92
RST 08H ⇒ 2CH CF
Call the SYNCHR routine to verify the next character matches ASCII comma (,). Enforces that a comma precedes the string expression.
5C94
GOSUB to ROM routine 2337H to evaluate the string expression at the current BASIC text position. On return, the string result is stored in the string accumulator and HL points past the expression.
5C97
EX (SP),HL E3
EXchange the value at the top of the stack with HL. This swaps the return address (on the stack) with the current BASIC text pointer (in HL), saving the text pointer on the stack and putting the return address in HL.
5C98
PUSH HL E5
Save HL (the return address) back onto the stack. The BASIC text pointer is now below it on the stack.
5C99
GOSUB to ROM routine 29D7H to locate and return the string descriptor. This routine finds the most recent string result and returns a pointer to its 3-byte descriptor (length + address).
Extract String Descriptor Fields
HL now points to the string descriptor. Read the 3-byte descriptor: byte 0 = string length, bytes 1-2 = string data address (little-endian). Then restore HL to the descriptor start.
5C9C
LD A,(HL) 7E
Load Register A with the first byte of the string descriptor (the string length).
5C9D
INC HL 23
INCrement HL to point to the second byte of the descriptor (low byte of the string data address).
5C9E
LD E,(HL) 5E
Load Register E with the low byte of the string data address.
5C9F
INC HL 23
INCrement HL to point to the third byte of the descriptor (high byte of the string data address).
5CA0
LD D,(HL) 56
Load Register D with the high byte of the string data address. Register Pair DE now holds the complete address of the string's character data.
5CA1
DEC HL 2B
DECrement HL by 1.
5CA2
DEC HL 2B
DECrement HL by 1, restoring HL to point to the start of the 3-byte string descriptor.
5CA3
RET C9
RETurn to the caller. A = string length, DE = string data address, HL = descriptor pointer.
5CA4H - Numeric-to-String Converter and Descriptor Fetcher
This routine converts a numeric value to its string representation and then fetches the string descriptor. It calls ROM 0AF4H to convert the number in the BASIC accumulator (4121H) to an ASCII string, then calls ROM 29DEH to create a string descriptor for the result, and finally falls into the descriptor extraction code at 5C9CH. This is a PUBLIC entry point used for converting numeric results to printable strings.
5CA4
GOSUB to ROM routine 0AF4H to convert the numeric value in the BASIC accumulator (at 4121H) to an ASCII decimal string representation. The result string is placed in the BASIC string buffer.
5CA7
GOSUB to ROM routine 29DEH to create a string descriptor for the converted number string. This allocates space in string memory and sets up the 3-byte descriptor (length + address).
5CAA
JUMP back to 5C9CH to extract the string descriptor fields (length into A, data address into DE) and return to the caller.
5CACH - Zero-and-Assign Numeric Variable
This routine stores a zero byte at the memory location pointed to by HL, then calls ROM 28BFH to copy/convert a numeric value, and finally jumps to ROM 285DH to assign the result to a BASIC variable. Used as a helper for initializing and assigning numeric variables during statement processing.
5CAC
LD (HL),00H 36 00
Store 00H to the memory location pointed to by HL, zeroing out the first byte of the variable's storage area.
5CAE
PUSH HL E5
Save HL (pointer to the variable storage) onto the stack.
5CAF
GOSUB to ROM routine 28BFH to copy or convert the current numeric value in the BASIC accumulator.
5CB2
POP HL E1
Restore HL (the variable storage pointer) from the stack.
5CB3
JUMP to ROM routine 285DH to assign the numeric value to the variable pointed to by HL. This completes the assignment and returns to the original caller via the address on the stack.
5CB6H - File Status Checker (B Register Test)
This routine tests Register B for nonzero and jumps to ROM 09D6H if B is nonzero. ROM 09D6H is a file completion or status handler. If B is zero, the routine simply returns. Called during file I/O operations to check whether a file operation completed with an error or status flag. This is a PUBLIC entry point called by SYS20.
5CB6
LD A,B 78
Load Register A with Register B (the file status byte to be tested).
5CB7
OR A B7
OR Register A with itself. This sets the Z FLAG if B was 0 (no error/status), or NZ if B was nonzero (error or special status).
5CB8
If the NZ FLAG has been set (B was nonzero - a file status condition exists), JUMP to ROM routine 09D6H to handle the file completion status.
5CBB
RET C9
RETurn to the caller. B was zero, indicating no error or special status condition.
5CBCH - Space Fill Routine
This routine fills C bytes at (HL) with spaces (20H). Register C holds the count of spaces to fill. If C is zero on entry, the routine returns immediately. The INC/DEC pattern tests whether C is zero before filling. This is a PUBLIC entry point called by SYS11 and SYS12 for padding string fields and output formatting.
5CBC
INC C 0C
INCrement Register C by 1 (anticipate the upcoming DEC to test for zero).
5CBD
DEC C 0D
LOOP START - space fill
DECrement Register C by 1. If C is now zero (it was 1 after the INC, meaning originally 0), the Z FLAG is set.
5CBE
RET Z C8
LOOP EXIT
If the Z FLAG has been set (C has reached zero - all spaces filled), RETurn to the caller.
5CBF
LD (HL),20H 36 20
Store 20H (ASCII: space) to the memory location pointed to by HL.
5CC1
INC HL 23
INCrement HL to point to the next byte to fill.
5CC2
LOOP - fill next byte
JUMP back to 5CBDH to test C and continue filling.
5CC4H - Numeric Expression Evaluator with File Handler
This routine saves HL, evaluates a numeric expression via ROM 2843H, restores HL, and then jumps to ROM 09D3H for file I/O handling. Used during FIELD statement processing to evaluate field width expressions and pass results to the file manager.
5CC4
PUSH HL E5
Save HL (current pointer) onto the stack.
5CC5
GOSUB to ROM routine 2843H to evaluate the numeric expression and convert the result to an 8-bit integer in Register A.
5CC8
POP HL E1
Restore HL from the stack.
5CC9
JUMP to ROM routine 09D3H to handle the file field assignment with the evaluated width. Returns to the original caller via the return address on the stack.
5CCCH - BASIC Line Skip (Scan Past Null-Terminated Text)
This routine advances HL past a null-terminated text section within a BASIC program line. It skips the first 3 overhead bytes (link pointer + type byte), then reads bytes until it finds a 00H null terminator. On return, HL points to the byte immediately after the null terminator. This is a PUBLIC entry point called by SYS11 and SYS13 for skipping over tokenized BASIC statements.
5CCC
INC HL 23
INCrement HL by 1 (skip first overhead byte).
5CCD
INC HL 23
INCrement HL by 1 (skip second overhead byte).
5CCE
INC HL 23
INCrement HL by 1 (skip third overhead byte). HL now points to the start of the tokenized BASIC text.
5CCF
LD A,(HL) 7E
LOOP START - scan for null
Load Register A with the byte at the memory location pointed to by HL.
5CD0
OR A B7
OR Register A with itself to set the Z FLAG if the byte is 00H (null terminator).
5CD1
INC HL 23
INCrement HL to point to the next byte. This is done before the conditional jump so that when the null is found, HL points past it.
5CD2
LOOP - continue scanning
If the NZ FLAG has been set (the byte was not 00H - more text remains), JUMP back to 5CCFH to read the next byte.
5CD4
RET C9
RETurn to the caller. HL points to the byte immediately following the null terminator.
5CD5H - Multi-Digit Decimal Number Parser (Unlimited Digits Entry)
This is the unlimited-digit entry point for the multi-digit decimal number parser. It sets B=FFH (maximum digit count of 255) and falls through to the main parser at 5CD7H. The parser reads ASCII digit characters from (HL), converts them to a 16-bit binary value in DE using the multiply-by-10-and-add algorithm, and counts the digits in C. On return, DE holds the binary result, C holds the digit count (0 if no digits found), and HL points past the last digit. If the result overflows 16 bits, the routine returns with CARRY set. This is the entry point called by 5B9CH (CMD"F=SS") and other routines that need to parse numbers of arbitrary length.
5CD5
LD B,FFH 06 FF
Load Register B with FFH (255), setting the maximum digit count to effectively unlimited. This is the entry point for parsing numbers of any length.
Main Parser Entry (5CD7H)
This is the main entry point when the caller wants to limit the number of digits parsed. On entry, B holds the maximum digit count. The parser initializes DE=0000H as the accumulator and C=0 as the digit counter. This entry (5CD7H) is called by the JKL routines at 5B6FH and elsewhere with specific B values to parse fixed-width numbers.
5CD7
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H, initializing the numeric accumulator to zero.
5CDA
LD C,E 4B
Load Register C with Register E (00H), initializing the digit counter to zero.
Digit Reading Loop
Each iteration reads one character from (HL), tests if it is a digit (0-9), and if so, multiplies the accumulator by 10 and adds the digit value. The multiply-by-10 is implemented as: result = (old × 4 + old) × 2 + digit = old × 10 + digit, using shifts and adds with overflow detection via Register A as a carry extension.
5CDB
LD A,B 78
LOOP START - digit parsing
Load Register A with Register B (the remaining digit count).
5CDC
OR A B7
OR Register A with itself. This sets the Z FLAG if B is zero (maximum digit count exhausted).
5CDD
RET Z C8
If the Z FLAG has been set (digit count exhausted - B reached zero), RETurn. DE holds the accumulated result, C holds the digit count.
5CDE
DEC B 05
DECrement Register B (the remaining digit count) by 1.
5CDF
LD A,(HL) 7E
Load Register A with the byte at the memory location pointed to by HL (the current character from the BASIC text).
5CE0
SUB 30H D6 30
SUBtract 30H (ASCII: 0) from Register A, converting the ASCII digit character to its binary value (0-9). If the character was not a digit, the result is either negative (carry set for chars below '0') or >= 10.
5CE2
CP 0AH FE 0A
Compare Register A against 0AH (decimal 10). If A < 10, the character was a valid digit and the CARRY FLAG is set. If A >= 10, the character was not a digit and the NO CARRY FLAG is set.
5CE4
RET NC D0
If the NO CARRY FLAG has been set (the character was not a digit), RETurn. The number parsing is complete. DE holds the result, C holds the digit count, HL still points to the non-digit character.
5CE5
INC HL 23
INCrement HL to point past the digit character just read.
5CE6
INC BC 03
INCrement Register Pair BC by 1. Since B holds the remaining count (decremented above) and C holds the digit count, this effectively increments C by 1 (the digit counter). The INC BC also restores B to its pre-DEC value, but B will be decremented again at the top of the loop.
Multiply Accumulator by 10 and Add Digit
The algorithm computes: new_DE = old_DE × 10 + digit. This is done as: HL = DE × 2 × 2 (= DE × 4), then HL = HL + DE (= DE × 5), then HL = HL × 2 (= DE × 10), then HL = HL + digit. Register A is used as a high-byte overflow detector, starting at 0 and accumulating carries from each ADD HL,HL via ADC A,A.
5CE7
PUSH HL E5
Save HL (the BASIC text pointer) onto the stack.
5CE8
PUSH BC C5
Save BC (digit count and remaining count) onto the stack.
5CE9
LD C,A 4F
Load Register C with Register A (the current digit value, 0-9).
5CEA
LD B,00H 06 00
Load Register B with 00H. BC now holds the digit value as a 16-bit number (00:digit).
5CEC
LD H,D 62
Load Register H with Register D (copy high byte of the current accumulator).
5CED
LD L,E 6B
Load Register L with Register E. HL now holds a copy of DE (the current accumulator value).
5CEE
XOR A AF
XOR Register A with itself, setting A to 00H. A serves as the overflow detection byte for the multiply operation.
5CEF
ADD HL,HL 29
ADD HL to itself, doubling the value. HL = DE × 2. Carry is set if overflow occurred.
5CF0
ADC A,A 8F
ADD Register A to itself plus carry. A accumulates any overflow from the HL doubling.
5CF1
ADD HL,HL 29
ADD HL to itself again. HL = DE × 4.
5CF2
ADC A,A 8F
Accumulate overflow carry into A.
5CF3
ADD HL,DE 19
ADD DE (original accumulator value) to HL. HL = DE × 4 + DE = DE × 5.
5CF4
ADC A,A 8F
Accumulate overflow carry into A.
5CF5
ADD HL,HL 29
ADD HL to itself. HL = DE × 10.
5CF6
ADC A,A 8F
Accumulate overflow carry into A.
5CF7
ADD HL,BC 09
ADD BC (the digit value) to HL. HL = DE × 10 + digit. This is the new accumulator value.
5CF8
POP BC C1
Restore BC (digit count and remaining count) from the stack.
5CF9
ADC A,A 8F
Final overflow check: accumulate any carry from the ADD HL,BC into A.
5CFA
POP DE D1
Restore DE from the stack. DE now holds the saved BASIC text pointer (from the PUSH HL at 5CE7H, which saved the text pointer before the multiply).
5CFB
EX DE,HL EB
EXchange DE and HL. DE now holds the new accumulator value (the multiply result), and HL holds the BASIC text pointer (restored for the next iteration).
5CFC
LOOP - continue parsing
If the Z FLAG has been set (A is zero - no overflow occurred during the multiply-and-add), JUMP back to 5CDBH to read the next digit.
Overflow Exit
If A is nonzero, the multiply-by-10-and-add overflowed the 16-bit range. Return with CARRY set to signal the overflow error.
5CFE
SCF 37
Set the CARRY FLAG to indicate that the parsed number overflowed 16 bits.
5CFF
RET C9
RETurn to the caller with CARRY set (overflow). DE holds the partial result, C holds the digit count parsed before overflow.
5D00H - Number-to-String Conversion Copy Routine
This routine converts a 16-bit number in DE to its ASCII decimal representation and copies the result to a destination buffer at (BC). It calls 5D0BH to perform the conversion (storing the ASCII result in the scratch buffer at 5D2AH), then copies D bytes from (HL) to (BC). On entry, DE holds the number to convert and BC points to the destination buffer. On return, HL points past the ASCII string and BC is advanced past the copied bytes. This is a PUBLIC entry point called by SYS11.
5D00
GOSUB to 5D0BH to convert the 16-bit value in DE to an ASCII decimal string. On return, HL points to the first significant digit in the scratch buffer at 5D2AH, D holds the number of significant digits, and E holds the digit count.
Copy Loop
Copy D bytes from (HL) to (BC), transferring the ASCII digit string from the scratch buffer to the caller's destination buffer.
5D03
LD A,(HL) 7E
LOOP START - copy digits
Load Register A with the byte at (HL) - the next ASCII digit character from the scratch buffer.
5D04
LD (BC),A 02
Store Register A (the ASCII digit) to the memory location pointed to by BC (the destination buffer).
5D05
INC BC 03
INCrement BC to point to the next destination byte.
5D06
INC HL 23
INCrement HL to point to the next source digit.
5D07
DEC D 15
DECrement Register D (the remaining digit count) by 1.
5D08
LOOP - continue copying
If the NZ FLAG has been set (more digits remain to copy), JUMP back to 5D03H.
5D0A
RET C9
RETurn to the caller. BC points past the last copied digit in the destination buffer.
5D0BH - 16-Bit Integer to ASCII Decimal Converter
This routine converts a 16-bit unsigned integer in DE to its ASCII decimal representation, stored in the 6-byte scratch buffer at 5D2AH. It uses ROM routine 132FH to perform the actual conversion (which converts the value at 4121H to ASCII at a destination buffer). After conversion, leading zeros are stripped. On return, HL points to the first significant digit, D holds the count of significant digits (minimum 1 for value 0), and E=D. This is a PUBLIC entry point called by the JKL routines at 5AB9H, 5B1DH, and 5B28H, and by 5D00H and 5D67H.
5D0B
PUSH BC C5
Save Register Pair BC onto the stack (preserved for the caller).
5D0C
LD BC,0000H 01 00 00
Load Register Pair BC with 0000H. BC is passed to the ROM conversion routine as a parameter (format control: no padding).
5D0F
LD (4121H),DE ED 53 21 41
Store Register Pair DE (the 16-bit value to convert) to memory location 4121H. 4121H is the BASIC string descriptor pointer / numeric accumulator. ROM routine 132FH reads the value to convert from this location.
5D13
Load Register Pair HL with 5D2AH, pointing to the 6-byte scratch buffer where the ASCII result will be stored.
5D16
PUSH HL E5
Save the scratch buffer address (5D2AH) onto the stack for later retrieval.
5D17
GOSUB to ROM routine 132FH to convert the 16-bit integer at 4121H to an ASCII decimal string. The result is written to the buffer pointed to by HL (5D2AH). The output is a fixed-width string with leading zeros.
5D1A
POP HL E1
Restore HL with the scratch buffer address (5D2AH).
5D1B
POP BC C1
Restore Register Pair BC from the stack.
Strip Leading Zeros
The ROM conversion produces a fixed-width output (up to 5 digits for a 16-bit value, with leading '0' characters). This loop advances HL past any leading '0' characters, counting the remaining significant digits in D. D starts at 4 (maximum digits minus 1 for 5-digit number) and decrements for each leading zero skipped.
5D1C
LD D,04H 16 04
Load Register D with 04H. D is the leading zero counter: up to 4 leading zeros can be stripped from a 5-digit number (leaving at least 1 digit).
5D1E
LD A,(HL) 7E
LOOP START - strip leading zeros
Load Register A with the byte at (HL) - the current character in the ASCII output.
5D1F
CP 30H FE 30
Compare Register A against 30H (ASCII: 0). If the character is not '0', it is a significant digit.
5D21
SIGNIFICANT DIGIT FOUND
If the NZ FLAG has been set (the character is not '0' - first significant digit found), JUMP to 5D27H to finalize the digit count.
5D23
INC HL 23
INCrement HL past the leading '0' character.
5D24
DEC D 15
DECrement Register D (the remaining strippable zeros counter) by 1.
5D25
LOOP - check next character
If the NZ FLAG has been set (D has not reached zero - more zeros may be stripped), JUMP back to 5D1EH.
Finalize Digit Count
D has been decremented for each leading zero stripped. Now increment D by 1 to get the actual count of significant digits (including the current position). Copy D to E for the return value.
5D27
INC D 14
INCrement Register D by 1. D now holds the number of significant digits in the ASCII string.
5D28
LD E,D 5A
Load Register E with Register D. Both D and E hold the significant digit count on return.
5D29
RET C9
RETurn to the caller. HL points to the first significant digit in the scratch buffer, D=E=significant digit count.
5D2AH - Numeric Conversion Scratch Buffer (6 Bytes)
This is a 6-byte work area used by the 16-bit integer to ASCII conversion routine at 5D0BH. ROM routine 132FH writes the ASCII decimal representation of the number here. The buffer is large enough for a 5-digit unsigned integer (0-65535) plus a null terminator.
5D2A
DEFB 00H,00H
00H,00H,00H,00H 00 00 00 00 00 00
Six bytes of 00H - scratch buffer for ASCII decimal conversion. Written to by ROM 132FH during the conversion at 5D0BH. Also referenced by LD HL,5D2AH at 5D13H and LD BC,5D2AH at 5D67H.
5D30H - Multi-Character Display with Leading Space
This routine displays A characters to the screen, each preceded by a leading space. It calls 5D3DH (the single-character display routine that outputs a space then the character) in a loop controlled by Register B (loaded from A). This is a PUBLIC entry point called by SYS12.
5D30
LD B,A 47
Load Register B with Register A (the number of characters to display). B serves as the loop counter.
5D31
LOOP - display one space+char pair
GOSUB to 5D3DH to display a space followed by one character from the number string.
5D34
LOOP - continue until all characters displayed
DECrement Register B by 1 and JUMP back to 5D31H if B is not zero.
5D36
RET C9
RETurn to the caller.
5D37H - Convert and Display 16-Bit Number
This routine converts a 16-bit number (implicitly zero, since DE is loaded with 0000H) to ASCII and displays it with leading spaces. It initializes DE=0000H and calls 5D67H to perform the conversion and display. This appears to be a reset/initialization display entry.
5D37
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H (the value to convert and display is zero).
5D3A
GOSUB to 5D67H to convert the value in DE to ASCII and display each digit with a leading space. Falls through to 5D3DH below on return (no, this is a CALL not a fall-through).
5D3DH - Display Character with Leading Space
This routine displays a space character followed by an optional second character. It outputs a space (20H) to the screen via ROM 0033H, then conditionally outputs a second character if a flag at 5D45H is set to match a comparison value. The self-modifying code at 5D44H-5D45H and 5D46H-5D47H controls whether the second character is displayed. This is a PUBLIC entry point called by SYS12 and is the core display primitive for formatted number output.
5D3D
LD A,20H 3E 20
Load Register A with 20H (ASCII: space). This is the leading space character to output before the actual data character.
5D3F
PUSH DE D5
Save Register Pair DE onto the stack (preserving the caller's value).
5D40
PUSH AF F5
Save Register A and flags onto the stack (the character to display, or the space).
5D41
GOSUB to ROM routine 0033H to display the character in Register A at the current cursor position and advance the cursor.
5D44
LD A,00H 3E 00
SELF-MODIFYING CODE TARGET at 5D45H] - The immediate byte at 5D45H is written to by 6430H and SYS12/4D04H. When modified, it holds a flag value controlling whether the second character output is performed.
Load Register A with 00H.
5D46
CP 24H FE 24
SELF-MODIFYING CODE TARGET at 5D47H] - The byte at 5D47H can be modified. If A matches the comparison value, the Z FLAG is set and the second character will be output.
Compare Register A against 24H.
5D48
POP DE D1
Restore DE from the stack. D now holds the previously-pushed A value (the character from PUSH AF above, since POP DE gets the AF bytes into D and E).
5D49
LD A,D 7A
Load Register A with Register D (the previously saved character value).
5D4A
If the Z FLAG has been set (the flag at 5D45H matched the comparison at 5D47H), GOSUB to ROM routine 003BH to display the character in Register A. This outputs the second character only when the self-modifying flag is configured for dual-character output.
5D4D
POP DE D1
Restore Register Pair DE from the stack (the caller's original value).
5D4E
RET C9
RETurn to the caller.
5D4FH - Display Character with Leading Space and Carriage Return
This routine calls 5D3DH to output a leading space, then loads A with 0DH (carriage return) and jumps into 5D3FH to output it. This outputs a space-then-CR sequence, used to terminate a line of formatted output. This is a PUBLIC entry point called by SYS12.
5D4F
GOSUB to 5D3DH to output a space character followed by the optional second character.
5D52
LD A,0DH 3E 0D
Load Register A with 0DH (carriage return character).
5D54
JUMP back to 5D3FH to output the carriage return character using the standard display routine (PUSH DE, PUSH AF, CALL 0033H, etc.).
5D56H - 16-Bit Unsigned Division (HL ÷ C)
This routine performs a 16-bit unsigned division: HL ÷ C. The quotient is returned in HL and the remainder in A. It uses the standard Z80 shift-and-subtract division algorithm over 16 iterations. Register A serves as the running remainder, and the quotient bits are assembled in HL by setting bit 0 of L for each successful subtraction. This is a PUBLIC entry point called by SYS21.
5D56
LD C,A 4F
Load Register C with Register A (the divisor). The dividend is already in HL.
5D57
LD B,10H 06 10
Load Register B with 10H (decimal 16). B is the loop counter - one iteration per bit of the 16-bit dividend.
5D59
XOR A AF
XOR Register A with itself, clearing A to 00H. A is the running remainder, initialized to zero.
DIVISION LOOP
Each iteration shifts the dividend (HL) left by one bit. The bit shifted out of H goes into the remainder (A) via RLA. If the remainder is greater than or equal to the divisor (C), the divisor is subtracted and bit 0 of L is set (quotient bit = 1). After 16 iterations, HL holds the quotient and A holds the remainder.
5D5A
ADD HL,HL 29
LOOP START - division iteration
ADD HL to itself (left shift HL by 1 bit). The MSB of H is shifted into the CARRY FLAG.
5D5B
RLA 17
Rotate Left through carry into A. The carry bit (from the HL shift) enters as bit 0 of A, and A's bit 7 goes to carry. This shifts the next dividend bit into the remainder.
5D5C
If the CARRY FLAG has been set (the remainder overflowed 8 bits - it is definitely greater than any 8-bit divisor), JUMP to 5D61H to perform the subtraction unconditionally.
5D5E
CP C B9
Compare Register A (the remainder) against Register C (the divisor). CARRY set if A < C (remainder is less than divisor - quotient bit is 0).
5D5F
QUOTIENT BIT = 0
If the CARRY FLAG has been set (remainder < divisor), JUMP to 5D63H to skip the subtraction (quotient bit remains 0).
5D61
SUB C 91
SUBtract Register C (divisor) from Register A (remainder). The remainder is reduced, and the quotient bit is 1.
5D62
INC L 2C
QUOTIENT BIT = 1
INCrement Register L by 1. This sets bit 0 of L, recording a quotient bit of 1. Since the ADD HL,HL at the top of the loop shifts L left each iteration, this builds the quotient from MSB to LSB.
5D63
LOOP - next bit
DECrement Register B by 1 and JUMP back to 5D5AH if B is not zero.
5D65
OR A B7
OR Register A with itself. Sets Z FLAG if the remainder is zero (division was exact), NZ if there is a remainder.
5D66
RET C9
RETurn to the caller. HL holds the quotient, A holds the remainder, Z FLAG indicates whether the division was exact.
5D67H - Convert 16-Bit Number and Display Each Digit
This routine converts a 16-bit number in DE to ASCII via 5D0BH (using the scratch buffer at 5D2AH and the copy routine at 5D00H), then displays each digit with a leading space by calling 5D3FH in a loop. On entry, DE holds the number. This is a PUBLIC entry point called by SYS12.
5D67
LD BC,5D2AH 01 2A 5D
Load Register Pair BC with 5D2AH, pointing to the scratch buffer. BC serves as the destination for the copy in 5D00H.
5D6A
PUSH BC C5
Save BC (the scratch buffer address) onto the stack for later retrieval as HL.
5D6B
GOSUB to 5D00H to convert the 16-bit number in DE to ASCII and copy the result to the scratch buffer at (BC). On return, E holds the significant digit count.
5D6E
POP HL E1
Restore the scratch buffer address from the stack into HL. HL now points to 5D2AH (the start of the ASCII digit string).
5D6F
LD B,E 43
Load Register B with Register E (the significant digit count). B serves as the loop counter for displaying digits.
DISPLAY LOOP
Read each digit from the scratch buffer and display it with a leading space via 5D3FH.
5D70
LD A,(HL) 7E
LOOP START - display digits
Load Register A with the byte at (HL) - the next ASCII digit to display.
5D71
INC HL 23
INCrement HL to point to the next digit.
5D72
GOSUB to 5D3FH to display the character in A (with the optional second-character output logic).
5D75
LOOP - display next digit
DECrement Register B by 1 and JUMP back to 5D70H if B is not zero.
5D77
RET C9
RETurn to the caller. All digits have been displayed.
5D78H - BASIC Line Link and Variable Reader
This routine scans past BASIC text colons/statements (via 5D8BH), then reads a 3-byte structure: it checks the 2-byte link field for zero (end-of-program), and if nonzero, reads a 2-byte value into DE and stores it at 57B8H (the state flag for LOAD/SAVE operations). This is a PUBLIC entry point called by SYS19 and SYS21.
5D78
GOSUB to 5D8BH to scan past any colons and advance to the next BASIC statement. On return, HL points to the start of the next statement's data, or to end-of-line if no more statements exist.
5D7B
INC HL 23
INCrement HL to point past the first byte of the link structure.
5D7C
LD A,(HL) 7E
Load Register A with the second byte of the structure (low byte of the link pointer).
5D7D
INC HL 23
INCrement HL past the second byte.
5D7E
OR (HL) B6
OR Register A with the byte at (HL) (the high byte of the link pointer). If both bytes are zero (link = 0000H), the result is zero and the Z FLAG is set, indicating end-of-program.
5D7F
INC HL 23
INCrement HL past the high byte of the link pointer.
5D80
END OF PROGRAM
If the Z FLAG has been set (the link pointer was 0000H - end of program), JUMP to ROM 1997H, the default statement dispatcher, to return to the BASIC command loop.
READ VARIABLE ADDRESS AND STORE
The link pointer was nonzero, indicating valid data follows. Read the next 2-byte value into DE and store it at 57B8H (the LOAD/SAVE state flag variable).
5D83
LD E,(HL) 5E
Load Register E with the low byte of the value at (HL).
5D84
INC HL 23
INCrement HL past the low byte.
5D85
LD D,(HL) 56
Load Register D with the high byte of the value. DE now holds the complete 16-bit value.
5D86
LD (57B8H),DE ED 53 B8 57
SELF-MODIFYING CODE] - 57B8H is the state flag for BASIC file LOAD/SAVE operations, read by SYS19/5322H.
Store Register Pair DE to memory location 57B8H.
5D8A
RET C9
RETurn to the caller. DE and 57B8H hold the extracted value.
5D8BH - BASIC Statement Colon Scanner
This routine scans the BASIC text from the current position, skipping over colon (3AH) statement separators and advancing past each sub-statement delimited by the BASIC token 93H (which is the token for the SUB keyword, used here as an internal marker). If the text pointer reaches end-of-line (00H via CHRGET's Z flag), the routine returns. Otherwise it synchronizes on the 93H token and scans past the following sub-statement text until end-of-line. This routine provides the "skip to next statement" functionality used by 5D78H and other callers.
5D8B
DEC HL 2B
DECrement HL by 1, backing up the BASIC text pointer so the next CHRGET re-reads the current character.
5D8C
RST 10H D7
Call the CHRGET routine to get the next non-space character into Register A. Z FLAG set if end-of-statement.
5D8D
OR A B7
OR Register A with itself. Sets the Z FLAG if A is 00H (end of line), clearing carry.
5D8E
RET Z C8
END OF LINE - return
If the Z FLAG has been set (end of line reached), RETurn.
5D8F
CP 3AH FE 3A
Compare Register A against 3AH (ASCII: colon :). Colon is the BASIC statement separator.
5D91
If the NZ FLAG has been set (the character is not a colon - it is a token or other character), JUMP to 5D96H to check for the sub-statement token.
5D93
RST 10H D7
Call CHRGET to advance past the colon and get the next character.
5D94
LOOP - skip colons
JUMP back to 5D8FH to check if the next character is another colon (multiple consecutive colons are allowed).
SUB-STATEMENT TOKEN CHECK
The character is not a colon. Synchronize on the 93H token (the SUB keyword token, used here as an internal statement delimiter), then scan past the remaining text until end-of-line.
5D96
RST 08H ⇒ 93H CF 93
Call the SYNCHR routine to verify the next character matches the BASIC token for SUB. If it does not match, a Syntax Error is generated. Otherwise, the SYNCHR routine verifies the current character is 93H and advances HL past it.
5D99
RET Z C8
If the Z FLAG has been set (end of line), RETurn.
5D9A
RST 10H D7
Call CHRGET to get the next character.
5D9B
LOOP - skip remaining text
JUMP back to 5D98H to test for end-of-line.
5D9DH - Error Code Jump Table (Data Table)
This is NOT executable code - it is a data table of error code entries using the classic Z80 "LD BC eats next byte" trick. Each 3-byte entry consists of: 01H (the opcode for LD BC,nnnn which is a 3-byte instruction that harmlessly "eats" the next 2 bytes), followed by 3EH xxH (the opcode for LD A,xxH which is the REAL entry point). SYS overlay files and internal code JP into this table at the 3EH byte (offset +1 from each 01H byte), which executes LD A,error and then falls through to the error handler at 5DE2H. The first entry at 5D9DH is special: it starts directly with 3EH 2AH (no preceding 01H) because it is the first entry and there is no prior LD BC to absorb.
Ira is not sure about this. The NEWDOS/80 v2.0 Manual has different errors than those listed. Perhaps this needs to be revisited once SYS13 has been processed.
ERROR CODE TABLE
Each entry is 3 bytes. The JP target address (shown in brackets) is the address of the 3EH byte within each entry. When jumped to, the Z80 executes LD A,error and then falls through the subsequent 01H bytes (which harmlessly execute as LD BC,nnnn) until reaching the handler at 5DE2H. Error codes are NEWDOS/80 extended error numbers.
5D9D
DEFB 3EH,2AH 3E 2A
[JP 5D9DH] → LD A,2AH - Error code 2AH (decimal 42): General error. First table entry, no preceding 01H byte.
5D9F
DEFB 01H,3EH,2EH 01 3E 2E
[JP 5DA0H] → LD A,2EH - Error code 2EH (decimal 46): Device not ready.
5DA2
DEFB 01H,3EH,64H 01 3E 64
[JP 5DA3H] → LD A,64H - Error code 64H (decimal 100): Bad file mode.
5DA5
DEFB 01H,3EH,68H 01 3E 68
[JP 5DA6H] → LD A,68H - Error code 68H (decimal 104): File already open.
5DA8
DEFB 01H,3EH,6CH 01 3E 6C
[JP 5DA9H] → LD A,6CH - Error code 6CH (decimal 108): File not open. This is a frequently-used entry, called by SYS10 and SYS20.
5DAB
DEFB 01H,3EH,6EH 01 3E 6E
[JP 5DACH] → LD A,6EH - Error code 6EH (decimal 110): Bad file number.
5DAE
DEFB 01H,3EH,7CH 01 3E 7C
[JP 5DAFH] → LD A,7CH - Error code 7CH (decimal 124): Input past end.
5DB1
DEFB 01H,3EH,7EH 01 3E 7E
[JP 5DB2H] → LD A,7EH - Error code 7EH (decimal 126): Bad record number.
5DB4
DEFB 01H,3EH,80H 01 3E 80
[JP 5DB5H] → LD A,80H - Error code 80H (decimal 128): File not found.
5DB7
DEFB 01H,3EH,84H 01 3E 84
[JP 5DB8H] → LD A,84H - Error code 84H (decimal 132): Bad file data.
5DBA
DEFB 01H,3EH,8CH 01 3E 8C
[JP 5DBBH] → LD A,8CH - Error code 8CH (decimal 140): Direct statement in file.
5DBD
DEFB 01H,3EH,8EH 01 3E 8E
[JP 5DBEH] → LD A,8EH - Error code 8EH (decimal 142): Too many files.
5DC0
DEFB 01H,3EH,90H 01 3E 90
[JP 5DC1H] → LD A,90H - Error code 90H (decimal 144): Disk full.
5DC3
DEFB 01H,3EH,92H 01 3E 92
[JP 5DC4H] → LD A,92H - Error code 92H (decimal 146): Input statement error.
5DC6
DEFB 01H,3EH,94H 01 3E 94
[JP 5DC7H] → LD A,94H - Error code 94H (decimal 148): Line too long.
5DC9
DEFB 01H,3EH,98H 01 3E 98
[JP 5DCAH] → LD A,98H - Error code 98H (decimal 152): FIELD overflow.
5DCC
DEFB 01H,3EH,9AH 01 3E 9A
[JP 5DCDH] → LD A,9AH - Error code 9AH (decimal 154): Internal error.
5DCF
DEFB 01H,3EH,9CH 01 3E 9C
[JP 5DD0H] → LD A,9CH - Error code 9CH (decimal 156): Bad file name.
5DD2
DEFB 01H,3EH,9EH 01 3E 9E
[JP 5DD3H] → LD A,9EH - Error code 9EH (decimal 158): Illegal direct (not allowed in direct mode).
5DD5
DEFB 01H,3EH,A2H 01 3E A2
[JP 5DD6H] → LD A,A2H - Error code A2H (decimal 162): Rename across disks.
5DD8
DEFB 01H,3EH,A4H 01 3E A4
[JP 5DD9H] → LD A,A4H - Error code A4H (decimal 164): Missing operand.
5DDB
DEFB 01H,3EH,A6H 01 3E A6
[JP 5DDCH] → LD A,A6H - Error code A6H (decimal 166): Undefined error code (last entry in the table).
5DDEH - Error Handler: ROM Error Dispatch
This is the alternate error handler entry point. Register A holds the error code. It copies A to E and then jumps to ROM 19A2H, the standard BASIC error handler which displays the error message and returns to READY. This entry is used by the error table fall-through (when falling past all table entries) and by the clear-and-error path at 5DEBH.
5DDE
LD E,A 5F
Load Register E with Register A (the error code). ROM 19A2H expects the error code in E.
5DDF
JUMP to ROM routine 19A2H, the standard BASIC error handler. This displays the error message corresponding to the code in E and returns to the BASIC READY prompt.
5DE2H - Error Handler: Store Error Code and Process
This is the main error handler entry point. All error table entries at 5D9DH-5DDBH fall through to this address after executing their LD A,error instruction. The error code in A is stored at 5DECH (a self-modifying code location within the LD A instruction at 5DEBH), then ROM routines 1AF8H and 1B59H are called for error processing (error line tracking, ON ERROR GOTO handling, etc.). After the ROM calls, the code clears A to 00H and jumps to 5DDEH to dispatch via ROM 19A2H. This is a PUBLIC entry point called by SYS11, SYS13, and other modules.
5DE2
LD (5DECH),A 32 EC 5D
SELF-MODIFYING CODE] - 5DECH is the immediate operand of the LD A instruction at 5DEBH. This saves the error code so it can be retrieved later after the ROM calls.
Store Register A (the error code) to memory location 5DECH.
5DE5
GOSUB to ROM routine 1AF8H for error processing. This routine handles error line number tracking and the first phase of ON ERROR GOTO dispatch.
5DE8
GOSUB to ROM routine 1B59H for additional error processing. This handles the second phase of error recovery (RESUME support, error flag management).
5DEB
LD A,00H 3E 00
SELF-MODIFYING CODE TARGET at 5DECH] - The immediate byte at 5DECH was overwritten at 5DE2H with the actual error code. When this instruction executes after the ROM calls return, A is loaded with the stored error code, not 00H.
Load Register A with 00H.
5DED
JUMP back to 5DDEH to copy A to E and dispatch to ROM 19A2H for the final error display.
5DEFH - DOS-to-BASIC Error Code Translator
This routine translates a DOS error code (received in Register A from an SVC call or DOS operation) to the corresponding BASIC error code. It OR's A with C0H to set the high bits (flagging it as a disk error), stores the result at 57E5H, then searches a lookup table at 5E0FH to find the matching BASIC error number. If no match is found in the table, a default error code of 72H is used. After translation, it checks the ON ERROR GOTO vector at 40F0H and either calls the error redirect at 57E4H (if ON ERROR GOTO is set) or falls through to 5DDFH (JP 19A2H). This is a PUBLIC entry point called by SYS19, SYS20, and SYS21.
5DEF
LD C,A 4F
Load Register C with Register A (the raw DOS error code). C preserves the original code for the table search.
5DF0
OR C0H F6 C0
OR Register A with C0H, setting bits 7 and 6. This flags the error code as a disk-related error (the high bits distinguish disk errors from BASIC errors in the error reporting system).
5DF2
LD (57E5H),A 32 E5 57
SELF-MODIFYING CODE] - 57E5H stores the disk error code for later retrieval by the error display routines.
Store Register A (the DOS error code with high bits set) to memory location 57E5H.
5DF5
LD HL,5E0FH 21 0F 5E
Load Register Pair HL with 5E0FH, pointing to the start of the DOS-to-BASIC error code translation table.
5DF8
LD E,72H 1E 72
Load Register E with 72H (decimal 114). This is the default BASIC error code used if no match is found in the lookup table.
TABLE SEARCH LOOP
The translation table at 5E0FH consists of pairs: [DOS_error] [BASIC_error], terminated by a 00H byte. Each iteration compares the DOS code in C against the table entry. If a match is found, the corresponding BASIC error code is loaded into E.
5DFA
LD A,(HL) 7E
LOOP START - search table
Load Register A with the byte at (HL) - the DOS error code entry from the table.
5DFB
CP C B9
Compare Register A (table DOS code) against Register C (the input DOS error code). Z FLAG set if they match.
5DFC
INC HL 23
INCrement HL to point to the BASIC error code that corresponds to this DOS code.
5DFD
If the NZ FLAG has been set (no match), JUMP to 5E00H to skip loading the BASIC code and continue to the next entry.
5DFF
LD E,(HL) 5E
MATCH FOUND
Load Register E with the BASIC error code from (HL). This replaces the default 72H with the matched translation.
5E00
INC HL 23
INCrement HL to point to the next table entry (or to the terminator byte).
5E01
LD A,(HL) 7E
Load Register A with the next byte from the table.
5E02
OR A B7
OR Register A with itself. Sets Z FLAG if the byte is 00H (end-of-table terminator).
5E03
LOOP - continue search
If the NZ FLAG has been set (not end of table), JUMP back to 5DFAH to check the next entry.
CHECK ON ERROR GOTO VECTOR
The table search is complete. E holds either the matched BASIC error code or the default 72H. Now check if an ON ERROR GOTO handler is active by examining the vector at 40F0H. If the vector is 0000H, no handler is installed.
5E05
LD HL,(40F0H) 2A F0 40
Load Register Pair HL with the value at 40F0H - the ON ERROR GOTO line number vector. If this is 0000H, no error handler is installed.
5E08
LD A,H 7C
Load Register A with Register H (high byte of the ON ERROR GOTO vector).
5E09
OR L B5
OR Register A with Register L. This sets the Z FLAG if HL is 0000H (no error handler installed).
5E0A
If the Z FLAG has been set (no ON ERROR GOTO handler is active), GOSUB to 57E4H. This routine at 57E4H handles the error display when no user error handler exists.
5E0D
JUMP back to 5DDFH (JP 19A2H) to dispatch the error through the ROM error handler with the translated error code in E.
5E0FH - DOS-to-BASIC Error Code Translation Table (Data)
This is the lookup table used by the DOS-to-BASIC error translator at 5DEFH. Each entry is a 2-byte pair: [DOS_error] [BASIC_error]. The table is terminated by a 00H byte. The disassembler has misinterpreted these data bytes as Z80 instructions; they should be read as byte pairs. Note: the table at 5E0FH appears to continue through approximately 5E33H based on the pattern of data bytes.
5E0F
DEFB 0FH,88H 0F 88
DOS error 0FH → BASIC error 88H (decimal 136): FIELD error.
5E11
DEFB 13H,80H 13 80
DOS error 13H → BASIC error 80H (decimal 128): File not found.
5E13
DEFB 18H,6AH 18 6A
DOS error 18H → BASIC error 6AH (decimal 106): Direct statement in file.
5E15
DEFB 19H,8AH 19 8A
DOS error 19H → BASIC error 8AH (decimal 138): File access denied.
5E17
DEFB 1AH,86H 1A 86
DOS error 1AH → BASIC error 86H (decimal 134): Bad record number.
5E19
DEFB 1BH,7AH 1B 7A
DOS error 1BH → BASIC error 7AH (decimal 122): File not open.
5E1B
DEFB 1CH,7CH 1C 7C
DOS error 1CH → BASIC error 7CH (decimal 124): Input past end.
5E1D
DEFB 1DH,7CH 1D 7C
DOS error 1DH → BASIC error 7CH (decimal 124): Input past end (same BASIC code as 1CH).
5E1F
DEFB 1EH,7AH 1E 7A
DOS error 1EH → BASIC error 7AH (decimal 122): File not open (Internal mapping).
5E21
DEFB 1FH,66H 1F 66
DOS error 1FH → BASIC error 66H (decimal 102): Disk I/O error.
5E23
DEFB 20H,80H 20 80
DOS error 20H → BASIC error 80H (decimal 128): File not found.
5E25
DEFB 21H,66H 21 66
DOS error 21H → BASIC error 66H (decimal 102): Disk I/O error.
5E27
DEFB 22H,66H 22 66
DOS error 22H → BASIC error 66H (decimal 102): Disk I/O error (e.g., CRC error).
5E29
DEFB 23H,66H 23 66
DOS error 23H → BASIC error 66H (decimal 102): Disk I/O error (e.g., Seek error).
5E2B
DEFB 24H,66H 24 66
DOS error 24H → BASIC error 66H (decimal 102): Disk I/O error (e.g., Data timeout).
5E2D
DEFB 25H,8AH 25 8A
DOS error 25H → BASIC error 8AH (decimal 138): File access denied (Write protected).
5E2F
DEFB 26H,66H 26 66
DOS error 26H → BASIC error 66H (decimal 102): Disk I/O error.
5E31
DEFB 30H,80H 30 80
DOS error 30H → BASIC error 80H (decimal 128): File not found.
5E34H - Unused Padding (NOP Fill Area, 9 Bytes)
Nine bytes of 00H (NOP) fill. This is unused reserved space between the error translation table and the next routine at 5E3CH. The continuation instructions identify this as one of the NOP fill areas in BASIC/CMD.
5E34
DEFB 00H,00H,00H,00H,00H,00H,00H,00H,00H 00 00 00 00 00 00 00 00 00
Nine bytes of 00H - unused padding / reserved space (5E34H–5E3BH). No code references this area.
5E3CH - FIELD Statement Handler (Disk BASIC Extension)
This routine handles the FIELD statement, which defines the layout of fields within a random access file buffer. It is reached via the jump table entry at 67E5H (JP 5E3CH). On entry, HL points to the BASIC text after the FIELD keyword. The routine calls 5F53H to parse the file number (prefixed by #), validates the FCB status flags (checking bits 7 and 0-1 for proper file mode), then enters a loop that parses comma-separated field width/variable pairs. Each pair consists of a numeric width followed by "AS" and a string variable name. The field width and variable descriptor are stored into the FCB's field definition area. The routine uses self-modifying error exits via JP to the error table at 5DA3H and 5DA9H.
5E3C
GOSUB to 5F53H to parse the file number from the BASIC text. This routine expects an optional "#" prefix, evaluates the file number expression, validates the file number range (1 to max files), and returns with BC pointing to the FCB for the specified file. Register A holds the FCB status flags.
5E3F
If the Z FLAG has been set (the FCB status byte from 5F53H indicates the file is not currently open - status byte is zero), JUMP forward to 5E48H to skip the mode validation and proceed directly to field setup.
VALIDATE FILE MODE
The file is open. Check that it is open in a compatible mode for FIELD operations. The status byte in A is tested: XOR with 80H flips bit 7, then AND with 83H isolates bits 7, 1, and 0. For FIELD to be valid, specific bit combinations must be present.
5E41
XOR 80H EE 80
XOR Register A with 80H, flipping bit 7 of the FCB status byte. This inverts the "file open" flag.
5E43
AND 83H E6 83
AND Register A with 83H (binary: 10000011), isolating bits 7, 1, and 0. After the XOR, if the file was properly open (bit 7 was set) and in a valid mode (bits 0-1), the result is tested for zero.
5E45
ERROR - invalid file mode for FIELD
If the NZ FLAG has been set (the file mode is invalid for FIELD operations), JUMP to error table entry 5DA9H which loads error code 6CH (File not open / bad file mode).
INITIALIZE FIELD OFFSET
Set up the field buffer offset. DE is loaded with 002DH (decimal 45), which is the offset from the FCB base to the start of the record buffer area within the FCB structure. BC holds the FCB base address from 5F53H.
5E48
LD DE,002DH 11 2D 00
Load Register Pair DE with 002DH (decimal 45). This is the offset to the record buffer area within the FCB. The FCB header occupies bytes 00H-2CH; the actual data buffer starts at offset 2DH.
5E4B
EX DE,HL EB
EXchange DE and HL. HL now holds the buffer offset (002DH), DE holds the BASIC text pointer.
5E4C
ADD HL,BC 09
ADD BC (the FCB base address) to HL (the buffer offset). HL now points to the start of the record buffer within the FCB (FCB_base + 2DH).
5E4D
EX DE,HL EB
EXchange DE and HL. DE now holds the record buffer address, HL holds the BASIC text pointer.
5E4E
LD B,A 47
Load Register B with Register A (the validated status flags, or 0 if file was not open). B is used as a running total of field widths already assigned.
5E4F
LD A,2CH 3E 2C
Load Register A with 2CH (ASCII: comma). Prepare to check if a comma precedes the next field definition.
5E51
CP (HL) BE
Compare Register A (comma) against the byte at (HL) (the current BASIC text character). Z FLAG set if there is a comma (another field definition follows).
5E52
RET NZ C0
END OF FIELD LIST
If the NZ FLAG has been set (no comma - no more field definitions), RETurn. The FIELD statement is complete.
PARSE FIELD WIDTH AND VARIABLE NAME
A comma was found. Parse the next field definition: a numeric width expression, the keyword "AS", and a string variable name. The width is evaluated by ROM 2B1BH, the "AS" keyword (token 41H then 53H) is verified by RST 08H, and 5E7BH evaluates the variable reference.
5E53
PUSH DE D5
Save DE (the current buffer position within the FCB record area) onto the stack.
5E54
PUSH BC C5
Save BC (B=running total of field widths, C=preserved) onto the stack.
5E55
GOSUB to ROM routine 2B1BH to evaluate a numeric expression and return the result as an 8-bit unsigned value in Register A. This is the field width (number of bytes this field occupies in the record buffer).
5E58
PUSH AF F5
Save the field width (A) and flags onto the stack.
5E59
RST 08H ⇒ 41H CF 41/span>
Call the SYNCHR routine to verify the next character matches ASCII A - the first character of the "AS" keyword. (In tokenized BASIC, "AS" is stored as two separate characters, not a single token.)
5E5B
RST 08H ⇒ 53H CF 53
Call SYNCHR again for ASCII S - the second character of "AS".
5E5D
GOSUB to 5E7BH to evaluate the string variable reference following "AS". This calls ROM 260DH to locate/create the variable, then ROM 0AF4H to convert the result. On return, the variable's VARPTR is available for the field assignment.
5E60
POP AF F1
Restore the field width from the stack into Register A.
5E61
POP BC C1
Restore BC from the stack (B=running total of field widths assigned so far).
5E62
LD C,A 4F
Load Register C with Register A (the current field width).
5E63
ADD A,B 80
ADD Register B (running total) to Register A (current field width). A now holds the cumulative total of all field widths.
5E64
If the NO CARRY FLAG has been set (the total has not overflowed 255 - valid), JUMP to 5E68H to store the field definition.
5E66
ERROR - FIELD overflow
If the NZ FLAG has been set (overflow occurred AND the result is nonzero - the total exceeds 255 bytes), JUMP to 5E78H which dispatches to error 5DA3H (error code 64H: Bad file mode / FIELD overflow).
STORE FIELD DEFINITION
Store the 3-byte field descriptor (width, variable address low, variable address high) into the FCB's field definition area at the current buffer position (DE from stack).
5E68
EX (SP),HL E3
EXchange HL with the top of stack. HL gets the buffer position (saved DE from 5E53H), and the BASIC text pointer goes onto the stack.
5E69
EX DE,HL EB
EXchange DE and HL. HL now holds the buffer position within the FCB record area.
5E6A
LD (HL),C 71
Store Register C (the field width) as the first byte of the field descriptor at (HL).
5E6B
INC HL 23
INCrement HL to the second byte of the descriptor.
5E6C
LD (HL),E 73
Store Register E (low byte of the variable address) as the second byte.
5E6D
INC HL 23
INCrement HL to the third byte.
5E6E
LD (HL),D 72
Store Register D (high byte of the variable address) as the third byte.
5E6F
POP HL E1
Restore HL (the BASIC text pointer) from the stack.
5E70
LD B,00H 06 00
Load Register B with 00H, resetting the field width running total for the overflow check calculation. (The cumulative total is already validated; B is reset for the next iteration's ADD A,B.)
5E72
LOOP - next field
If the NO CARRY FLAG is set (no overflow), JUMP back to 5E4BH to check for another comma and process the next field definition.
CHECK FOR TRAILING COMMA
If carry was set (edge case from the ADD), check if there is a trailing comma. If no comma, return normally. If comma present, it is an error (field overflow).
5E74
LD A,(HL) 7E
Load Register A with the current BASIC text character at (HL).
5E75
CP 2CH FE 2C
Compare Register A against 2CH (ASCII: comma). Z FLAG set if there are more field definitions.
5E77
RET NZ C0
If the NZ FLAG has been set (no more commas - FIELD statement is complete), RETurn normally.
5E78
ERROR - FIELD overflow or bad mode
JUMP to error table entry 5DA3H which loads error code 64H (Bad file mode / FIELD overflow).
5E7BH - Variable Reference Evaluator (String Variable for FIELD)
This routine evaluates a variable reference in the BASIC text and converts it to a usable form. It calls ROM 260DH (the variable reference evaluator, which locates or creates the variable and returns its VARPTR in DE), then jumps to ROM 0AF4H to convert the numeric result to ASCII. This is called from the FIELD handler at 5E5DH and from the LSET/RSET handler at 58E4H.
5E7B
GOSUB to ROM routine 260DH to evaluate the variable reference at the current BASIC text position. On return, DE points to the variable's VARPTR (the address of the variable's value storage), and HL points past the variable name in the BASIC text.
5E7E
JUMP to ROM routine 0AF4H to convert the numeric value to its ASCII string representation. Returns to the original caller via the return address on the stack.
5E81H - Hash/Channel Prefix Checker for PRINT/INPUT
This routine checks if the current BASIC text character is a "#" (23H), indicating a file channel number prefix for PRINT# or INPUT# statements. If "#" is found, it peeks ahead to check for the USING token (CEH) - if USING follows, the "#" is part of a PRINT# USING construct and is handled differently. If "#" without USING, it calls 5F36H to set up the file channel and jumps to ROM 21C3H for PRINT# processing. If the character is not "#", it returns immediately. This is a jump table target reached via 683FH (JP 5E81H).
5E81
CP 23H FE 23
Compare Register A against 23H (ASCII: #). Z FLAG set if the character is "#".
5E83
RET NZ C0
If the NZ FLAG has been set (the character is not "#"), RETurn. No file channel prefix is present; this is a regular PRINT statement.
5E84
PUSH HL E5
Save HL (the current BASIC text pointer, pointing to the "#") onto the stack.
5E85
RST 10H D7
Call CHRGET to advance past the "#" and get the next non-space character into Register A.
5E86
CP CEH FE CE
Compare Register A against CEH - the BASIC token for the USING keyword. If USING follows "#", this is a PRINT# USING statement.
5E88
POP HL E1
Restore HL (the text pointer back to the "#" position) from the stack.
5E89
LD A,(HL) 7E
Re-load Register A with the character at (HL), which is the "#" character (23H).
5E8A
RET Z C8
If the Z FLAG has been set (the character after "#" was the USING token), RETurn. The caller will handle PRINT# USING via the standard path.
PRINT# WITHOUT USING
The "#" is followed by a file number, not USING. Call 5F36H to parse the file number with channel setup (C=20H flag), then jump to ROM 21C3H for PRINT# output routing.
5E8B
GOSUB to 5F36H to parse the file number with the channel flag C=20H, set up the FCB for output, and prepare the file channel for PRINT# output.
5E8E
EX (SP),HL E3
EXchange HL with the top of stack. This replaces the return address on the stack with the current BASIC text pointer, effectively redirecting the return to the ROM PRINT handler.
5E8F
JUMP to ROM routine 21C3H, the PRINT# output handler. This processes the remainder of the PRINT# statement, outputting data to the file channel established by 5F36H.
5E92H - LINE INPUT# Statement Handler
This routine handles the LINE INPUT# statement, which reads an entire line from a file into a string variable. It calls 6382H to set up the file for input, pops the return address adjustment, then checks the result code and dispatches to ROM 2B4AH (if result is "+") or ROM 2282H (otherwise) for the actual line input processing. Reached via jump table entry 6848H (JP 5E92H).
5E92
GOSUB to 6382H to set up the file for input. This routine parses the file number, validates the file is open for input, and prepares the I/O channel.
5E95
POP AF F1
POP AF from the stack, discarding the return address adjustment (or restoring flags from the caller).
5E96
CP 2BH FE 2B
Compare Register A against 2BH (ASCII: +). This tests a flag or character returned from the file setup.
5E98
If the Z FLAG has been set (the result character was "+"), JUMP to ROM routine 2B4AH to process the line input with the "+" mode (append/continuation mode).
5E9B
JUMP to ROM routine 2282H for standard line input processing (read until CR/LF).
5E9EH - PRINT# TAB Handler (B=01H)
Short entry point that sets B=01H (indicating TAB function in PRINT# context) and jumps to 5EBFH for processing. Reached via jump table entry 67CAH.
5E9E
LD B,01H 06 01
Load Register B with 01H, indicating the TAB function mode for PRINT# formatting.
5EA0
JUMP forward to 5EBFH to execute the common PRINT# formatting handler.
5EA2H - PRINT# SPC Handler (B=02H)
Short entry point that sets B=02H (indicating SPC function in PRINT# context) and jumps to 5EBFH for processing. Reached via jump table entry 67D0H.
5EA2
LD B,02H 06 02
Load Register B with 02H, indicating the SPC function mode for PRINT# formatting.
5EA4
JUMP forward to 5EBFH to execute the common PRINT# formatting handler.
5EA6H - PRINT# USING Format String Scanner
This routine handles the PRINT# USING statement by scanning the format string for special formatting characters. It pushes a return address (E123H) onto the stack, then enters a loop that reads format characters from the format string at (DE), comparing each against a template at 5EA6H (the "$%" pattern). Register B tracks state via bit rotation (RRC B), and C counts characters. When the format pattern is matched or exhausted, it falls through to 5EBFH for the common formatting handler. Reached via jump table entry 67CDH (JP 5EAAH, which enters at the LD DE,5EA6H instruction).
5EA6
DEFB 24H,25H 24 25
Data bytes: 24H ($) and 25H (%). These are the format pattern characters that this scanner looks for in PRINT# USING format strings. They are embedded in the code and referenced by DE=5EA6H below.
5EA8
LD HL,E123H 21 23 E1
Load Register Pair HL with E123H. This is a constructed address: the bytes 23H E1H decode as "INC HL / POP HL" when executed as a return sequence, but here it is loaded as a return address value.
5EAB
EX (SP),HL E3
EXchange HL with the top of the stack. This pushes the E123H return address onto the stack and retrieves the previous return address into HL.
5EACH
LD DE,5EA6H 11 A6 5E
Load Register Pair DE with 5EA6H, pointing to the "$%" format pattern data above.
5EAFH
LD BC,8005H 01 05 80
Load Register Pair BC with 8005H. B=80H (initial bit rotation state with bit 7 set), C=05H (character count / match counter).
FORMAT PATTERN MATCHING LOOP
This loop rotates B right to cycle through matching states, decrements C, and compares characters from the format string against the pattern at (DE). When a match is found, CHRGET advances past it. When C reaches zero or a mismatch occurs, the loop exits.
5EB2
RRC B CB 08
LOOP START - pattern match
Rotate Register B right through carry. This cycles the bit pattern in B, used as a state tracker for the format matching.
5EB4
DEC C 0D
DECrement Register C (the match counter) by 1.
5EB5
If the Z FLAG has been set (C reached zero - pattern scan exhausted), JUMP to 5EBDH to exit the loop.
5EB7
LD A,(DE) 1A
Load Register A with the byte at (DE) - the next character from the format pattern.
5EB8
CP (HL) BE
Compare Register A (pattern character) against (HL) (the current BASIC text character).
5EB9
INC DE 13
INCrement DE to point to the next pattern character.
5EBA
LOOP - no match, continue
If the NZ FLAG has been set (no match), JUMP back to 5EB2H to rotate B and try the next position.
5EBC
RST 10H D7
Call CHRGET to advance past the matched format character in the BASIC text.
5EBD
EX (SP),HL E3
EXchange HL with the top of stack, swapping the BASIC text pointer with the return address.
5EBE
PUSH HL E5
Save the return address back onto the stack.
5EBFH - Common PRINT# Formatting Handler
This is the common handler for PRINT# TAB, SPC, and USING formatting. It calls 5FC9H (a file position/width calculator), tests the mode in B, and conditionally calls 6634H (if B has bits 1-2 set) and 5EE1H (the 24-bit multiply for position calculation). It then converts the result to a BASIC numeric value by calling ROM 0AEFH, setting up the accumulator at 4124H-4125H with values 98H and 80H, calling ROM 0765H for normalization, and jumping to 6357H for final output.
5EBF
GOSUB to 5FC9H to calculate the file output position or width. On return, registers hold position data needed for the formatting calculation.
5EC2
LD A,B 78
Load Register A with Register B (the formatting mode: 01H=TAB, 02H=SPC, other=USING).
5EC3
AND 06H E6 06
AND Register A with 06H, isolating bits 1 and 2. For TAB (B=01H), result is 0. For SPC (B=02H), result is 02H (nonzero).
5EC5
If the NZ FLAG has been set (SPC or USING mode), GOSUB to 6634H to perform additional width/position adjustments.
5EC8
If the NZ FLAG is still set after the previous call (SPC or USING mode), GOSUB to 5EE1H to perform the 24-bit multiply/position calculation.
5ECB
GOSUB to ROM routine 0AEFH to convert the position/width value to the BASIC numeric format in the accumulator.
Set up Floating Point Representation
Store the exponent and sign bytes at 4124H-4125H to complete the single-precision floating-point representation of the position value. 98H is the exponent (representing 2^24), 80H is the sign/mantissa MSB.
5ECE
LD E,C 59
Load Register E with Register C.
5ECF
LD C,H 4C
Load Register C with Register H.
5ED0
LD D,L 55
Load Register D with Register L.
5ED1
LD B,00H 06 00
Load Register B with 00H.
5ED3
LD HL,4124H 21 24 41
Load Register Pair HL with 4124H, pointing to the BASIC accumulator exponent byte.
5ED6
LD (HL),98H 36 98
Store 98H at 4124H. This is the floating-point exponent byte representing 2^24 (the value is a 24-bit integer scaled to single-precision format).
5ED8
INC HL 23
INCrement HL to 4125H (the sign/MSB byte of the accumulator).
5ED9
LD (HL),80H 36 80
Store 80H at 4125H. Bit 7 set indicates a positive value with the MSB of the mantissa set.
5EDB
GOSUB to ROM routine 0765H to normalize the floating-point value in the accumulator. This adjusts the exponent and mantissa to standard form.
5EDE
JUMP to 6357H for final PRINT# output processing. This completes the formatting operation and outputs the result to the file.
5EE1H - 24-Bit Multiply (DE:HL = A × BC, 24-Bit Precision)
This routine performs a 24-bit precision multiply of an 8-bit value by a 16-bit value. On entry, A holds the multiplier and 5702H holds the multiplicand (read into BC). The result is returned as a 24-bit value in DE:A (DE=high 16 bits, A=low 8 bits), with C holding a position count. The algorithm uses 24 iterations of shift-and-subtract, using the AF' (alternate accumulator) register pair as a loop counter. This routine is called from 5EC8H for PRINT# position calculations.
5EE1
EX DE,HL EB
EXchange DE and HL. Move the input value from DE to HL for the division/multiply setup.
5EE2
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H, initializing the high word of the result accumulator to zero.
5EE5
LD A,C 79
Load Register A with Register C (saving the original C value before BC is overwritten).
5EE6
LD BC,(5702H) ED 4B 02 57
Load Register Pair BC with the 16-bit value at memory location 5702H. This is the multiplicand (the record size or field width stored at 5702H during file setup).
5EEA
EX AF,AF' 08
EXchange AF with the alternate AF' register pair. This saves the current A (the original C value) into AF'.
5EEB
LD A,18H 3E 18
Load Register A with 18H (decimal 24). A serves as the loop counter for 24 iterations.
5EED
EX AF,AF' 08
EXchange AF with AF'. The loop counter (18H) is stored in AF', and A is restored to the original C value.
24-Bit Shift and Subtract Loop
Each iteration shifts the 24-bit dividend (A:DE) left by one bit, with overflow going into HL. If the shifted value in HL is greater than or equal to BC (the divisor/multiplicand), BC is subtracted from HL and bit 0 of A is set. After 24 iterations, DE:A holds the quotient.
5EEE
ADD A,A 87
LOOP START - 24-bit operation
ADD Register A to itself (left shift A by 1 bit). The MSB of A goes into the CARRY FLAG.
5EEF
EX DE,HL EB
EXchange DE and HL. Swap the low word (DE) into HL for the ADC operation.
5EF0
ADC HL,HL ED 6A
ADD HL to itself with carry (left shift the low word, incorporating the carry from the A shift).
5EF2
EX DE,HL EB
EXchange DE and HL. Swap back so DE=low word, HL=high word.
5EF3
ADC HL,HL ED 6A
ADD HL to itself with carry (left shift the high word, incorporating the carry from the low word shift).
5EF5
If the CARRY FLAG has been set (overflow from the HL shift - the value in HL exceeds 16 bits), JUMP to 5EFDH to subtract unconditionally.
5EF7
OR A B7
Clear the CARRY FLAG for the SBC instruction.
5EF8
SBC HL,BC ED 42
SUBtract BC (multiplicand) from HL (high accumulator) with borrow. This is a trial subtraction to see if the dividend portion is large enough.
5EFA
ADD HL,BC 09
ADD BC back to HL, undoing the subtraction. If the SBC set carry (HL was less than BC), the trial subtraction failed.
5EFB
If the CARRY FLAG has been set (HL < BC - trial subtraction was invalid), JUMP to 5F01H to skip the actual subtraction.
5EFD
OR A B7
Clear the CARRY FLAG.
5EFE
SBC HL,BC ED 42
SUBtract BC from HL permanently. The trial subtraction succeeded, so the quotient bit is 1.
5F00
INC A 3C
INCrement Register A by 1. This sets bit 0 of A, recording a quotient bit of 1 (since A was just shifted left, bit 0 was 0).
5F01
EX AF,AF' 08
EXchange AF with AF'. Retrieve the loop counter from AF'.
5F02
DEC A 3D
DECrement Register A (the loop counter) by 1.
5F03
LOOP - continue 24-bit operation
If the NZ FLAG has been set (loop counter has not reached zero - more iterations remain), JUMP back to 5EEDH.
5F05
EX AF,AF' 08
EXchange AF with AF'. Retrieve the final A value (the low 8 bits of the result) from AF'.
Check for Remainder and Overflow
After 24 iterations, DE:A holds the quotient and HL holds the remainder. Check if there is a remainder (DE nonzero); if so, increment C. If C overflows to zero, increment HL. If HL overflows to zero, jump to error 5DB2H (Bad record number).
5F06
EX DE,HL EB
EXchange DE and HL. DE=remainder, HL=low word of quotient.
5F07
LD C,A 4F
Load Register C with Register A (the low 8 bits of the result).
5F08
LD A,D 7A
Load Register A with Register D (high byte of the remainder).
5F09
OR E B3
OR Register A with Register E (low byte of remainder). Z FLAG set if the remainder is zero (exact division).
5F0A
RET Z C8
If the Z FLAG has been set (no remainder - exact result), RETurn. C holds the low byte, HL holds the high word.
5F0B
INC C 0C
INCrement Register C by 1 (round up the result due to nonzero remainder).
5F0C
RET NZ C0
If the NZ FLAG has been set (C did not overflow to zero), RETurn with the rounded-up result.
5F0D
INC HL 23
INCrement HL by 1 (C overflowed from FFH to 00H, so carry the increment to the high word).
5F0E
LD A,H 7C
Load Register A with Register H.
5F0F
OR L B5
OR Register A with Register L. Z FLAG set if HL overflowed to 0000H (result exceeds 24-bit range).
5F10
RET NZ C0
If the NZ FLAG has been set (no overflow), RETurn with the valid result.
5F11
ERROR - record number overflow
JUMP to error table entry 5DB2H which loads error code 7EH (Bad record number). The 24-bit result overflowed, indicating the record position is too large.
5F14H - PRINT Statement Dispatcher (Jump Table Target from 683CH)
This routine is the PRINT statement entry point, called via the jump table at 683CH (JP 5F14H). It sets up the file channel by calling 6382H (which evaluates the file number and loads the FCB pointer into IX), then decides whether to route to the ROM PRINT position handler at 2130H or the standard PRINT handler at 2156H based on whether the BASIC text pointer (L register) indicates a position parameter (ASCII digit < 30H).
5F14
GOSUB to 6382H to evaluate the file number from the BASIC text, set up IX to point to the FCB for the specified file, and push the file status flags onto the stack. On return, IX points to the active FCB and the caller's HL (BASIC text pointer) has been pushed onto the stack.
5F17
POP HL E1
Restore Register Pair HL from the stack. HL now holds the BASIC text pointer, positioned after the file number expression that was parsed by 6382H.
5F18
LD A,L 7D
Load Register A with Register L (the low byte of the BASIC text pointer address). This is used as a quick check to determine the type of PRINT operation requested.
5F19
CP 30H FE 30
Compare Register A against 30H (ASCII '0'). If the low byte of the BASIC text pointer is less than 30H, the CARRY FLAG is set, indicating a position parameter follows (e.g., PRINT#n, expression). If 30H or above, the NO CARRY FLAG is set.
5F1B
LD A,(570AH) 3A 0A 57
Load Register A with the value stored at 570AH (the current print column position counter within the FCB work area). This column position is used by the ROM print routines to manage cursor positioning within the file output line.
5F1E
If the CARRY FLAG is set (the BASIC text pointer low byte is less than 30H, indicating a print position parameter), JUMP to ROM 2130H - the PRINT position handler, which processes TAB, SPC, and comma formatting within the output line.
5F21
Unconditional JUMP to ROM 2156H - the standard PRINT expression handler. This routine evaluates and outputs the PRINT expression list to the file channel established by the earlier call to 6382H.
5F24H - INPUT Statement Dispatcher (Jump Table Target from 6836H)
This routine is the INPUT statement entry point for file I/O, called via the jump table at 6836H (JP 5F24H). It sets up the file channel, restores the BASIC text pointer, and jumps to the ROM INPUT handler at 20E9H.
5F24
GOSUB to 6382H to evaluate the file number, set up IX to point to the FCB, and push file status flags onto the stack.
5F27
POP HL E1
Restore Register Pair HL from the stack. HL now holds the BASIC text pointer, positioned after the file number in the INPUT# statement.
5F28
Unconditional JUMP to ROM 20E9H - the INPUT handler. This ROM routine reads data from the file channel set up by 6382H and assigns values to the variables listed in the INPUT# statement.
5F2BH - USING Token Checker (Jump Table Target from 6833H)
This routine is called via the jump table at 6833H (JP 5F2BH). It checks whether the current BASIC token is the USING keyword (token CEH). If USING is present, it returns with Z set and A holding the current byte at (HL). If not, it loads C with 40H (a flag indicating standard PRINT mode) and falls through to 5F38H to check for the '#' prefix. Entry from 5F36H (called from 5E8BH) loads C=20H instead, indicating PRINT# mode.
5F2B
PUSH HL E5
Save Register Pair HL (BASIC text pointer) onto the stack, preserving the current parse position before lookahead.
5F2C
RST 10H D7
Call CHRGET via RST 10H. This advances the BASIC text pointer and returns the next non-space character in Register A, setting flags (Z if end-of-statement, C if numeric digit).
5F2D
CP CEH FE CE
Compare Register A against CEH - the BASIC token code for the USING keyword. If Register A equals CEH, the Z FLAG is set (USING keyword found).
5F2F
POP HL E1
Restore Register Pair HL from the stack (original BASIC text pointer position, before the lookahead).
5F30
LD A,(HL) 7E
Load Register A with the byte at the current BASIC text pointer position (HL). This reloads the current character so the caller can inspect it.
5F31
RET Z C8
If the Z FLAG is set (the next token was USING at CEH), RETURN to the caller with Z set to signal that PRINT USING mode is active.
Standard PRINT Mode Entry
If USING was not found, the routine falls through to set up a mode flag in Register C. The value 40H indicates that this is a standard PRINT statement (not PRINT#), while entry at 5F36H sets C=20H for PRINT# file output mode.
5F32
LD C,40H 0E 40
Load Register C with 40H - a flag value indicating standard PRINT mode (console output). This flag is tested later at 5F45H (AND C) to determine the output destination.
5F34
JUMP forward to 5F38H to check whether the '#' file channel prefix follows, skipping the alternate C=20H entry.
5F36H - PRINT# Channel Setup (Called from 5E8BH)
Alternate entry point for setting up a PRINT# file output channel. Sets C=20H to indicate PRINT# mode, then falls through to 5F38H. Called from 5E8BH (the hash/channel prefix checker) with the file access mode already partially validated.
5F36
LD C,20H 0E 20
Load Register C with 20H - a flag value indicating PRINT# file output mode (as opposed to 40H for console PRINT). This flag is later ANDed with the FCB status byte at 5F45H.
Common '#' Check
Both the standard PRINT entry (5F32H, C=40H) and the PRINT# entry (5F36H, C=20H) converge here. The routine checks whether the current character is '#' (23H), indicating a file channel number follows. If not '#', this is a syntax error and the routine returns NZ.
5F38
CP 23H FE 23
Compare Register A (the current character at the BASIC text pointer, loaded at 5F30H) against 23H (ASCII '#'). If the character is '#', the Z FLAG is set.
5F3A
RET NZ C0
If the NZ FLAG is set (the character is not '#'), RETURN to the caller. This indicates no file channel was specified, so the caller should handle console I/O instead.
File Channel Validation
A '#' prefix was found. The routine now evaluates the file number, validates the file is open, checks that the file access mode is compatible with the requested operation (PRINT requires output mode), and sets up the file position pointers.
5F3B
PUSH BC C5
Save Register Pair BC onto the stack, preserving the mode flag in Register C (20H or 40H) across the file evaluation call.
5F3C
PUBLIC - called by SYS20
GOSUB to 62C0H to evaluate the file number from the BASIC text and retrieve the FCB status byte. On return, Register A holds the FCB status flags byte (from offset 00H of the FCB), HL points into the FCB, and IX points to the FCB base.
5F3F
BIT 7,A CB 7F
Test bit 7 of Register A (the FCB status byte). Bit 7 set indicates the file is in an error state or has a special condition that prevents normal I/O operations.
5F41
POP BC C1
Restore Register Pair BC from the stack, recovering the mode flag in Register C (20H for PRINT# or 40H for standard PRINT).
5F42
If bit 7 was set (NZ - file error/special condition), JUMP to 5DA9H - the error code entry point that loads A with error code 6CH (file not in correct mode) and dispatches to the error handler.
5F45
AND C A1
AND Register A (FCB status byte) with Register C (mode flag: 20H for PRINT# or 40H for PRINT). This tests whether the FCB has the required output mode bit set. If the AND result is zero, the file is not open in the required mode.
5F46
PUSH HL E5
Save Register Pair HL (pointing into the FCB) onto the stack.
5F47
LD A,(HL) 7E
Load Register A with the byte at the current HL position within the FCB. This reads a secondary status or mode byte that indicates whether the file is actively open for I/O.
5F48
If the Z FLAG is set (the mode byte is zero - the file is not open or the required mode bit was not set), JUMP to 5DA9H for error code 6CH (file mode error).
5F4B
GOSUB to 61ACH to load the current file position into Register C (sector offset from IX+12H) and Register Pair HL (position word from 5717H). This retrieves the current read/write pointer for the file.
5F4E
PUBLIC - called by SYS10
GOSUB to 6117H to store the current position (C and HL) as the alternate file position. This saves C into IX+07H and HL into 5708H, and sets bit 6 of IX+01H to mark the alternate position as valid.
5F51
POP HL E1
Restore Register Pair HL from the stack (FCB pointer).
5F52
RET C9
RETURN to the caller. The file channel is now set up: IX points to the FCB, the file position has been saved, and the caller can proceed with file I/O through the ROM routines.
5F53H - File Number Parser (Called from 5F7CH, 5E3CH, 6295H)
This routine parses a file number from the BASIC text, validates that it is within the valid file number range, and calculates the FCB address for the specified file. It optionally skips a leading '#' prefix if present, evaluates a string expression for the file number, converts it to an integer, then computes BC = base_address + (file_number × FCB_size). The FCB size is stored at 649EH and the base address is at 66BEH (the program entry point, which also serves as the FCB area base during BASIC operation).
5F53
DEC HL 2B
DECrement Register Pair HL by 1. This backs up the BASIC text pointer by one byte so that the subsequent RST 10H (CHRGET) will re-read the current character. This is a standard technique to "un-get" the current character before calling CHRGET.
5F54
RST 10H D7
Call CHRGET via RST 10H. Advance the BASIC text pointer and return the next non-space character in Register A. Sets Z if end-of-statement (colon or zero), C if numeric digit.
5F55
CP 23H FE 23
Compare Register A against 23H (ASCII '#'). This checks whether the file number expression is preceded by a '#' prefix, as in INPUT #1 or PRINT #2.
5F57
If the Z FLAG is set (a '#' was found), GOSUB to ROM 1D78H - the CHRGET internal entry point - to advance past the '#' character. This skips the optional '#' prefix so the file number expression can be evaluated.
5F5A
GOSUB to ROM 2337H - the string expression evaluator. This evaluates the file number expression (which can be a variable, constant, or expression) and returns the result as a string value ready for numeric conversion.
5F5D
GOSUB to ROM 2B1FH to convert the expression result to an 8-bit unsigned integer. On return, Register A holds the file number (1-based).
5F60
DEC A 3D
DECrement Register A by 1, converting the file number from 1-based (user-facing) to 0-based (internal index). File #1 becomes index 0, file #2 becomes index 1, etc.
5F61
CP 00H FE 00
. Note: The self-modifying code at 5F62H is written by 6504H, which stores the maximum file count here, so the 00H is actually a runtime variable.
Compare Register A against 00H. This is an entry point at 5F61H (called from 5FABH). After the DEC, if A was originally 0 (invalid file number 0), A is now FFH and the comparison sets the NO CARRY FLAG. A valid 0-based file index (0 or higher) sets the CARRY FLAG if A is less than the maximum.
Self-Modifying Code at 5F62H
The immediate operand at address 5F62H (the 00H in CP 00H) is written at runtime by code at 6504H, which stores the actual maximum file count configured during initialization. At runtime, this instruction compares Register A against the maximum valid file index, not against 00H.
5F63
If the NO CARRY FLAG is set (Register A is equal to or greater than the maximum file count - the file number is out of range), JUMP to 5DA6H - the error entry point that loads error code 68H (Bad File Number) and dispatches to the error handler.
FCB Address Calculation
The file number is valid. Now calculate the FCB address: BC = 66BEH + (file_index × FCB_size). The FCB size (012DH = 301 bytes) is stored at 649EH (written during initialization by 6711H). The base address 66BEH is the program entry point, which during BASIC operation serves as the start of the FCB array in memory.
5F66
PUSH HL E5
Save Register Pair HL (BASIC text pointer) onto the stack, preserving the parse position during the FCB address calculation.
5F67
LD HL,66BEH 21 BE 66
Point Register Pair HL to 66BEH - the program entry point address, which also serves as the base address of the FCB array. The first FCB starts at 66BEH.
5F6A
LD BC,(649EH) ED 4B 9E 64
Load Register Pair BC with the 16-bit value stored at 649EH - the FCB size in bytes (012DH = 301 decimal, stored during initialization by code at 6711H). This is the stride between consecutive FCB entries in memory.
5F6E
OR A B7
OR Register A with itself to set the flags. If Register A is zero (file index 0), the Z FLAG is set and the multiply loop is skipped entirely - HL already points to the first FCB at 66BEH.
5F6F
If the Z FLAG is set (file index is 0), JUMP forward to 5F75H to skip the multiply loop. File #1 (index 0) maps to the FCB at the base address 66BEH without any offset.
FCB Address Multiply Loop
For file indices greater than 0, this loop adds the FCB size (BC) to the base address (HL) once for each file index. After A iterations, HL points to the start of the requested FCB.
5F71
ADD HL,BC 09
ADD Register Pair BC (FCB size, 012DH) to Register Pair HL (running FCB address). This advances the pointer past one FCB entryLOOP START]
5F72
DEC A 3D
DECrement Register A (the remaining file index count) by 1.
5F73
LOOP END
If the NZ FLAG is set (there are more FCB entries to skip), LOOP back to 5F71H to add another FCB stride.
5F75
OR (HL) B6
OR Register A (now zero from the loop or from being file index 0) with the byte at (HL) - the first byte of the FCB (the status flags byte at FCB offset 00H). This loads the FCB status into the flags: Z is set if the FCB status byte is zero (file not open), NZ if the file is open.
5F76
LD B,H 44
Load Register B with Register H (high byte of the FCB address). Together with the next instruction, this copies the FCB address from HL to BC.
5F77
LD C,L 4D
Load Register C with Register L (low byte of the FCB address). Register Pair BC now holds the calculated FCB base address for the requested file number.
5F78
POP HL E1
Restore Register Pair HL from the stack (the BASIC text pointer, saved at 5F66H).
5F79
RET C9
. Note: This address (5F79H) is also a jump table target from 6839H - a standalone RET used as a no-op dispatch entry.
RETURN to the caller. Register Pair BC holds the FCB base address. Z flag indicates file status (Z=not open, NZ=open). HL holds the BASIC text pointer.
5F7AH - PUT/GET Statement Handler (Jump Table Target from 67EEH)
This routine handles the PUT and GET statements for random access files, dispatched via the jump table at 67EEH (JP 5F7AH). It processes a list of file numbers, calling the file number parser (5F53H) for each, then calling the file close/flush routine (5F8BH) and the SVC execution routine (6368H) to write or read the current record. The loop continues until all file numbers in the statement have been processed.
5F7A
If the Z FLAG is set on entry (no file number expression follows - the statement is just PUT or GET with no arguments), JUMP to 5F8FH to handle the "close all open files" case. This processes all currently open FCBs.
PUT/GET File Loop
A file number expression follows. The loop parses each file number, flushes/reads the record, then checks if more file numbers follow (separated by commas, handled by 6368H returning NZ).
5F7C
GOSUB to 5F53H to parse the next file number from the BASIC text, convert it to a 0-based index, and calculate the FCB address in BC. On return, BC points to the FCB and HL holds the updated BASIC text pointerLOOP START]
5F7F
GOSUB to 5F8BH to set up and execute the SVC file operation (write or read the current record buffer to/from disk). This routine clears A, pushes AF, and falls through to the SVC dispatch at 5FAEH.
5F82
PUBLIC - called by SYS10, SYS19, SYS20
GOSUB to 6368H - a routine that checks whether more file numbers follow in the statement (separated by commas). On return, NZ indicates another file number is available; Z indicates end of the file list.
5F85
LOOP END
If the NZ FLAG is set (more file numbers follow), LOOP back to 5F7CH to parse and process the next file number.
5F87
RET C9
RETURN to the caller. All file numbers in the PUT/GET statement have been processed.
5F88H - FCB Setup for Default File (BC=5700H Entry)
This short entry point loads BC with 5700H (the FCB work area base address), then falls through to 5F8BH to execute the file operation. This is used when a default file (the system FCB at 5700H) should be the target of the operation rather than a user-specified file number.
5F88
LD BC,5700H 01 00 57
Load Register Pair BC with 5700H - the base address of the FCB work area. This selects the default system FCB rather than a numbered user file.
5F8B
XOR A AF
Clear Register A to zero. This indicates a "no special mode" flag for the SVC dispatch that follows.
5F8C
PUSH AF F5
Save Register AF onto the stack. The zero in A (and cleared flags) will be retrieved later by the SVC handler loop at 5FC6H to determine when to stop iterating.
5F8D
JUMP forward to 5FAEH to enter the common SVC dispatch section, which sets up the file operation parameters and calls the DOS SVC to execute the read or write.
5F8FH - Close/Flush All Open Files
This routine iterates through all allocated FCBs and flushes (PUT/GET) each file that is currently open. It is reached from the PUT/GET handler (5F7AH) when no file number is specified - meaning "process all open files." It reads the maximum file count from the self-modifying byte at 5F62H, walks the FCB array starting at 66BEH with a stride of 012DH (301 bytes), and calls the SVC dispatch for each file whose FCB status byte is non-zero (open).
5F8F
LD A,(5F62H) 3A 62 5F
Load Register A with the value at 5F62H - the maximum file count (a self-modifying byte written by 6504H during initialization). This tells the routine how many FCB slots to check.
5F92
OR A B7
OR Register A with itself to set the flags. If the maximum file count is zero (no files allocated), the Z FLAG is set.
5F93
RET Z C8
If the Z FLAG is set (no files are allocated), RETURN immediately - there is nothing to flush.
5F94
PUSH HL E5
Save Register Pair HL (BASIC text pointer) onto the stack, preserving it across the loop.
5F95
LD B,A 47
Load Register B with Register A (the maximum file count). Register B serves as the loop counter for the DJNZ loop at 5FA2H.
5F96
LD C,A 4F
Load Register C with Register A (the maximum file count). Register C serves as a running file index counter that is decremented for each file processed by the inner loop at 5FA7H-5FC7H.
5F97
LD HL,66BEH 21 BE 66
Point Register Pair HL to 66BEH - the base address of the FCB array (the program entry point, which is repurposed as FCB storage during BASIC operation).
5F9A
LD DE,012DH 11 2D 01
Load Register Pair DE with 012DH (301 decimal) - the size of each FCB entry. This is the stride used to advance HL from one FCB to the next.
FCB Scan Loop
This loop walks through each FCB slot. It reads the first byte (status flags) of each FCB. If non-zero (file is open), the loop exits early to process that file. If zero (file not open), it advances to the next FCB by adding 012DH. Register B counts down from the maximum file count.
5F9D
LD A,(HL) 7E
LOOP START
Load Register A with the byte at (HL) - the status flags byte (offset 00H) of the current FCB. Non-zero means this file is open.
5F9E
OR A B7
OR Register A with itself to set the flags. If the FCB status byte is non-zero (file is open), the NZ FLAG is set.
5F9F
If the NZ FLAG is set (this FCB is open), JUMP forward to 5FA4H to exit the scan loop and process this file.
5FA1
ADD HL,DE 19
ADD Register Pair DE (012DH, the FCB stride) to Register Pair HL to advance to the next FCB slot.
5FA2
LOOP END
DECrement Register B (the FCB scan counter) and LOOP back to 5F9DH if not zero.
5FA4
POP HL E1
Restore Register Pair HL from the stack (the BASIC text pointer).
5FA5
RET Z C8
If the Z FLAG is set (all FCB slots were scanned and none were open - the DJNZ loop completed without finding an open file), RETURN. There are no files to flush.
Process Open Files Loop
At least one open file was found. The routine now iterates through the remaining file indices (stored in C), calling the SVC dispatch for each. Register C is decremented for each iteration, and the loop continues until C reaches zero.
5FA6
LD A,C 79
Load Register A with Register C - the current file index counter (counting down from the max file count).
5FA7
OR A B7
LOOP START
OR Register A with itself to test if the counter has reached zero.
5FA8
RET Z C8
. Note: Address 5FA8H is a self-modifying target written by SYS19/5224H.
If the Z FLAG is set (the file counter has reached zero - all files have been processed), RETURN to the caller.
5FA9
DEC A 3D
DECrement Register A (the file index) by 1, converting from the 1-based counter to a 0-based file index for the FCB address calculation at 5F61H.
5FAA
PUSH AF F5
Save Register AF onto the stack, preserving the decremented file index and flags for the next iteration of the loop.
5FAB
GOSUB to 5F61H - the file index validator and FCB address calculator (entered mid-routine, bypassing the DEC HL/RST 10H preamble). Register A holds the 0-based file index. On return, BC holds the FCB base address.
5FAEH - SVC File Operation Dispatch (Common Entry Point)
This is the common entry point for executing a DOS SVC file operation on the FCB pointed to by BC. It loads the FCB's buffer metadata (offset 0DH) into DE, checks whether the file has a dirty buffer (bit 6 of the FCB status byte), calls the appropriate DOS flush routine (4428H) if needed, then calls the SVC executor (6362H) with B=2DH. On error, it jumps to the error translator at 5DEFH. The loop at 5FA7H-5FC7H iterates back to process additional open files.
5FAE
PUSH HL E5
Save Register Pair HL (BASIC text pointer) onto the stack, preserving it across the SVC execution.
5FAF
LD HL,000DH 21 0D 00
Load Register Pair HL with 000DH - the offset to the FCB's buffer metadata byte within the FCB structure.
5FB2
ADD HL,BC 09
ADD Register Pair BC (the FCB base address) to Register Pair HL. HL now points to FCB+0DH, the buffer metadata byte for this file.
5FB3
EX DE,HL EB
Exchange DE and HL. Register Pair DE now points to FCB+0DH and HL is free for reuse.
5FB4
LD H,B 60
Load Register H with Register B (high byte of the FCB base address). Together with the next instruction, this copies the FCB base address from BC to HL.
5FB5
LD L,C 69
Load Register L with Register C (low byte of the FCB base address). Register Pair HL now points to the FCB base (offset 00H - the status flags byte).
5FB6
BIT 6,(HL) CB 76
Test bit 6 of the byte at (HL) - the FCB status byte at offset 00H. Bit 6 indicates the file buffer is "dirty" (modified data that has not been written to disk).
5FB8
If the NZ FLAG is set (bit 6 was set - the buffer is dirty), GOSUB to 4428H - a DOS entry point that flushes the dirty buffer to disk. This ensures any pending write data is committed before the SVC operation.
5FBB
PUSH AF F5
Save Register AF onto the stack, preserving the result flags from the flush operation (or the unmodified flags if no flush was needed).
5FBC
LD B,2DH 06 2D
Load Register B with 2DH (decimal 45). This is the SVC parameter byte that specifies the type of file operation to execute - a record-level read/write operation code.
5FBE
GOSUB to 6362H to execute the DOS SVC with the parameters set up in BC (FCB address) and B (operation code 2DH). This routine performs the actual disk I/O operation. On return, NZ indicates an error occurred.
5FC1
POP AF F1
Restore Register AF from the stack (the flags from the flush operation).
5FC2
If the NZ FLAG is set (the SVC returned an error), JUMP to 5DEFH - the DOS-to-BASIC error translator, which converts the DOS error code to a BASIC error code and dispatches to the error handlerPUBLIC - called by SYS19, SYS20, SYS21]
5FC5
POP HL E1
Restore Register Pair HL from the stack (the BASIC text pointer).
5FC6
POP AF F1
Restore Register AF from the stack. This retrieves the file index counter that was pushed at 5FAAH (or the initial zero pushed at 5F8CH for the single-file case). Register A holds the decremented file count for the next iteration.
5FC7
LOOP - continue processing open files
JUMP back to 5FA7H to test the file counter (OR A / RET Z) and process the next open file if any remain.
5FC9H - File Position and Width Calculator (Called from 5EBFH)
This routine is called from the PRINT# formatting handler at 5EBFH. It evaluates a file number expression, validates that the file is open, and retrieves file position and configuration information. It calls 5F5DH to convert the expression result to a file index, calls 6298H to look up the file, validates the file is open, and returns with the FCB status flags in registers. It also loads the alternate file position and checks the access mode bits to determine the appropriate output strategy.
5FC9
PUSH BC C5
Save Register Pair BC onto the stack, preserving the caller's context across the file lookup.
5FCA
GOSUB to 5F5DH (entered mid-routine at the 2B1FH call) to convert the expression result to an 8-bit unsigned file number, decrement to a 0-based index, and validate the range. On return, Register A holds the validated file index.
5FCD
GOSUB to 6298H to look up the file by its index. This routine loads the FCB pointer into IX and returns with the file status information. Z flag indicates whether the file is open (NZ=open, Z=not found/closed).
5FD0
If the Z FLAG is set (file is not open or not found), JUMP to 5DA9H - error code 6CH (file mode error).
5FD3
POP BC C1
Restore Register Pair BC from the stack (the caller's saved context).
5FD4
LD DE,(5700H) ED 5B 00 57
Load Register Pair DE with the 16-bit value at 5700H - the FCB work area status word. The high byte (D) contains extended status flags, and the low byte (E) contains mode/access flags.
5FD8
PUBLIC - called by SYS10
GOSUB to 61B3H to load the alternate file position. On return, Register A holds the value at 5715H (alternate sector byte) and Register Pair HL holds the value at 5719H (alternate position word).
5FDB
LD C,A 4F
Load Register C with Register A (the alternate sector byte from 5715H). This preserves the alternate position information while the mode flags are tested.
5FDC
LD A,B 78
Load Register A with Register B (the high byte from the caller's saved BC - contains operational mode bits from the PRINT# handler).
5FDD
AND 22H E6 22
AND Register A with 22H (binary 00100010). This masks out all bits except bits 5 and 1, testing for specific access mode conditions. If either bit is set, the result is non-zero.
5FDF
RET NZ C0
If the NZ FLAG is set (one of the tested mode bits is set - indicating a special access condition), RETURN immediately. The caller handles this condition separately.
Access Mode Dispatch
The mode bits 5 and 1 were not set. The routine now checks additional mode flags to determine the file operation type. Bit 3 of B indicates random access mode. If set, the routine jumps to the alternate position loader at 6129H. Otherwise, it loads the current position and checks various flag combinations in the DE status word to determine the correct output handling path.
5FE0
BIT 3,B CB 58
Test bit 3 of Register B. Bit 3 indicates random access file mode.
5FE2
PUBLIC - called by SYS10
If bit 3 is set (NZ - random access mode), JUMP to 6129H to load the alternate file position from IX+07H and 5708H, check whether the alternate position is valid (bit 6 of IX+01H), and return with that position data.
5FE5
GOSUB to 61ACH to load the current file position. On return, Register C holds the sector offset (from IX+12H) and Register Pair HL holds the position word (from 5717H).
5FE8
BIT 6,D CB 72
Test bit 6 of Register D (the high byte of the status word loaded from 5700H). Bit 6 indicates the file has a special buffering condition (buffer position valid flag).
5FEA
If bit 6 of D is clear (Z - no special buffering), JUMP forward to 6028H to check for random access mode (bit 2 of B) and handle accordingly.
5FEC
BIT 7,E CB 7B
Test bit 7 of Register E (the low byte of the status word from 5700H). Bit 7 indicates an EOF or error condition on the file.
5FEE
If bit 7 of E is clear (Z - no EOF/error), JUMP forward to 600DH to continue with the standard output path.
5FF0
PUBLIC - called by SYS10
GOSUB to 6122H to load the primary file position from IX+04H (into C) and 5705H (into HL). This retrieves the saved position before the EOF condition.
5FF3
BIT 3,E CB 5B
Test bit 3 of Register E. Bit 3 indicates a buffer flag condition.
5FF5
If bit 3 of E is clear (Z - no buffer condition), JUMP forward to 600DH to continue with the standard output path.
5FF7
BIT 2,E CB 53
Test bit 2 of Register E. Bit 2 indicates a buffer operation flag.
5FF9
If bit 2 of E is set (NZ - buffer operation active), JUMP forward to 600AH to call the absolute position calculator at 603EH.
5FFB
GOSUB to 61A6H. This routine loads DE with 444EH (a DOS entry point address) and jumps to 621EH, which calls the DOS routine to perform a position-related operation on the file.
5FFE
LOOP ENTRY
GOSUB to 6031H to load the current position (via 61ACH) and compare it with the alternate position (via 61BDH). The comparison determines whether the file position has advanced to a new record boundary.
6001
If the NO CARRY FLAG is set (the current position is at or past the alternate position - no more data to process in this record), JUMP forward to 600DH to exit the position comparison loop.
6003
PUBLIC - called by SYS10
GOSUB to 6258H to advance the file position by one record. This updates the current position pointers to point to the next sequential record.
6006
LOOP - continue advancing
If the NZ FLAG is set (the advance operation was successful and more records remain), LOOP back to 5FFEH to compare the position again.
6008
Unconditional JUMP forward to 600DH to continue with the output handling path.
600A
PUBLIC - called by SYS10
GOSUB to 603EH - the absolute position calculator. This routine computes the total byte position by adding the record position (5707H) and the byte offset (5702H) with carry from 5709H. Returns the 24-bit result in H:L:C.
600DH - Output Completion and ROM Dispatch
This section handles the final output dispatch for PRINT# operations. It tests access mode bits in Register B to determine if output is actually needed, pops the return address, compares the current position with the record position, sets up the comparison result (FFH or 00H) for the ROM routine, and dispatches to ROM 098DH with a return address of 6357H pushed onto the stack.
600D
LD A,B 78
Load Register A with Register B (the operational mode byte from the caller).
600E
AND 41H E6 41
AND Register A with 41H (binary 01000001). This masks for bits 6 and 0 - testing whether the file requires special output handling (bit 6) or read mode (bit 0).
6010
RET Z C8
If the Z FLAG is set (neither bit 6 nor bit 0 is set - no output or special handling required), RETURN to the caller. The file position has been set up but no I/O dispatch is needed.
6011
POP DE D1
Restore Register Pair DE from the stack. This pops the return address pushed by the caller, effectively discarding it. The routine will instead jump to a ROM handler and return through the address pushed at 6024H.
6012
GOSUB to 6034H to load both the current and alternate positions (via 61BDH) and compare them using RST 18H (CPDEHL). This determines the relationship between the current file position and the record position. On return, Z indicates equal positions, C indicates the current position is before the record position.
6015
LD A,FFH 3E FF
Load Register A with FFH - a default "true" value indicating the position comparison result is valid (positions are not equal and current > record). This is used as a flag passed to the ROM routine at 098DH.
6017
If the Z FLAG is set (current position equals record position), JUMP forward to 6021H to use the FFH "true" result, skipping the additional checks below.
6019
If the CARRY FLAG is set (current position is before the record position), JUMP forward to 601FH to load A=00H (indicating positions are not aligned).
601B
BIT 6,B CB 70
Test bit 6 of Register B (the mode flags). Bit 6 indicates a special condition where the "greater than" comparison result should still use the FFH value.
601D
If bit 6 of B is set (NZ - special condition), JUMP forward to 6021H to keep A=FFH.
601F
LD A,00H 3E 00
Load Register A with 00H - a "false" value indicating the file positions are not properly aligned for the requested output operation.
6021
LD HL,6357H 21 57 63
Point Register Pair HL to 6357H - the return address for the ROM dispatch. After the ROM routine at 098DH completes, execution will resume at 6357H, which is a BASIC statement completion handler.
6024
PUSH HL E5
Save Register Pair HL (6357H) onto the stack. This sets up the return address so that when the ROM routine executes RET, control returns to 6357H instead of the original caller.
6025
Unconditional JUMP to ROM 098DH - a file output dispatch routine that uses the flag value in Register A (FFH or 00H) to determine how to output data to the file channel. When the ROM routine completes, it will RET to 6357H (pushed at 6024H).
6028H - Random Access Mode Check (from 5FEAH)
This short routine is reached from 5FEAH when bit 6 of D (buffer position valid flag) was clear. It checks bit 2 of B (random access mode) and either falls through to 600DH or returns zero values (HL=0, C=0) for files that are not in random access mode.
6028
BIT 2,B CB 50
Test bit 2 of Register B. Bit 2 indicates random access mode for the file.
602A
If bit 2 is clear (Z - file is not in random access mode), JUMP back to 600DH to continue with the standard output completion path.
602C
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H - zero position value, indicating the start of the file or no valid position for a non-buffered random access file.
602F
LD C,L 4D
Load Register C with Register L (which is 00H). This sets the sector offset to zero.
6030
RET C9
RETURN to the caller with HL=0000H and C=00H, indicating a zero/initial file position for this random access file.
6031H - Position Compare (Current vs Alternate)
This routine loads both the current and alternate file positions, then compares them using RST 18H (CPDEHL). It first loads the current position via 61ACH into DE (through the EX at 61BDH), then the alternate position, and compares. The result indicates whether the current position has reached or passed the target alternate position.
6031
GOSUB to 61ACH to load the current file position. On return, Register C holds the sector offset (IX+12H) and Register Pair HL holds the position word (5717H).
6034
GOSUB to 61BDH. This routine exchanges HL into DE, then loads the alternate position into HL (from 61B3H: A from 5715H, HL from 5719H), then exchanges again. On return, DE holds the alternate position and HL holds the current position.
6037
RST 18H DF
Call CPDEHL via RST 18H. This compares Register Pair DE with Register Pair HL. Sets Z if DE=HL (positions are equal), C if DE<HL (alternate position is before current position, meaning current has passed it).
6038
RET NZ C0
If the NZ FLAG is set (the word portions of the positions are not equal), RETURN. The Z and C flags from RST 18H indicate the comparison result.
6039
LD A,C 79
Load Register A with Register C (the sector offset byte from the current position, loaded by 61ACH). When the word portions are equal, the sector offset bytes must also be compared.
603A
CP (IX+15H) DD BE 15
Compare Register A (current sector offset) against the byte at IX+15H (the record position within the sector stored in the FCB). This completes the multi-part position comparison.
603D
RET C9
RETURN to the caller. The Z and C flags indicate the full comparison result: Z if positions are exactly equal, C if current position is before the record position, NC if current is at or past the record position.
603EH - Absolute Position Calculator [PUBLIC - Called by SYS10]
This routine calculates the absolute byte position within a file by adding the record base position (16-bit value at 5707H) and the byte offset (16-bit value at 5702H) with carry from 5709H. The result is a 24-bit position returned in H:L:C format (H=high byte, L=middle byte, C=low byte). This is used to compute the total byte offset for random access record positioning.
603E
LD HL,(5707H) 2A 07 57
Load Register Pair HL with the 16-bit value at 5707H - the record base position word stored in the FCB work area. This is the starting sector/record position for the current file operation.
6041
LD DE,(5702H) ED 5B 02 57
Load Register Pair DE with the 16-bit value at 5702H - the byte offset within the record. This represents the number of bytes past the record boundary for the current position.
6045
ADD HL,DE 19
ADD Register Pair DE (byte offset) to Register Pair HL (record base). This combines the two 16-bit components of the position. If the sum overflows 16 bits, the CARRY FLAG is set.
6046
LD A,(5709H) 3A 09 57
Load Register A with the byte at 5709H - the high byte (carry byte) of the record position. This is the 17th-24th bits of the 24-bit position value.
6049
ADC 00H CE 00
ADD 00H with carry to Register A. This propagates the carry from the ADD HL,DE at 6045H into the high byte, completing the 24-bit addition: position = (5709H : 5707H) + 5702H.
Result Rearrangement
The 24-bit result is currently in A:H:L format. The routine now rearranges it into H:L:C format (A=high byte moved to H, H=middle byte moved to L, L=low byte moved to C) for the caller's expected register layout.
604B
LD C,L 4D
Load Register C with Register L (the low byte of the 24-bit result).
604C
LD L,H 6C
Load Register L with Register H (the middle byte moves down to L).
604D
LD H,A 67
Load Register H with Register A (the high byte moves down to H). The 24-bit position is now in H:L:C format.
604E
RET C9
RETURN to the caller. The 24-bit absolute position is returned in H:L:C (H=high byte, L=middle byte, C=low byte).
604FH - Character Output to File Handler
This routine handles outputting a single character to a file. It is called with the character to output in Register A. It first calls 6382H to set up the file channel (which evaluates the file number and loads IX to point to the FCB), then swaps HL with the return address on the stack. It checks whether the file has a special buffering mode (bit 6 of FCB status at 5700H), manages the print column counter at 570AH (incrementing for printable characters, resetting to zero on carriage return 0DH), and conditionally calls the SVC write routine at 6205H to flush the character to disk.
604F
GOSUB to 6382H to evaluate the file number from the BASIC text and set up the FCB pointer in IX. The self-modifying routine at 6382H either performs NOP + INC SP + INC SP + RET (when no file is active) or RET immediately (when a file channel has been established by 6386H).
6052
EX (SP),HL E3
Exchange the top of the stack with Register Pair HL. This swaps the return address (pushed by the CALL that invoked this routine) with the current HL value. After this, HL holds the caller's return address and the BASIC text pointer is on the stack.
6053
PUSH DE D5
Save Register Pair DE onto the stack, preserving it across the character output operation.
6054
LD HL,5700H 21 00 57
Point Register Pair HL to 5700H - the FCB work area base address. The first byte at 5700H contains the FCB status flags.
6057
BIT 6,(HL) CB 76
Test bit 6 of the byte at (HL) - the FCB status byte at 5700H. Bit 6 indicates the file has a special buffering condition (dirty buffer / position tracking mode). If clear, the routine skips the column tracking logic.
6059
If bit 6 is clear (Z - no special buffering), JUMP forward to 606FH to skip column tracking and proceed directly to the register restoration and return.
Column Position Tracking
The file has special buffering active. The routine now manages the print column counter at 570AH. For printable characters (ASCII 20H and above), the column counter is incremented. For carriage return (0DH), it is reset to zero. For other control characters, the column counter is not changed. Register A holds the character being output.
605B
LD HL,570AH 21 0A 57
Point Register Pair HL to 570AH - the print column position counter within the FCB work area. This byte tracks how many characters have been output on the current line.
605E
INC (HL) 34
INCrement the byte at (HL) - the column counter at 570AH - by 1, tentatively counting this character as a printable column advance.
605F
CP 20H FE 20
Compare Register A (the character being output) against 20H (ASCII space - the lowest printable character). If A is 20H or above, the NO CARRY FLAG is set (printable character, keep the increment). If A is below 20H, the CARRY FLAG is set (control character).
6061
If the NO CARRY FLAG is set (character is printable, 20H or above), JUMP forward to 606AH. The column increment is valid - push AF and call the SVC write routine.
6063
DEC (HL) 35
DECrement the byte at (HL) - undo the tentative column increment at 570AH, because this is a control character that does not advance the print column.
6064
CP 0DH FE 0D
Compare Register A against 0DH (carriage return). If the character is a CR, the Z FLAG is set - the column counter should be reset to zero.
6066
If the NZ FLAG is set (the character is a control character other than CR - e.g., line feed, escape, etc.), JUMP forward to 606AH without resetting the column counter.
6068
LD (HL),00H 36 00
Store 00H into (HL) - reset the column counter at 570AH to zero. A carriage return means the cursor is back at the start of the line.
606A
PUSH AF F5
Save Register AF onto the stack, preserving the character being output (A) and the comparison flags.
606B
GOSUB to 6205H - the SVC write dispatch routine. This loads DE with 001BH (a DOS SVC parameter), then falls through to 621EH which calls the DOS file write SVC to output the character to the file buffer.
606E
POP AF F1
Restore Register AF from the stack (the character and flags).
606F
POP DE D1
Restore Register Pair DE from the stack (saved at 6053H).
6070
POP HL E1
Restore Register Pair HL from the stack (the BASIC text pointer, swapped onto the stack at 6052H).
6071
POP BC C1
Restore Register Pair BC from the stack.
6072
RET C9
RETURN to the caller. The character has been output to the file channel, the column counter has been updated, and all registers have been restored.
6073H - SVC File Setup (Called from 572EH)
This routine sets up a file for SVC operations. It is called from the SVC dispatch entry points in the 572EH-57A8H range. It begins by loading BC=0120H (a buffer size or SVC parameter), calls 635AH to clear the FCB work area, loads BC=5700H and calls 6298H to look up the file. It sets bit 7 of IX+2DH (marking the buffer as needing special handling), evaluates a string expression for the filename, extracts the string descriptor, validates the length, copies file metadata to 570DH, and then calls one of two DOS entry points (4420H for read or 4424H for write) based on bit 0 of Register B. On return, it stores the file position data into the FCB work area variables.
6073
LD BC,0120H 01 20 01
Load Register Pair BC with 0120H (288 decimal). This value is pushed onto the stack and later popped as a parameter for the SVC file operation - it represents the buffer allocation size or record length for the file setup.
6076
PUSH BC C5
Save Register Pair BC (0120H parameter) onto the stack for later use by the file operation setup.
6077
PUSH HL E5
Save Register Pair HL (BASIC text pointer) onto the stack.
6078
GOSUB to 635AH to clear the FCB work area. This routine calls 6392H (which disables the file guard flag), then loads HL=5700H, B=2EH, and fills 2EH bytes with 00H using a DJNZ loop - zeroing the entire FCB work area at 5700H-572DH.
607B
LD BC,5700H 01 00 57
Load Register Pair BC with 5700H - the FCB work area base address, which will be used as the target FCB for the file lookup.
607E
GOSUB to 6298H to look up the file associated with the FCB at BC. This routine reads the guard flag byte at 6382H, validates the file state, stores the FCB pointer at 6352H, calls 6386H to enable the file guard flag, sets up IX=5700H via POP IX, initializes IX+2DH, and copies 2DH bytes from the user FCB (pointed to by HL at entry from 6295H) into the 5700H work area.
6081
SET 7,(IX+2DH) DD CB 2D FE
Set bit 7 of the byte at IX+2DH (the buffer flags byte in the FCB). Bit 7 marks the buffer as requiring special handling - indicating that this FCB was set up through the SVC path rather than through the normal BASIC OPEN statement.
6085
POP HL E1
Restore Register Pair HL from the stack (the BASIC text pointer, saved at 6077H).
6086
POP BC C1
Restore Register Pair BC from the stack (the 0120H parameter, saved at 6076H).
6087
PUSH BC C5
PUBLIC - called by SYS20
Save Register Pair BC (0120H parameter) back onto the stack - it will be retrieved again later.
6088
LD A,(5700H) 3A 00 57
Load Register A with the byte at 5700H - the FCB status flags byte. If the FCB status is non-zero after the file lookup, it means the file is already open or has an error condition.
608B
OR A B7
OR Register A with itself to set the flags. If the FCB status is non-zero, the NZ FLAG is set.
608C
If the NZ FLAG is set (the FCB is not empty - the file is already open or in an error state), JUMP to 5DACH - error code 6EH (File Already Open).
608F
GOSUB to ROM 2337H - the string expression evaluator. This evaluates the filename string expression from the BASIC text and returns the string descriptor on the string stack.
6092
EX (SP),HL E3
Exchange the top of the stack with Register Pair HL. This saves the updated BASIC text pointer onto the stack and retrieves the 0120H parameter into HL.
6093
PUSH HL E5
Save Register Pair HL (the 0120H parameter) onto the stack again for later retrieval.
6094
GOSUB to 5C99H - the string descriptor extraction routine. On return, Register A holds the string length, Register Pair DE holds the string address in memory, and HL points past the descriptor.
6097
CP 20H FE 20
Compare Register A (the string length) against 20H (32 decimal). If the filename string is 32 characters or longer, it exceeds the maximum allowed filename length.
6099
If the NO CARRY FLAG is set (string length is 20H or more - too long), JUMP to 5DB5H - error code 80H (Bad File Name).
609C
LD HL,570DH 21 0D 57
Point Register Pair HL to 570DH - the filename buffer within the FCB work area. The filename will be copied here for the DOS file open call.
609F
PUSH HL E5
Save Register Pair HL (570DH pointer) onto the stack.
60A0
PUBLIC - called by SYS20
GOSUB to 5CB7H - the file status checker and string copy routine. This checks the file mode byte in Register B and copies the filename string (from DE, length A) into the buffer at HL.
60A3
POP DE D1
Restore Register Pair DE from the stack (the 570DH filename buffer address).
60A4
LD (HL),00H 36 00
Store 00H at the current HL position - null-terminating the filename string in the buffer. HL now points just past the last character copied by 5CB7H.
60A6
LD HL,(6352H) 2A 52 63
Load Register Pair HL with the 16-bit value at 6352H - the stored FCB pointer (the original user FCB address, saved by 62A2H during the file lookup at 6298H). This is used as the destination for the DOS buffer setup.
60A9
LD BC,002DH 01 2D 00
Load Register Pair BC with 002DH (45 decimal) - the offset from the FCB base to the buffer area. Adding this to the FCB base gives the address of the file's data buffer.
60AC
ADD HL,BC 09
ADD Register Pair BC (002DH) to Register Pair HL (FCB base). HL now points to FCB+2DH, the start of the file data buffer.
60AD
BIT 7,(IX+2DH) DD CB 2D 7E
Test bit 7 of IX+2DH (the buffer flags byte). Bit 7 was set at 6081H to indicate this FCB was set up through the SVC path. If set, the buffer address should be overridden to point to 4300H (the PDRIVE table area) instead of the normal FCB buffer.
60B1
If bit 7 is clear (Z - normal BASIC OPEN path), JUMP forward to 60B6H to use the calculated buffer address at FCB+2DH.
60B3
LD HL,4300H 21 00 43
Point Register Pair HL to 4300H - the PDRIVE table area. When the SVC path is used (bit 7 set), the file buffer is redirected to 4300H instead of the FCB's own buffer area.
60B6
POP BC C1
Restore Register Pair BC from the stack (the 0120H parameter pushed at 6087H or the operational mode flags, depending on the call path).
60B7
BIT 0,B CB 40
Test bit 0 of Register B (the operation mode byte). Bit 0 distinguishes between read mode (bit 0 set) and write/output mode (bit 0 clear).
60B9
PUSH BC C5
Save Register Pair BC (mode flags) onto the stack, preserving them across the DOS call.
60BA
LD B,00H 06 00
Load Register B with 00H - clear the high byte of BC, which will be used as a parameter for the DOS call. Only the buffer address (HL) and filename (DE) matter to the DOS routine.
60BC
If the NZ FLAG is set from the BIT 0,B test (bit 0 was set - read mode), JUMP forward to 60C3H to call the read-mode DOS open routine at 4424H.
60BE
GOSUB to DOS entry point 4420H - the write/output mode file open routine. DE points to the filename at 570DH, HL points to the buffer, B=00H. On return, NZ indicates an error.
60C1
JUMP forward to 60C6H to check for errors and continue with post-open setup.
60C3
GOSUB to DOS entry point 4424H - the read/input mode file open routine. Same parameters as 4420H. On return, NZ indicates an error.
60C6
If the NZ FLAG is set (the DOS open call returned an error), JUMP to 5DEFH - the DOS-to-BASIC error translator, which converts the DOS error code and dispatches to the error handler.
Post-Open Position Initialization
The DOS file open succeeded. The routine now initializes the file position variables. HL is cleared to 0000H, and the position data is stored conditionally based on the mode flags in Register B.
60C9
XOR A AF
Clear Register A to zero and clear all flags. A=00H represents the initial sector offset (no bytes read/written yet).
60CA
LD H,A 67
Load Register H with Register A (00H). Together with the next instruction, this sets HL=0000H for the initial file position word.
60CB
LD L,A 6F
Load Register L with Register A (00H). Register Pair HL is now 0000H - the initial file position.
60CC
POP BC C1
Restore Register Pair BC from the stack (the mode flags, saved at 60B9H).
60CD
BIT 2,B CB 50
Test bit 2 of Register B. Bit 2 indicates random access mode. If set, the alternate position should also be initialized.
60CF
PUBLIC - called by SYS10
If bit 2 is set (NZ - random access mode), GOSUB to 60EBH to store the initial position (HL=0000H, A=00H) as the alternate position: HL is stored at 5719H and A at 5715H.
60D2
BIT 1,B CB 48
Test bit 1 of Register B. Bit 1 indicates output/write mode. If set, the alternate position loader should be called to initialize the write position.
60D4
If bit 1 is set (NZ - output mode), GOSUB to 61B3H to load the alternate file position from 5715H (into A) and 5719H (into HL). This reads back the position that may have just been stored at 60EBH.
60D7
LD (5717H),HL 22 17 57
SELF-MODIFYING CODE - 5717H is a runtime variable
Store Register Pair HL (the current/initial position word) at 5717H - the primary file position word in the FCB work area.
60DA
LD (5712H),A 32 12 57
SELF-MODIFYING CODE - 5712H is a runtime variable
Store Register A (the sector offset byte, initially 00H) at 5712H - the sector position byte in the FCB work area.
60DD
LD A,B 78
Load Register A with Register B (the mode flags byte).
60DE
AND F8H E6 F8
AND Register A with F8H (binary 11111000). This clears the low 3 bits (mode bits 0-2: read, write, random) while preserving the upper 5 bits (which contain the file type and operational flags).
60E0
LD B,A 47
Load Register B with Register A (the masked mode flags, with the low 3 bits cleared). BC will now be stored as the FCB status word.
60E1
LD (5700H),BC ED 43 00 57
SELF-MODIFYING CODE - 5700H is a runtime variable
Store Register Pair BC at 5700H - writing the FCB status word. B (upper flags) goes to 5700H, C goes to 5701H. This finalizes the FCB status flags after the file open.
60E5
SET 6,(IX+0EH) DD CB 0E F6
Set bit 6 of the byte at IX+0EH - a secondary FCB flag byte. Bit 6 indicates the file has been successfully opened and initialized through this SVC path.
60E9
POP HL E1
Restore Register Pair HL from the stack (the BASIC text pointer).
60EA
RET C9
RETURN to the caller. The file has been opened via the DOS SVC path, the FCB status flags have been set, and the position variables have been initialized.
60EBH - Store Alternate Position [PUBLIC - Called by SYS10]
This small utility stores the current HL and A values as the alternate file position. HL is stored at 5719H and A at 5715H. Called from 60CFH during file open initialization and by SYS10 for position management.
60EB
LD (5719H),HL 22 19 57
SELF-MODIFYING CODE - 5719H is a runtime variable
Store Register Pair HL (the alternate position word) at 5719H - the alternate file position word in the FCB work area.
60EE
LD (5715H),A 32 15 57
SELF-MODIFYING CODE - 5715H is a runtime variable
Store Register A (the alternate sector offset byte) at 5715H - the alternate sector position byte in the FCB work area.
60F1
RET C9
RETURN to the caller.
60F2H - File Read Helper [PUBLIC - Called by SYS19, SYS20]
This routine reads a byte from a file using ROM routine 0013H. It pushes DE, loads DE with 570DH (the filename/data buffer pointer in the FCB work area), calls ROM 0013H to perform the read operation, restores DE, and returns Z if the read was successful. If an error occurred, it jumps to 6379H for error handling.
60F2
PUSH DE D5
Save Register Pair DE onto the stack, preserving it across the ROM read call.
60F3
LD DE,570DH 11 0D 57
Load Register Pair DE with 570DH - the filename/data buffer pointer in the FCB work area. This tells the ROM read routine where to find the file control information.
60F6
GOSUB to ROM 0013H - the file read routine. DE points to the file control block at 570DH. On return, Z indicates success (byte read into A), NZ indicates an error or end-of-file condition.
60F9
POP DE D1
Restore Register Pair DE from the stack.
60FA
RET Z C8
If the Z FLAG is set (read operation was successful), RETURN to the caller with the data byte in Register A.
60FB
If the read failed (NZ), JUMP to 6379H - an error handler that checks the error code (1DH for past-EOF, 1CH for before-start) and dispatches accordingly. Errors other than position errors are passed to 5DEFH (DOS-to-BASIC error translator).
60FEH - File Open with SVC 2CH Dispatch
This routine performs a file open operation through the SVC 2CH path. It sets the carry/sign flags with OR AFH, pushes AF, evaluates the file number via 6295H, calls the SVC 2CH helper at 610AH, then jumps to 4D03H (in SYS overlay space) to continue processing.
60FE
OR AFH F6 AF
OR Register A with AFH (binary 10101111). This sets specific bits in Register A as flag values - bit 7, bit 5, bit 3, bit 2, bit 1, and bit 0 are all set. The result is non-zero (NZ flag set), and the sign flag (S) is set due to bit 7.
6100
PUSH AF F5
Save Register AF onto the stack, preserving the flag byte for later use by the SVC dispatcher.
6101
GOSUB to 6295H to evaluate the file number from the BASIC text (calls 5F53H) and set up the FCB lookup (calls 6298H). On return, the FCB work area at 5700H has been populated with the file's control information.
6104
GOSUB to 610AH - the SVC 2CH helper that sends function code 2CH to the DOS and stores the returned position data at IX+04H and 5705H.
6107
Unconditional JUMP to 4D03H - a SYS overlay entry point that continues the file operation processing. This hands off control to the DOS overlay system for further file manipulation.
610AH - SVC 2CH Helper (Comma + SVC Call)
This routine sends SVC function code 2CH to the DOS via RST 28H, then loads the current file position (via 61ACH) and stores it as the primary position at IX+04H and 5705H. The SVC 2CH function performs a file seek or position operation.
610A
LD A,2CH 3E 2C
Load Register A with 2CH - the SVC function code for a file seek/position operation.
610C
RST 28H EF
Execute NEWDOS/80 Supervisor Call (SVC) with function code 2CH in Register A. This performs the DOS-level file positioning operation.
610D
PUBLIC - called by SYS10
GOSUB to 61ACH to load the current file position. On return, Register C holds the sector offset (from IX+12H) and Register Pair HL holds the position word (from 5717H).
6110
LD (IX+04H),C DD 71 04
PUBLIC - called by SYS10
Store Register C (the sector offset) into the FCB at IX+04H - the primary position byte 1 (sector offset) within the FCB structure.
6113
LD (5705H),HL 22 05 57
SELF-MODIFYING CODE - 5705H is a runtime variable
Store Register Pair HL (the position word) at 5705H - the primary position word in the FCB work area.
6116
RET C9
RETURN to the caller. The current file position has been saved as the primary position in both the FCB (IX+04H) and the work area (5705H).
6117H - Store Alternate Position from Current [PUBLIC - Called by SYS10]
This routine stores the current position (Register C and Register Pair HL) as the alternate file position. C goes to IX+07H, HL goes to 5708H, and bit 6 of IX+01H is set to mark the alternate position as valid.
6117
LD (IX+07H),C DD 71 07
Store Register C (the sector offset) into the FCB at IX+07H - the alternate position byte (sector offset) within the FCB structure.
611A
LD (5708H),HL 22 08 57
SELF-MODIFYING CODE - 5708H is a runtime variable
Store Register Pair HL (the position word) at 5708H - the alternate position word in the FCB work area.
611D
SET 6,(IX+01H) DD CB 01 F6
Set bit 6 of the byte at IX+01H (the secondary FCB flags byte). Bit 6 marks the alternate position as valid - indicating that the values at IX+07H and 5708H contain a meaningful file position that can be used for comparison or restoration.
6121
RET C9
RETURN to the caller.
6122H - Load Primary Position [PUBLIC - Called by SYS10]
This routine loads the primary file position from the FCB and work area: Register C from IX+04H (sector offset) and Register Pair HL from 5705H (position word).
6122
LD C,(IX+04H) DD 4E 04
Load Register C with the byte at IX+04H - the primary position sector offset stored in the FCB structure.
6125
LD HL,(5705H) 2A 05 57
Load Register Pair HL with the 16-bit value at 5705H - the primary position word from the FCB work area.
6128
RET C9
RETURN to the caller with C=sector offset and HL=position word.
6129H - Load Alternate Position with Validity Check [PUBLIC - Called by SYS10]
This routine loads the alternate file position from IX+07H and 5708H, then checks whether the alternate position is valid (bit 6 of IX+01H). If valid, it returns immediately. If not valid, it falls through to 615BH which jumps to error code 6CH (file mode error) at 5DA9H.
6129
LD C,(IX+07H) DD 4E 07
Load Register C with the byte at IX+07H - the alternate position sector offset stored in the FCB structure.
612C
LD HL,(5708H) 2A 08 57
Load Register Pair HL with the 16-bit value at 5708H - the alternate position word from the FCB work area.
612F
BIT 6,(IX+01H) DD CB 01 76
PUBLIC - called by SYS10
Test bit 6 of the byte at IX+01H. Bit 6 marks the alternate position as valid (set by 611DH). If set, the alternate position is a meaningful value.
6133
RET NZ C0
If the NZ FLAG is set (bit 6 is set - alternate position is valid), RETURN to the caller with the alternate position in C and HL.
6134
If the alternate position is not valid (bit 6 clear), JUMP forward to 615BH which executes JP 5DA9H - error code 6CH (file not in correct mode). The alternate position has not been set, so it cannot be used.
6136H - Record Count Validator [PUBLIC - Called by SYS10]
This routine validates a record count in Register B against the maximum allowed value stored at 5094H (a DOS system variable). If B exceeds the maximum, it is clamped to the maximum. Then it checks whether adding 80H to the (clamped) value causes an overflow - if so, the record count is too large and requires special handling via the 61C8H record position validator. The routine is used to ensure record-level operations do not exceed the file's capacity.
6136
LD A,(5094H) 3A 94 50
Load Register A with the byte at 5094H - a DOS system variable that holds the maximum record count or sector size limit for the current file configuration.
6139
CP B B8
Compare Register A (maximum value) against Register B (the requested record count). If A < B (the maximum is less than the requested count), the CARRY FLAG is set.
613A
If the CARRY FLAG is set (maximum is less than the requested count - B exceeds the limit), JUMP forward to 613DH to use B as-is (it will be clamped by the subsequent code path).
613C
LD A,B 78
Load Register A with Register B (the requested record count, which is within the maximum limit).
613D
LD B,A 47
Load Register B with Register A. After the comparison logic above, B now holds the smaller of the two values - the clamped record count.
613E
ADD 80H C6 80
ADD 80H to Register A. If the result overflows past FFH (the clamped count was 80H or larger), the CARRY FLAG is set. This checks whether the record count fits within a signed byte range.
6140
RET NC D0
If the NO CARRY FLAG is set (no overflow - the record count is small enough, less than 80H), RETURN to the caller. Register B holds the validated record count.
Large Record Count Handling
The record count is 80H or larger. The routine now sets up for a call to 61C8H (the record position validator) which handles the extended range calculation. Error code 71H is loaded in case the validation fails.
6141
LD A,71H 3E 71
Load Register A with 71H - an error code placeholder (decimal 113). This is used as a parameter for the record position validator at 61C8H if the extended range check fails.
6143
LD C,B 48
Load Register C with Register B (the clamped record count). Register C preserves the count while B is modified for the 61C8H call.
6144
LD B,00H 06 00
Load Register B with 00H. The combination of B=00H and the original count in C is used by 61C8H for the extended position calculation.
6146
PUBLIC - called by SYS10
GOSUB to 61C8H - the record position validator. This checks whether the position (computed from B and C) would exceed the file's capacity. If it overflows, it jumps to 5DBEH (error code 8EH). Otherwise it stores the result at 61CAH and returns.
6149
LD B,C 41
Load Register B with Register C (the record count, preserved before the call). Restore B to the validated record count for the caller.
614A
LD A,B 78
Load Register A with Register B (the validated record count).
614B
RET C9
RETURN to the caller. Register B and A both hold the validated record count. The count has been checked against the maximum at 5094H and validated for range at 61C8H.
614CH - FCB Status Checker [PUBLIC - Called by SYS10]
This routine checks the FCB status flags at 5700H to determine whether the file is open in a compatible mode. It reads the status word into DE, rotates the low byte (E) left to test specific bits, and either returns with CARRY set (file is accessible) or jumps to error code 6CH at 5DA9H if the file mode is incompatible.
614C
LD DE,(5700H) ED 5B 00 57
Load Register Pair DE with the 16-bit status word at 5700H. Register D gets the byte at 5701H (extended flags), Register E gets the byte at 5700H (primary status flags).
6150
LD A,E 7B
Load Register A with Register E (the primary FCB status flags byte from 5700H).
6151
RLCA 07
Rotate Register A left one bit. The original bit 7 moves into the CARRY FLAG, and all other bits shift left by one position. Bit 7 of the FCB status indicates the file is in an error or special state.
6152
If the NO CARRY FLAG is set (original bit 7 was 0 - the file is not open or has no valid status), JUMP forward to 615BH to dispatch error code 6CH at 5DA9H.
6154
BIT 5,A CB 6F
Test bit 5 of Register A (after the left rotation). This corresponds to bit 4 of the original status byte. Bit 4 indicates a special file mode (e.g., append mode).
6156
If bit 5 is set (NZ - special mode flag active in the original byte), JUMP forward to 6159H to perform one more rotation and test carry.
6158
RLCA 07
Rotate Register A left one more bit. This shifts the remaining bits left again, testing additional mode bits.
6159
RLCA 07
Rotate Register A left one bit. The carry flag now reflects the bit being tested after the cumulative rotations.
615A
RET C D8
If the CARRY FLAG is set (the file mode bit being tested is set - the file is accessible for the requested operation), RETURN to the caller with carry set indicating success.
615B
Unconditional JUMP to 5DA9H - error entry point that loads error code 6CH (file not in correct mode) and dispatches to the error handler. The file is not open in the required mode for the requested operation.
615EH - Position Compare and Buffer Dirty Handler [PUBLIC - Called by SYS10]
This routine compares the current and alternate file positions (via 6034H), and if the current position is at or past the alternate, it marks the buffer as dirty and handles the necessary buffer management. It checks the FCB access mode (random access bit 2 of status) and calls the position advance routine (61A6H) and HL decrement loop (6188H) to adjust the buffer state. This is a critical routine for maintaining data consistency in random access file operations.
615E
GOSUB to 6034H to load both positions (alternate via 61BDH, current via 61ACH) and compare them using RST 18H (CPDEHL). Returns Z if equal, C if current is before alternate.
6161
RET C D8
If the CARRY FLAG is set (current position is before the alternate position - no buffer conflict), RETURN to the caller. No buffer management is needed.
6162
SET 4,(IX+2DH) DD CB 2D E6
Set bit 4 of IX+2DH (the buffer flags byte). Bit 4 indicates the buffer is "dirty" - it has been modified and needs to be written to disk before it can be reused.
6166
RET Z C8
If the Z FLAG is set (current and alternate positions are exactly equal), RETURN. The buffer has been marked dirty, but no further position adjustment is needed since the positions match.
Position Mismatch Handling
The current position is past the alternate position (NC and NZ). This means the file has advanced beyond the expected buffer boundary. The routine now checks whether the file is in random access mode and performs the necessary buffer readjustment.
6167
LD A,(IX+00H) DD 7E 00
Load Register A with the byte at IX+00H - the primary FCB status flags byte.
616A
BIT 2,A CB 57
Test bit 2 of Register A. Bit 2 indicates random access mode.
616C
If bit 2 is clear (Z - not in random access mode), JUMP to 5DDCH - error code A6H. A sequential file cannot have its position past the buffer boundary without being in error.
616F
AND 03H E6 03
AND Register A with 03H (binary 00000011). This isolates bits 0 and 1 - the read (bit 0) and write (bit 1) mode flags.
6171
RET Z C8
If the Z FLAG is set (neither read nor write mode is active - the file has no I/O mode), RETURN. No buffer operation can be performed.
6172
PUSH HL E5
Save Register Pair HL onto the stack.
6173
PUSH BC C5
Save Register Pair BC onto the stack.
6174
EX DE,HL EB
Exchange Register Pairs DE and HL. HL now holds the alternate position word (from 61BDH), and DE holds the current position word.
6175
LD C,(IX+15H) DD 4E 15
Load Register C with the byte at IX+15H - the record position within the current sector, from the FCB structure.
6178
GOSUB to 61A6H. This loads DE with 444EH (a DOS entry point) and jumps to 621EH, which calls the DOS routine to perform a position-related write/flush operation on the file.
617B
LD HL,(5702H) 2A 02 57
Load Register Pair HL with the 16-bit value at 5702H - the byte offset within the current record. This tells the decrement loop how many bytes need to be adjusted.
617E
GOSUB to 6188H - the HL decrement loop. This routine clears A and B, then repeatedly calls 61DFH (a single-byte write/advance) while decrementing HL, until HL reaches zero. This effectively writes zero-bytes to fill the gap between the current and alternate positions.
6181
POP BC C1
Restore Register Pair BC from the stack.
6182
POP HL E1
Restore Register Pair HL from the stack.
6183
LOOP - continue until positions align
JUMP back to 615EH to re-compare the positions after the adjustment. This loop continues until the current position is at or before the alternate position.
6185H - HL Decrement Loop (Zero-Fill Writer)
This routine writes zero bytes to a file by calling 61DFH in a loop, decrementing HL each iteration until HL reaches zero. Entry at 6185H tests HL first (skips if HL is already zero). Entry at 6188H clears A and B before starting the loop.
6185
LD A,H 7C
Load Register A with Register H (high byte of the loop counter).
6186
OR L B5
OR Register A with Register L. If HL is zero (both H and L are zero), the Z FLAG is set - the loop is complete.
6187
RET Z C8
If the Z FLAG is set (HL has reached zero - all bytes have been written), RETURN to the caller.
6188
XOR A AF
Clear Register A to zero. This is the byte value that will be written to the file - zero-filling.
6189
LD B,A 47
Load Register B with Register A (00H). Register B serves as a parameter for the 61DFH call.
618A
LOOP BODY
GOSUB to 61DFH - a single-byte write/advance routine that outputs one byte to the file and advances the file position.
618D
DEC HL 2B
DECrement Register Pair HL by 1 (the remaining byte count).
618E
LOOP - continue writing zero bytes
JUMP back to 6185H to test whether HL has reached zero.
6190H - String Expression with Descriptor Extraction [PUBLIC - Called by SYS10, SYS20]
This routine evaluates a string expression from the BASIC text, checks whether the result is a string type, and if so, extracts the string descriptor (length, low address byte, high address byte) into registers B, C, and H respectively. It is a key utility called by SYS10 (5 times) and SYS20 (3 times). Entry is through a call with the BASIC text pointer on the stack.
6190
GOSUB to ROM 2337H - the string expression evaluator. Evaluates the current BASIC expression and pushes the result descriptor onto the string stack. On return, HL points to the updated BASIC text position.
6193
EX (SP),HL E3
Exchange the top of the stack with Register Pair HL. The updated BASIC text pointer goes onto the stack and the caller's saved HL (or return context) comes into HL.
6194
PUSH HL E5
Save the retrieved HL value back onto the stack, preserving it for later restoration.
6195
RST 20H E7
Call GETYP via RST 20H. This checks the current variable type. Z flag is set if the type is string, NZ if numeric.
6196
RET NZ C0
If the NZ FLAG is set (the expression result is numeric, not a string), RETURN to the caller immediately. The caller must handle the numeric case separately.
String Descriptor Extraction
The expression result is a string. The routine now calls ROM 29D7H to locate the string descriptor, then extracts the three descriptor bytes: length (into B), low address byte (into C and later L), and high address byte (into H). The result is a direct pointer to the string data with its length.
6197
PUSH AF F5
Save Register AF onto the stack, preserving the flags from the type check.
6198
GOSUB to ROM 29D7H - the string descriptor locator. On return, HL points to the 3-byte string descriptor in the string descriptor area. The descriptor format is: [length] [addr_low] [addr_high].
619B
POP AF F1
Restore Register AF from the stack (the type check flags).
619C
LD B,(HL) 46
Load Register B with the byte at (HL) - the string length from the descriptor. B now holds the number of characters in the string.
619D
INC HL 23
INCrement Register Pair HL to point to the next byte in the descriptor (the low byte of the string address).
619E
LD C,(HL) 4E
Load Register C with the byte at (HL) - the low byte of the string data address.
619F
INC HL 23
INCrement Register Pair HL to point to the next byte in the descriptor (the high byte of the string address).
61A0
LD H,(HL) 66
Load Register H with the byte at (HL) - the high byte of the string data address.
61A1
LD L,C 69
Load Register L with Register C (the low byte of the string address). Register Pair HL now points directly to the string data in memory. B holds the string length.
61A2
RET C9
RETURN to the caller. Register B holds the string length, Register Pair HL points to the string data, and the Z flag is set (indicating string type). Register C also holds the low byte of the address.
61A3H - Load Primary Position and Write via 444EH
This two-instruction sequence loads the primary file position (via 6122H) and then falls through to 61A6H, which sets DE=444EH (a DOS position-write entry point) and jumps to the common SVC dispatcher at 621EH. The combined effect is: read the primary position from IX+04H and 5705H, then call the DOS to perform a position-related write operation using that position.
61A3
GOSUB to 6122H to load the primary file position. On return, Register C holds the sector offset (from IX+04H) and Register Pair HL holds the position word (from 5705H).
61A6H - DOS Position Write Dispatcher [PUBLIC - Called by SYS10]
This routine loads DE with 444EH - a DOS entry point that performs a position-related write/flush operation on the file - and then jumps to the common SVC dispatcher at 621EH. It is called from 61A3H (after loading the primary position), from 6178H (during buffer dirty handling), and from 6250H (after position advance with overflow).
61A6
LD DE,444EH 11 4E 44
Load Register Pair DE with 444EH - the address of a DOS entry point routine that handles position-related write operations on the file. DE is used by the SVC dispatcher at 621EH to determine which DOS routine to call.
61A9
Unconditional JUMP to 621EH - the common SVC dispatch entry. This routine calls 622DH to set up the stack (pushes DE=444EH, loads DE=570DH), which causes the RET at 6231H to transfer control to 444EH with DE pointing to the FCB work area at 570DH.
61ACH - Load Current Position
This utility loads the current file position into Register C (sector offset from IX+12H) and Register Pair HL (position word from 5717H). Called extensively throughout the file I/O routines for position tracking.
61AC
LD C,(IX+12H) DD 4E 12
Load Register C with the byte at IX+12H - the current sector position byte within the FCB structure. This is the byte offset within the current sector being accessed.
61AF
LD HL,(5717H) 2A 17 57
Load Register Pair HL with the 16-bit value at 5717H - the primary file position word from the FCB work area. Together with C, this forms the complete current file position.
61B2
RET C9
RETURN to the caller with C=sector offset and HL=position word.
61B3H - Load Alternate Position [PUBLIC - Called by SYS10]
This utility loads the alternate file position into Register A (sector byte from 5715H) and Register Pair HL (position word from 5719H). Called from 60D4H, 5FD8H, and various position comparison routines.
61B3
LD A,(5715H) 3A 15 57
Load Register A with the byte at 5715H - the alternate sector offset byte from the FCB work area.
61B6
LD HL,(5719H) 2A 19 57
Load Register Pair HL with the 16-bit value at 5719H - the alternate position word from the FCB work area.
61B9
RET C9
RETURN to the caller with A=alternate sector byte and HL=alternate position word.
61BAH - Load Both Positions (Current into DE, Alternate into HL)
This routine loads both the current and alternate file positions, arranging them for comparison. It loads the current position into HL (via 61ACH), exchanges into DE, loads the alternate position into HL (via 61B3H), then exchanges back. Final result: DE=alternate position word, HL=current position word. Called from 631DH (buffer state logic).
61BA
GOSUB to 61ACH to load the current file position. Register C = sector offset (IX+12H), Register Pair HL = position word (5717H).
61BD
EX DE,HL EB
Exchange Register Pairs DE and HL. The current position word moves from HL to DE.
61BE
GOSUB to 61B3H to load the alternate file position. Register A = alternate sector byte (5715H), Register Pair HL = alternate position word (5719H).
61C1
EX DE,HL EB
Exchange Register Pairs DE and HL again. Now HL = current position word, DE = alternate position word. This arrangement is ready for comparison via RST 18H (CPDEHL).
61C2
RET C9
RETURN to the caller with HL=current position, DE=alternate position, C=current sector offset, A=alternate sector byte.
61C3H - DOS Position Read Dispatcher
This routine loads DE with 0013H - a DOS SVC parameter for a position-read operation - and jumps to the common SVC dispatcher at 621EH. Called from 626CH and 628DH (record type decoder).
61C3
LD DE,0013H 11 13 00
Load Register Pair DE with 0013H - a DOS SVC parameter code that specifies a position-read operation on the file.
61C6
JUMP forward to 621EH - the common SVC dispatch entry that calls the DOS routine specified by DE with the FCB work area at 570DH.
61C8H - Record Position Validator [PUBLIC - Called by SYS10]
This routine validates whether a record operation would exceed the file's capacity. It computes the negative of (B+1) as a 16-bit value: 0000H - (B+1). If this subtraction carries (B+1 is zero - impossible since INC DE always makes it at least 1 - or the result is invalid), it jumps to error 8EH at 5DBEH. Otherwise, the result is stored at the self-modifying location 61CAH for later use by position comparison code at 632BH. After storing the limit, it checks bit 2 of IX+2DH and, if clear, performs an extended position validation by calling 65A8H and comparing against IX+15H.
61C8
PUSH HL E5
Save Register Pair HL onto the stack, preserving it across the record limit calculation.
61C9
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H. This is the starting value for the subtraction that computes the negative record limit.
61CA
LD E,B 58
. Note: The instruction at 61CAH is also the target of a self-modifying write at 61D6H. The two bytes at 61CAH-61CBH are overwritten with the computed record limit value. However, they are first used here as the LD E,B instruction during the current execution.
Load Register E with Register B (the record count).
61CB
LD D,00H 16 00
Load Register D with 00H. Register Pair DE now holds the 16-bit extension of the record count B (DE = 00:B).
61CD
INC DE 13
INCrement Register Pair DE by 1. DE is now B+1 - the total number of records including the current one.
61CE
OR A B7
Clear the CARRY FLAG by ORing A with itself (OR A clears carry). This prepares for the SBC instruction that follows.
61CF
SBC HL,DE ED 52
Subtract Register Pair DE (B+1) from Register Pair HL (0000H) with borrow. The result is HL = 0000H - (B+1) = -(B+1). If B was 0, DE=1, result=FFFFH. If B was FFH, DE=100H, result=FF00H. The CARRY FLAG is set because DE > HL (subtracting a positive value from zero).
61D1
If the CARRY FLAG is set (the subtraction borrowed - which it always does when subtracting from zero, so this check is for edge cases where the carry propagation indicates an invalid state), JUMP to 5DBEH - error code 8EH (record position overflow). Note: In normal operation, carry is always set here from the SBC, but the JP C is reached only if A had a non-zero carry-in from the earlier OR A. Since OR A clears carry, this JP C is effectively never taken in the normal path - it guards against re-entry with stale carry.
Self-Modifying Store at 61CAH
The computed record limit (the negative of B+1) is stored at 61CAH. This overwrites the LD E,B / LD D,00H instruction bytes with the 16-bit limit value. The value at 61CAH is later read by code at 632BH (LD HL,(61CAH)) to compare against the current file position during buffer state checking.
61D4
LD (61CAH),HL 22 CA 61
Store Register Pair HL (the computed record limit -(B+1)) at 61CAHSELF-MODIFYING CODE - 61CAH is a runtime variable]
61D7
POP HL E1
Restore Register Pair HL from the stack (the original HL saved at 61C8H).
61D8
BIT 2,(IX+2DH) DD CB 2D 56
Test bit 2 of IX+2DH (the buffer flags byte). Bit 2 indicates a buffer operation is already in progress or the extended validation is not needed.
61DC
RET NZ C0
If bit 2 is set (NZ - buffer operation active), RETURN. The record limit has been stored and no further validation is needed.
Extended Position Validation
Bit 2 of IX+2DH is clear - extended validation is required. The routine now calls 65A8H to get the file's maximum position, subtracts the record position (IX+15H) and the position words, and checks whether the requested record operation would exceed the file's end. If it would, and bit 7 of IX+01H (EOF flag) is not set, error 90H is raised at 5DC1H.
61DD
PUSH HL E5
Save Register Pair HL onto the stack.
61DE
PUSH AF F5
Save Register AF onto the stack, preserving A (the error code from 6141H, typically 71H) and the flags.
61DF
GOSUB to 65A8H to retrieve the file's maximum position or size information. On return, Register A holds a byte position value and Register Pair HL and DE hold related position data.
61E2
NOP 00
No operation. This NOP may be a placeholder left from a development or patch cycle, or it may align the following instruction to a specific address.
61E3
SUB (IX+15H) DD 96 15
SUBtract the byte at IX+15H (the record position within the sector) from Register A. This computes the remaining bytes in the current record from the file's perspective.
61E6
SBC HL,DE ED 52
Subtract Register Pair DE (with borrow from the SUB) from Register Pair HL. This computes the remaining position capacity as a 16-bit value.
61E8
If the NO CARRY FLAG is set (no borrow - the remaining capacity is sufficient or the file has room), JUMP forward to 61F4H to check the EOF flag.
61EA
ADD A,B 80
ADD Register B (the record count) to Register A (the remaining byte count). This adjusts the position calculation by adding back the record count to see if the total fits.
61EB
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H. This prepares for the ADC HL,DE which propagates the carry from the ADD A,B into the 16-bit result.
61EE
ADC HL,DE ED 5A
ADD Register Pair DE (0000H) with carry to Register Pair HL. This propagates the carry from the 8-bit ADD A,B at 61EAH into the 16-bit HL value, completing the 24-bit position adjustment.
61F0
If the NO CARRY FLAG is set (the adjusted position is within bounds), JUMP forward to 61FBH to restore registers and continue with the write operation.
61F4
BIT 7,(IX+01H) DD CB 01 7E
Test bit 7 of IX+01H (the secondary FCB flags byte). Bit 7 is the EOF flag - set when the file has reached its end-of-file condition.
61F8
If the Z FLAG is set (bit 7 is clear - EOF has NOT been reached, meaning the file still has defined boundaries that would be exceeded), JUMP to 5DC1H - error code 90H (position past end of file). The operation would write beyond the file's current extent without EOF mode active.
61FB
POP AF F1
Restore Register AF from the stack.
61FC
POP HL E1
Restore Register Pair HL from the stack.
61FD
GOSUB to 6205H - the SVC write dispatch routine (LD DE,001BH / JR 621EH). This performs the actual write operation through the DOS.
6200
LD A,B 78
Load Register A with Register B (the record count / byte to write).
6201
OR A B7
OR Register A with itself to test whether B is zero.
6202
RET Z C8
If the Z FLAG is set (B is zero - no more bytes to write), RETURN to the caller.
6203
JUMP forward to 620AH to check bit 2 of IX+2DH and potentially perform an additional DOS call with DE=443CH.
6205H - SVC Write Dispatch (DE=001BH)
This utility loads DE with 001BH - a DOS SVC parameter for a write operation - and jumps to the common SVC dispatcher at 621EH. Called from 606BH (character output), 61FDH (record validator), and other write paths.
6205
LD DE,001BH 11 1B 00
Load Register Pair DE with 001BH - a DOS SVC parameter that specifies a byte-level write operation to the file.
6208
JUMP forward to 621EH - the common SVC dispatch entry that calls the DOS routine via the stack trick at 622DH.
620AH - Conditional DOS Call (DE=443CH or 4436H)
This routine checks bit 2 of IX+2DH (buffer operation flag). If set, it returns immediately. Otherwise, it falls through to load DE with either 443CH or 4436H (DOS file operation entry points), sets or clears bit 7 of IX+0EH, stores A at 5716H, and calls 621EH. The two entry points at 620AH and 6214H use 443CH and 4436H respectively.
620A
BIT 2,(IX+2DH) DD CB 2D 56
Test bit 2 of IX+2DH (the buffer flags byte). Bit 2 indicates a buffer operation is already in progress.
620E
RET NZ C0
If bit 2 is set (NZ - buffer operation active), RETURN immediately. No additional DOS call is needed.
620F
LD DE,443CH 11 3C 44
Load Register Pair DE with 443CH - a DOS entry point for a file read/position operation.
6212
JUMP forward to 6217H to set bit 7 of IX+0EH and continue with the SVC dispatch.
6214
LD DE,4436H 11 36 44
Load Register Pair DE with 4436H - a DOS entry point for a file write operation. This is an alternate entry for write-mode dispatch.
6217
SET 7,(IX+0EH) DD CB 0E FE
Set bit 7 of IX+0EH (a secondary FCB flag byte). Bit 7 marks that a DOS file operation has been initiated and the results need post-processing.
621B
LD (5716H),A 32 16 57
SELF-MODIFYING CODE - 5716H is a runtime variable
Store Register A at 5716H - the position parameter byte in the FCB work area. This preserves the current byte value for the DOS routine.
621EH - Common SVC Dispatch Entry [PUBLIC - Called by SYS10, SYS20]
This is the central dispatch point for all DOS file SVC operations in BASIC/CMD. It calls 622DH (which pushes the DOS routine address from DE onto the stack and loads DE=570DH), executes the DOS routine via the RET trick, checks for errors (calling 5DEFH if NZ), and then conditionally calls 610AH (SVC 2CH position store) if the self-modifying byte at 6226H is non-zero.
621E
GOSUB to 622DH. This routine pushes DE (the DOS routine address, e.g. 444EH, 001BH, 443CH) onto the stack, then loads DE=570DH and executes RET. The RET pops the DOS address from the stack and transfers control to the DOS routine with DE pointing to the FCB work area at 570DH. When the DOS routine completes, it returns here (to 6221H).
6221
If the NZ FLAG is set (the DOS routine returned an error), GOSUB to 5DEFH - the DOS-to-BASIC error translator. This converts the DOS error code to a BASIC error code and dispatches to the error handler.
6224
PUSH AF F5
Save Register AF onto the stack, preserving the DOS return value and flags.
6225
LD A,00H 3E 00
Load Register A with 00H.
Note: Address 6226H (the immediate operand) is a self-modifying target written by 642DH and SYS10/4D05H. At runtime, this byte may be non-zero, indicating that post-operation position storing should be performed.
6227
OR A B7
OR Register A with itself to test whether the self-modifying byte at 6226H is non-zero.
6228
If the NZ FLAG is set (the self-modifying byte at 6226H was non-zero - post-operation position store is requested), GOSUB to 610AH - the SVC 2CH helper that stores the current position at IX+04H and 5705H.
622B
POP AF F1
Restore Register AF from the stack (the DOS return value).
622C
RET C9
RETURN to the caller. The DOS file operation has been completed, any errors have been handled, and the position has been optionally updated.
622DH - Stack Trick for DOS Dispatch
This three-instruction routine implements the classic Z80 "RET as indirect CALL" trick. It pushes DE (containing the DOS routine address) onto the stack, loads DE with 570DH (the FCB work area pointer), and executes RET - which pops the DOS address from the stack and jumps to it. The DOS routine sees DE=570DH and the return address on the stack is 6221H (the instruction after the CALL 622DH at 621EH).
622D
PUSH DE D5
Save Register Pair DE (the DOS routine address - e.g. 444EH, 001BH, 0013H, 443CH, 4436H) onto the stack. This becomes the "return address" for the RET at 6231H.
622E
LD DE,570DH 11 0D 57
Load Register Pair DE with 570DH - the filename/data buffer address in the FCB work area. The DOS routine expects DE to point to the file control information.
6231
RET C9
RETURN - but this pops the DOS routine address (pushed at 622DH) from the stack and transfers control to that DOS routine. The DOS routine will execute with DE=570DH and will return to 6221H (the address pushed by the CALL 622DH at 621EH).
6232H - DOS Write with RES Bit 7 (DE=4436H Entry)
These short entry points load DE with DOS routine addresses and dispatch through 621EH. The 6232H and 6237H entries clear bit 7 of IX+0EH (via RES at 623AH) before dispatching, while 6240H dispatches directly.
6232
LD DE,4436H 11 36 44
Load Register Pair DE with 4436H - a DOS file write entry point.
6235
JUMP forward to 623AH to clear bit 7 of IX+0EH and dispatch via 621EH.
6237
LD DE,443CH 11 3C 44
PUBLIC - called by SYS10
Load Register Pair DE with 443CH - a DOS file read/position entry point.
623A
RES 7,(IX+0EH) DD CB 0E BE
Clear bit 7 of IX+0EH (the secondary FCB flag byte). This resets the "DOS operation initiated" flag that was set at 6217H, indicating that the current operation sequence is being reset or restarted.
623E
JUMP back to 621EH to dispatch the DOS routine through the common SVC entry.
6240
LD DE,443FH 11 3F 44
PUBLIC - called by SYS19
Load Register Pair DE with 443FH - another DOS entry point for file operations.
6243
JUMP back to 621EH to dispatch through the common SVC entry.
6245H - Position Advance with Overflow Check
This routine advances the current file position by B bytes. It loads the current position via 61ACH, adds B to the sector offset (C), propagates the carry into HL, and if no overflow occurs, dispatches through 61A6H (444EH). If the addition causes a 16-bit overflow (carry from ADC HL,DE), the file has been positioned past its end, so error code 1DH (position past EOF) is raised via 5DEFH.
6245
LD A,B 78
Load Register A with Register B (the number of bytes to advance the file position).
6246
GOSUB to 61ACH to load the current file position. Register C = sector offset (IX+12H), Register Pair HL = position word (5717H).
6249
ADD A,C 81
ADD Register C (the current sector offset) to Register A (the byte advance count). If A+C overflows past FFH, the CARRY FLAG is set - the advance crosses a sector boundary.
624A
LD C,A 4F
Load Register C with Register A (the new sector offset after the advance).
624B
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H. This prepares for the ADC HL,DE which propagates the carry from the ADD A,C into the 16-bit position word.
624E
ADC HL,DE ED 5A
ADD Register Pair DE (0000H) with carry to Register Pair HL. This propagates the carry from the 8-bit addition at 6249H into the 16-bit position word. If HL was FFFFH and carry was set, HL wraps to 0000H and the CARRY FLAG is set (24-bit overflow).
6250
If the NO CARRY FLAG is set (no 16-bit overflow - the new position is valid), JUMP to 61A6H to dispatch the position write through DOS entry 444EH.
6253
LD A,1DH 3E 1D
Load Register A with 1DH - DOS error code for "position past end of file." The 16-bit overflow means the file position has exceeded its maximum addressable range.
6255
Unconditional JUMP to 5DEFH - the DOS-to-BASIC error translator, which converts error code 1DH to a BASIC error and dispatches to the error handler.
6258H - Record Advance Helper [PUBLIC - Called by SYS10]
This routine advances to the next record by rearranging the position bytes, calling the position comparison at 6334H, the record type decoder at 626CH, and conditionally the position advance at 6246H. It returns with CARRY set on error, or NZ with FFH (OR FFH) on success. Called from 6003H (file position loop) and by SYS10.
6258
PUSH HL E5
Save Register Pair HL onto the stack.
6259
PUSH BC C5
Save Register Pair BC onto the stack.
625A
LD H,L 65
Load Register H with Register L. This rearranges the position bytes - the low byte of the position moves to the high byte position, creating a byte-swapped value for the comparison at 6334H.
625B
LD L,C 69
Load Register L with Register C (the sector offset). HL now holds L:C - the rearranged position value for comparison.
625C
GOSUB to 6334H - the position comparison routine that subtracts the record base position (5707H) from the current position (now in HL after rearrangement), then subtracts the byte offset (5702H). Returns NC if the position is valid, C if it would underflow.
625F
GOSUB to 626CH - the record type decoder. This calls 61C3H (DOS position read with DE=0013H), then decodes the returned A value into a mode flag in Register B. Returns Z if no record, NZ with mode flags if valid.
6262
LD A,B 78
Load Register A with Register B (the decoded record type / mode flags from 626CH).
6263
POP BC C1
Restore Register Pair BC from the stack.
6264
POP HL E1
Restore Register Pair HL from the stack.
6265
RET C D8
If the CARRY FLAG is set (error from 6334H or 626CH), RETURN with carry indicating failure.
6266
If the NZ FLAG is set (valid record type in A - B was non-zero from 626CH), GOSUB to 6246H to advance the file position by A bytes (the record's byte count).
6269
OR FFH F6 FF
OR Register A with FFH. This sets A to FFH and sets the NZ FLAG (since FFH is non-zero). This serves as a "success" indicator: A=FFH, NZ=true.
626B
RET C9
RETURN to the caller with A=FFH and NZ indicating success. The file position has been advanced by one record.
626CH - Record Type Decoder [PUBLIC - Called by SYS10]
This routine reads a record type byte from the file (via 61C3H / DOS position read) and decodes it into a mode flag value in Register B. The decoding works by subtracting 80H and then 10H from the raw byte, then using a cascading series of DEC A / JR Z tests to map the type value to specific bit patterns: B=02H, B=04H, or B=08H. If none match, it raises error 2AH at 5D9DH. A type value that causes carry after ADD 80H or ADD 10H gets special handling via 628DH (calls 61C3H again and returns with A=03H).
626C
GOSUB to 61C3H - the DOS position read dispatcher (DE=0013H). This performs a position-read operation on the file and returns with Register A holding the record type byte and the file position advanced.
626F
OR A B7
OR Register A with itself to test whether the record type byte is zero.
6270
RET Z C8
If the Z FLAG is set (record type byte is zero - no record or end of data), RETURN with Z indicating no valid record was found.
6271
ADD 80H C6 80
ADD 80H to Register A. This shifts the type byte range: values 80H-FFH become 00H-7FH (with carry), values 00H-7FH become 80H-FFH (without carry). If the original byte was 80H or above, CARRY is set.
6273
If the CARRY FLAG is set (original type byte was 80H or above - a high-range type code), JUMP to 6290H to handle it as a special type (B=A, A=03H, return NZ).
6275
ADD 10H C6 10
ADD 10H to Register A. Further adjusts the type value for the cascading decode. Values that were originally 70H (now 00H after +80H) produce a Z result here (00H+10H=10H... no, 00H+10H=10H). This tests whether the original value was 70H: 70H+80H=F0H with carry... actually the ADD 80H at 6271H needs to NOT carry for us to reach here. So original was 00H-7FH. After +80H: 80H-FFH. Then +10H: 90H-0FH (with potential carry). The exact decode depends on the specific type codes used by NEWDOS/80.
6277
RET Z C8
If the Z FLAG is set after the ADD 10H (the adjusted result is zero - corresponding to a specific type code), RETURN with Z set. This indicates a type that does not require further processing.
6278
DEC A 3D
DECrement Register A by 1. This is the first step of the cascading type decode.
6279
If the Z FLAG is set (adjusted type code was 01H - meaning the original type decodes to "call 61C3H again"), JUMP to 628DH to perform another position read and return with A=03H.
627B
LD B,02H 06 02
Load Register B with 02H - a mode flag value for one type of record (output/write mode). This is the tentative assignment if the next DEC A produces Z.
627D
DEC A 3D
DECrement Register A by 1. If A was 02H (adjusted), it is now zero.
627E
If the Z FLAG is set (original type decodes to B=02H), JUMP to 628BH to merge: OR B and return.
6280
LD B,04H 06 04
Load Register B with 04H - a mode flag for random access mode.
6282
DEC A 3D
DECrement Register A by 1.
6283
If the Z FLAG is set (original type decodes to B=04H), JUMP to 628BH.
6285
LD B,08H 06 08
Load Register B with 08H - a mode flag for append mode.
6287
DEC A 3D
DECrement Register A by 1.
6288
If the NZ FLAG is set (none of the type codes matched - unknown record type), JUMP to 5D9DH - error code 2AH (general error). The record type byte is not a recognized value.
628B
OR B B0
OR Register A (now zero from the DEC that matched) with Register B (the mode flag: 02H, 04H, or 08H). Register A now holds the mode flag value, and since B was non-zero, NZ is set.
628C
RET C9
RETURN to the caller with A=mode flag (02H, 04H, or 08H) and NZ indicating a valid record type was decoded.
628D
GOSUB to 61C3H - perform another DOS position read (DE=0013H). This reads a second byte from the file (the extended type information).
6290
LD B,A 47
Load Register B with Register A (the type value - either the second byte from 628DH or the high-range type from 6273H).
6291
LD A,03H 3E 03
Load Register A with 03H - a combined mode flag indicating both read and write modes (bits 0 and 1 set).
6293
OR A B7
OR Register A with itself to set NZ (since 03H is non-zero). This ensures the NZ flag is set on return.
6294
RET C9
RETURN to the caller with A=03H (read+write mode), B=type value, NZ=valid record type.
6295H - File Number Eval + FCB Lookup
This routine combines file number evaluation (5F53H) with FCB lookup (6298H). It calls 5F53H to parse the file number and compute the FCB address in BC, then falls through to 6298H to load the FCB data into the work area at 5700H. Called from 60FEH, 6101H, and 62C0H.
6295
GOSUB to 5F53H to parse the file number from the BASIC text, validate the range, and calculate the FCB address. On return, Register Pair BC holds the FCB base address and HL holds the updated BASIC text pointer.
6298H - FCB Lookup and Work Area Copy
This routine loads the FCB data from the user's FCB (pointed to by BC from 5F53H or 6295H) into the system work area at 5700H. It first checks the guard flag at 6382H - if the guard is already active (non-zero), it raises error A4H at 5DD9H (re-entrant file access attempt). Otherwise, it stores the FCB pointer at 6352H, enables the guard via 6386H, sets IX=5700H, initializes IX+2DH to 2DH, and uses LDIR to copy 2DH (45) bytes from the user FCB into 5700H-572CH. On return, A holds the FCB status byte and Z/NZ indicates whether the file is open.
6298
LD A,(6382H) 3A 82 63
Load Register A with the byte at 6382H - the file guard flag (self-modifying code byte). If this byte is 00H (NOP), no file operation is in progress. If C9H (RET), a file operation is already active.
629B
OR A B7
OR Register A with itself to set the flags. If the guard flag is non-zero (a file operation is already in progress), NZ is set.
629C
If the NZ FLAG is set (guard flag is active - re-entrant file access), JUMP to 5DD9H - error code A4H (re-entrant file operation). This prevents concurrent access to the file I/O system which could corrupt the work area at 5700H.
629F
PUSH HL E5
Save Register Pair HL (BASIC text pointer) onto the stack.
62A0
LD H,B 60
Load Register H with Register B (high byte of the FCB address from BC).
62A1
LD L,C 69
Load Register L with Register C (low byte of the FCB address). Register Pair HL now points to the user's FCB.
62A2
LD (6352H),HL 22 52 63
SELF-MODIFYING CODE - 6352H is a runtime variable
Store Register Pair HL (the user's FCB address) at 6352H. This saves the pointer for later use when the work area data needs to be written back.
62A5
GOSUB to 6386H to enable the file guard flag. This writes C9H (RET opcode) to 6382H, preventing re-entrant access to the file I/O work area.
62A8
LD DE,5700H 11 00 57
Load Register Pair DE with 5700H - the FCB work area base address. This is the destination for the LDIR copy.
62AB
PUSH DE D5
Save Register Pair DE (5700H) onto the stack.
62AC
POP IX DD E1
Pop the value (5700H) into Register Pair IX. IX now points to the FCB work area at 5700H, providing indexed access to the work area fields (IX+00H, IX+04H, IX+12H, etc.).
62AE
LD (IX+2DH),2DH DD 36 2D 00
Store 00H into IX+2DH (address 572DH) - initialize the buffer flags byte to zero.
Note: The disassembly shows the instruction as "LD (IX+2DH),2DH" but the actual bytes DD 36 2D 00 decode as LD (IX+2DH),00H. The 2DH in the mnemonic column is the offset, not the stored value. The value stored is 00H.
62B2
LD BC,002DH 01 2D 00
Load Register Pair BC with 002DH (45 decimal) - the number of bytes to copy from the user's FCB to the work area. This covers FCB offsets 00H through 2CH.
62B5
LDIR ED B0
Block copy: copy BC (45) bytes from the source at (HL) - the user's FCB - to the destination at (DE) - the work area at 5700H. After execution, HL and DE point past the copied data.
62B7
POP HL E1
Restore Register Pair HL from the stack (the BASIC text pointer).
62B8
LD A,(5700H) 3A 00 57
Load Register A with the byte at 5700H - the first byte of the copied FCB data (the file status flags byte).
62BB
OR A B7
OR Register A with itself to set the flags. Z indicates the file is not open (status byte is zero), NZ indicates the file is open.
62BC
RET C9
RETURN to the caller. IX=5700H, A=FCB status byte, Z/NZ=file open state. The work area at 5700H now contains a copy of the user's FCB data.
62BDH - FCB Lookup from Saved Pointer
Short entry that pushes HL and jumps to 62A8H, using the current HL value as a saved context while the FCB work area is initialized from 5700H.
62BD
PUSH HL E5
Save Register Pair HL onto the stack.
62BE
JUMP back to 62A8H to set DE=5700H, IX=5700H, clear IX+2DH, copy 2DH bytes via LDIR, and return with the FCB status in A.
62C0H - File Number Eval + Comma + FCB Status [PUBLIC - Called by SYS20]
This routine evaluates a file number (via 6295H), verifies a comma follows (RST 08H / SYNCHR ','), then jumps to 62B8H to read the FCB status. Called from 5F3CH (PRINT# channel setup) and by SYS20.
62C0
GOSUB to 6295H to parse the file number and set up the FCB work area at 5700H.
62C3
RST 08H ⇒ 2CH CF 2C
Call SYNCHR via RST 08H - verify the next BASIC text character matches ",". If not, this triggers a syntax error. If yes, this confirms the syntax "file_number, ..."
62C5
JUMP back to 62B8H to load the FCB status byte from 5700H, set flags, and return.
62C7H - Buffer Position Valid Check [PUBLIC - Called by SYS10]
This routine checks bit 6 of IX+2DH (buffer position valid flag). If clear, it jumps to error 9EH at 5DD3H. If set, it returns Z. The 62CEH entry provides an alternate path that first increments DE and tests bit 6 with the opposite polarity (returns NZ if valid).
62C7
BIT 6,(IX+2DH) DD CB 2D 76
Test bit 6 of IX+2DH (the buffer flags byte). Bit 6 indicates the buffer position is valid - the buffer contains data that corresponds to the current file position.
62CB
RET Z C8
If bit 6 is clear (Z - buffer position is NOT valid), RETURN with Z set. The caller must handle the invalid buffer case.
62CC
JUMP forward to 62D5H to dispatch error 9EH at 5DD3H. If we reach here, bit 6 was set but the routine falls through to the error - this path is used when the buffer IS valid but that condition is unexpected.
62CE
EX DE,HL EB
Exchange Register Pairs DE and HL.
62CF
INC DE 13
INCrement Register Pair DE by 1.
62D0
BIT 6,(IX+2DH) DD CB 2D 76
Test bit 6 of IX+2DH (buffer position valid flag).
62D4
RET NZ C0
If bit 6 is set (NZ - buffer position IS valid), RETURN with NZ. The buffer is valid and DE has been incremented.
62D5
Unconditional JUMP to 5DD3H - error code 9EH (buffer position invalid). The buffer does not contain valid data for the current file position.
62D8H - Write Mode and Variable Reader [PUBLIC - Called by SYS10]
This routine checks if the file is in write mode (bit 1 of IX+00H), loads the max record size from 5094H, checks whether the current character is '#' or '$' (which trigger the 62CEH increment path), and otherwise evaluates a variable reference (via ROM 260DH), loads the variable length into B, checks the variable type (RST 20H), and validates buffer position for string variables. Called from SYS10 for reading/writing variable data to files.
62D8
BIT 1,(IX+00H) DD CB 00 4E
Test bit 1 of IX+00H (the primary FCB status flags byte). Bit 1 indicates write mode is active for this file.
62DC
RET Z C8
If bit 1 is clear (Z - file is not in write mode), RETURN immediately. No variable writing is needed.
62DD
LD A,(5094H) 3A 94 50
Load Register A with the byte at 5094H - the maximum record size or sector size from the DOS system variables.
62E0
LD C,A 4F
Load Register C with Register A (the max record size). Register C preserves this value during the subsequent processing.
62E1
LD A,(HL) 7E
Load Register A with the byte at (HL) - the current character at the BASIC text pointer.
62E2
CP 23H FE 23
Compare Register A against 23H (ASCII '#'). The '#' prefix indicates a numeric variable with special file formatting.
62E4
If the Z FLAG is set (character is '#'), JUMP back to 62CEH to exchange DE/HL, increment DE, and check the buffer position validity.
62E6
CP 24H FE 24
Compare Register A against 24H (ASCII '$'). The '$' suffix indicates a string variable.
62E8
If the Z FLAG is set (character is '$'), JUMP back to 62CEH for the same increment-and-validate path.
62EA
PUSH BC C5
Save Register Pair BC (C=max record size) onto the stack.
62EB
GOSUB to ROM 260DH - the variable reference evaluator. This parses the variable name from the BASIC text, looks up the variable in the variable table, and returns with HL pointing to the variable's data and DE pointing to the next BASIC text position.
62EE
POP BC C1
Restore Register Pair BC (C=max record size).
62EF
EX DE,HL EB
Exchange Register Pairs DE and HL. HL now holds the BASIC text pointer (returned in DE by 260DH), and DE holds the variable data pointer.
62F0
LD B,(HL) 46
Load Register B with the byte at (HL) - the variable's length or type byte.
Note: After the EX DE,HL, HL actually holds the BASIC text position, not the variable data. This reads the next character of the BASIC text, which serves as a length/type indicator for the file write formatting.
62F1
RST 20H E7
Call GETYP via RST 20H to check the current variable type. Z=string, NZ=numeric.
62F2
If the NZ FLAG is set (variable is numeric, not a string), JUMP forward to 62FBH to skip the string-specific buffer check.
62F4
BIT 6,(IX+2DH) DD CB 2D 76
Test bit 6 of IX+2DH (buffer position valid flag). For string variables, the buffer must be in a valid state.
62F8
If bit 6 is clear (Z - buffer position is invalid for a string variable), JUMP to 5DD3H - error code 9EH. String variable data requires a valid buffer position.
62FB
OR D B2
OR Register A with Register D. This combines the type check result with the high byte of the variable address. The result is used to set NZ if D is non-zero (variable has a valid address).
62FC
LD A,00H 3E 00
Load Register A with 00H. This clears A without affecting the flags set by the OR D instruction.
62FE
RET C9
RETURN to the caller. A=00H, Z/NZ reflects whether the variable address is valid (NZ=valid, Z=null address).
62FFH - Buffer State and Position Decision Logic
This routine reads the FCB status at 5700H and examines multiple bit combinations (bits 4, 3, 2, 1, 0 of the status byte and bits 4, 3 of IX+2DH) to determine the correct buffer handling path. It is the central decision point for whether the file buffer needs flushing, position comparison, or zero-filling before the next operation. Depending on the bit pattern, it routes to the position subtraction at 61BAH/6185H or to the stored record limit at 61CAH/6185H.
62FF
LD A,(5700H) 3A 00 57
Load Register A with the byte at 5700H - the primary FCB status flags.
6302
BIT 4,A CB 67
Test bit 4 of Register A. Bit 4 indicates a special file mode (e.g., append or extended access).
6304
RET Z C8
If bit 4 is clear (Z - no special mode), RETURN. No buffer state adjustment is needed.
6305
BIT 3,A CB 5F
Test bit 3 of Register A. Bit 3 indicates a buffer-related flag.
6307
RET Z C8
If bit 3 is clear (Z), RETURN. Both bits 4 and 3 must be set for the buffer state logic to apply.
6308
LD B,(IX+2DH) DD 46 2D
Load Register B with the byte at IX+2DH - the buffer flags byte. Used for additional bit testing below.
630B
BIT 1,A CB 4F
Test bit 1 of Register A (write mode flag).
630D
If bit 1 is set (NZ - write mode active), JUMP forward to 6328H to check bit 4 of B and use the stored record limit at 61CAH.
630F
BIT 0,A CB 47
Test bit 0 of Register A (read mode flag).
6311
RET Z C8
If bit 0 is clear (Z - neither read nor write), RETURN.
6312
BIT 2,A CB 57
Test bit 2 of Register A (random access mode flag).
6314
If bit 2 is set (NZ - random access mode), JUMP forward to 632BH to use the stored record limit at 61CAH for the zero-fill loop.
6316
BIT 4,B CB 60
Test bit 4 of Register B (IX+2DH buffer flags). Bit 4 is the "dirty" flag set at 6162H.
6318
RET NZ C0
If bit 4 is set (NZ - buffer is already dirty), RETURN. No additional buffer state processing is needed.
6319
BIT 3,B CB 58
Test bit 3 of Register B (IX+2DH buffer flags). Bit 3 is an additional buffer state flag.
631B
If bit 3 is clear (Z - no special buffer state), JUMP forward to 632BH to use the record limit for zero-fill.
Position Subtraction Path
Both bits 4 and 3 of the status are set, read mode is active, not random access, buffer is not dirty, and buffer bit 3 IS set. This specific combination requires computing the difference between the alternate and current positions, then zero-filling that many bytes.
631D
GOSUB to 61BAH to load both positions. On return, HL=current position word, DE=alternate position word, C=current sector offset, A=alternate sector byte.
6320
SUB C 91
SUBtract Register C (current sector offset) from Register A (alternate sector byte). The result is the byte difference between the two sector offsets.
6321
EX DE,HL EB
Exchange Register Pairs DE and HL. HL now holds the alternate position word, DE holds the current.
6322
SBC HL,DE ED 52
Subtract DE (current position) from HL (alternate position) with borrow from the SUB at 6320H. The result is the number of positions (sectors/records) between the two.
6324
LD H,L 65
Load Register H with Register L. This rearranges the result - moving the low byte up to H for the byte count format expected by 6185H.
6325
LD L,A 6F
Load Register L with Register A (the byte difference from the SUB at 6320H). HL now holds the total byte count to zero-fill.
6326
JUMP forward to 632EH to dispatch the zero-fill loop at 6185H.
6328
BIT 4,B CB 60
Test bit 4 of Register B (IX+2DH buffer dirty flag). This is the write-mode path from 630DH.
632A
RET Z C8
If bit 4 is clear (Z - buffer is not dirty), RETURN. No flushing is needed.
632B
LD HL,(61CAH) 2A CA 61
Load Register Pair HL with the 16-bit value at 61CAH - the stored record limit value, computed and stored by the record position validator at 61C8H. This is the negative of (B+1), which represents the remaining bytes to zero-fill.
632E
Unconditional JUMP to 6185H - the HL decrement loop (zero-fill writer). This writes HL zero bytes to the file, filling the remaining buffer space before the next record boundary.
6331H - Position Comparison (5704H vs 5707H and 5702H)
This routine compares position values from the FCB work area. It loads HL from 5704H and DE from 5707H, subtracts DE from HL (with entry at 6334H), then loads HL from 5702H and subtracts the result from HL. Returns NC if the position is within bounds, or C with JP to error 8EH at 5DBEH if the position would underflow. Used by 625CH (record advance helper).
6331
LD HL,(5704H) 2A 04 57
Load Register Pair HL with the 16-bit value at 5704H - a position comparison value from the FCB work area.
6334
LD DE,(5707H) ED 5B 07 57
Load Register Pair DE with the 16-bit value at 5707H - the record base position word from the FCB work area.
6338
OR A B7
Clear the CARRY FLAG (OR A always clears carry). Prepares for the SBC that follows.
6339
SBC HL,DE ED 52
Subtract Register Pair DE (record base position) from Register Pair HL (comparison position) without borrow. The result is the offset of the comparison position relative to the record base.
633B
EX DE,HL EB
Exchange Register Pairs DE and HL. DE now holds the offset result, HL is free for the next load.
633C
LD HL,(5702H) 2A 02 57
Load Register Pair HL with the 16-bit value at 5702H - the byte offset within the current record.
633F
OR A B7
Clear the CARRY FLAG for the next SBC.
6340
SBC HL,DE ED 52
Subtract Register Pair DE (the position offset) from Register Pair HL (the byte offset). If the byte offset is less than the position offset, CARRY is set (underflow - position is past the current record).
6342
RET NC D0
If the NO CARRY FLAG is set (the byte offset is greater than or equal to the position offset - the position is within the current record), RETURN. The position is valid.
6343
If carry was set (position underflow - the record would be accessed past its boundary), JUMP to 5DBEH - error code 8EH (record position overflow).
6346H - Position-to-Record Conversion [PUBLIC - Called by SYS10]
This routine converts the current file position (from 61ACH) into a format suitable for the position comparison at 6334H. It loads the current position (C=sector offset, HL=position word), rearranges the bytes (H=L, L=C), and jumps to 6334H for the comparison.
6346
GOSUB to 61ACH to load the current file position. C = sector offset (IX+12H), HL = position word (5717H).
6349
LD H,L 65
Load Register H with Register L (move the low byte of the position word to the high byte position).
634A
LD L,C 69
Load Register L with Register C (the sector offset). HL now holds L:C - the rearranged current position for comparison.
634B
JUMP back to 6334H to perform the position comparison against the record base (5707H) and byte offset (5702H).
634DH - FCB Work Area Writeback
This routine writes the FCB work area at 5700H back to the user's FCB. It pushes HL, loads HL=5700H as the source, DE=0000H (which will be replaced by the LDIR at 62B2H using the stored FCB pointer context), and jumps to 62B2H to copy 2DH bytes back. Called from 6357H (BASIC statement completion handler).
634D
PUSH HL E5
Save Register Pair HL onto the stack.
634E
LD HL,5700H 21 00 57
Point Register Pair HL to 5700H - the FCB work area base. This is the source for the LDIR copy.
6351
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H.
Note: The actual destination address is determined by the stored FCB pointer at 6352H. The LD DE,0000H at 6351H uses address 6352H-6353H as its operand, and 6352H is written at runtime by 62A2H with the actual FCB address. So this instruction effectively becomes LD DE,(stored_fcb_ptr)
6354
JUMP to 62B2H to execute LD BC,002DH / LDIR - copy 45 bytes from the work area (5700H) to the user's FCB (address in DE, loaded from the self-modifying operand at 6352H). Then POP HL and return.
6357H - BASIC Statement Completion Handler
This routine is the standard completion point after file I/O operations. It is used as a return address (pushed at 6024H before JP 098DH) and called directly from various paths. It calls 634DH to write the FCB work area back to the user's FCB, then calls 635AH to clear the work area and disable the guard flag.
6357
GOSUB to 634DH to write the FCB work area (5700H) back to the user's FCB at the address stored in 6352H. This persists any changes made during the file operation.
635AH - Clear FCB Work Area and Disable Guard
This routine clears the entire FCB work area (5700H-572DH) by filling it with 2EH (46) zero bytes, and disables the file guard flag by calling 6392H. This is the cleanup routine called after file operations complete, restoring the work area and guard flag to their idle state.
635A
PUBLIC - called by SYS19
GOSUB to 6392H to disable the file guard flag. This writes 00H (NOP) to 6382H, allowing the next file operation to proceed without a re-entrancy error.
635D
LD HL,5700H 21 00 57
Point Register Pair HL to 5700H - the start of the FCB work area.
6360
LD B,2EH 06 2E
Load Register B with 2EH (46 decimal) - the number of bytes to clear. This covers the entire FCB work area from 5700H through 572DH.
Zero-Fill Loop
This DJNZ loop writes 00H to each byte from 5700H through 572DH, clearing the entire FCB work area.
6362
LD (HL),00H 36 00
LOOP START
Store 00H at the current (HL) position - clearing the byte.
6364
INC HL 23
INCrement Register Pair HL to point to the next byte.
6365
LOOP END
DECrement Register B and LOOP back to 6362H if not zero. Continues clearing until all 46 bytes have been written.
6367
RET C9
RETURN to the caller. The FCB work area at 5700H-572DH has been cleared to all zeros and the guard flag has been disabled.
6368H - Comma Checker [PUBLIC - Called by SYS10, SYS19, SYS20]
This routine checks whether a comma follows in the BASIC text. It backs up the text pointer by one (DEC HL), calls CHRGET (RST 10H) to re-read the current character, and if it is an end-of-statement (Z set), returns immediately. Otherwise, it calls SYNCHR (RST 08H) to verify a comma (2CH) is present - raising a syntax error if not. After the comma, it compares the next character against FFH and returns. This is the standard "check for more items in a list" utility, called extensively by SYS overlay modules.
6368
DEC HL 2B
DECrement Register Pair HL (BASIC text pointer) by 1, backing up to re-read the current character via CHRGET.
6369
RST 10H D7
Call CHRGET via RST 10H. Advance the text pointer past spaces and return the next non-space character in Register A. Z is set if end-of-statement (colon 3AH or NUL 00H), C if numeric digit.
636A
RET Z C8
If the Z FLAG is set (end-of-statement - no more items in the list), RETURN to the caller with Z indicating the list is complete.
636B
RST 08H ⇒ 2CH CF 2C
Call SYNCHR via RST 08H - verify the next character matches 2CH (ASCII comma) - the required separator between list items. SYNCHR advances the text pointer past this comma or issues a SYNTAX ERROR if the character wasn't a comma.
636D
CP FFH FE FF
Compare Register A (the character after the comma) against FFH. FFH is a special BASIC token that indicates end-of-line in some contexts. If A=FFH, Z is set; otherwise NZ is set indicating more text follows.
636F
RET C9
RETURN to the caller. NZ indicates more items follow the comma; Z indicates the comma was followed by an end marker.
6370H - File Write with Error Filter [PUBLIC - Called by SYS19]
This routine writes to a file via DOS entry 4436H, then filters the error result. If the write succeeds (Z), it returns immediately. If the error code is 1DH (position past EOF) or 1CH (position before start), it clears the error and returns Z (treating position errors as non-fatal). All other errors are passed to the DOS-to-BASIC error translator at 5DEFH.
6370
LD DE,570DH 11 0D 57
Load Register Pair DE with 570DH - the filename/data buffer address in the FCB work area. The DOS write routine expects DE to point to the file control data.
6373
GOSUB to DOS entry point 4436H - the file write routine. On return, Z indicates success, NZ indicates an error with the error code in Register A.
6376
RET Z C8
If the Z FLAG is set (write succeeded), RETURN immediately.
6377
CP 1DH FE 1D
Compare Register A (the error code) against 1DH (position past end of file).
6379
If the Z FLAG is set (error is 1DH - past EOF), JUMP forward to 6380H to clear the error and return success. Position-past-EOF is treated as a non-fatal condition during file writes.
637B
CP 1CH FE 1C
Compare Register A against 1CH (position before start of file).
637D
If the NZ FLAG is set (error is NOT 1CH - it is some other error besides position errors), JUMP to 5DEFH - the DOS-to-BASIC error translator for fatal error handling.
6380
OR A B7
OR Register A with itself. Since A is non-zero (it holds 1DH or 1CH), this sets NZ. However, the intent is to clear the carry flag, and the next instruction provides the actual return status.
6381
RET C9
RETURN to the caller. The position error has been absorbed - the write is treated as successful from the caller's perspective.
6382H - File Guard Flag (Self-Modifying Code)
This is the file guard flag mechanism - a block of self-modifying code that controls re-entrant access to the file I/O work area at 5700H. The first byte at 6382H is modified at runtime between 00H (NOP) and C9H (RET). When 00H: the sequence NOP / INC SP / INC SP / RET executes, which discards the caller's return address from the stack (INC SP twice pops 2 bytes) and returns to the caller's caller. When C9H: the RET executes immediately, returning normally. This provides a gating mechanism - when no file is active (00H), calling 6382H cancels the current operation; when a file is active (C9H), it passes through normally.
6382
NOP 00
SELF-MODIFYING CODE - 6382H is the guard flag byte
SELF MODIFYING INSTRUCTION! Currently, NO OPeration - the default state (no file channel active). At runtime, this byte is overwritten with C9H (RET) by 6386H when a file operation begins, and restored to 00H (NOP) by 6392H when the operation ends.
6383
INC SP 33
INCrement the Stack Pointer by 1. This is the first half of discarding the return address. When the guard is 00H (NOP), this instruction executes after the NOP.
6384
INC SP 33
INCrement the Stack Pointer by 1 again. Together with the previous INC SP, this removes the 2-byte return address that was pushed by the CALL instruction that invoked 6382H. The effect is that the RET at 6385H returns to the caller's caller, not to the immediate caller.
6385
RET C9
RETURN. When the guard is 00H (NOP state), this returns to the caller's caller (the return address was discarded by the two INC SP instructions). When the guard is C9H (RET state), execution never reaches here - the RET at 6382H returns immediately.
6386H - Enable File Guard [PUBLIC - Called by SYS19]
This routine enables the file guard flag by writing C9H (the RET opcode) to 6382H. After this call, any subsequent call to 6382H will execute RET immediately, allowing the file operation to proceed normally. Called from 62A5H (during FCB lookup) and by SYS19.
6386
LD A,C9H 3E C9
Load Register A with C9H - the Z80 opcode for RET. This is the "guard enabled" value.
6388
LD (6382H),A 32 82 63
SELF-MODIFYING CODE - writes to 6382H
Store Register A at 6382H - overwriting the first byte of the guard flag routine.
638B
RET C9
RETURN to the caller. The guard is now enabled.
638CH - Save and Clear Guard [PUBLIC - Called by SYS19]
This routine saves the current guard flag state to the backup location at 6396H, then clears the guard by falling through to 6392H. This allows a nested operation to temporarily disable the guard while preserving the ability to restore it later via 6395H.
638C
LD A,(6382H) 3A 82 63
Load Register A with the byte at 6382H - the current guard flag value (00H or C9H).
638F
LD (6396H),A 32 96 63
SELF-MODIFYING CODE - 6396H is the guard backup variable
Store Register A at 6396H - saving the current guard state for later restoration.
6392H - Disable File Guard [PUBLIC - Called by SYS19]
This routine disables the file guard flag by writing 00H (NOP) to 6382H. After this call, any call to 6382H will execute the NOP / INC SP / INC SP / RET sequence, which discards the return address and cancels the file operation. Called from 635AH (clear work area) and as the fallthrough from 638CH.
6392
XOR A AF
Clear Register A to zero (00H - the NOP opcode, which is the "guard disabled" value).
6393
JUMP back to 6388H to store 00H at 6382H, disabling the guard.
6395H - Restore Guard from Backup
This routine restores the guard flag from the backup stored at 6396H (saved by 638CH). The operand of the LD A instruction at 6396H is the self-modifying byte that holds the saved guard value.
6395
LD A,00H 3E 00
Load Register A with 00H.
The immediate operand at address 6396H is self-modifying - it was written by 638FH with the saved guard state (00H or C9H). At runtime, this instruction loads A with whatever value was saved.
6397
JUMP back to 6388H to store the restored guard value at 6382H.
6399H - BASIC Line Execution Intercept
This routine is called during BASIC line execution as an intercept/hook. It pops AF (restoring the BASIC execution state), swaps HL with the stack (getting the line address), and compares the BASIC text pointer against two ROM addresses: 1D9EH (a specific BASIC execution point) and 1D21H (another execution context). If the pointer matches 1D9EH, it jumps to 63F8H (the single-step check). If it matches 1D21H, it calls 641EH (which stores A at 645BH) and reads the next byte. If neither matches, it jumps to ROM 035BH (a BASIC execution handler). This is the mechanism that enables single-step mode (CMD"F=SS") to intercept each line.
6399
POP AF F1
Restore Register AF from the stack - recovering the BASIC execution state flags.
639A
EX (SP),HL E3
Exchange the top of the stack with Register Pair HL. This retrieves the return address (the BASIC text pointer or execution point) into HL, and pushes the current HL onto the stack.
639B
PUSH DE D5
Save Register Pair DE onto the stack.
639C
LD DE,1D9EH 11 9E 1D
Load Register Pair DE with 1D9EH - a ROM address representing a specific point in the BASIC line execution flow.
639F
RST 18H DF
Call CPDEHL via RST 18H - compare DE (1D9EH) with HL (the return address). Z if equal.
63A0
If the NZ FLAG is set (the return address is not 1D9EH), JUMP forward to 63A6H to check the second address.
63A2
POP DE D1
Restore Register Pair DE from the stack.
63A3
EX (SP),HL E3
Exchange HL back with the stack, restoring the original stack state.
63A4
JUMP forward to 63F8H - the single-step mode check. This path is taken when the execution point is 1D9EH (normal line execution).
63A6
LD DE,1D21H 11 21 1D
Load Register Pair DE with 1D21H - another ROM execution point address.
63A9
RST 18H DF
Call CPDEHL via RST 18H - compare DE (1D21H) with HL. Z if equal.
63AA
POP DE D1
Restore Register Pair DE from the stack.
63AB
EX (SP),HL E3
Exchange HL back with the stack, restoring the original stack layout.
63AC
If the NZ FLAG is set (the return address is neither 1D9EH nor 1D21H), JUMP to ROM 035BH - the standard BASIC execution handler. This is a non-intercepted execution point.
1D21H Execution Context
The return address matched 1D21H. This is a different execution context (e.g., direct mode or a specific statement handler). The routine calls 641EH to set up the step mode parameter, reads the next byte, and falls through to 63F8H for the single-step check.
63AF
GOSUB to 641EH - a helper that loads A with 18H and stores it at 645BH (the step mode size parameter). This sets up the step interval for the 1D21H execution context.
63B2
LD A,(HL) 7E
Load Register A with the byte at (HL) - the current byte at the BASIC text pointer.
63B3
OR A B7
OR Register A with itself to set flags based on the byte value.
63B4
. Note: The immediate operand at 63B5H (the 42H offset) has the address 63B4H listed as a self-modifying target written by 5BAFH (the CMD"F=SS" handler). At runtime, the jump offset may be different, controlling the step mode behaviorSELF-MODIFYING CODE at 63B4H - single-step mode byte
JUMP forward to 63F8H - the single-step check.
63B6H - Single-Step Display and Wait Handler
This routine is the heart of the single-step debugging feature (CMD"F=SS"). When single-step mode is active, this routine is called for each BASIC line. It reads the BASIC line number from the line header (bytes at HL+1 and HL+2), checks if it is zero (program end), and if not, displays the line number on the screen, waits for a keypress (Enter to continue, BREAK/Ctrl-A to stop), and returns. The display is done by converting the line number to a string (via 5D00H) and filling the current video line with spaces (via 6407H).
63B6
PUSH HL E5
Save Register Pair HL (BASIC text pointer) onto the stack.
63B7
PUSH DE D5
Save Register Pair DE onto the stack.
63B8
PUSH BC C5
Save Register Pair BC onto the stack.
63B9
INC HL 23
INCrement HL to point to the first byte of the line number field (HL was pointing to the line link pointer).
63BA
LD A,(HL) 7E
Load Register A with the low byte of the line number.
63BB
INC HL 23
INCrement HL to point to the high byte of the line number.
63BC
OR (HL) B6
OR Register A with the high byte of the line number. If both bytes are zero, the Z FLAG is set - this is the end-of-program marker.
63BD
If the Z FLAG is set (line number is zero - end of program), JUMP forward to 63F5H to restore registers and exit without displaying anything.
63BF
INC HL 23
INCrement HL past the line number high byte to point to the line number's additional bytes.
63C0
LD E,(HL) 5E
Load Register E with the low byte of the actual line number value.
63C1
INC HL 23
INCrement HL to the high byte.
63C2
LD D,(HL) 56
Load Register D with the high byte. Register Pair DE now holds the 16-bit line number.
63C3
LD HL,0000H 21 00 00
. Note: Address 63C4H (the immediate operand) is a self-modifying target written by 5BA5H (the CMD"F=SS" handler) - it holds the single-step interval counter. At runtime, HL is loaded with the actual step countSELF-MODIFYING CODE at 63C4H
Load Register Pair HL with 0000H.
63C6
LD A,H 7C
Load Register A with Register H (high byte of the step counter).
63C7
OR L B5
OR Register A with Register L. If the step counter is zero (HL=0000H), Z is set - every line should be displayed.
63C8
If the Z FLAG is set (step counter is zero - display every line), JUMP forward to 63CFH to store the zero counter and display.
63CA
OR A B7
Clear the CARRY FLAG.
63CB
SBC HL,DE ED 52
Subtract DE (the current line number) from HL (the step counter). If HL < DE, carry is set and the line numbers have not yet reached the step target.
63CD
If the NZ FLAG is set (the step counter does not match the line number - this line should be skipped), JUMP forward to 63F5H to exit without displaying.
63CF
LD (63C4H),HL 22 C4 63
SELF-MODIFYING CODE write to 63C4H
Store Register Pair HL (the updated step counter, now zero or the remainder) at 63C4H - the self-modifying step counter.
Line Number Display
The current line should be displayed. The routine sets up the video output position using BC=3C39H (video RAM row address), writes a '@' character (40H) as a step-mode indicator, and calls 5D00H to convert and display the line number. Then it calls 6407H to fill the rest of the video line with spaces.
63D2
LD BC,3C39H 01 39 3C
Load Register Pair BC with 3C39H - a video RAM address. 3C00H is the start of video RAM, so 3C39H is column 57 of the first row (near the right side of the screen). The step-mode line number is displayed in the upper-right corner.
63D5
LD A,40H 3E 40
Load Register A with 40H (ASCII '@'). This character is used as a visual indicator that single-step mode is active.
63D7
LD (BC),A 02
Store Register A ('@') at the address in BC (video RAM at 3C39H). This writes the step indicator character to the screen.
63D8
PUSH BC C5
Save Register Pair BC (the video position) onto the stack for later use by 6407H.
63D9
INC BC 03
INCrement BC to the next video position (3C3AH) where the line number digits will be written.
63DA
PUBLIC - called by SYS11
GOSUB to 5D00H - the number-to-string copy routine. This converts the line number in DE to ASCII digits and writes them to the video RAM starting at BC.
63DD
GOSUB to 6407H - the video line fill routine. This fills the remaining positions on the current video line with spaces (20H), starting from the current BC position up to the end of the 64-column row.
Keyboard Wait Loop
After displaying the line number, the routine waits for a keypress. Enter (0DH) continues execution. Ctrl-A (01H) breaks out of single-step mode. Any other key is ignored and the loop continues.
63E0
LOOP START - keyboard wait
GOSUB to ROM 0049H - the keyboard scan routine. Returns the key code in Register A (00H if no key pressed).
63E3
CP 01H FE 01
Compare Register A against 01H (Ctrl-A / BREAK key code). If pressed, Z is set - the user wants to exit single-step mode.
63E5
If the Z FLAG is set (Ctrl-A/BREAK pressed), JUMP forward to 63EBH to exit the wait loop and stop single-stepping.
63E7
SUB 0DH D6 0D
SUBtract 0DH (Enter key code) from Register A. If Enter was pressed, A becomes zero and Z is set.
63E9
LOOP END
If the NZ FLAG is set (neither Enter nor Ctrl-A - no actionable key), LOOP back to 63E0H to scan the keyboard again.
63EB
POP BC C1
Restore Register Pair BC from the stack (the video position saved at 63D8H).
63EC
PUSH AF F5
Save Register AF onto the stack - preserving the key result (Z if Enter, NZ if BREAK) for the caller.
63ED
GOSUB to 6407H to fill the video line with spaces again, erasing the step-mode display before continuing execution.
63F0
POP AF F1
Restore Register AF from the stack (the key result).
63F1
POP BC C1
Restore Register Pair BC from the stack.
63F2
POP DE D1
Restore Register Pair DE from the stack.
63F3
POP HL E1
Restore Register Pair HL from the stack (the BASIC text pointer).
63F4
RET C9
RETURN to the caller. If Enter was pressed, A=00H (Z set) and execution continues. If BREAK, A is non-zero (NZ) and the caller should terminate single-step mode.
63F5
POP BC C1
Restore BC (skipped-line exit path - line number was zero or step count did not match).
63F8H - Single-Step Mode Check
This routine is the entry point for the single-step check, reached from 63A4H and 63B4H. It clears A, then checks the self-modifying byte at 63FAH. If non-zero, the single-step handler at 63B6H needs to be called. If zero, it checks the BASIC flag byte at 4289H bit 5 - if clear, it jumps to ROM 035BH; if set, it clears A and returns.
63F8
XOR A AF
Clear Register A to zero.
63F9
OR 00H F6 00
. Note: Address 63FAH (the immediate operand) is a self-modifying target written by 64EEH and SYS19/524EH. When non-zero, this OR produces a non-zero result (NZ), which triggers the single-step path at 6405H. When 00H, the result remains zero (Z)SELF-MODIFYING CODE at 63FAH
OR Register A with 00H.
63FB
If the NZ FLAG is set (the self-modifying byte at 63FAH was non-zero - single-step mode or special tracing is active), JUMP forward to 6405H to clear A and return (allowing the caller to invoke the step display).
63FD
LD A,(4289H) 3A 89 42
Load Register A with the byte at 4289H - a BASIC system flag byte. Bit 5 of this byte controls whether the BASIC execution intercept is active.
6400
AND 20H E6 20
AND Register A with 20H (binary 00100000) - isolating bit 5. If bit 5 is set, the result is non-zero.
6402
If the Z FLAG is set (bit 5 of 4289H is clear - intercept is not active), JUMP to ROM 035BH - the standard BASIC execution handler. This bypasses the single-step mechanism entirely.
6405
XOR A AF
Clear Register A to zero.
6406
RET C9
RETURN to the caller with A=00H. The single-step flag or intercept flag is active, and the caller should proceed with the step handler.
6407H - Video Line Fill with Spaces
This routine fills video RAM positions with space characters (20H), starting at the address in BC, until the low byte of BC reaches a 64-byte boundary (i.e., the end of a video row). Since Model III video RAM rows are 64 bytes wide, this clears from the current position to the end of the row.
6407
LD A,20H 3E 20
LOOP START
Load Register A with 20H (ASCII space).
6409
LD (BC),A 02
Store Register A (space) at the video RAM address in BC.
640A
INC BC 03
INCrement Register Pair BC to the next video position.
640B
LD A,C 79
Load Register A with Register C (the low byte of the video address).
640C
AND 3FH E6 3F
AND Register A with 3FH (binary 00111111). This masks the low 6 bits - the column position within the 64-byte row, as there are only 64 possible resulting numbers. If the result is zero, the address has wrapped to the start of the next row.
640E
LOOP END
If the NZ FLAG is set (not yet at a 64-byte boundary - more positions to fill), LOOP back to 6407H.
6410
RET C9
RETURN to the caller. The video row has been filled with spaces from the starting position to the end of the row.
6411H - File Open with Step Size 20H
This short entry point loads A with 20H (a step size parameter), then jumps to 6420H to store it at 645BH and proceed with the initialization/reset handler. The 6415H entry provides an alternate path that first opens a file via 6073H and calls DOS 442CH before falling through.
6411
LD A,20H 3E 20
Load Register A with 20H - a step size parameter value (32 decimal). This controls the spacing or interval for the subsequent operation.
6413
JUMP forward to 6420H to store A at 645BH and enter the initialization handler.
6415
GOSUB to 6073H - the SVC file setup routine. Opens a file through the DOS SVC path with BC=0120H.
6418
GOSUB to DOS entry point 442CH - a file operation routine (possibly file close or flush after the open).
641B
If the NZ FLAG is set (DOS error), JUMP to 5DEFH - the error translator.
641E
LD A,18H 3E 18
Load Register A with 18H - a step size parameter (24 decimal).
6420
LD (645BH),A 32 5B 64
SELF-MODIFYING CODE - 645BH is a runtime variable
Store Register A at 645BH - the step size parameter used by the JR instruction at 645BH (which is a self-modifying jump offset).
6423H - Initialization / Reset Handler
This is the main initialization and reset handler for BASIC/CMD file state. It saves all registers, calls 6496H (which sets the reset vector at 6427H to point to 6496H), clears several self-modifying variables (65A2H, 6226H, 5D45H) to zero, sets 40A9H to 01H, clears bit 6 of the BASIC flag at 4289H, then checks whether the file guard is active. If a file is active, it handles the cleanup - either flushing via 5F88H or writing back the FCB via 634DH - before clearing the work area via 635AH. If no file is active, it simply restores registers and returns.
6423
PUSH HL E5
Save Register Pair HL onto the stack.
6424
PUSH DE D5
Save Register Pair DE onto the stack.
6425
PUSH BC C5
Save Register Pair BC onto the stack.
6426
GOSUB to 6496H - a RET instruction that also serves as an address. The purpose of this call is that 6497H (immediately after) stores 6496H at the reset vector 6427H, setting up the return-to-idle behavior.
Variable Initialization
Clear several self-modifying code locations to zero, initializing the file I/O system to its idle state. These variables control display mode, SVC post-operation behavior, and data storage.
6429
XOR A AF
Clear Register A to zero.
642A
LD (65A2H),A 32 A2 65
SELF-MODIFYING CODE - 65A2H
Store 00H at 65A2H - clearing a runtime variable.
642D
LD (6226H),A 32 26 62
SELF-MODIFYING CODE - 6226H
Store 00H at 6226H - clearing the SVC post-operation flag. After this, the LD A,00H at 6225H will load zero, and the CALL NZ,610AH at 6228H will not be executed.
6430
LD (5D45H),A 32 45 5D
SELF-MODIFYING CODE - 5D45H
Store 00H at 5D45H - clearing the display mode flag used by the character output routine at 5D3DH.
6433
INC A 3C
INCrement Register A from 00H to 01H.
6434
LD (40A9H),A 32 A9 40
Store 01H at 40A9H - a BASIC system variable that controls some aspect of the runtime state (possibly file count or mode indicator).
6437
LD HL,4289H 21 89 42
Point Register Pair HL to 4289H - the BASIC system flag byte.
643A
RES 6,(HL) CB B6
Clear bit 6 of the byte at 4289H. Bit 6 was set during CMD"C" cassette handler setup (at 59B7H). Clearing it resets the cassette state flag.
643C
LD A,(6382H) 3A 82 63
Load Register A with the guard flag byte at 6382H. 00H means no file is active; C9H means a file operation is in progress.
643F
OR A B7
OR Register A with itself to set flags. Z if guard is disabled (no file active).
6440
If the Z FLAG is set (guard disabled - no file operation active), JUMP forward to 6492H to skip the file cleanup and go straight to restoring registers.
Active File Cleanup
The guard flag is active (C9H) - a file operation is in progress. The routine must clean up the file state. It checks bit 7 of IX+2DH (572DH) to determine whether the SVC path was used. If so, it calls 5F88H (default FCB flush) and modifies the code at 5FA8H. Otherwise, it checks the return address on the stack against 19B4H and handles the FCB writeback.
6442
LD HL,572DH 21 2D 57
Point Register Pair HL to 572DH - the buffer flags byte in the FCB work area (IX+2DH when IX=5700H).
6445
BIT 7,(HL) CB 7E
Test bit 7 of the buffer flags at 572DH. Bit 7 indicates the SVC path was used (set at 6081H).
6447
If bit 7 is clear (Z - normal BASIC OPEN path), JUMP forward to 6453H for the standard FCB cleanup.
6449
GOSUB to 5F88H - the default FCB setup routine (BC=5700H, then XOR A, PUSH AF, JR 5FAEH). This flushes the default file's buffer through the SVC dispatch.
644C
LD HL,5FA8H 21 A8 5F
Point Register Pair HL to 5FA8H - the self-modifying location in the close-all loop (the RET Z instruction that was noted as a self-modifying target).
644F
LD (HL),C8H 36 C8
Store C8H (the RET Z opcode) at 5FA8H. This restores the instruction to its default state (RET Z), undoing any modification made by SYS19/5224H.
6451
JUMP forward to 648FH to call 635AH (clear work area + disable guard) and continue cleanup.
6453
POP BC C1
Restore Register Pair BC from the stack (the saved BC from 6425H). This is used to check the return context.
6454
LD HL,19B4H 21 B4 19
Load Register Pair HL with 19B4H - a ROM address used to identify the return context. If BC matches 19B4H, the cleanup was triggered from a specific error recovery path.
6457
OR A B7
Clear the CARRY FLAG.
6458
SBC HL,BC ED 42
Subtract BC from HL. If HL=BC (the return address matches 19B4H), Z is set.
645A
PUSH BC C5
Save BC back onto the stack.
645B
. Note: Address 645BH is a self-modifying target - the JR offset (2FH) is written by 6420H with either 18H or 20H, changing where this jump goesSELF-MODIFYING CODE at 645BH
If the NZ FLAG is set (return address is NOT 19B4H), JUMP to 648CH to call 634DH (FCB writeback) then 635AH (clear work area).
19B4H Context - File Position Comparison and Cleanup
The return address was 19B4H. The routine now reads the stored FCB pointer from 6352H, checks whether the file is still open, and if so, performs a detailed position comparison to determine whether the FCB flags need to be adjusted before writeback.
645D
LD HL,(6352H) 2A 52 63
Load Register Pair HL with the stored user FCB pointer from 6352H.
6460
LD A,(HL) 7E
Load Register A with the byte at (HL) - the first byte of the user's FCB (status flags).
6461
OR A B7
Test whether the FCB status is zero (file not open).
6462
If Z (file is not open), JUMP to 648FH to clear and return without writeback.
6464
PUSH HL E5
Save the FCB pointer onto the stack.
6465
GOSUB to 61ACH to load the current file position from the work area (C=IX+12H, HL=5717H).
6468
EX (SP),HL E3
Exchange HL (current position word) with the stack (FCB pointer). Now HL=FCB pointer, position word is on stack.
6469
LD A,(570EH) 3A 0E 57
Load Register A with the byte at 570EH - the tertiary FCB flags byte (IX+0EH) from the work area copy.
646C
PUSH AF F5
Save the flags byte onto the stack.
646D
GOSUB to 62BDH - the FCB lookup from saved pointer. This re-reads the user FCB into the work area, getting a fresh copy of the FCB data.
6470
LD (HL),00H 36 00
Store 00H at the current HL position (the end of the LDIR copy - just past the work area). This terminates the copied data.
6472
POP BC C1
Restore BC - this gets the saved IX+0EH flags byte (was pushed as AF, so B=flags, C=A value).
6473
POP DE D1
Restore DE - this gets the current position word (pushed at 6468H via EX (SP),HL).
6474
LD C,(IX+0EH) DD 4E 0E
Load Register C with the re-read IX+0EH flags byte from the refreshed work area copy.
6477
LD HL,(5717H) 2A 17 57
Load Register Pair HL with the position word from the refreshed work area at 5717H.
647A
RST 18H DF
Call CPDEHL via RST 18H - compare DE (old position) with HL (new position from refreshed FCB). Z if positions are equal.
647B
If NZ (positions differ - the file was modified between the two reads), JUMP to 6485H to adjust the flags.
647D
BIT 4,C CB 61
Test bit 4 of Register C (the refreshed IX+0EH flags). Bit 4 is checked to see if the refreshed copy has a specific condition set.
647F
If bit 4 is clear (Z), JUMP to 6485H.
6481
BIT 4,B CB 60
Test bit 4 of Register B (the saved IX+0EH flags from before the refresh).
6483
. Note: JR NZ with offset 00H means it falls through regardless - this is effectively a NOP jump, likely a patch or placeholder.
If bit 4 is set (NZ), JUMP to 6485H.
6485
RES 4,C CB A1
Clear bit 4 of Register C (the flags byte to be written back).
6487
SET 5,C CB E9
Set bit 5 of Register C. This marks a specific state in the FCB flags that indicates the reset handler has processed this file.
6489
LD (IX+0EH),C DD 71 0E
Store Register C (the adjusted flags) at IX+0EH in the work area. This updates the tertiary flags with the reset handler's modifications.
648C
GOSUB to 634DH - write the FCB work area back to the user's FCB at the address stored in 6352H.
648F
GOSUB to 635AH - clear the FCB work area (5700H-572DH) and disable the guard flag.
6492
POP BC C1
Restore Register Pair BC from the stack.
6493
POP DE D1
Restore Register Pair DE from the stack.
6494
POP HL E1
Restore Register Pair HL from the stack.
6495
XOR A AF
Clear Register A to zero and set Z flag.
6496
RET C9
RETURN to the caller with A=00H and Z set.
6497H - Set Reset Vector [PUBLIC - Called by SYS19, SYS21]
This routine stores the address 6496H (the RET instruction at the end of the reset handler) at the self-modifying location 6427H. This sets the reset vector so that future calls through the reset path will effectively be no-ops (they jump to 6496H which is just RET). Called by SYS19 and SYS21 to initialize the reset behavior.
6497
LD HL,6496H 21 96 64
Load Register Pair HL with 6496H - the address of the RET instruction at the end of the reset handler.
649A
LD (6427H),HL 22 27 64
Store Register Pair HL at 6427H - the reset vector location. This overwrites the CALL target at 6426H, making future resets call 6496H (RET) instead of doing full cleanupSELF-MODIFYING CODE - 6427H]
649D
RET C9
RETURN to the caller.
64A0H - Standalone RET
A standalone RET instruction, possibly used as a no-op target or placeholder entry point.
64A0
RET C9
RETURN to the caller. This standalone RET serves as a null entry point or placeholder.
64A1H - BASIC Initialization: Memory Test and Configuration
This is the main BASIC initialization sequence, called after the program entry point at 66BEH performs command line parsing. It reads the DOS configuration byte from 2C00H, tests and sizes available RAM, displays the startup banner, copies the jump table into low memory, zeroes the FCB array, and parses any command line arguments for auto-run. This is the most critical startup code in BASIC/CMD - it configures the entire runtime environment.
64A1
LD A,(2C00H) 3A 00 2C
Load Register A with the byte at 2C00H - a DOS or system configuration byte. This value is read but not directly used in the next instructions; it may set flags or be consumed by later code through the alternate register set.
High Memory Limit Determination
The routine determines the top of usable RAM. The self-modifying value at 64A4H (two bytes, initially 0000H) can be set by the entry point code at 66CEH to specify a user-requested memory limit. If 0000H, the system default from 4411H is used. The value at 4411H is the DOS high memory limit.
64A3
LD HL,0000H 21 00 00
. Note: Address 64A4H is a self-modifying target - written by 66CEH and 6741H with the user-specified memory limit. If 0000H, the default limit is usedSELF-MODIFYING CODE at 64A4H
Load Register Pair HL with 0000H.
64A6
LD A,H 7C
Load Register A with Register H (high byte of the memory limit).
64A7
OR L B5
OR Register A with Register L. If HL is 0000H (no user-specified limit), Z is set.
64A8
LD DE,(4411H) ED 5B 11 44
Load Register Pair DE with the 16-bit value at 4411H - the DOS high memory limit. This is the maximum address available for BASIC to use.
64AC
If NZ (user specified a non-zero memory limit in HL), JUMP to 64B1H to use the user-specified limit instead of the DOS default.
64AE
LD H,D 62
Load Register H with Register D (high byte of DOS limit).
64AF
LD L,E 6B
Load Register L with Register E. HL now holds the DOS default memory limit from 4411H.
64B1
LD A,D 7A
Load Register A with Register D (high byte of the DOS limit).
64B2
CP H BC
Compare Register A (DOS high byte) against Register H (selected limit high byte). If the DOS limit is less than the user limit, the CARRY FLAG is set.
64B3
If NZ (high bytes differ), JUMP to 64B7H to test carry and enforce the limit.
64B5
LD A,E 7B
Load Register A with Register E (DOS low byte - for comparison when high bytes are equal).
64B6
CP L BD
Compare Register A (DOS low byte) against Register L (selected limit low byte).
64B7
If the CARRY FLAG is set (the DOS limit is LESS than the selected limit - the user requested more memory than is available), JUMP to 57C9H - which dispatches to the SYSTEM command (CMD"S"). This exits BASIC because the memory configuration is invalid.
RAM Write Test
The memory limit is valid. The routine now performs a write test on the top-of-memory address to verify the RAM is functional. It saves the original byte, writes D9H (a distinctive test pattern), reads it back, and compares. If the write fails (ROM or bad RAM), it exits to SYSTEM.
64BA
LD B,(HL) 46
Load Register B with the byte at (HL) - save the original value at the top-of-memory address for restoration after the test.
64BB
LD A,D9H 3E D9
Load Register A with D9H - a test pattern byte. D9H (11011001) is chosen because it has a mix of set and cleared bits, making it a good test for stuck-at faults.
64BD
LD (HL),A 77
Store the test pattern D9H at the top-of-memory address (HL).
64BE
CP (HL) BE
Compare Register A (D9H) against the byte at (HL). If the memory is writable, the comparison succeeds (Z set). If it is ROM or defective, the value read back will not match (NZ set).
64BF
If NZ (write test failed - memory is not writable at this address), JUMP to 57C9H to exit to SYSTEM. The memory configuration is unusable.
64C2
LD (HL),B 70
Restore the original byte (saved in Register B) at the top-of-memory address, undoing the write test.
BASIC System Variable Initialization
The memory is valid. The routine now sets up the BASIC system variables: top of arrays pointer (40B1H), BASIC program area start (40A0H with offset FFCEH = -50), displays the startup banner, and initializes various system pointers.
64C3
LD (40B1H),HL 22 B1 40
Store Register Pair HL (the validated top-of-memory address) at 40B1H - the top of arrays pointer. This tells BASIC where the highest usable memory address is.
64C6
LD DE,FFCEH 11 CE FF
Load Register Pair DE with FFCEH (-50 in two's complement). This offset reserves 50 bytes below the top of memory for system use (stack space, etc.).
64C9
ADD HL,DE 19
ADD Register Pair DE (FFCEH = -50) to Register Pair HL (top of memory). HL now points to the BASIC program start area, 50 bytes below the top of RAM.
64CA
LD (40A0H),HL 22 A0 40
Store Register Pair HL at 40A0H - the BASIC program area start pointer. BASIC programs will be stored starting from this address downward.
64CD
LD HL,675CH 21 5C 67
Point Register Pair HL to 675CH - the startup banner text string ("DISK BASIC. RADIO SHACK'S ROM ENHANCED WITH..." etc.).
64D0
GOSUB to DOS entry point 4467H - the string display routine. This outputs the null/CR-terminated string at HL to the screen, displaying the BASIC startup banner.
64D3
LD HL,FFFEH 21 FE FF
Load Register Pair HL with FFFEH (-2 in two's complement). This is stored at 40A2H as a system configuration value.
64D6
LD (40A2H),HL 22 A2 40
Store Register Pair HL (FFFEH) at 40A2H - a BASIC system variable. The value FFFEH is used as a flag or sentinel value indicating an initialized but unconfigured state.
64D9
LD HL,64A3H 21 A3 64
Load Register Pair HL with 64A3H - the address of the memory limit variable at the top of this initialization routine. This address is stored as a callback or re-entry point.
64DC
LD (40A7H),HL 22 A7 40
Store Register Pair HL (64A3H) at 40A7H - a BASIC system pointer that points to the memory configuration routine. This allows the system to re-invoke the memory sizing if needed.
64DF
LD HL,4289H 21 89 42
Point Register Pair HL to 4289H - the BASIC system flag byte.
64E2
RES 7,(HL) CB BE
Clear bit 7 of the byte at 4289H. Bit 7 is reset during initialization to indicate a clean startup state.
Execution Intercept Hook Setup
The routine checks bit 6 of the DOS flag byte at 428CH. If set, the execution intercept is enabled: the self-modifying byte at 63FAH is set to a non-zero value (the high byte of HL, which is 42H), and the opcode at 4478H is set to C3H (JP) to enable the hook. If bit 6 is clear, the hook is disabled by writing C9H (RET) to 4478H.
64E4
LD A,(428CH) 3A 8C 42
Load Register A with the byte at 428CH - a DOS/BASIC configuration flag byte.
64E7
BIT 6,A CB 77
Test bit 6 of Register A. Bit 6 controls whether the BASIC line execution intercept (single-step debugging support) should be enabled.
64E9
LD A,C9H 3E C9
Load Register A with C9H (RET opcode) - the default "hook disabled" value. This will be stored at 4478H if bit 6 is clear.
64EB
If Z (bit 6 is clear - intercept disabled), JUMP to 64F3H to store C9H (RET) at 4478H, disabling the hook.
64ED
LD A,H 7C
Load Register A with Register H. HL is 4289H, so H=42H. This non-zero value is stored at 63FAH to enable the single-step intercept check.
64EE
LD (63FAH),A 32 FA 63
SELF-MODIFYING CODE - 63FAH
Store Register A (42H, non-zero) at 63FAH - the self-modifying operand in the OR instruction at 63F9H. When non-zero, the single-step check at 63F8H will detect that the intercept is active.
64F1
LD A,C3H 3E C3
Load Register A with C3H (JP opcode). This enables the execution hook at 4478H - when 4478H contains C3H (JP), the hook is active and will jump to the intercept routine.
64F3
LD (4478H),A 32 78 44
EXTERNAL WRITE - 4478H
Store Register A (C9H=RET for disabled, C3H=JP for enabled) at 4478H - the execution hook entry point in the DOS vector table. This controls whether BASIC line execution triggers the single-step intercept.
64F6H - Jump Table Copy and FCB Initialization
This section copies the 49-entry jump table from 67BBH to 4152H (the BASIC dispatch vector area in low RAM), sets the default file count to 3, and zeroes the FCB array. The jump table copy is performed with interrupts disabled (DI/LDIR/EI) because the vectors are live - any interrupt during the partial copy could dispatch through an incomplete table. After the copy, the FCB array at 66BEH is zeroed for each of the configured files.
64F6
LD HL,67BBH 21 BB 67
Point Register Pair HL to 67BBH - the source address of the jump table (49 entries × 3 bytes each, located at the end of BASIC/CMD in the Block 2 data area).
64F9
LD DE,4152H 11 52 41
Load Register Pair DE with 4152H - the destination address in low RAM where the BASIC dispatch vectors are stored. The ROM and DOS use these vectors to dispatch BASIC statement execution.
64FC
LD BC,0093H 01 93 00
Load Register Pair BC with 0093H (147 decimal) - the total size of the jump table. 49 entries × 3 bytes = 147 bytes.
64FF
DI F3
Disable Interrupts. The jump table vectors at 4152H are live dispatch targets - interrupts must be disabled during the copy to prevent the system from dispatching through a partially-written table.
6500
LDIR ED B0
Block copy: copy 147 bytes from the jump table at 67BBH to the dispatch vector area at 4152H. After execution, the BASIC statement dispatch vectors are installed.
6502
LD A,03H 3E 03
. Note: The value at 6502H is a self-modifying target written by 6726H and 6747H during command line parsing; the initial value of 03H may be overwritten before this code executes.
Load Register A with 03H - the default number of open files. This is stored at 5F62H as the maximum file count for the CP instruction at 5F61H.
6504
LD (5F62H),A 32 62 5F
Store Register A (03H = default file count) at 5F62H - the self-modifying CP operand in the file number validator at 5F61H. This limits file numbers to 0, 1, 2 (files #1, #2, #3)SELF-MODIFYING CODE - 5F62H]
6507
LD HL,66BEH 21 BE 66
Point Register Pair HL to 66BEH - the base address of the FCB array. This is the program entry point address, which during BASIC operation is repurposed as storage for the FCB entries (each 012DH = 301 bytes).
650A
LD SP,650DH 31 0D 65
Load the Stack Pointer with 650DH. This sets SP to point at the EI instruction at 650DH, which is the next instruction to execute. This is an unusual technique - it effectively makes the stack empty at a known location within the code itself, ensuring a clean stack state for the initialization that follows.
650D
EI FB
Enable Interrupts. Interrupts were disabled at 64FFH for the jump table copy. They are now re-enabled since the vectors are fully installed.
650E
OR A B7
OR Register A (file count, 03H) with itself to set flags. If A is zero (no files configured), Z is set and the zeroing loop is skipped.
650F
If Z (file count is zero - no files to allocate), JUMP forward to 6522H to skip the FCB zeroing loop.
FCB Array Zeroing Loop
This nested loop zeroes the FCB array. The outer loop (EX AF,AF' / DEC A / JR NZ) counts down the number of files. The inner loop fills each FCB with 00H bytes for (649EH) = 012DH bytes. The alternate accumulator (AF') is used as the outer loop counter - an unusual but efficient Z80 technique that avoids using the stack or an extra register pair.
6511
EX AF,AF' 08
OUTER LOOP START
Exchange AF with the alternate accumulator AF'. This saves the file count (A) in AF' and retrieves whatever was previously in AF'. The alternate accumulator serves as the outer loop counter.
6512
LD BC,(649EH) ED 4B 9E 64
Load Register Pair BC with the 16-bit value at 649EH - the FCB size in bytes (012DH = 301 decimal). This is the number of bytes to zero for each FCB entry.
6516
LD (HL),00H 36 00
INNER LOOP START
Store 00H at the current HL position, zeroing one byte of the FCB.
6518
DEC BC 0B
DECrement Register Pair BC (the remaining byte count) by 1.
6519
INC HL 23
INCrement Register Pair HL to the next byte position.
651A
LD A,B 78
Load Register A with Register B (high byte of remaining count).
651B
OR C B1
OR Register A with Register C. If BC has reached zero (all bytes zeroed for this FCB), Z is set.
651C
INNER LOOP END
If NZ (more bytes to zero in this FCB), LOOP back to 6516H.
651E
EX AF,AF' 08
Exchange AF with AF' - retrieve the outer loop counter (file count).
651F
DEC A 3D
DECrement Register A (the remaining file count) by 1.
6520
OUTER LOOP END
If NZ (more FCBs to zero), LOOP back to 6511H.
6522H - Program Area Setup and Command Line Processing
After the FCB array has been zeroed, HL points just past the last FCB. This routine stores a zero terminator, saves the result as the BASIC program area start (40A4H), verifies there is enough memory for the program area plus a 012CH-byte workspace, and then processes the command line to determine whether a BASIC program should be auto-loaded and run.
6522
LD (HL),00H 36 00
Store 00H at the current HL position - a zero terminator marking the end of the FCB array and the start of the BASIC program area.
6524
INC HL 23
INCrement HL past the terminator byte.
6525
LD (40A4H),HL 22 A4 40
Store Register Pair HL at 40A4H - the BASIC program area start pointer. This is where BASIC program lines will be stored in memory. The area extends from here up toward the top of memory.
6528
LD DE,012CH 11 2C 01
Load Register Pair DE with 012CH (300 decimal) - the minimum workspace size required above the program area start. This ensures there is enough room for at least one record buffer and working space.
652B
ADD HL,DE 19
ADD DE (012CH) to HL (program area start). The result is the minimum address that must be below the top of arrays pointer for BASIC to have enough working space.
652C
EX DE,HL EB
Exchange DE and HL. DE now holds the minimum required address.
652D
LD HL,(40B1H) 2A B1 40
Load Register Pair HL with the top of arrays pointer from 40B1H (stored at 64C3H during memory sizing).
6530
RST 18H DF
Call CPDEHL via RST 18H - compare DE (minimum required) with HL (top of arrays). If DE > HL (not enough memory), CARRY is set.
6531
If CARRY (not enough memory for BASIC to operate), JUMP to 57C9H - exit to SYSTEM command. There is insufficient RAM for the configured number of files plus workspace.
6534
GOSUB to ROM 1B4DH - a system initialization routine that sets up the BASIC runtime environment (clears variables, resets the program pointer, etc.).
Command Line Auto-Run Check
The initialization is complete. The routine now checks the command line for an auto-run filename. The self-modifying value at 6537H (initially 0000H) points to the command line text. If the first character is '*' (2AH), a BASIC program filename follows and should be loaded and run automatically. If 0DH (carriage return), no command was given. Otherwise, the autostart handler at 6562H is invoked.
6537
LD HL,0000H 21 00 00
. Note: Address 6537H+1 (6538H-6539H) is a self-modifying target written by 6551H and 674BH with the command line pointer. At runtime, HL is loaded with the actual command line text addressSELF-MODIFYING CODE at 6537H
Load Register Pair HL with 0000H.
653A
LD A,(HL) 7E
Load Register A with the first character of the command line text.
653B
CP 2AH FE 2A
Compare Register A against 2AH (ASCII '*'). A '*' prefix on the command line indicates a BASIC program to auto-load and run.
653D
If NZ (first character is not '*'), JUMP forward to 6556H to check for carriage return or other commands.
Auto-Run '*' Command Processing
The command line starts with '*'. The text after '*' is treated as a BASIC program filename to load and RUN. The routine sets up the program area with a null link pointer, calls ROM 1B5AH for additional setup, stores the RUN command vector at 54E4H in 6537H for later execution, and then falls through to the autostart dispatch.
653F
LD BC,0000H 01 00 00
. Note: Address 653FH+1 is a self-modifying target written by 66DDH with the starting line number for the RUN commandSELF-MODIFYING CODE at 653FH
Load Register Pair BC with 0000H.
6542
LD HL,(40A4H) 2A A4 40
Load Register Pair HL with the BASIC program area start from 40A4H.
6545
LD (HL),C 71
Store Register C (00H) at the program area start - the low byte of a null link pointer, indicating an empty program.
6546
INC HL 23
INCrement HL to the next byte.
6547
LD (HL),B 70
Store Register B (00H) - the high byte of the null link pointer. The two zero bytes mark the end of the BASIC program (no lines).
6548
LD HL,0000H 21 00 00
. Note: Address 6548H+1 is a self-modifying target written by 66E7H with the top of string space pointerSELF-MODIFYING CODE at 6548H
Load Register Pair HL with 0000H.
654B
GOSUB to ROM 1B5AH - additional BASIC runtime initialization that sets up the string space, variable tables, and execution state using the value in HL.
654E
LD HL,54E4H 21 E4 54
Load Register Pair HL with 54E4H - the address of the RUN command handler in the SYS overlay space. This vector will be stored at 6537H so that the autostart code at 6562H will execute the RUN command after loading the program.
6551
LD (6537H),HL 22 37 65
SELF-MODIFYING CODE - 6537H
Store Register Pair HL (54E4H) at 6537H - overwriting the command line pointer with the RUN vector address. When the autostart handler reads from 6537H, it will get the RUN command entry point.
6554
JUMP forward to 655AH to set up the autostart dispatch vector at 5205H and enter BASIC.
6556
CP 0DH FE 0D
Compare Register A (the first command line character) against 0DH (carriage return). CR indicates no command was given - start BASIC in interactive mode.
6558
If Z (carriage return - no command), JUMP forward to 6560H to enter BASIC in interactive mode via ROM 1A19H.
655A
LD HL,6562H 21 62 65
Load Register Pair HL with 6562H - the address of the autostart handler routine.
655D
LD (5205H),HL 22 05 52
EXTERNAL WRITE - 5205H
Store Register Pair HL (6562H) at 5205H - a BASIC overlay vector that is called during the startup sequence. This hooks the autostart handler into the BASIC initialization flow.
6560
Unconditional JUMP to ROM 1A19H - the BASIC system restart/re-entry point. This enters the BASIC interpreter main loop. If the autostart vector at 5205H was set, it will be called during the startup sequence to load and run the specified program.
6562H - Autostart Handler
This routine is the autostart handler, installed at 5205H by 655DH. When BASIC starts up and calls the vector at 5205H, this routine executes. It first restores the 5205H vector to 0033H (the ROM character display routine - the default vector), then displays a prompt string at 6585H via 4467H, copies the command line text (from the pointer at 6537H) into the BASIC command buffer (at 40A7H), and jumps to ROM 0379H to execute the command as if the user had typed it.
6562
POP HL E1
Discard the return address from the stack. The autostart handler does not return to its caller - it takes over execution by jumping to ROM 0379H.
6563
LD HL,0033H 21 33 00
Load Register Pair HL with 0033H - the ROM character display routine address. This is the default value for the vector at 5205H.
6566
LD (5205H),HL 22 05 52
EXTERNAL WRITE - 5205H
Store 0033H at 5205H - restoring the BASIC overlay vector to its default (ROM character display). This ensures the autostart handler runs only once.
6569
PUSH BC C5
Save Register Pair BC onto the stack.
656A
LD HL,6585H 21 85 65
Point Register Pair HL to 6585H - a short prompt or prefix string displayed before the auto-executed command. The bytes at 6585H are 1DH, 1BH, 1FH - control codes (cursor movement/clear).
656D
GOSUB to 4467H - the DOS string display routine. This outputs the control code string at 6585H to position the cursor for the command display.
Command Line Copy Loop
The routine copies the command line text from the source (pointed to by 6537H, which may be the original command line or the RUN vector at 54E4H) into the BASIC command buffer (at 40A7H). The copy continues until a carriage return (0DH) is encountered.
6570
LD DE,(6537H) ED 5B 37 65
Load Register Pair DE with the 16-bit value at 6537H - the command line text source pointer (self-modifying, set by 6551H or 674BH).
6574
LD HL,(40A7H) 2A A7 40
Load Register Pair HL with the BASIC command buffer pointer from 40A7H (set to 64A3H at 64DCH, or overwritten by ROM init).
6578
LD A,(DE) 1A
LOOP START
Load Register A with the byte at (DE) - the next character from the command line source.
6579
CP 0DH FE 0D
Compare Register A against 0DH (carriage return). If CR, the command line is complete.
657B
LD (HL),A 77
Store Register A (the command character) at (HL) - writing it into the BASIC command buffer. The CR is also copied to terminate the string.
657C
INC DE 13
INCrement DE (source pointer) to the next character.
657D
INC HL 23
INCrement HL (destination pointer) to the next buffer position.
657E
LOOP END
If NZ (the character was not CR - more text to copy), LOOP back to 6578H.
6580
XOR A AF
Clear Register A to zero.
6581
PUSH AF F5
Save AF (A=00H with Z set) onto the stack. This serves as a parameter for the ROM routine at 0379H.
6582
DEC HL 2B
DECrement HL back one position (pointing to the CR character in the buffer).
6583
Unconditional JUMP to ROM 0379H - the BASIC command execution entry point. This processes the command in the buffer as if the user had typed it at the BASIC prompt. For auto-run, the command is "RUN filename" or whatever was on the command line.
6585H - Autostart Prompt Control Codes (DATA)
Three bytes of control codes used as a prompt prefix by the autostart handler at 656AH. These are cursor control characters displayed via 4467H before the auto-executed command.
6585
DEFB 1DH 1D
Control code 1DH - cursor control (home cursor or clear to end of line, depending on the terminal mode).
6586
DEFB 1BH 1B
Control code 1BH - escape or cursor positioning code.
6587
DEFB 1FH 1F
Control code 1FH - home cursor. This positions the cursor at the top-left of the screen before the command text is displayed. The string is terminated by the 00H or CR that follows in memory (the NOP fill or subsequent data).
65A2H - Runtime Data Storage (4 NOPs)
Four bytes of zero-initialized storage used as runtime variables. Address 65A2H is written by 642AH (initialization handler) and read by various runtime code. Addresses 65A3H-65A5H are referenced by SYS11/4D5CH (LD DE,65A3H) as a data pointer.
65A2
DEFB 00H 00
SELF-MODIFYING CODE - 65A2H
Runtime variable at 65A2H - cleared to 00H by initialization at 642AH.
65A3
DEFB 00H 00
Runtime data at 65A3H. Referenced by SYS11/4D5CH as a data pointer destination.
65A4
DEFB 00H 00
Runtime data at 65A4H.
65A5
DEFB 00H 00
Runtime data at 65A5H.
65A6H - File Position Retrieval Helper
This routine is part of the file position retrieval system, called from 61DFH (single-byte write/advance). It loads a position value from a self-modifying address, calls 61BAH to load both file positions, copies the sector offset to A, pops BC, and returns. The LD HL at 65A6H uses the address C52AH in the disassembly, but this is the raw bytes "2A 2A C5" which decode as LD HL,(C52AH) - however, the 2AH-2AH pattern suggests this may be related to the pre-entry bytes at 66BCH (which are also 2A 2A 01). The actual address read from depends on runtime context.
65A6
LD HL,(C52AH) 2A 2A C5
. Note: This instruction sequence appears anomalous - C52AH is likely not a valid data address in the BASIC/CMD context. The bytes 2A 2A C5 may represent: LD HL,(C52AH) as decoded, OR this may be entered at 65A8H (skipping the first byte 2AH) where the sequence becomes LD HL,(xxxx) with different context. Address 65A8H is called from 61E1H.
Load Register Pair HL from the address C52AH.
65A8
- (entry at 65A8H)
Entry point 65A8H is called from 61E1H (record position validator). When entered here, the preceding bytes form a different instruction context. The CALL 61BAH at 65A9H loads both file positions.
65A9
GOSUB to 61BAH to load both positions: HL=current position, DE=alternate position, C=sector offset, A=alternate sector byte.
65AC
LD A,C 79
Load Register A with Register C (the current sector offset).
65AD
POP BC C1
Restore Register Pair BC from the stack.
65AE
RET C9
RETURN to the caller with A=sector offset, HL and DE holding position data.
65AFH - FCB Size Loader
Simple utility that loads the FCB size from 649EH into DE and returns.
65AF
LD DE,(649EH) ED 5B 9E 64
Load Register Pair DE with the FCB size from 649EH (012DH = 301 bytes).
65B3
RET C9
RETURN with DE=FCB size.
65B4H - Set Bit 7 of IX+04H [PUBLIC - Called by SYS21]
Sets bit 7 of the byte at IX+04H (primary position sector offset in the FCB) and returns.
65B4
SET 7,(IX+04H) DD CB 04 FE
Set bit 7 of IX+04H - marks the primary position with a high-bit flag (possibly indicating the position is modified or needs special handling).
65B9H - PDRIVE Entry Comparator [PUBLIC - Called by SYS21]
This routine validates that Z is set on entry (JP NZ to Illegal Function Call if not), then reads the drive configuration byte at 5102H to determine which PDRIVE table to use (4300H for drive 0, 4317H for drive 1+). It compares the FCB position fields (IX+05H/06H) against the PDRIVE entry fields (IY+05H/06H) and walks through PDRIVE entries (stride 17H = 23 bytes) comparing the sector count at IY+00H against Register C. Sets bit 6 of IX+04H if a match is found.
65B9
If the NZ FLAG is set on entry, JUMP to ROM 1E4AH - Illegal Function Call error. This routine requires Z to be set by the caller.
65BC
LD A,(5102H) 3A 02 51
Load Register A with the byte at 5102H - a drive configuration byte that indicates which drive is active.
65BF
OR A B7
Test if A is zero (drive 0).
65C0
LD IY,4300H FD 21 00 43
Point Register Pair IY to 4300H - the PDRIVE table for drive 0.
65C4
If Z (drive 0), JUMP to 65CAH to use the 4300H PDRIVE table.
65C6
LD IY,4317H FD 21 17 43
Point Register Pair IY to 4317H - the PDRIVE table for drive 1 (offset by one 17H-byte entry from 4300H).
65CA
PUSH HL E5
Save Register Pair HL onto the stack.
65CB
LD L,(IX+05H) DD 6E 05
Load Register L with IX+05H - the low byte of the FCB position word.
65CE
LD H,(IX+06H) DD 66 06
Load Register H with IX+06H - the high byte. HL now holds the FCB position word.
65D1
LD E,(IY+05H) FD 5E 05
Load Register E with IY+05H - the low byte of the PDRIVE entry's position fieldLOOP START]
65D4
LD D,(IY+06H) FD 56 06
Load Register D with IY+06H - the high byte. DE holds the PDRIVE entry's position.
65D7
RST 18H DF
Call CPDEHL - compare DE (PDRIVE position) with HL (FCB position). Z if equal.
65D8
If NZ (positions do not match), JUMP to 65DEH to advance to the next PDRIVE entry.
65DA
SET 6,(IX+04H) DD CB 04 F6
Set bit 6 of IX+04H - marks that a matching PDRIVE entry was found for this FCB's position.
65DE
LD DE,0017H 11 17 00
Load Register Pair DE with 0017H (23 decimal) - the size of each PDRIVE table entry.
65E1
ADD IY,DE FD 19
ADD DE to IY - advance to the next PDRIVE entry.
65E3
LD A,(IY+00H) FD 7E 00
Load Register A with the first byte of the next PDRIVE entry (the sector count or entry type byte).
65E6
CP C B9
Compare Register A against Register C. Register C holds the target sector count to match against.
65E7
LOOP END
If CARRY (the PDRIVE entry's count is less than the target - more entries to check), LOOP back to 65D1H.
65E9
POP HL E1
Restore Register Pair HL.
65EA
RET C9
RETURN. Bit 6 of IX+04H indicates whether a match was found.
65EBH - Conditional Store to 4F02H [PUBLIC - Called by SYS21]
Tests bit 6 of IX+04H. If set (match was found by 65B9H), returns without action. If clear, stores A at 4F02H - a DOS workspace variable.
65EB
BIT 6,(IX+04H) DD CB 04 76
Test bit 6 of IX+04H (match-found flag from 65B9H/65DAH).
65EF
RET NZ C0
If NZ (match found), RETURN without storing.
65F0
LD (4F02H),A 32 02 4F
Store Register A at 4F02H - a DOS workspace variable.
65F4H - Conditional Return with Position [PUBLIC - Called by SYS21]
Loads E from IX+13H, tests bit 6 of IX+04H. If clear (Z), returns normally. If set, pops AF from the stack (discarding a return address level), adds BC to HL, and returns - modifying the return path.
65F4
LD E,(IX+13H) DD 5E 13
Load Register E with IX+13H - a byte from the FCB structure.
65F7
BIT 6,(IX+04H) DD CB 04 76
Test bit 6 of IX+04H.
65FB
RET Z C8
If Z (bit clear), RETURN normally.
65FC
POP AF F1
Discard the return address from the stack (skip one caller level).
65FD
ADD HL,BC 09
ADD BC to HL.
65FE
RET C9
RETURN to the caller's caller with HL adjusted.
65FFH - Conditional ADD Loop [PUBLIC - JP Target from SYS21]
Tests bit 6 of IX+04H. If set, returns. If clear, adds DE to HL in a DJNZ loop (B iterations), effectively computing HL = HL + (DE × B).
65FF
BIT 6,(IX+04H) DD CB 04 76
Test bit 6 of IX+04H.
6603
RET NZ C0
If NZ (bit set), RETURN without modification.
6604
ADD HL,DE 19
LOOP BODY
ADD DE to HL.
6605
LOOP
DECrement B and loop back to 6604H if not zero.
6607
RET C9
RETURN with HL = original_HL + (DE × B_iterations).
6608H - FCB Header Store and Block Copy [PUBLIC - Called by SYS21]
Stores H at IX+00H, reads a byte from (BC), adds BC to HL, exchanges DE/HL, tests bit 6 of IX+04H (returns if set), then performs a LDDR block copy of BC bytes from HL to DE (if BC is non-zero). Clears A on exit.
6608
LD (IX+00H),H DD 74 00
. Note: The instruction bytes are DD 74 0A but the mnemonic shows IX+00H - the disassembly may be slightly off. The actual offset depends on the specific encoding.
Store Register H at IX+00H - writing the high byte of HL to the FCB status flags position.
660A
LD A,(BC) 0A
Load Register A with the byte at (BC).
660B
ADD HL,BC 09
ADD BC to HL.
660C
EX DE,HL EB
Exchange DE and HL.
660D
BIT 6,(IX+04H) DD CB 04 76
Test bit 6 of IX+04H.
6611
RET NZ C0
If NZ (bit set), RETURN without the block copy.
6612
LD A,B 78
Load Register A with Register B.
6613
OR C B1
OR A with C. Test if BC is zero.
6614
If Z (BC=0, nothing to copy), JUMP to 661AH.
6616
DEC HL 2B
DECrement HL (adjust source for LDDR - copies from high to low).
6617
DEC DE 1B
DECrement DE (adjust destination).
6618
LDDR ED B8
Block copy BC bytes from (HL) to (DE), decrementing both pointers. This copies data in reverse order.
661A
XOR A AF
Clear Register A to zero.
661B
RET C9
RETURN with A=00H.
661CH - String Expression + SYS10 Dispatch [PUBLIC - JP Target from SYS10]
Calls 6623H (which evaluates a string expression via 6190H and dispatches to SYS overlay at 4DE4H), pushes HL, and jumps to SYS overlay at 4E17H.
661C
GOSUB to 6623H - evaluates a string expression and dispatches to 4DE4H.
661F
PUSH HL E5
Save HL onto the stack.
6620
JUMP to SYS overlay entry at 4E17H for continued processing.
6623
GOSUB to 6190H - the string expression with descriptor extraction routine.
6626
POP HL E1
Restore HL from the stack.
6627
EX (SP),HL E3
Exchange HL with the stack top.
6628
PUSH HL E5
Save HL onto the stack.
6629
JUMP to SYS overlay entry at 4DE4H.
662CH - Validation: OR L / OR C / Error Check
Short validation routine that ORs L and C into A. If the result is zero (both L and C are zero), it jumps to error 7EH at 5DB2H (Bad Record Number). Otherwise, it loads A with C and returns.
662C
OR L B5
OR Register A with Register L.
662D
OR C B1
OR Register A with Register C. If A, L, and C are all zero, Z is set.
662E
If Z (all values zero), JUMP to 5DB2H - error code 7EH (Bad Record Number).
6631
LD A,C 79
Load Register A with Register C.
6632
OR A B7
Set flags based on A.
6633
RET C9
RETURN with A=C and flags set.
6634H - Random Access Mode Validator
Checks bit 2 of IX+00H (random access mode flag). If clear (not in random access mode), jumps to error 6CH at 5DA9H. If set, returns normally. Called from the PRINT# formatting handler at 5EBFH (via 6634H).
6634
BIT 2,(IX+00H) DD CB 00 56
Test bit 2 of IX+00H (the FCB status flags byte). Bit 2 indicates random access mode.
6638
If Z (bit 2 clear - file is NOT in random access mode), JUMP to 5DA9H - error code 6CH (file not in correct mode). The operation requires random access mode.
663B
RET C9
RETURN. The file is in random access mode - operation can proceed.
663CH - NOP FILL AREA (Block 1 Padding)
Reserved/unused area - 128 bytes of 00H (NOP) from Block 1 of the /CMD file. Block 1 loads from 5700H through 66BBH. This padding area from 663CH through 66BBH is overwritten when Block 2 loads at 66BCH. In Block 1, these bytes serve no purpose and exist only to pad the block to a full boundary before the Block 2 overlay region begins.
663C
NOP × 128 00 × 128 (663CH–66BBH)
128 bytes of 00H (NOP instructions). This is Block 1 padding that occupies 663CH through 66BBH. The entire region is overwritten by Block 2 of the /CMD file, which loads starting at 66BCH. These NOPs are never executed.
66BCH - /CMD BLOCK 2 HEADER BYTES
Block 2 of the BASIC/CMD file loads starting at 66BCH, overwriting the NOP fill from Block 1. The first two bytes (66BCH-66BDH) are part of the /CMD record header structure and are not executable code. The transfer address in the /CMD file specifies 66BEH as the program entry point.
66BC
DEFB 2AH, 2AH, 01H 2A 2A 01
/CMD Block 2 record header bytes. 2AH 2AH = asterisk markers (standard /CMD record prefix). 01H = record type byte indicating a load-address data block. The disassembler incorrectly decodes these as LD HL,(012AH) because it treats all bytes as Z80 instructions, but these are /CMD file format overhead, not executable code.
66BEH - PROGRAM ENTRY POINT
This is the first code executed when BASIC/CMD is loaded and run. The /CMD transfer address specifies 66BEH. This entry point code parses the command line for options: an asterisk prefix (*) for auto-run, a numeric file count (stored at 6502H), a memory limit (stored at 64A4H), a verify flag 'V' (stored at 649FH), a starting line number, and string space configuration. After parsing, execution falls through to the BASIC initialization sequence at 64A3H (Part 17).
The /CMD loader sets the transfer address to 66BEH. At entry, HL points to the command line buffer in the DOS command area. The first byte at 66BFH is C4H (CALL NZ opcode) but the 3-byte sequence at 66BFH-66C1H is actually an artifact of the /CMD block boundary - the disassembler shows CALL NZ,C366H but this call target (C366H) is outside BASIC/CMD address space. In practice, the Z FLAG state from the /CMD loader determines whether this instruction is skipped (Z set) or taken (NZ set). The code path that matters begins at 66C4H.
66BF
Conditional CALL to C366H if the NZ FLAG is set. This is a /CMD block boundary artifact. The bytes C4 66 C3 at 66BFH-66C1H span the transition from the Block 2 header into executable code. In normal operation from the DOS loader, the Z FLAG is set, so this CALL is not taken and execution falls through.
66C2
LD L,D 6A
Load Register L with the contents of Register D. This instruction is part of the /CMD boundary transition and is effectively a no-op in the context of the entry sequence - its result is immediately overwritten at 66C4H.
66C3
LD D,A 57
Load Register D with the contents of Register A. Like the previous instruction, this is part of the /CMD boundary transition and its result is immediately overwritten.
Real Entry Point
Execution effectively begins here. HL points to the DOS command line buffer. The code decrements HL to back up one position, then calls RST 10H to fetch the next character from the command line.
66C4
DEC HL 2B
DECrement Register Pair HL by 1. Back up the command line pointer by one byte to prepare for the RST 10H character-fetch call, which increments HL before reading.
66C5
RST 10H D7
GOSUB to ROM routine at 0010H to fetch the next non-space character from the command line pointed to by HL. On return, Register A holds the character and HL points to the character after it.
66C6
CP 2AH FE 2A
Compare Register A against 2AH (ASCII *). If Register A equals 2AH, the Z FLAG is set, indicating the user typed an asterisk prefix for auto-run mode (e.g., BASIC *PROGRAM). If not equal, the NZ FLAG is set.
66C8
If the NZ FLAG has been set (the first command line character is NOT an asterisk, meaning this is a normal BASIC invocation without auto-run), JUMP forward to 670DH to parse numeric parameters (file count, verify flag, etc.).
Auto-Run Path
The asterisk (*) prefix was found. This path saves the current program area boundaries, checks string space, computes the file count from available memory, and then jumps to the initialization sequence.
66CA
PUSH HL E5
Save Register Pair HL (the command line pointer, now past the asterisk) onto the stack. This pointer will be used later to extract the program filename for auto-run.
66CB
LD HL,(40B1H) 2A B1 40
Load Register Pair HL with the 16-bit value at 40B1H (the top-of-arrays pointer from the ROM BASIC workspace). This is the current upper boundary of BASIC's variable/array storage area.
66CE
LD (64A4H),HL 22 A4 64
Store Register Pair HL (the top-of-arrays value from 40B1H) into the memory limit variable at 64A4H. This sets the BASIC memory ceiling to the current top-of-arrays boundarySELF-MODIFYING CODE] - writes the operand of the instruction at 64A3H.
66D1
LD HL,(40A4H) 2A A4 40
Load Register Pair HL with the 16-bit value at 40A4H (the program area start pointer from the ROM BASIC workspace). This is the base address where BASIC program text begins.
66D4
PUSH HL E5
Save Register Pair HL (the program area start address from 40A4H) onto the stack. This will be used to calculate the program size for the file count computation.
66D5
LD E,(HL) 5E
Load Register E with the byte at the address in HL (the first byte of the BASIC program area). In a BASIC program, the first two bytes of each line are the link pointer to the next line. This fetches the low byte of that link pointer.
66D6
INC HL 23
INCrement Register Pair HL by 1 to point to the high byte of the line link pointer.
66D7
LD D,(HL) 56
Load Register D with the byte at the address in HL (the high byte of the first line's link pointer). Register Pair DE now holds the complete 16-bit link pointer to the second BASIC program line.
66D8
EX DE,HL EB
Exchange Register Pairs DE and HL. HL now holds the link pointer (the address of the second program line), and DE holds the address of the first line's high link byte.
66D9
LD A,H 7C
Load Register A with the high byte of Register Pair HL (the link pointer). This prepares to test whether the link pointer is 0000H, which would mean no BASIC program is loaded.
66DA
OR L B5
OR Register L into Register A. If HL was 0000H (no BASIC program loaded), Register A is now 00H and the Z FLAG is set. If a program is loaded, the NZ FLAG is set.
66DB
If the Z FLAG has been set (the link pointer is 0000H, meaning no BASIC program is currently in memory), JUMP forward to 66E4H to skip the starting line number extraction and proceed to string space setup.
A BASIC program IS loaded in memory. Extract the starting line number from the first program line and store it for auto-run.
66DD
LD (653FH),HL 22 3F 65
Store Register Pair HL (the link pointer to the second program line, which serves as a reference for the first line's starting line number) into the start-line-number variable at 653FH. [SELF-MODIFYING CODE] - writes the operand at 653FH used by the initialization sequence to set the RUN starting line.
66E0
EX DE,HL EB
Exchange Register Pairs DE and HL. HL now points back to the first program line area, DE holds the link pointer.
66E1
RST 18H DF
GOSUB to ROM routine at 0018H to compare HL against DE. This comparison checks the relative position of the program area pointer against the link pointer.
66E2
If the NO CARRY FLAG has been set (the comparison indicates an inconsistent program area state), JUMP to 673DH to exit with an error via 57C9H (the SYSTEM exit/error path).
66E4
LD HL,(40F9H) 2A F9 40
Load Register Pair HL with the 16-bit value at 40F9H (the string space top pointer from the ROM BASIC workspace). This is the upper boundary of string storage.
66E7
LD (6548H),HL 22 48 65
Store Register Pair HL (the string space top address from 40F9H) into the string space configuration variable at 6548H. [SELF-MODIFYING CODE] - writes the operand used by the initialization sequence to configure BASIC's string space.
66EA
DEC HL 2B
DECrement Register Pair HL by 1 to point to the last byte of the string space area.
66EB
LD A,(HL) 7E
Load Register A with the byte at the address in HL (the last byte of the string space). This reads the high byte of a potential stored value.
66EC
DEC HL 2B
DECrement Register Pair HL by 1 to point to the byte before the last string space byte.
66ED
OR (HL) B6
OR the byte at the address in HL into Register A. If both the last two bytes of the string space are 00H, the Z FLAG is set, indicating the string space is clear/empty.
66EE
If the NZ FLAG has been set (the top of string space contains non-zero data, indicating a corrupted or incompatible state), JUMP to 673DH to exit with an error via 57C9H.
66F0
RST 18H DF
GOSUB to ROM routine at 0018H. Context-dependent comparison check on the current program state.
66F1
If the CARRY FLAG has been set (comparison indicates an invalid state), JUMP to 673DH to exit with an error via 57C9H.
66F3
OR FFH F6 FF
OR Register A with FFH. This sets Register A to FFH and clears the Z FLAG. Importantly, it also clears the CARRY FLAG. Register A = FFH serves as the initial file count accumulator (will be incremented to 00H on first loop iteration).
File Count Calculation Loop
This loop calculates how many FCBs can fit in the memory space between the program area start and the entry point code. Each FCB is 012DH (301) bytes.
66F5
POP HL E1
Restore Register Pair HL from the stack. HL now holds the program area start address (saved at 66D4H).
66F6
LD DE,66BFH 11 BF 66
Load Register Pair DE with 66BFH (the address of the entry point code area). This is the upper boundary for the FCB allocation space.
66F9
SBC HL,DE ED 52
SUBtract with Carry Register Pair DE (66BFH) from Register Pair HL (program area start). Since the CARRY FLAG was cleared by the OR FFH at 66F3H, this is a pure subtraction. HL = program_start − 66BFH, which is a negative value representing the available space (as a complement).
66FB
LD DE,(649EH) ED 5B 9E 64
Load Register Pair DE with the 16-bit value at 649EH (the FCB size, default 012DH = 301 bytes). This is the size of one File Control Block.
66FF
ADD HL,DE 19
ADD Register Pair DE (FCB size, 012DH) to Register Pair HL (the running space calculation). Each iteration adds one FCB's worth of space to see if it fits.
6700
INC A 3C
INCrement Register A by 1. Register A is the file count accumulator, starting from FFH (first increment makes it 00H, then 01H, 02H, etc.).
6701
OR A B7
OR Register A with itself. This sets flags based on the current file count value and clears the CARRY FLAG for the subsequent SBC instruction.
6702
SBC HL,DE ED 52
SUBtract Register Pair DE (FCB size, 012DH) from Register Pair HL. This checks whether another FCB would fit in the remaining space. If HL goes negative (borrow), the CARRY FLAG is set.
6704
If the Z FLAG has been set (the subtraction result is exactly zero, meaning the space is exactly filled), JUMP to 6747H to store the calculated file count and continue initialization.
6707
CP 0FH FE 0F
Compare Register A (the file count accumulator) against 0FH (decimal 15). The maximum allowed file count is 15. If Register A ≥ 0FH, the NO CARRY FLAG is set.
6709
If the CARRY FLAG has been set (Register A < 0FH, meaning the file count has not yet reached the maximum of 15), JUMP back to 6700H to try fitting another FCB. [LOOP — continue counting]
670B
Unconditional JUMP to 673DH to exit with an error via 57C9H. This is reached if the file count reached 15 without the space being exactly consumed - indicating an invalid memory configuration for auto-run mode.
Normal Entry Path
No asterisk prefix was found on the command line. This path parses explicit numeric parameters: file count, verify flag (V), starting line number, and FCB size override.
670D
DEC HL 2B
DECrement Register Pair HL by 1. Back up the command line pointer by one byte because the RST 10H at 66C5H advanced it past the first character, but since no asterisk was found, we need to re-examine from the current position.
670E
LD BC,012DH 01 2D 01
Load Register Pair BC with 012DH (decimal 301). This is the default FCB size in bytes (the standard NEWDOS/80 File Control Block size).
6711
LD (649EH),BC ED 43 9E 64
Store Register Pair BC (012DH, the default FCB size) into the FCB size variable at 649EH. [SELF-MODIFYING CODE] - writes the operand used throughout BASIC for FCB size calculations (5F6AH, 6512H, 66FBH).
6715
RST 10H D7
GOSUB to ROM routine at 0010H to fetch the next non-space character from the command line pointed to by HL. On return, Register A holds the character and HL points past it.
6716
If the NO CARRY FLAG has been set (the character from RST 10H is NOT a digit - RST 10H sets CARRY for digits 0-9), JUMP forward to 674BH to store the command line pointer and begin initialization. This handles the case where no numeric file count was specified.
6718
GOSUB to 5CD5H (the decimal number parser in Part 10). This routine parses a decimal number string from the command line and returns the result in Register Pair DE. The number parsed is the user-specified file count.
671B
If the CARRY FLAG has been set (the decimal parser returned an error - invalid number syntax), JUMP to 673DH to exit with an error via 57C9H.
671D
LD A,D 7A
Load Register A with the high byte of Register Pair DE (the parsed file count). If the number is greater than 255, Register D will be non-zero.
671E
OR A B7
OR Register A with itself. If Register D is non-zero (the file count exceeds 255), the NZ FLAG is set.
671F
If the NZ FLAG has been set (the parsed number has a non-zero high byte, meaning it is 256 or greater), JUMP to 6740H. Numbers ≥ 256 are treated as a memory limit address rather than a file count - the value is decremented by 1 and stored at 64A4H as the memory ceiling.
6721
LD A,E 7B
Load Register A with the low byte of Register Pair DE (the parsed file count, now confirmed to be 0-255).
6722
CP 10H FE 10
Compare Register A (the file count) against 10H (decimal 16). If Register A ≥ 10H, the NO CARRY FLAG is set. The maximum allowed file count is 0FH (15).
6724
If the NO CARRY FLAG has been set (the file count is 16 or greater, exceeding the maximum of 15), JUMP to 673DH to exit with an error via 57C9H.
6726
LD (6502H),A 32 02 65
Store Register A (the validated file count, 0-15) into the file count variable at 6502H. [SELF-MODIFYING CODE] - writes the operand used by the initialization sequence to configure the number of FCBs.
6729
LD A,(HL) 7E
Load Register A with the byte at the address in HL (the next character on the command line after the file count number).
672A
CP 56H FE 56
Compare Register A against 56H (ASCII V). If Register A equals 56H, the Z FLAG is set, indicating the user specified the Verify option on the command line.
672C
If the NZ FLAG has been set (the next character is NOT 'V', so no verify option), JUMP forward to 6734H to continue checking for additional parameters (comma separator or end of line).
672E
LD A,02H 3E 02
Load Register A with 02H. This is the verify flag value - 02H means "verify after write" is enabled.
6730
LD (649FH),A 32 9F 64
Store Register A (02H, the verify enable flag) into the verify flag variable at 649FH. [SELF-MODIFYING CODE] - writes the operand read by SYS20 to determine whether disk writes should be verified.
6733
RST 10H D7
GOSUB to ROM routine at 0010H to fetch the next non-space character from the command line. This advances past the 'V' character.
6734
LD A,(HL) 7E
Load Register A with the byte at the address in HL (the current command line character).
6735
CP 2CH FE 2C
Compare Register A against 2CH (ASCII ,). If Register A equals 2CH, the Z FLAG is set, indicating a comma separator separating additional parameters on the command line.
6737
If the Z FLAG has been set (a comma was found), JUMP back to 6715H to parse the next parameter from the command line. [LOOP - parse next parameter]
6739
CP 0DH FE 0D
Compare Register A against 0DH (ASCII carriage return). If Register A equals 0DH, the Z FLAG is set, indicating the end of the command line has been reached.
673B
If the Z FLAG has been set (end of command line reached), JUMP forward to 674BH to store the command line pointer and begin initialization.
673D
Unconditional JUMP to 57C9H (CMD"S" / SYSTEM exit). This is the error exit for all command line parsing failures - invalid file count, bad memory limit, corrupted auto-run state, or unrecognized characters. Returns to the DOS command prompt.
Memory Limit Path
The parsed number was ≥ 256, so it is treated as a memory address limit rather than a file count.
6740
DEC DE 1B
DECrement Register Pair DE by 1. The user-specified memory limit is decremented by 1 to convert from a "memory size" to a "highest usable address" value.
6741
LD (64A4H),DE ED 53 A4 64
Store Register Pair DE (the adjusted memory limit address) into the memory limit variable at 64A4H. [SELF-MODIFYING CODE] - writes the operand of the instruction at 64A3H, overriding the default memory ceiling.
6745
Unconditional JUMP back to 6734H to continue checking for additional command line parameters (comma separator, 'V' flag, or end of line).
File Count Store - Auto-Run Path
Reached from the auto-run FCB calculation loop when the space is exactly consumed.
6747
LD (6502H),A 32 02 65
Store Register A (the calculated file count from the auto-run FCB fitting loop) into the file count variable at 6502H. [SELF-MODIFYING CODE]
674A
POP HL E1
Restore Register Pair HL from the stack. HL now holds the command line pointer (saved at 66CAH), pointing to the auto-run program filename past the asterisk.
Common Initialization Entry
Both the auto-run and normal paths converge here. HL points to the command line (either the filename for auto-run, or the position after all parsed parameters). The code stores the command line pointer, copies ROM system variables, and jumps to the main BASIC initialization at 64A3H.
674B
LD (6537H),HL 22 37 65
Store Register Pair HL (the command line pointer) into the command line pointer variable at 6537H. [SELF-MODIFYING CODE] - writes the operand used by the initialization sequence at 6522H to resume command line processing after memory and FCB setup.
674E
LD HL,18F7H 21 F7 18
Load Register Pair HL with 18F7H (a ROM address). This is the source address for a block of ROM BASIC system variables that need to be copied into RAM.
6751
LD DE,4080H 11 80 40
Load Register Pair DE with 4080H (a RAM address). This is the destination for the ROM system variable block - the BASIC workspace area starting at 4080H.
6754
LD BC,0027H 01 27 00
Load Register Pair BC with 0027H (decimal 39). This is the number of bytes to copy from the ROM system variable table to the BASIC workspace.
6757
LDIR ED B0
Block copy 39 bytes from ROM at 18F7H to RAM at 4080H. This initializes the BASIC workspace with default system variable values from the ROM table. HL advances to 191EH, DE advances to 40A7H, BC decrements to 0000H.
6759
Unconditional JUMP to 64A3H to enter the main BASIC initialization sequence (Part 17). That code performs memory testing, banner display, jump table installation, FCB allocation, and finally enters the BASIC command loop.
675CH - STARTUP BANNER TEXT
Startup banner text displayed by the BASIC initialization routine at 64A1H (Part 17) via the DOS message display routine at 4467H. The text is preceded by screen control codes: 1CH (HOME cursor) and 1FH (CLEAR to end of screen). The string is terminated with 0DH (carriage return). Line feed characters (0AH) separate the two display lines.
675C
DEFM 1CH+1FH+"DISK BASIC. RADIO SHACK'S ROM ENHANCED WITH"+0AH
Startup banner line 1. 1CH = HOME cursor (move cursor to top-left of screen). 1FH = CLEAR screen from cursor to end. The text "DISK BASIC. RADIO SHACK'S ROM ENHANCED WITH" is displayed, followed by 0AH (line feed) to advance to the next display line. 47 bytes from 675CH through 678AH.
678B
DEFM "APPARAT'S NEWDOS80 EXTENDED AND DISK FEATURES."+0AH+0DH
Startup banner line 2. The text "APPARAT'S NEWDOS80 EXTENDED AND DISK FEATURES." is displayed, followed by 0AH (line feed) and 0DH (carriage return / string terminator). 48 bytes from 678BH through 67BAH.
67BBH - BASIC JUMP TABLE (49 Entries)
Jump table containing 49 entries (48 JP instructions plus 1 special inline SVC entry). During initialization at 64F6H (Part 17), the entire 147-byte table is block-copied from 67BBH to the ROM BASIC patch area at 4152H-41E4H using DI/LDIR/EI. Each 3-byte entry replaces a corresponding ROM BASIC vector, redirecting ROM functions to NEWDOS/80's Disk BASIC extensions. The special entry at 680FH contains LD A,2FH / RST 28H (an inline SVC 2FH call) instead of a JP instruction.
[JUMP TABLE - 49 entries, 67BBH through 684BH, copied to 4152H-41E4H during init
Format: Source Address → JP Target (Handler Description) → Installed at ROM Patch Address
67BB
Jump table slot 0 → 58CEH (CLOSE/FIELD common entry). Installed at 4152H.
67BE
Jump table slot 1 → 577FH (SVC 36H entries). Installed at 4155H.
67C1
Jump table slot 2 → 58CBH (CLOSE/FIELD entry). Installed at 4158H.
67C4
Jump table slot 3 → 583FH (PRINT# position handler). Installed at 415BH.
67C7
Jump table slot 4 → 58C8H (CLOSE/FIELD entry). Installed at 415EH.
67CA
Jump table slot 5 → 5E9EH (PRINT# TAB function). Installed at 4161H.
67CD
Jump table slot 6 → 5EAAH (PRINT USING scanner). Installed at 4164H.
67D0
Jump table slot 7 → 5EA2H (PRINT# SPC function). Installed at 4167H.
67D3
Jump table slot 8 → 58B7H (OPEN mode "I" entry). Installed at 416AH.
67D6
Jump table slot 9 → 58B4H (OPEN mode "O" entry). Installed at 416DH.
67D9
Jump table slot 10 → 58B1H (OPEN mode "R" entry). Installed at 4170H.
67DC
Jump table slot 11 → 57ECH (filename extraction). Installed at 4173H.
67DF
JP 3030H C3 30 30
Jump table slot 12 → 3030H (ROM routine). Installed at 4176H.
67E2
Jump table slot 13 → 5795H (SVC entry). Installed at 4179H.
67E5
Jump table slot 14 → 5E3CH (FIELD statement handler). Installed at 417CH.
67E8
Jump table slot 15 → 60FFH (file open alternate entry). Installed at 417FH.
67EB
Jump table slot 16 → 60FEH (file open + SVC 2CH). Installed at 4182H.
67EE
Jump table slot 17 → 5F7AH (PUT/GET handler). Installed at 4185H.
67F1
Jump table slot 18 → 574AH (SVC entry). Installed at 4188H.
67F4
Jump table slot 19 → 572EH (SVC dispatch, SVC 35H). Installed at 418BH.
67F7
Jump table slot 20 → 1E4AH (ROM "Illegal Function Call" error routine). Installed at 418EH.
67FA
Jump table slot 21 → 6415H (file open + step 6073H + 442CH). Installed at 4191H.
67FD
Jump table slot 22 → 5790H (SVC entry). Installed at 4194H.
6800
Jump table slot 23 → 58E1H (FIELD definition handler). Installed at 4197H.
6803
Jump table slot 24 → 58E2H (FIELD alternate entry). Installed at 419AH.
6806
Jump table slot 25 → 5786H (SVC 36H entry). Installed at 419DH.
6809
Jump table slot 26 → 573BH (BC=8440H entry). Installed at 41A0H.
680C
Jump table slot 27 → 579FH (SVC entry). Installed at 41A3H.
[SPECIAL ENTRY] - Slot 28 at 680FH is NOT a JP instruction. It contains LD A,2FH / RST 28H, which is an inline SVC call to SVC function 2FH. When the ROM BASIC vector at 41A6H is executed, it loads function code 2FH into Register A and calls RST 28H (the NEWDOS/80 SVC dispatcher) directly.
680F
LD A,2FH 3E 2F
Jump table slot 28 (SPECIAL) - Load Register A with 2FH (SVC function code 2FH). This is the first half of an inline SVC call embedded directly in the jump table data. Installed at 41A6H.
6811
RST 28H EF
GOSUB to RST 28H (the NEWDOS/80 SVC dispatcher) with Register A = 2FH. This completes the inline SVC 2FH call. The 3 bytes (3E 2F EF) occupy the same space as a normal JP instruction. Installed at 41A8H.
6812
Jump table slot 29 → 587FH (file setup + random access). Installed at 41A9H.
6815
JP 2169H C3 69 21
Jump table slot 30 → 2169H (ROM routine). Installed at 41ACH.
6818
Jump table slot 31 → 575DH (stack manipulation). Installed at 41AFH.
681B
Jump table slot 32 → 5756H (SVC 34H path). Installed at 41B2H.
681E
Jump table slot 33 → 638CH (save+clear guard flag). Installed at 41B5H.
6821
Jump table slot 34 → 6395H (restore guard flag). Installed at 41B8H.
6824
Jump table slot 35 → 5F8FH (close/flush all files). Installed at 41BBH.
6827
Jump table slot 36 → 6411H (file open + step 20H). Installed at 41BEH.
682A
Jump table slot 37 → 604FH (character output handler). Installed at 41C1H.
682D
Jump table slot 38 → 6399H (line intercept handler). Installed at 41C4H.
6830
Jump table slot 39 → 5746H (conditional RET C). Installed at 41C7H.
6833
Jump table slot 40 → 5F2BH (PRINT USING check). Installed at 41CAH.
6836
Jump table slot 41 → 5F24H (INPUT# handler). Installed at 41CDH.
6839
Jump table slot 42 → 5F79H (RET - placeholder). Installed at 41D0H.
683C
Jump table slot 43 → 5F14H (PRINT# handler). Installed at 41D3H.
683F
Jump table slot 44 → 5E81H ('#' file number check). Installed at 41D6H.
6842
Jump table slot 45 → 578BH (SVC entry). Installed at 41D9H.
6845
Jump table slot 46 → 579AH (SVC entry). Installed at 41DCH.
6848
Jump table slot 47 → 5E92H (LINE INPUT# handler). Installed at 41DFH.
684B
Jump table slot 48 → 5F79H (RET - placeholder). Installed at 41E2H. This is the last entry in the jump table and the last byte of the BASIC/CMD file.