5700H - FCB WORK AREA AND RESERVED SPACE: File Control Block Work Area
This area (5700H-570CH) serves as the active File Control Block (FCB) work area. When a file is opened, the 45-byte FCB structure is copied here from the FCB table at 66BEH. The NOPs represent uninitialized storage that gets populated with file status, position pointers, and buffer addresses during file operations.
5700
NOP 00
FCB+00: Status byte storage. Bit 0=file open, Bit 1=write mode enabled. Initialized to 00H (no file open).
5701
NOP 00
FCB+01: Flags byte. Bit 3=write active, Bit 4=buffer dirty, Bit 5=file modified, Bit 7=file valid.
5702
NOP 00
FCB+02: File position low byte. Combined with 5703H-5704H forms 24-bit file pointer.
5703
NOP 00
FCB+03: File position middle byte.
5704
NOP 00
FCB+04: File position high byte (allows files up to 16MB, though disk limits are much smaller).
5705
NOP 00
FCB+05: Saved position low byte (for record operations).
5706
NOP 00
FCB+06: Saved position high byte.
5707
NOP 00
FCB+07: EOF position low byte.
5708
NOP 00
FCB+08: EOF position middle byte.
5709
NOP 00
FCB+09: EOF position high byte.
570A
NOP 00
FCB+0A: Column/character count for formatted output.
570B
NOP 00
FCB+0B: Reserved.
570C
NOP 00
FCB+0C: Reserved.
572DH - CMD COMMAND DISPATCHER ENTRY POINTS: CMD"S" Entry Point (System Command)
This section contains entry points for various CMD commands. Each entry point sets up Register BC with a return address, loads Register A with an SVC code, and jumps to the common dispatcher at 576CH. The CMD dispatcher at 57C3H examines the character following CMD" to route to the appropriate handler.
572D
NOP 00
Placeholder/alignment byte before entry point.
572E
[CMD"S" ENTRY] CALL the file open/setup routine at 609AH to prepare for system operations. This initializes the FCB work area.
5731
LD BC,5334H 01 34 53
Load BC with return address 5334H - this is where execution continues after the CMD"S" operation completes.
5734
Jump to 5752H to load A=35H and continue to common dispatcher. SVC 35H handles system file operations.
[CMD"F" Entry] - Filespec/Format command entry point
5736
LD BC,559CH 01 9C 55
[CMD"F" ENTRY] Load BC with return address 559CH for filespec command completion.
5739
Jump to common path at 5752H (A will be set to 35H).
[CMD"?" Entry] - Opens file with special mode flags
573B
LD BC,8440H 01 40 84
[CMD"?" ENTRY] Load BC with 8440H - this encodes both a return address component and mode flags (84H = special open mode).
573E
CALL alternate file setup entry at 609DH (slightly different initialization path).
5741
LD BC,55C5H 01 C5 55
Load BC with return address 55C5H for post-operation continuation.
5744
Jump to 5752H to continue with SVC 35H dispatch.
[5746H] - Conditional return on Carry flag
5746
RET C D8
Return if Carry flag is set - used for error condition early exit.
5747
LD A,01H 3E 01
Load A with 01H - indicates single file/buffer mode.
5749
LD B,AFH 06 AF
Load B with AFH - this is an XOR A opcode! Used as a parameter that also serves as inline code.
574B
PUSH AF F5
Save A (01H) and flags on stack for later retrieval.
574C
CALL file open/setup routine.
574F
LD BC,5202H 01 02 52
Load BC with return address 5202H.
[5752H] - Common entry: Set A=35H and jump to dispatcher
5752
LD A,35H 3E 35
Load A with SVC code 35H. This is the supervisor call for disk file operations.
5754
Jump to the SVC dispatcher at 576CH to execute the system call.
[5756H] - Push AF/BC then load alternate return address
5756
PUSH AF F5
Save accumulator and flags.
5757
PUSH BC C5
Save BC register pair.
5758
LD BC,54FFH 01 FF 54
Load BC with return address 54FFH.
575B
Jump to 576AH to load A=34H and dispatch.
[575DH] - Stack manipulation for error recovery
575D
POP HL E1
Pop top of stack into HL (discarding a return address).
575E
POP HL E1
Pop another value from stack into HL.
575F
PUSH HL E5
Push HL back - net effect is to remove one stack level.
5760
LD DE,1A7EH 11 7E 1A
Load DE with ROM address 1A7EH - BASIC's main loop entry point.
5763
RST 18H DF
RST 18H - Compare HL with DE (ROM comparison routine).
5764
If HL ≠ DE (not at BASIC main loop), jump to ROM error handler at 036BH.
5767
LD BC,5202H 01 02 52
Load BC with return address 5202H.
[576AH] - Entry with SVC 34H
576A
LD A,34H 3E 34
Load A with SVC code 34H - alternate disk operation supervisor call.
[576CH] - Main SVC Dispatcher - executes RST 28H with code in A
576C
PUSH BC C5
[SVC DISPATCHER] Push return address (in BC) onto stack.
576D
CP 00H FE 00
Compare A with 00H - check if SVC code is zero (no operation).
576F
RET Z C8
If A=00H, return immediately (NOP case). Otherwise continue to execute SVC.
5770
PUSH HL E5
Save HL (BASIC's current position pointer).
5771
LD HL,576EH 21 6E 57
Load HL with address 576EH - this is the byte after the CP instruction, used for self-modifying code.
5774
LD (HL),00H 36 00
Store 00H at 576EH - clears the comparison value (self-modifying: changes CP 00H operand).
5776
CALL 57B5H to execute RST 28H (supervisor call) with the SVC code in A.
5779
If NZ (error occurred), jump to error handler at 5E16H.
577C
LD (HL),A 77
Store A (result) at 576EH - preserves the return code for later inspection.
577D
POP HL E1
Restore HL (BASIC position pointer).
577E
RET C9
Return to address that was in BC (now on stack).
577FH - More CMD Command Entry Points
These entry points handle additional CMD commands. Each loads BC with a specific return address and A with SVC code 36H, then uses the common dispatcher. SVC 36H is used for extended disk operations including KILL, RENAME, and directory functions.
577F
LD BC,534AH 01 4A 53
[Entry Point] Load BC with return address 534AH.
5782
LD A,36H 3E 36
Load A with SVC code 36H - extended disk operations supervisor call.
5784
Jump back to SVC dispatcher at 576CH.
5786
LD BC,53F2H 01 F2 53
[Entry Point] Load BC with return address 53F2H.
5789
Jump to 5782H to set A=36H and dispatch.
578B
LD BC,5462H 01 62 54
[Entry Point] Load BC with return address 5462H.
578E
Jump to set A=36H and dispatch.
5790
LD BC,54C5H 01 C5 54
[Entry Point] Load BC with return address 54C5H.
5793
Jump to set A=36H and dispatch.
5795
LD BC,5504H 01 04 55
[Entry Point] Load BC with return address 5504H.
5798
Jump to set A=36H and dispatch.
579A
LD BC,55D4H 01 D4 55
[Entry Point] Load BC with return address 55D4H.
579D
Jump to set A=36H and dispatch.
579F
LD BC,55E8H 01 E8 55
[Entry Point] Load BC with return address 55E8H.
57A2
Jump to set A=36H and dispatch.
57A4
PUSH BC C5
Push current BC (preserving caller's value).
57A5
LD BC,5202H 01 02 52
Load BC with return address 5202H.
57A8
Jump to set A=36H and dispatch.
57AAH - SVC Wrapper Routines
These routines provide wrappers for executing supervisor calls (RST 28H) and include a lowercase-to-uppercase conversion function used when parsing filenames and commands.
57AA
LD B,28H 06 28
Load B with 28H (40 decimal) - parameter for SVC call.
57AC
Jump to 57B0H to execute SVC 57H.
57AE
LD B,20H 06 20
Load B with 20H (32 decimal) - alternate parameter.
57B0
LD A,57H 3E 57
Load A with SVC code 57H.
57B2
RST 28H EF
Execute supervisor call 57H - this is a direct RST 28H to DOS.
57B3
LD A,37H 3E 37
Load A with SVC code 37H.
57B5
RST 28H EF
[SVC EXECUTOR] Execute supervisor call with code in A. This is the main entry point for all SVC operations.
57B6
NOP 00
Padding/reserved space after RST (SVC may modify following bytes).
57B8
NOP 00
Reserved - also used as pointer storage (low byte).
57B9
NOP 00
Reserved - pointer storage (high byte).
[57BAH] - Lowercase to Uppercase Conversion Routine
57BA
CP 61H FE 61
[UPPER CASE] Compare A with 61H (a). Check if character is lowercase letter.
57BC
RET C D8
If A < 61H (not lowercase), return unchanged.
57BD
CP 7BH FE 7BH
Compare A with 7BH (one past z).
57BF
RET NC D0
If A ≥ 7BH (not a-z range), return unchanged.
57C0
SUB 20H D6 20
Subtract 20H to convert lowercase to uppercase (a→A, b→B, etc.).
57C2
RET C9
Return with uppercase character in A.
57C3H - CMD Command Character Router
This is the main CMD command dispatcher. When BASIC encounters CMD"X" where X is any character, this routine examines X and routes to the appropriate handler. It supports: S (system), F (filespec), C (copy/compress), J (jump), O (open device), E (enable/disable interrupts), D (debug), R (reset/repeat), and T (timer).
57C3
LD A,(HL) 7E
[CMD ROUTER] Load A with character at (HL) - this is the command letter after CMD".
57C4
CP 53H FE 53
Compare A with 53H (S). Check for CMD"S" (System command).
57C6
POP HL E1
Pop return address into HL (stack cleanup).
57C7
If not S, jump to 57CCH to check other commands.
57C9
[CMD"S"] Jump to DOS Ready (warm start) at 402DH. CMD"S" returns to DOS.
57CC
CP 46H FE 46
Compare A with 46H (F). Check for CMD"F" (Filespec/Format).
57CE
[CMD"F"] If F, jump to CMD"F" handler at 5736H.
57D1
CP 43H FE 43
Compare A with 43H (C). Check for CMD"C" (Copy/Compress).
57D3
[CMD"C"] If C, jump to COMPRESS routine at 59ADH.
57D6
CP 4AH FE 4A
Compare A with 4AH (J). Check for CMD"J" (Jump table).
57D8
[CMD"J"] If J, jump to DATE$ function handler at 5A9DH.
57DB
CP 4FH FE 4F
Compare A with 4FH (O). Check for CMD"O" (Open device).
57DD
[CMD"O"] If O, jump to SVC executor at 57B3H with A=37H.
57E0
CP 45H FE 45
Compare A with 45H (E). Check for CMD"E" (Enable/disable).
57E2
If not E, jump to 57E9H to check more commands.
57E4
LD A,C0H 3E C0
[CMD"E"] Load A with C0H - this becomes the opcode at 4012H.
57E6
Jump to error handler at 4409H - CMD"E" not fully implemented here.
57E9
CP 44H FE 44
Compare A with 44H (D). Check for CMD"D" (Debug).
57EB
RET Z C8
[CMD"D"] If D, simply return (debug mode toggle is a NOP in user mode).
57EC
LD B,C3H 06 C3
Load B with C3H - this is the JP opcode, used to enable interrupts.
57EE
CP 52H FE 52
Compare A with 52H (R). Check for CMD"R" (Reset/Repeat).
57F0
[CMD"R"] If R, jump to 57F9H to write JP opcode.
57F2
CP 54H FE 54
Compare A with 54H (T). Check for CMD"T" (Timer).
57F4
If not T, jump to ROM syntax error at 1E4AH - unknown command.
57F7
LD B,C9H 06 C9
[CMD"T"] Load B with C9H - this is the RET opcode, used to disable interrupts.
57F9
LD A,B 78
Copy B (C3H or C9H) to A.
57FA
LD (4012H),A 32 12 40
Store opcode at 4012H - this is the interrupt vector, JP (C3H) enables, RET (C9H) disables.
57FD
EI FB
Enable interrupts.
57FE
RET C9
Return to BASIC.
57FFH - BASIC NAME Statement (Rename File)
This routine handles the BASIC NAME statement which renames files on disk. Syntax: NAME "oldname" AS "newname". It parses both filenames, validates them, and calls the DOS rename function.
57FF
[NAME STMT] CALL ROM routine 2337H - this evaluates a string expression and returns pointer in HL, length in A.
5802
PUSH HL E5
Save HL (pointer to evaluated string, the old filename).
5803
LD DE,(4121H) ED 5B 21 41
Load DE with string descriptor from 4121H (ROM BASIC's string work area).
5807
CALL 5CCBH - parse and validate filename string, returns length in A.
580A
DEC A 3D
Decrement A (filename length) to check if within valid range.
580B
CP 4FH FE 4F
Compare A with 4FH (79). Maximum filename length check.
580D
If A ≥ 4FH (filename too long), jump to syntax error at 1E4AH.
5810
INC A 3C
Restore A to original length.
5811
LD HL,4318H 21 18 43
Load HL with 4318H - DOS command buffer address.
5814
LD B,A 47
Copy length to B (loop counter).
5815
LD C,A 4F
Copy length to C (preserved copy).
5816
PUSH HL E5
Save destination buffer pointer.
[LOOP START] - Copy filename to command buffer, converting to uppercase
5817
LD A,(DE) 1A
[LOOP] Load character from source string (DE points to filename).
5818
INC DE 13
Advance source pointer.
5819
CALL uppercase conversion routine - converts a-z to A-Z.
581C
LD (HL),A 77
Store converted character in command buffer.
581D
INC HL 23
Advance destination pointer.
581E
Decrement B and loop until all characters copied. [LOOP END]
5820
LD (HL),0DH 36 0D
Store carriage return (0DH) as string terminator.
Now scan backwards to find the last non-space character
5822
DEC HL 2B
[TRIM LOOP] Move back one character.
5823
LD A,(HL) 7E
Load character at current position.
5824
CP 20H FE 20
Compare with space (20H).
5826
If space, continue scanning backwards. [TRIM LOOP END]
5828
POP HL E1
Restore buffer start pointer.
5829
DEC C 0D
Decrement original length counter.
582A
If length was 1 (now 0), jump to CMD router - single char is a command.
582D
CP 24H FE 24
Compare last non-space char with 24H ($).
582F
If not $, jump to 57A4H for standard file rename.
5832
CALL ROM 2611H - expects "AS" keyword next in BASIC line.
5835
Jump back to 5807H to parse the new filename.
5837H - FILE DEVICE HANDLER AND OPEN ROUTINES: File Device Setup
These routines handle file device setup, including setting the device type byte and calling ROM routines for file operations. They interface with both the BASIC file handling and DOS file operations.
5837
RST 10H D7
[FILE SETUP] RST 10H - BASIC's "get next character" from program line.
5838
LD A,80H 3E 80
Load A with 80H - device type flag indicating disk file.
583A
LD (40DCH),A 32 DC 40
Store device type at 40DCH - BASIC's current device byte.
583D
OR (HL) B6
OR A with byte at (HL) - combines current device flags with additional flags from memory.
583E
LD B,A 47
Copy combined flags to Register B for later use.
583F
CALL ROM 2612H - expects "AS" token in BASIC line (for OPEN...AS statement).
5842
Jump to 584CH to check device type result.
[5844H] - Alternate entry: Set device type directly
5844
LD A,80H 3E 80
Load A with 80H - disk file device type flag.
5846
LD (40DCH),A 32 DC 40
Store device type at 40DCH (BASIC's current device byte).
5849
CALL ROM 260DH - evaluate expression, result in 40AFH.
[584CH] - Check device type and return
584C
LD A,(40AFH) 3A AF 40
Load A with device type from 40AFH (set by ROM evaluation).
584F
CP 03H FE 03
Compare A with 03H - check if device number is valid (0-2 are special devices).
5851
RET C9
Return with Z flag set if device=3, indicating disk file. NZ indicates other device.
5852H - BASIC OPEN Statement
This routine handles the BASIC OPEN statement (token BEH). Syntax: OPEN "mode",#n,"filename" where mode is "I" (input), "O" (output), or "R" (random). It parses the parameters and sets up the file control block.
5852
CP BEH FE BE
[OPEN STMT] Compare A with BEH - this is the OPEN token. Check if current statement is OPEN.
5854
If not OPEN token, jump to 586FH to check for CLOSE statement.
5856
CALL file device setup at 5837H - initializes device type.
5859
CALL ROM 2828H - evaluate numeric expression, result in HL (file buffer number).
585C
LD A,L 7D
Copy low byte of result to A.
585D
LD (DE),A 12
Store low byte at (DE) - file buffer assignment.
585E
INC DE 13
Advance pointer.
585F
LD A,H 7C
Copy high byte of result to A.
5860
LD (DE),A 12
Store high byte at (DE).
5861
LD A,28H 3E 28
Load A with 28H - ASCII for ( left parenthesis.
5863
CP (HL) BE
Compare with character at (HL) - looking for opening parenthesis.
5864
If not (, jump to ROM error at 1F05H ("(" expected).
5867
RST 10H D7
RST 10H - get next character from BASIC line.
5868
CALL ROM 260DH - evaluate next expression parameter.
586B
LD A,2CH 3E 2C
Load A with 2CH - ASCII for , comma.
586D
Jump back to 5863H to check for comma separator and continue parsing.
586FH - BASIC CLOSE Statement
This routine handles the BASIC CLOSE statement (token C1H). Syntax: CLOSE #n or CLOSE #n,#m,... It parses file numbers and closes each specified file buffer.
586F
CP C1H FE C1
[CLOSE STMT] Compare A with C1H - this is the CLOSE token.
5871
If not CLOSE token, jump to ROM 1997H - continue statement dispatch.
5874
CALL device number parser at 5883H - gets file number, returns vector in DE.
5877
PUSH DE D5
Save device vector pointer.
5878-5879
RST 08H ⇒ D5 CF D5
RST 08H - syntax check, expects D5 Character Code.
587A
CALL ROM 2B02H - close the file, release buffer.
587D
EX (SP),HL E3
Exchange HL with top of stack - get device vector.
587E
LD (HL),E 73
Store low byte of result at device vector location.
587F
INC HL 23
Advance pointer.
5880
LD (HL),D 72
Store high byte of result.
5881
POP HL E1
Restore HL (BASIC line pointer).
5882
RET C9
Return to BASIC interpreter.
5883H - Parse Device/File Number
This routine parses a device number (0-9) from the BASIC line and returns a pointer to the corresponding entry in the device vector table at 58B0H. Each entry is 2 bytes, so the number is doubled to get the offset.
5883
LD DE,58B0H 11 B0 58
[PARSE DEVICE] Load DE with 58B0H - base address of device vector table.
5886
RST 10H D7
RST 10H - get next character from BASIC line.
5887
RET NC D0
If Carry not set (not a digit), return with DE pointing to default entry.
5888
SUB 30H D6 30
Subtract 30H - convert ASCII digit 0-9 to binary 0-9.
588A
ADD A,A 87
Double A - each table entry is 2 bytes.
588B
ADD A,E 83
Add to low byte of base address.
588C
LD E,A 5F
Store result in E.
588D
If no carry from addition, skip increment.
588F
INC D 14
Carry occurred - increment high byte.
5890
RST 10H D7
RST 10H - get next character (skip the digit).
5891
RET C9
Return with DE pointing to device table entry.
5892H - PRINT# Statement Handler
This routine handles the PRINT# statement, which outputs data to a file device. It retrieves the device number, evaluates the expression to print, and sends the data to the appropriate file buffer. The routine begins by restoring flags from a previous operation and then calls the device parser to determine which file device to use.
Entry point for PRINT# statement. The stack contains the return address and flags from the BASIC interpreter. Register A contains the current character from the BASIC program line.
5892
POP AF F1
Restore the Accumulator and Flags from the stack. The flags were previously pushed by the BASIC interpreter before calling this routine, preserving the state of the last comparison or arithmetic operation.
5893
Call the Device Parser routine at 5883H. This routine parses the device number from the BASIC line (e.g., the "1" in PRINT#1) and returns with DE pointing to the appropriate entry in the device vector table at 58B0H. The device number determines which file buffer will receive the output.
5896
PUSH DE D5
Save the device vector pointer (DE) on the stack. DE now points into the device vector table at 58B0H, which contains the address of the handler routine for this device number. This is preserved while we evaluate the expression to print.
5897
Call ROM routine at 252CH to evaluate an expression. This parses and evaluates whatever expression follows the device number in the PRINT# statement (variables, strings, numeric expressions, etc.). The result is placed in the appropriate BASIC registers (typically in the floating-point accumulator for numbers, or string descriptor for strings).
589A
EX (SP),HL E3
Exchange the top of stack with HL. Before: HL contains the current BASIC line pointer, stack top has the device vector pointer. After: HL contains the device vector pointer, and the BASIC line pointer is saved on the stack. This gives us quick access to the device handler address.
589B
LD C,(HL) 4E
Load register C with the low byte of the device handler address. HL points into the device vector table at 58B0H, and this byte is the low byte of the jump address for the appropriate I/O handler.
589C
INC HL 23
Increment HL to point to the next byte in the device vector table, which contains the high byte of the handler address.
589D
LD B,(HL) 46
Load register B with the high byte of the device handler address. Now BC contains the complete 16-bit address of the I/O handler routine for this device.
589E
LD HL,5881H 21 81 58
Load HL with the address 5881H, which is a simple RET instruction. This will be pushed onto the stack as the return address, so when the device handler completes, execution will return here and then immediately return to the caller.
58A1
PUSH HL E5
Push the return address (5881H) onto the stack. This sets up the return path for the device handler - after the handler executes, it will RET to 5881H, which contains another RET to return to the original caller.
58A2
PUSH BC C5
Push the device handler address (in BC) onto the stack. The next RET instruction will "call" this handler by returning to it. This is a common technique for computed calls - push the target address and execute RET.
58A3
Call routine at 584CH to check the device type. This routine loads the value from memory location 40AFH (the current device type flag) and compares it to 03H (string device). The result determines how the output will be formatted. Returns with Z flag set if device type equals 03H (string device).
58A6
PUSH AF F5
Save the flags on the stack. The Z flag indicates whether this is a string device (Z set) or numeric device (Z not set). This information is needed after the conversion call.
58A7
If Z flag is set (device type = 03H, meaning string device), call ROM routine at 29DAH. This routine converts a numeric value to its string representation, preparing it for output to a string-type device. If Z is not set (binary device), this call is skipped.
58AA
EX DE,HL EB
Exchange DE and HL. After the expression evaluation and possible conversion, DE contains the pointer to the result data. This moves that pointer to HL for easier manipulation.
58AB
LD HL,4121H 21 21 41
Load HL with address 4121H, which is the string work area pointer in BASIC's memory. This is where temporary string data is stored during string operations. The address 4121H points to a 2-byte location that holds the current string workspace address.
58AE
POP AF F1
Restore the flags that were saved at 58A6H. The Z flag still indicates whether we're dealing with a string device.
58AF
RET C9
Return to the address that was pushed at 58A2H - this is the computed jump to the device handler. The device handler will then process the output data and eventually return to 5881H, then back to the BASIC interpreter.
58B0H - Device Vector Table
This is a data table containing 10 two-byte addresses for device handlers. Each entry corresponds to a device number (0-9) used with file I/O statements like PRINT#, INPUT#, etc. Device 0 is typically the keyboard/display, and devices 1-9 are disk files. The table is accessed by the device parser at 5883H which calculates an offset based on the device number.
Data table: 10 device vector entries (20 bytes total). Each 2-byte entry is an address to a device handler routine. The addresses are stored in little-endian format (low byte first).
58B0
4A 1E data
Device 0: Address 1E4AH - This points to the ROM Syntax Error handler. Device 0 is typically the keyboard/screen, so attempting file I/O on device 0 produces a syntax error in this DISK BASIC context.
58B2
4A 1E data
Device 1: Address 1E4AH - Syntax Error handler (device not initialized or invalid).
58B4
4A 1E data
Device 2: Address 1E4AH - Syntax Error handler.
58B6
4A 1E data
Device 3: Address 1E4AH - Syntax Error handler.
58B8
4A 1E data
Device 4: Address 1E4AH - Syntax Error handler.
58BA
4A 1E data
Device 5: Address 1E4AH - Syntax Error handler.
58BC
4A 1E data
Device 6: Address 1E4AH - Syntax Error handler.
58BE
4A 1E data
Device 7: Address 1E4AH - Syntax Error handler.
58C0
4A 1E data
Device 8: Address 1E4AH - Syntax Error handler.
58C2
D7 data
Device 9 low byte: D7H - This is part of an actual handler address. Note: The disassembler shows this as a single byte because 58C3H starts a new instruction pattern.
58C3
1E data
Device 9 high byte: 1EH - Combined with D7H gives 1ED7H. However, this may be a different interpretation depending on context. The table effectively redirects most devices to the error handler until they are properly OPENed.
58C5H - TIME$ Function
This routine implements the TIME$ function which returns the current system time as a string in "HH:MM:SS" format. It calls the SYS0 time routine to get the current time values, formats them with a colon separator, and returns the result as a BASIC string. The routine allocates an 11-character string space for the result.
TIME$ function entry point. Returns the current time as an 8-character string "HH:MM:SS".
58C5
PUSH HL E5
Save the BASIC line pointer (HL) on the stack. HL points to the current position in the BASIC program being executed. This must be preserved because the time-getting routine will modify HL.
58C6
LD A,11H 3E 11
Load A with 11H (17 decimal). This is the length of the string to allocate for the time string result. The actual "HH:MM:SS" format is only 8 characters, but extra space is allocated for possible formatting or termination needs.
58C8
Call ROM routine at 2857H to allocate string space. Pass the desired length in A (11H bytes). Returns with DE pointing to the allocated string space in BASIC's string area. This space will hold the formatted time string.
58CB
EX DE,HL EB
Exchange DE and HL. Now HL points to the allocated string buffer where we'll build the time string, and DE is free for other uses.
58CC
Call SYS0 routine at 4470H to get the current system time. This NEWDOS/80 system routine retrieves the time from the system clock. The hours, minutes, and seconds values are returned in registers or stored at a known location, and the ASCII representation is built at the address in HL.
58CF
LD (HL),20H 36 20
Store a space character (20H) at the current position in the string buffer. This adds a separator or padding after the first time component (typically after hours).
58D1
INC HL 23
Increment HL to point to the next position in the string buffer, ready for the next time component.
58D2
Call SYS0 routine at 446DH to append additional time components. This continues building the time string, adding minutes and seconds with appropriate separators. The complete "HH:MM:SS" format is built in the string buffer.
58D5
Jump to ROM routine at 2884H to finalize the string and return it to BASIC. This routine sets up the string descriptor with the length and pointer, then returns to the BASIC interpreter with the TIME$ result ready for assignment or printing.
58D8H - INPUT# / LINE INPUT# Entry Points
These are the entry points for the INPUT# and LINE INPUT# statements, which read data from file devices. The INPUT# statement reads formatted data (comma or carriage-return delimited), while LINE INPUT# reads an entire line including commas. The routines share common code but differ in how they handle the data type (string vs numeric, fixed vs variable length).
Multiple entry points for different input types. The value loaded into A determines the record length or type of input operation.
58D8
LD A,08H 3E 08
Load A with 08H (8 decimal). This is the double-precision record length - 8 bytes. This entry point is used when INPUT# needs to read a double-precision floating-point value from a binary file.
58DA
LD BC,043EH 01 3E 04
Load BC with 043EH. B=04H is the single-precision length (4 bytes), and C=3EH (62 decimal) may be a type code or secondary parameter. Note: This is actually encoded as "LD A,04H" at 58DBH if you enter at that point.
58DB
LD A,04H 3E 04
(Alternate entry) Load A with 04H (4 decimal). This is the single-precision record length - 4 bytes. Used when INPUT# reads a single-precision floating-point value.
58DE
LD BC,023EH 01 3E 02
Load BC with 023EH. B=02H is the integer length (2 bytes). Note: Entering at 58DFH gives "LD A,02H" for integer record handling.
58E0
PUSH AF F5
Save A (the record length) on the stack. The value in A (02H, 04H, or 08H) indicates how many bytes to read for numeric input operations.
58E1
Call ROM routine at 2819H to parse the variable that will receive the input. This routine identifies the target variable from the BASIC statement (the variable after INPUT#n,) and prepares to store data into it.
58E4
POP AF F1
Restore A with the record length that was saved earlier (02H, 04H, or 08H depending on the data type).
58E5
Call ROM routine at 2857H to allocate buffer space for the input data. The number of bytes to allocate is in A. Returns with DE pointing to the allocated buffer.
58E8
EX DE,HL EB
Exchange DE and HL. Now HL points to the input buffer where the data will be stored, and DE holds the previous value of HL (BASIC line pointer).
58E9
Call ROM routine at 09FFH to perform the actual input from the file device. This reads the specified number of bytes from the file into the buffer pointed to by HL. The device number and FCB information determine where the data comes from.
58EC
Jump to ROM routine at 2A2BH to convert and assign the input data. This routine takes the binary data that was read and converts it to BASIC's internal format, then stores it in the target variable that was identified earlier.
58EFH - LINE INPUT# Statement Handler
This routine handles the LINE INPUT# statement, which reads an entire line from a file device into a string variable. Unlike regular INPUT#, LINE INPUT# reads all characters including commas until a carriage return is encountered. It uses the string handling routines to allocate space and copy the data.
LINE INPUT# entry point. Similar structure to INPUT# but handles string data with different record lengths.
58EF
LD A,08H 3E 08
Load A with 08H (8 decimal). This may represent a maximum field width or type indicator. For LINE INPUT#, string data handling uses different size parameters than numeric INPUT#.
58F1
LD BC,043EH 01 3E 04
Load BC with 043EH. This sets up parameters for the string operation - B=04H may indicate a type code, C=3EH (62) may be a maximum length or format indicator.
58F4
LD BC,023EH 01 3E 02
Load BC with 023EH. Alternative parameter set - B=02H for a different mode, C=3EH remains the same.
58F7
PUSH AF F5
Save the type/length indicator (A) on the stack. This will be restored after parsing the target variable.
58F8
Call routine at 5CC0H to get string parameters. This routine retrieves the string descriptor including length and pointer. For LINE INPUT#, it helps determine how much space is needed.
58FB
POP AF F1
Restore the type indicator from the stack.
58FC
LD (40AFH),A 32 AF 40
Store A into memory location 40AFH. This is the device type flag - it indicates the current device type for I/O operations. Values include: 02H=integer, 03H=string, 04H=single, 08H=double.
58FF
DEC A 3D
Decrement A to adjust the length value. This converts from a 1-based count to a 0-based maximum index, or adjusts for buffer sizing calculations.
5900
CP (HL) BE
Compare A with the byte at (HL). HL points to a length or count value from the string descriptor. This checks if the requested size exceeds the available space.
5901
If A >= (HL) (no carry), jump to Syntax Error at 1E4AH. This error occurs when the input operation would exceed the available buffer size or when parameters are invalid.
5904
EX DE,HL EB
Exchange DE and HL. Move the string pointer to HL for the read operation.
5905
Jump to ROM routine at 09F7H to read the line from the file. This reads characters until a carriage return is found, storing them in the buffer. Unlike INPUT#, commas are included in the input.
5908H - MID$ Assignment Statement
This routine handles the MID$ assignment statement (MID$(string$,start,length)=replacement$), which replaces a portion of an existing string with new characters. It's different from the MID$ function which extracts a substring. The routine must validate the start position and length, locate the target string in memory, and perform the character replacement without changing the original string's length.
MID$ assignment entry point. This handles statements like MID$(A$,3,2)="XY" which replaces characters 3-4 of A$ with "XY".
5908
OR AFH F6 AF
OR A with AFH. This sets the NZ flag (A will never be zero after this OR) and sets specific bits. This may be a flag indicator for the subsequent processing to distinguish MID$ assignment from other string operations. The value AFH (10101111 binary) sets multiple bits.
590A
PUSH AF F5
Save AF on the stack. The flags and type indicator are preserved for later use in determining how to process the string assignment.
590B
Call routine at 5EA2H to parse the MID$ parameters. This routine extracts the target string variable, start position, and optional length from the statement. It validates that the parameters are within legal ranges.
590E
PUSH HL E5
Save HL on the stack. HL contains the BASIC line pointer at the position after the MID$ parameters, pointing to the "=" or the replacement string.
590F
PUSH DE D5
Save DE on the stack. DE contains information about the target string (either its address or descriptor location).
5910
EX DE,HL EB
Exchange DE and HL. Now HL points to the target string information and DE has the line pointer.
5911
INC HL 23
Increment HL to skip past the first byte of the string descriptor (typically the length byte).
5912
LD E,(HL) 5E
Load E with the low byte of the string address from the string descriptor. The descriptor contains: byte 0 = length, bytes 1-2 = address of string data.
5913
INC HL 23
Increment HL to point to the high byte of the string address.
5914
LD D,(HL) 56
Load D with the high byte of the string address. Now DE contains the complete 16-bit address where the target string's actual characters are stored in memory.
5915
LD HL,(40F9H) 2A F9 40
Load HL with the contents of memory location 40F9H. This is the string space boundary or start of string area in BASIC's memory map. Used to validate that the target string is in a legitimate location.
5918
RST 18H DF
Execute RST 18H - this is a compare HL with DE operation. It compares the string address (DE) with the string space boundary (HL). Sets flags based on whether DE >= HL.
5919
If carry (DE < HL, meaning the string is below the string space), jump to 5924H. This could indicate the string is in a protected area or the comparison was for boundary checking.
591B
LD HL,(40A4H) 2A A4 40
Load HL with the contents of 40A4H. This is the start of BASIC program area (also called TXTTAB). Used for another boundary check to ensure the string is in valid memory.
591E
RST 18H DF
Execute RST 18H again to compare HL (program start) with DE (string address). This checks if the string falls within the program area.
591F
POP HL E1
Pop HL from the stack, restoring the value saved at 590F (the original DE which had target string info).
5920
PUSH HL E5
Push HL back onto the stack. This effectively just peeks at the stack value.
5921
If carry is set (string is in program area), call routine at 5CEBH. This copies the string to a safe location because modifying a string that's embedded in the program code could corrupt the program. Only literal strings in the code need this treatment.
5924
POP HL E1
Pop HL from the stack, restoring the target string information pointer.
5925
EX (SP),HL E3
Exchange HL with the top of stack. Now HL has the BASIC line pointer (saved at 590EH) and the stack top has the string info.
5926
RST 08H CF
Execute RST 08H - compare and advance. This checks for a specific token in the BASIC line. For MID$ assignment, it should find the "=" token.
5927
PUSH DE D5
Save DE on the stack. DE may contain the destination address within the target string where replacement will begin.
5928
Call ROM routine at 2337H to evaluate the replacement string expression. This parses and evaluates whatever string expression appears after the "=" in the MID$ assignment. The result is the string that will replace characters in the target.
592B
POP BC C1
Pop BC from the stack. BC now contains the destination address within the target string (saved at 5927H).
592C
EX (SP),HL E3
Exchange HL with the top of stack. Swap the BASIC line pointer with the string info pointer on the stack.
592D
PUSH HL E5
Save HL (the string info pointer) on the stack for later restoration.
592E
PUSH BC C5
Save BC (the destination address) on the stack.
592F
Call routine at 5CC0H to get the string descriptor for the replacement string. This retrieves the length and address of the replacement string that was just evaluated.
5932
LD C,A 4F
Copy A (the replacement string length) to C. A contains the length from the string descriptor returned by 5CC0H.
5933
POP HL E1
Pop HL from the stack, restoring the destination address (saved at 592EH as BC, now in HL).
5934
PUSH DE D5
Save DE (the replacement string address from the descriptor) on the stack.
5935
LD B,(HL) 46
Load B with the byte at (HL). This is the number of characters to replace or the length value from the MID$ parameters.
5936
INC HL 23
Increment HL to point to the low byte of the target address within the string info structure.
5937
LD E,(HL) 5E
Load E with the low byte of the destination address in the target string.
5938
INC HL 23
Increment HL to point to the high byte.
5939
LD D,(HL) 56
Load D with the high byte of the destination address. Now DE points to where in the target string the replacement will begin.
593A
EX DE,HL EB
Exchange DE and HL. Now HL points to the destination in the target string, and DE is free.
593B
POP DE D1
Pop DE from the stack, restoring the replacement string address (saved at 5934H). Now DE points to the source characters.
593C
LD A,B 78
Copy B to A. B contains the maximum replacement length (from MID$ parameters or target string remaining length).
593D
SUB C 91
Subtract C from A. C is the replacement string length. Result: A = max_length - replacement_length. This calculates how many positions won't be filled or if replacement is too long.
593E
If carry (replacement longer than space available), jump to 5944H. This handles the case where the replacement string is longer than the specified length or remaining target space.
5940
LD B,C 41
Copy C to B. If we get here, the replacement fits. B now equals the actual number of characters to copy (the replacement string length).
5941
LD C,A 4F
Copy A (the remaining unfilled positions) to C. C = positions that won't be changed (difference between available space and replacement length).
5942
Jump to 5946H to perform the replacement, skipping the overflow handling.
5944
LD C,00H 0E 00
Load C with 00H. When replacement is longer than available space, there are no remaining positions - we'll copy only as many characters as fit.
5946
POP AF F1
Pop AF from the stack, restoring the flags and type indicator saved at 590AH.
5947
If Z flag is set, call routine at 5CE3H. This pads with spaces if needed. The Z flag condition indicates a specific mode where padding is required after the replacement.
594A
Call routine at 5CDDH to copy the replacement characters. This transfers B bytes from address DE (replacement string) to address HL (destination in target string).
594D
Call routine at 5CE3H to pad remaining space with spaces if the replacement string was shorter than the available space. This ensures the target string maintains its original length.
5950
POP HL E1
Pop HL from the stack, restoring the BASIC line pointer.
5951
RET C9
Return to the BASIC interpreter. The MID$ assignment is complete - the target string now contains the replacement characters at the specified position.
5952H - Keyword Token Table (Partial)
This area contains a keyword token table used by the BASIC tokenizer and detokenizer. Each entry consists of a length byte followed by the keyword text and a token value. The table maps keyword strings to their internal token numbers used in the tokenized BASIC program. This is a portion of the larger keyword table for DISK BASIC extensions.
Data area: Keyword token entries. Format for each entry: [length] [keyword chars] [token byte]. The disassembler shows these as instructions but they are actually data.
5952
04 50 4F 50 53 data
"POPS" keyword entry: Length=04H (4 chars), text="POPS", followed by token.
5957
16 53 data
Token value 53H for POPS, followed by next entry length 16H.
5959
04 50 4F 50 52 data
"POPR" keyword entry: Length=04H (4 chars), text="POPR".
595E
24 53 data
Token value and next entry - 24H 53H pattern.
5960
04 50 4F 50 4E data
"POPN" keyword entry: Length=04H (4 chars), text="POPN".
5965
34 53 data
Token value 34H, then 53H.
5967
05 45 52 41 53 45 data
"ERASE" keyword entry: Length=05H (5 chars), text="ERASE".
596D
AA 57 data
Token AAH for ERASE, then 57H.
596F
04 4B 45 45 50 data
"KEEP" keyword entry: Length=04H (4 chars), text="KEEP".
5974
AE 57 data
Token AEH for KEEP, then 57H.
5976
04 53 41 53 5A data
"SASZ" or similar keyword: Length=04H, chars="SASZ".
597B
5B 5C 04 data
Token bytes and length for next entry.
597E
53 57 41 50 data
"SWAP" keyword text.
5982
8A 59 data
Token 8AH for SWAP, address/pointer 59H.
5984
02 53 53 data
"SS" keyword: Length=02H, text="SS".
5987
B6 5B 00 data
Token B6H, address 5BH, table terminator 00H.
598AH - SWAP Statement Handler
This routine implements the SWAP statement which exchanges the values of two variables. The statement syntax is SWAP var1, var2. Both variables must be of the same type (both strings, both integers, etc.). The routine parses both variable references, validates type compatibility, and then exchanges their contents byte by byte.
SWAP statement entry point. Exchanges values between two variables of the same type.
598A
RST 08H CF
Execute RST 08H - syntax check and advance. This checks that the current character matches an expected token. For SWAP, it should verify proper statement syntax.
598B
2C byte
The expected token is 2CH which is the ASCII code for comma ,. RST 08H checks that a comma follows the first variable in the SWAP statement.
598C
Call ROM routine at 260DH to get the first variable. This routine parses a variable reference and returns with DE pointing to the variable's storage location in memory. The variable type is stored in 40AFH.
598F
PUSH DE D5
Save DE on the stack. DE contains the address of the first variable's data. This is preserved while we parse the second variable.
5990
LD A,(40AFH) 3A AF 40
Load A with the contents of 40AFH. This is the variable type flag that was set by the routine at 260DH. Values: 02H=integer, 03H=string, 04H=single, 08H=double.
5993
PUSH AF F5
Save AF on the stack. A contains the first variable's type. This will be compared with the second variable's type to ensure they match.
5994
RST 08H CF
Execute RST 08H again for another syntax check.
5995
2C byte
Check for comma , separator (2CH) between the two variables in the SWAP statement.
5996
Call ROM routine at 260DH to get the second variable. Returns with DE pointing to the second variable's storage location.
5999
POP BC C1
Pop BC from the stack. B now contains the first variable's type (was saved as A in AF at 5993H).
599A
LD A,(40AFH) 3A AF 40
Load A with the second variable's type from 40AFH. The call to 260DH at 5996H updated this location with the type of the second variable.
599D
CP B B8
Compare A (second variable type) with B (first variable type). This checks if both variables have the same type. Types must match for SWAP to work correctly.
599E
If not zero (types don't match), jump to Syntax Error at 1E4AH. SWAP requires both variables to be the same type - you cannot swap an integer with a string, for example.
59A1
EX (SP),HL E3
Exchange HL with the top of stack. Before: HL has BASIC line pointer, stack top has first variable address. After: HL has first variable address, stack has line pointer.
[LOOP START] - The following loop exchanges B bytes between the two variable locations.
59A2
LD C,(HL) 4E
Load C with the byte at (HL). This is a byte from the first variable. C temporarily holds this value during the swap.
59A3
LD A,(DE) 1A
Load A with the byte at (DE). This is the corresponding byte from the second variable.
59A4
LD (HL),A 77
Store A into (HL). The second variable's byte is now written to the first variable's location.
59A5
LD A,C 79
Copy C back to A. C contains the first variable's original byte that was saved at 59A2H.
59A6
LD (DE),A 12
Store A into (DE). The first variable's byte is now written to the second variable's location. The swap for this byte is complete.
59A7
INC HL 23
Increment HL to point to the next byte of the first variable.
59A8
INC DE 13
Increment DE to point to the next byte of the second variable.
59A9
DJNZ 59A2H 10 F7
Decrement B and Jump if Not Zero back to 59A2H. B contains the variable size in bytes. The loop continues until all B bytes have been exchanged between the two variables.
[LOOP END] - All bytes have been swapped. The two variables now contain each other's original values.
59AB
POP HL E1
Pop HL from the stack, restoring the BASIC line pointer.
59AC
RET C9
Return to the BASIC interpreter. The SWAP operation is complete.
59ADH - COMPRESS (CMD"C") Command Handler
This routine implements the CMD"C" command which compresses a BASIC program by removing unnecessary spaces and optionally REM statements. The compression reduces program size and can improve execution speed slightly. Options include: CMD"C" (default compression), CMD"C",R (remove REM statements), and CMD"C",S (keep spaces). The routine uses self-modifying code to control the compression behavior.
CMD"C" entry point. Compresses the current BASIC program in memory.
59AD
LD DE,(40A2H) ED 5B A2 40
Load DE with the contents of memory location 40A2H. This is the end of BASIC program pointer (VARTAB - start of variable table). DE now points to the byte after the last program byte.
59B1
LD A,D 7A
Load A with D (high byte of end-of-program address).
59B2
AND E A3
AND A with E (low byte). This operation checks if the address is FFFFH (which would indicate no program in memory).
59B3
INC A 3C
Increment A. If DE was FFFFH, the AND result was FFH, and after INC, A becomes 00H (Z flag set).
59B4
If not zero (a program exists), jump to 1997H which is... wait, this seems inverted. Actually if Z is NOT set, there IS a program. JP NZ to 1997H may be an Illegal Function Call error - indicating compress cannot run in direct mode or some other restriction.
59B7
LD BC,2800H 01 00 28
Load BC with 2800H. B=28H is the JR Z opcode (used for self-modifying code), C=00H is the NOP opcode. These values will be stored at 5A72H to control space handling.
59BA
DEC HL 2B
Decrement HL to back up one position in the BASIC line, preparing to check for options.
59BB
RST 10H D7
Execute RST 10H - get next character. This advances HL and loads the next non-space character into A, setting flags based on its value.
59BC
If zero (end of statement, no options specified), jump to 59D3H to use default compression settings (remove spaces, keep REMs).
59BE
LD BC,FE13H 01 13 FE
Load BC with FE13H. B=13H, C=FEH. These are alternative self-modifying code values, though this seems unusual. May be re-loaded below.
59C1
RST 08H CF
Execute RST 08H - syntax check for expected character.
59C2
2C byte
Expected character is comma , (2CH) before the option letter.
59C3
CP 52H FE 52
Compare A with 52H which is ASCII R. Check if user specified the "R" option to remove REM statements.
59C5
If not 'R', jump to 59CBH to check for other options.
59C7
LD C,00H 0E 00
Load C with 00H (NOP opcode). When C=00H (NOP), the REM removal code at 5A95H will execute instead of returning, causing REMs to be removed.
59C9
Jump to 59D0H to continue processing with REM removal enabled.
59CB
LD B,28H 06 28
Load B with 28H (JR Z opcode). This is the default value that causes spaces to be skipped during compression.
59CD
RST 08H CF
Execute RST 08H - syntax check.
59CE
53 byte
Expected character is 53H which is ASCII S. Check for "S" option to keep spaces.
59CF
DEC HL 2B
Decrement HL to back up. If we get here with 'S' option, we prepare to change space handling.
59D0
RST 10H D7
Execute RST 10H - get next character to verify end of statement or continue parsing.
59D1
If not end of statement (more options), jump back to 59C1H to continue parsing options.
59D3
LD A,B 78
Copy B to A. B contains either 28H (skip spaces) or 00H (NOP, keep spaces) depending on options.
59D4
LD (5A72H),A 32 72 5A
Store A at address 5A72H. This is self-modifying code - the byte at 5A72H is the first byte of an instruction. When A=28H, it creates "JR Z,..." to skip spaces. When A=00H, it creates "NOP" to keep spaces.
59D7
LD A,C 79
Copy C to A. C contains either C9H (RET, keep REMs) or 00H (NOP, remove REMs).
59D8
LD (5A95H),A 32 95 5A
Store A at address 5A95H. This is another self-modifying code location. When A=C9H (RET), the REM handler returns immediately (keeping REMs). When A=00H (NOP), execution continues to remove REMs.
59DB
LD HL,4369H 21 69 43
Load HL with address 4369H. This is a system flag byte that controls various BASIC behaviors.
59DE
SET 6,(HL) CB F6
Set bit 6 of the byte at (HL). This flag at 4369H bit 6 indicates that a compression operation is in progress, which may affect how line numbers are displayed or how the program is processed.
59E0
XOR A AF
XOR A with itself to clear A (A=00H). Also clears the carry flag.
59E1
LD (4317H),A 32 17 43
Store 00H at address 4317H. This clears a work variable used during the compression process, possibly a flag or counter.
59E4
LD HL,(40A4H) 2A A4 40
Load HL with the contents of 40A4H. This is TXTTAB, the start of BASIC program text. HL now points to the beginning of the program to compress.
59E7
LD D,H 54
Copy H to D. This begins setting DE equal to HL.
59E8
LD E,L 5D
Copy L to E. Now DE = HL = start of program. DE will be the write pointer (where compressed output goes) and HL will advance as the read pointer (source).
59E9
Jump to 5A31H to begin the main compression loop.
59EBH - COMPRESS Main Loop
This is the main processing loop for the COMPRESS command. It iterates through each line of the BASIC program, copying bytes from the source position (HL) to the destination position (DE). The loop handles the compression by selectively skipping spaces and REM statements based on the self-modifying code set up earlier. It uses a line buffer at 4D00H for processing each line.
[MAIN LOOP] - Process each line of the BASIC program. HL=read pointer, DE=write pointer, BC=line length/link.
59EB
EX DE,HL EB
Exchange DE and HL. This swaps the read and write pointers, allowing operations on the destination address.
59EC
OR A B7
OR A with itself to clear the carry flag and set Z/S flags based on A. Prepares for the subtraction comparison.
59ED
SBC HL,BC ED 42
Subtract with carry BC from HL. This calculates the difference between the current write position and the line data. Used to determine how much the program has been compressed.
59EF
ADD HL,BC 09
Add BC back to HL. This restores HL to its original value after the comparison. The flags from SBC are preserved.
59F0
EX DE,HL EB
Exchange DE and HL back to their original roles (HL=read, DE=write).
59F1
INC DE 13
Increment the write pointer (DE) to the next position.
59F2
INC HL 23
Increment the read pointer (HL) to the next position.
59F3
If not zero (line still has content to process), jump to 59FCH to continue processing.
59F5
DEC DE 1B
Decrement DE five times (59F5H-59F8H) to back up the write pointer by 5 bytes. This adjustment accounts for the line header that was already written.
59F6
DEC DE 1B
Second decrement of write pointer.
59F7
DEC DE 1B
Third decrement of write pointer.
59F8
DEC DE 1B
Fourth decrement of write pointer.
59F9
DEC DE 1B
Fifth decrement of write pointer. DE is now positioned correctly for the next line.
59FA
Jump to 5A31H to start processing the next line.
59FC
PUSH HL E5
Save the read pointer on the stack.
59FD
LD H,B 60
Copy B to H. BC contains line information, this starts building a pointer.
59FE
LD L,C 69
Copy C to L. Now HL contains the value from BC (line link or address).
59FF
PUSH HL E5
Save this line link value on the stack.
5A00
Call ROM routine at 2B7EH for string handling. This may convert or process the line data for compression.
5A03
XOR A AF
Clear A (A=00H). Used as a null terminator or flag.
5A04
LD (BC),A 02
Store 00H at the address in BC. This writes a null terminator to mark the end of processed data.
5A05
LD HL,(40A7H) 2A A7 40
Load HL with the contents of 40A7H. This is a BASIC work pointer, possibly pointing to tokenized line data.
5A08
Call ROM routine at 1BC0H for BASIC line processing. This routine tokenizes or processes the current line of BASIC code.
5A0B
POP BC C1
Pop BC from the stack, restoring the line link value.
5A0C
LD D,B 50
Copy B to D. Start building DE from BC.
5A0D
LD E,C 59
Copy C to E. Now DE contains the line link value.
5A0E
INC HL 23
Increment HL to point to the next byte in the line.
5A0F
LD A,(DE) 1A
Load A with the byte at (DE). Read from the line link address.
5A10
CP (HL) BE
Compare A with the byte at (HL). Check if the bytes match.
5A11
INC DE 13
Increment DE to the next byte.
5A12
If zero (bytes match), jump to 5A2DH to continue comparison.
5A14
LD HL,4D00H 21 00 4D
Load HL with address 4D00H. This is the line input buffer used during compression to hold the processed line.
[INNER LOOP] - Copy bytes from line buffer to destination.
5A17
LD A,(HL) 7E
Load A with the byte at (HL). Read a byte from the line buffer.
5A18
OR A B7
OR A with itself to set flags. Check if A is zero (end of buffer).
5A19
LD (BC),A 02
Store A at (BC). Write the byte to the destination.
5A1A
INC HL 23
Increment the source pointer (HL).
5A1B
INC BC 03
Increment the destination pointer (BC).
5A1C
If not zero (more bytes to copy), jump back to 5A17H to continue copying.
5A1E
PUSH BC C5
Save BC (the current destination position) on the stack.
5A1F
LD DE,0000H 11 00 00
Load DE with 0000H. This initializes the line number display value to zero.
5A22
Call routine at 5D8EH to display the line number. This shows progress to the user by printing the current line number being compressed.
5A25
LD A,08H 3E 08
Load A with 08H (backspace character). Used to position cursor for next line number.
5A27
SUB E 93
Subtract E from A. E contains the number of digits displayed. A = 8 - digits = number of backspaces needed.
5A28
Call routine at 5D57H to output A spaces or backspaces. This moves the cursor back for the next line number display.
5A2B
XOR A AF
Clear A (A=00H).
5A2C
POP DE D1
Pop DE from the stack, restoring the destination pointer.
5A2D
OR A B7
OR A with itself to set flags based on A.
5A2E
If not zero (more to process), jump back to 5A0EH.
5A30
POP HL E1
Pop HL from the stack, restoring the read pointer.
Start processing next line - read line link and line number.
5A31
LD C,(HL) 4E
Load C with the byte at (HL). This is the low byte of the line link (pointer to next line).
5A32
INC HL 23
Increment HL to the next byte.
5A33
LD B,(HL) 46
Load B with the byte at (HL). This is the high byte of the line link. BC now contains the address of the next line.
5A34
LD A,C 79
Copy C (low byte of link) to A.
5A35
LD (DE),A 12
Store A at (DE). Write the low byte of the link to the compressed output.
5A36
INC DE 13
Increment the write pointer.
5A37
LD A,B 78
Copy B (high byte of link) to A.
5A38
LD (DE),A 12
Store A at (DE). Write the high byte of the link.
5A39
INC DE 13
Increment the write pointer.
5A3A
INC HL 23
Increment the read pointer.
5A3B
LD A,B 78
Copy B to A again.
5A3C
OR C B1
OR A with C. Check if BC (line link) is 0000H, which marks end of program.
5A3D
If not zero (not end of program), jump to 5A4BH to continue with line number.
[END OF PROGRAM] - Compression complete, finalize and return.
5A3F
Call ROM routine at 1AF8H to finalize BASIC program. This updates all necessary pointers after the compression.
5A42
Call ROM routine at 1B59H to reset BASIC pointers. This ensures BASIC's internal pointers are consistent with the compressed program.
5A45
Call routine at 5D79H to output a carriage return. This ends the line number display and prepares for the Ready prompt.
5A48
Jump to ROM routine at 1A19H to return to BASIC Ready prompt. Compression is complete.
5A4B
LD C,(HL) 4E
Load C with the byte at (HL). This is the low byte of the line number.
5A4C
INC HL 23
Increment HL to the next byte.
5A4D
LD B,(HL) 46
Load B with the byte at (HL). This is the high byte of the line number.
5A4E
LD A,C 79
Copy C to A.
5A4F
LD (DE),A 12
Store the low byte of line number at (DE).
5A50
INC DE 13
Increment write pointer.
5A51
LD A,B 78
Copy B to A.
5A52
LD (DE),A 12
Store the high byte of line number at (DE).
5A53
LD (5A20H),BC ED 43 20 5A
Store BC (the line number) at address 5A20H. This is a self-modifying code location that stores the current line number for display purposes.
5A57
INC DE 13
Increment write pointer.
5A58
INC HL 23
Increment read pointer.
5A59
PUSH HL E5
Save the read pointer on the stack.
5A5A
LD B,D 42
Copy D to B. Start building BC from DE.
5A5B
LD C,E 4B
Copy E to C. Now BC = DE (write pointer).
5A5C
PUSH DE D5
Save DE on the stack.
5A5D
LD DE,4D00H 11 00 4D
Load DE with 4D00H - the line buffer address.
5A60
Call routine at 5A74H to copy and process line content. This handles the actual compression logic for each byte.
5A63
If not zero (more content), jump back to 5A60H to continue processing.
5A65
POP DE D1
Restore DE (write pointer).
5A66
POP HL E1
Restore HL (read pointer).
5A67
Call routine at 5A6FH to handle space compression.
5A6A
If not zero, continue processing.
5A6C
Jump back to 59EBH to continue main loop.
5A6FH - Space Compression Handler
This routine handles space character compression in the COMPRESS command. It uses self-modifying code at 5A72H to either skip spaces (default) or keep them (with S option). The byte at 5A72H is either 28H (JR Z opcode to skip spaces) or 00H (NOP to keep spaces).
5A6F
LD A,(HL) 7E
Load A with the byte at (HL). Read the next character from the source line.
5A70
CP 20H FE 20
Compare A with 20H (space character). Sets Z flag if the character is a space.
5A72
SELF-MODIFYING CODE: This byte is modified by the setup routine at 59D4H. When set to 28H (JR Z), spaces are skipped. When set to 00H (NOP), the JR Z becomes a NOP and spaces are kept.
5A74
LD A,(HL) 7E
Load A with the byte at (HL) again. This is the entry point for the copy routine.
5A75
OR A B7
OR A with itself to set flags. Check if character is null (end of line).
5A76
LD (DE),A 12
Store A at (DE). Copy the character to the destination buffer.
5A77
RET Z C8
Return if zero (end of line). All characters have been copied.
5A78
CP 22H FE 22
Compare A with 22H (double-quote character). Check if we're entering a string literal.
5A7A
If not a quote, jump to 5A86H to continue normal processing.
[STRING LITERAL HANDLER] - Copy entire quoted string without compression.
5A7C
INC HL 23
Increment source pointer past the opening quote.
5A7D
INC DE 13
Increment destination pointer.
5A7E
LD A,(HL) 7E
Load the next character from the string.
5A7F
OR A B7
Check if end of line (null terminator).
5A80
LD (DE),A 12
Copy the character to destination.
5A81
RET Z C8
Return if end of line (unterminated string).
5A82
CP 22H FE 22
Check if this is the closing quote.
5A84
If not closing quote, loop back to copy next character.
5A86
CP 3AH FE 3A
Compare A with 3AH (colon character). Check for statement separator.
5A88
If not colon, jump to 5A8DH.
5A8A
PUSH HL E5
Save HL temporarily.
5A8B
RST 10H D7
Get next character using RST 10H.
5A8D
CP 93H FE 93
Compare A with 93H - this is the token for REM statement.
5A8F
If REM token found, jump to 5A95H (the REM handler).
5A91
INC DE 13
Increment destination pointer.
5A92
INC HL 23
Increment source pointer.
5A93
OR D B2
OR A with D. This sets NZ flag (D is never zero) to continue loop.
5A94
RET C9
Return with NZ flag set to continue processing.
[REM HANDLER] - Self-modifying code controls REM removal.
5A95
NOP 00
SELF-MODIFYING CODE: This byte is modified by setup at 59D8H. When 00H (NOP), execution continues to remove REMs. When C9H (RET), the routine returns immediately, keeping the REM.
5A96
INC HL 23
Increment source pointer past REM token.
5A97
LD A,(HL) 7E
Load the next character (REM content).
5A98
OR A B7
Check if end of line.
5A99
LD (DE),A 12
Copy character (or null) to destination.
5A9A
If not end of line, loop to skip more REM content.
5A9C
RET C9
Return when REM handling is complete.
5A9DH - DATE$ Function (CMD"J")
This routine handles the DATE$ function through the CMD"J" command. It can both read and set the system date. When reading, it returns the date as a string in MM/DD/YY format. When setting, it parses the date string and converts it to the internal day-of-year format. The routine includes leap year calculations and month-day validation.
CMD"J" entry point for DATE$ handling. Determines if reading or setting the date.
5A9D
RST 08H CF
Execute RST 08H - syntax check.
5A9E
2C byte
Check for comma , (2CH) separator.
5A9F
Call routine at 61B7H to get the date string and parse it. Returns with parsed date components ready for processing.
5AA2
If NZ (parsing error or special case), jump to error handler at 5B0EH.
5AA4
LD A,(HL) 7E
Load A with the byte at (HL). Check the next character in the date string.
5AA5
CP 2DH FE 2D
Compare A with 2DH (minus sign -). This might indicate a date range or special format.
5AA7
LD A,B 78
Load A with B. B contains a parsed date component.
5AA8
If minus sign found, jump to 5B10H for alternate date format handling.
5AAA
CP 08H FE 08
Compare A with 08H. Check if string length is at least 8 characters (MM/DD/YY format).
5AAC
If carry (length < 8), jump to error handler - date string too short.
5AAE
LD BC,010CH 01 0C 01
Load BC with 010CH. B=01H (minimum value), C=0CH (12 decimal, maximum month). Used for month validation.
5AB1
Call routine at 5B6EH to parse and validate month number. Returns month in A.
5AB4
PUSH AF F5
Save the month value on the stack.
5AB5
Call routine at 5B66H to check for date separator (slash or dash).
5AB8
LD BC,011FH 01 1F 01
Load BC with 011FH. B=01H (minimum day), C=1FH (31 decimal, maximum day). Used for day validation.
5ABB
Call routine at 5B6EH to parse and validate day number.
5ABE
POP BC C1
Pop BC from stack. B now contains the month value (was saved at 5AB4H).
5ABF
DEC A 3D
Decrement A (the day value) to convert from 1-based to 0-based for calculations.
5AC0
LD C,A 4F
Copy A (adjusted day) to C. Now B=month, C=day-1.
5AC1
PUSH BC C5
Save month and day on the stack.
5AC2
Call routine at 5B66H to check for second date separator.
5AC5
Call routine at 5B80H to parse year and handle leap year. This parses the two-digit year and calculates leap year status.
5AC8
LD HL,5BA1H 21 A1 5B
Load HL with address 5BA1H. This is the days-per-month table.
5ACB
LD DE,0000H 11 00 00
Initialize DE to 0000H. This will accumulate the day-of-year.
5ACE
POP BC C1
Pop BC from stack. B=month, C=day-1.
[LOOP] - Calculate day-of-year by summing days in previous months.
5ACF
LD A,(HL) 7E
Load A with days in current month from table.
5AD0
ADD A,E 83
Add to E (low byte of day-of-year accumulator).
5AD1
LD E,A 5F
Store result back in E.
5AD2
INC HL 23
Move to next month in table.
5AD3
If no carry, skip increment of D.
5AD5
INC D 14
Increment D (high byte) if there was carry.
5AD6
DJNZ 5ACFH 10 F7
Decrement B (month counter) and loop if not zero.
5AD8
LD A,C 79
Load A with C (day-1 value).
5AD9
CP (HL) BE
Compare with days in target month. Validate day is within month.
5ADA
If day >= days in month (invalid), jump to error.
5ADC
EX DE,HL EB
Exchange DE and HL. Now HL has the day-of-year total.
5ADD
INC BC 03
Increment BC to adjust for 1-based day count.
5ADE
ADD HL,BC 09
Add the day of month to get final day-of-year.
5ADF
EX DE,HL EB
Exchange back. DE now has the complete day-of-year.
5AE0
Call routine at 5D32H to convert day-of-year to ASCII string.
5AE3
LD HL,5D53H 21 53 5D
Load HL with 5D53H - the numeric conversion buffer.
5AE6
LD DE,5BAEH 11 AE 5B
Load DE with 5BAEH - the DATE$ result buffer.
5AE9
LD BC,0003H 01 03 00
Load BC with 0003H - copy 3 bytes (the day-of-year string).
5AEC
LDIR ED B0
Block copy 3 bytes from (HL) to (DE).
5AEE
LD A,03H 3E 03
Load A with 03H - the string length (3 characters).
5AF0
POP HL E1
Pop HL from stack (BASIC line pointer).
5AF1
PUSH AF F5
Save A (string length) on stack.
5AF2
RST 08H CF
Syntax check.
5AF3
2C byte
Check for comma separator.
5AF4
Call ROM routine to get target variable for assignment.
5AF7
Call ROM routine at 0AF4H for string assignment preparation.
5AFA
POP AF F1
Restore A (string length).
5AFB
PUSH HL E5
Save BASIC line pointer.
5AFC
PUSH DE D5
Save destination pointer.
5AFD
Call ROM routine at 28BFH to allocate string space.
5B00
POP HL E1
Pop HL (was destination pointer).
5B01
Call ROM routine at 285DH to store string descriptor.
5B04
LD HL,5BAEH 21 AE 5B
Load HL with 5BAEH - the DATE$ buffer.
5B07
LD C,A 4F
Copy length to C.
5B08
LD B,00H 06 00
Set B=00H. BC now has the string length.
5B0A
LDIR ED B0
Block copy the date string to the allocated space.
5B0C
POP HL E1
Restore BASIC line pointer.
5B0D
RET C9
Return to BASIC interpreter.
5B0E
Jump to error handler at 5B6BH (syntax error).
5BA1H - Days Per Month Table
This is a data table containing the number of days in each month. It's used by the DATE$ routine for converting between MM/DD/YY format and day-of-year format. The table has 13 entries: a placeholder at index 0, then months 1-12. Note that February (index 2) at address 5BA3H is modified by the leap year routine to be either 28 or 29 days.
Data table: 13 bytes representing days per month. Month 0 is unused, months 1-12 correspond to Jan-Dec.
5BA1
00 data
Index 0: Placeholder/unused (00H).
5BA2
1F data
January: 1FH (31 decimal) days.
5BA3
1C data
February: 1CH (28 decimal) days. SELF-MODIFYING: Changed to 1DH (29) for leap years by routine at 5B91H.
5BA4
1F data
March: 1FH (31 decimal) days.
5BA5
1E data
April: 1EH (30 decimal) days.
5BA6
1F data
May: 1FH (31 decimal) days.
5BA7
1E data
June: 1EH (30 decimal) days.
5BA8
1F data
July: 1FH (31 decimal) days.
5BA9
1F data
August: 1FH (31 decimal) days.
5BAA
1E data
September: 1EH (30 decimal) days.
5BAB
1F data
October: 1FH (31 decimal) days.
5BAC
1E data
November: 1EH (30 decimal) days.
5BAD
1F data
December: 1FH (31 decimal) days.
5BAEH - DATE$ Result Buffer and Work Area
This is a work area used by the DATE$ function to build and store the date string result. It contains 8 bytes for the formatted date string plus additional temporary storage for day-of-year calculations.
5BAE
00 00 00 00 00 00 data
DATE$ result buffer: 6 bytes for the formatted date string (e.g., "MM/DD/" or day-of-year).
5BB4
00 00 data
Day-of-year temporary: 2 bytes for storing the calculated day-of-year value during conversions.
5B66H - DATE$ Helper Routines
These are helper routines used by the DATE$ function for parsing date components, validating values, and handling leap years. They include the slash/dash separator checker, numeric range validator, and leap year detector.
Helper routine: Check for date separator (slash character).
5B66
LD A,(HL) 7E
Load A with the byte at (HL). Get the next character from the date string.
5B67
CP 2FH FE 2F
Compare A with 2FH (slash character /). Check if it's a date separator.
5B69
INC HL 23
Increment HL to skip past the separator.
5B6A
RET Z C8
Return if separator found (Z set). Otherwise fall through to error.
5B6B
Jump to Syntax Error at 1E4AH. Date format is invalid.
Helper routine: Parse and validate numeric value within range.
5B6E
PUSH BC C5
Save BC (contains min/max range) on the stack.
5B6F
LD B,02H 06 02
Load B with 02H - parse 2 digits for the numeric value.
5B71
Call routine at 5B95H to parse B digits into a numeric value.
5B74
LD A,D 7A
Load A with D (high byte of parsed value).
5B75
OR A B7
OR A with itself. Check if high byte is non-zero (value > 255).
5B76
If non-zero (overflow), jump to error.
5B78
POP BC C1
Restore BC (min/max range).
5B79
LD A,E 7B
Load A with E (parsed value).
5B7A
SUB B 90
Subtract B (minimum value). A = value - min.
5B7B
CP C B9
Compare A with C (maximum - minimum). Check if within range.
5B7C
If no carry (value out of range), jump to error.
5B7E
LD A,E 7B
Reload A with the valid parsed value.
5B7F
RET C9
Return with A = parsed and validated value.
Helper routine: Parse year and determine leap year status.
5B80
LD BC,0064H 01 64 00
Load BC with 0064H. B=00H (min year), C=64H (100 decimal, max year for 2-digit format).
5B83
Call routine at 5B6EH to parse and validate year.
5B86
LD B,1CH 06 1C
Load B with 1CH (28 decimal) - default February days for non-leap year.
5B88
OR A B7
OR A with itself. Check if year is 00 (special case - year 2000 or 1900).
5B89
If year is 00, skip leap year check (handle as special case).
5B8B
AND 03H E6 03
AND A with 03H. This is the leap year test: year AND 3 = 0 means divisible by 4.
5B8D
If not divisible by 4 (not leap year), skip increment.
5B8F
INC B 04
Increment B. B becomes 1DH (29 decimal) for leap year February.
5B90
LD A,B 78
Copy B (February days) to A.
5B91
LD (5BA3H),A 32 A3 5B
Store A at address 5BA3H. This modifies the February entry in the days-per-month table to reflect leap year status.
5B94
RET C9
Return with February days set correctly for the year.
Helper routine: Parse B digits from string into DE.
5B95
PUSH BC C5
Save BC on the stack.
5B96
Call routine at 5CFEH to parse decimal digits from the string into DE.
5B99
LD A,C 79
Load A with C (number of digits parsed).
5B9B
If carry (overflow during parsing), jump to error.
5B9D
CP B B8
Compare A (digits parsed) with B (expected digits).
5B9E
If not equal (wrong number of digits), jump to error.
5BA0
RET C9
Return with parsed value in DE.
5BA1H - DAYS PER MONTH TABLE (DATA)
This 13-byte table stores the number of days in each month, indexed 0-12 where index 0 is unused and 1-12 correspond to January through December. The DATE$ function (CMD"J") uses this table to convert between MM/DD/YY format and day-of-year format. Critical: Address 5BA3H (February) is self-modifying - it gets changed from 1CH (28) to 1DH (29) for leap years by the leap year handler at 5B91H.
[DATA TABLE - Days Per Month. The disassembler shows these as instructions because it cannot distinguish data from code. These are actually raw byte values representing day counts.]
5BA1
00 data
Index 0 - unused placeholder. Month indexing starts at 1 for January.
5BA2
1F data
Index 1 - January: 31 days (1FH = 31 decimal).
5BA3
1C data
Index 2 - February: 28 days (1CH = 28 decimal). SELF-MODIFYING: This byte is changed to 1DH (29) for leap years by code at 5B91H. The leap year check tests (year AND 03H = 0), except year 00 which is not a leap year in this implementation.
5BA4
1F data
Index 3 - March: 31 days (1FH = 31 decimal).
5BA5
1E data
Index 4 - April: 30 days (1EH = 30 decimal).
5BA6
1F data
Index 5 - May: 31 days (1FH = 31 decimal).
5BA7
1E data
Index 6 - June: 30 days (1EH = 30 decimal).
5BA8
1F data
Index 7 - July: 31 days (1FH = 31 decimal).
5BA9
1F data
Index 8 - August: 31 days (1FH = 31 decimal).
5BAA
1E data
Index 9 - September: 30 days (1EH = 30 decimal).
5BAB
1F data
Index 10 - October: 31 days (1FH = 31 decimal).
5BAC
1E data
Index 11 - November: 30 days (1EH = 30 decimal).
5BAD
1F data
Index 12 - December: 31 days (1FH = 31 decimal).
5BAEH - DATE$ WORK BUFFERS (DATA)
These 8 bytes at 5BAEH-5BB5H serve as work buffers for the DATE$ function. The first 6 bytes (5BAEH-5BB3H) hold the formatted date result string in MM/DD/YY format. The last 2 bytes (5BB4H-5BB5H) store the day-of-year value as a 16-bit integer during calculations. These buffers are populated by the DATE$ helpers and read by the main DATE$ function when constructing the return string.
[DATA BUFFER - Reserved space initialized to zeros at load time. Used at runtime for DATE$ string construction and day-of-year intermediate storage.]
5BAE
00 00 00 00 00 00 data
DATE$ Result Buffer (6 bytes). Holds the formatted date string during DATE$ function execution. Format is MM/DD/YY as ASCII characters. The helper routines at 5B10H and 5B66H populate this buffer.
5BB4
00 00 data
Day-of-Year Temporary (2 bytes). A 16-bit integer (low byte first, Z80 little-endian) storing the day-of-year value (1-366) during date conversion calculations. Used when converting from MM/DD to day-of-year or vice versa.
5BB6H - TRON/LPRINT WIDTH STATEMENT
This routine handles the LPRINT WIDTH statement, which sets the line width and tab spacing for LPRINT output. The statement syntax is LPRINT WIDTH n where n is the line width, or LPRINT WIDTH n,N to also set tab spacing to 24 (18H) instead of the default 32 (20H). The routine parses the width value, stores it at 63EBH (printer line width), and sets the tab/zone width at 63DBH based on whether the "N" option was specified.
[ENTRY POINT for LPRINT WIDTH. Called when the BASIC parser encounters this statement. HL points to the character after "WIDTH" in the BASIC line.]
5BB6
LD DE,0000H 11 00 00
Initialize DE to zero. This is the default width value if no number follows. DE will hold the parsed width value.
5BB9
DEC HL 2B
Back up HL by one position. This compensates for the BASIC line pointer being one past the current token, so we can re-examine the current character.
5BBA
RST 10H D7
Call the CHRGET routine at 0010H. This advances HL to the next non-space character and loads it into A. Sets Z flag if end of statement (colon or CR).
5BBB
If Z flag is set (end of statement), jump to 5BCBH to store the default width (0) and exit. This handles LPRINT WIDTH with no argument.
5BBD
RST 08H CF
Call the SYNCHR routine at 0008H. The next byte (2CH) is the required character to match.
5BBE
2C parameter
RST 08H parameter: , (comma, ASCII 2CH). If the current character is not a comma, SYNCHR generates a Syntax Error. Otherwise, HL advances past the comma.
5BBF
CP 4EH FE 4E
Compare A (current character after comma) with 4EH (N). The "N" option sets a different tab width.
5BC1
If character is N, jump to 5BD4H to set tab width to 24 (18H) instead of the default 32.
5BC3
Call the number parsing routine at 5CFCH to convert the ASCII decimal string to a 16-bit integer in DE. C returns the digit count. This parses the width value.
5BC6
LD A,C 79
Copy C (digit count from number parser) into A. A value of 0 means no digits were parsed.
5BC7
OR A B7
Test if A is zero (no digits found). Sets Z flag if A=0.
5BC8
If no digits were parsed (Z set), jump to 1997H which is the Illegal Function Call error handler. A width value is required after the comma.
[Width value parsed successfully. DE contains the width, now store it and set default tab width.]
5BCB
DEC HL 2B
Back up HL to re-examine current character on next CHRGET. This is standard BASIC statement parsing behavior.
5BCC
LD (63EBH),DE ED 53 EB 63
Store DE (the parsed width value, or 0 if none given) into 63EBH - Printer Line Width. This memory location controls how many characters LPRINT outputs before inserting an automatic line break.
5BD0
LD A,20H 3E 20
Load A with 20H (32 decimal). This is the default tab/zone width for LPRINT. Tab stops occur every 32 characters.
5BD2
Jump forward to 5BD6H to store the tab width and exit, skipping the alternate tab width setup.
[Alternate entry - "N" option was specified, use narrower tab width.]
5BD4
LD A,18H 3E 18
Load A with 18H (24 decimal). This is the narrow tab/zone width when the "N" option is specified. Tab stops occur every 24 characters instead of 32.
5BD6
LD (63DBH),A 32 DB 63
Store A (tab width: 32 or 24) into 63DBH - Printer Tab/Zone Width. This controls LPRINT tab stop spacing and print zone widths.
5BD9
RST 10H D7
Call CHRGET to advance past any remaining characters and prepare for the next statement.
5BDA
RET C9
Return to BASIC interpreter. The LPRINT WIDTH statement has been executed.
5BDBH - VARIABLE TYPE PARSER
This critical routine parses variable names and determines their type based on suffix characters. BASIC variables can be: Integer (suffix %), String (suffix $), Single precision (suffix !), or Double precision (suffix #). If no suffix is given, the type defaults based on the first letter of the variable name using the DEFINT/DEFSNG/DEFDBL/DEFSTR settings stored in a 26-byte table at 0041H (one byte per letter A-Z). The routine also counts characters in the variable name and stores key information in self-modifying code locations for later use.
[ENTRY POINT for Variable Type Parser. HL points to the first character of a variable name. On exit: D=type code (02=int, 03=string, 04=single, 08=double), C=name length, B=first character, Z flag set if followed by '('.]
5BDB
DEC HL 2B
Back up HL by one. Standard preparation before calling CHRGET, which increments HL before reading.
5BDC
RST 10H D7
Call CHRGET at 0010H. Advances HL and loads the next non-space character into A. This gets the first character of the variable name.
5BDD
LD B,A 47
Save the first character of the variable name into B. This will be stored later at 5C30H for reference by other routines.
5BDE
Call the alphabetic check routine at 1E3DH. Tests if A contains a letter (A-Z or a-z). Returns C flag set if alphabetic, cleared if not.
5BE1
If C flag is set (character IS alphabetic), jump to Illegal Function Call error at 1997H. Wait - this seems backwards! Actually, the 1E3DH routine returns C=1 if NOT alphabetic. So this jumps to error if the first character is not a letter, which is correct - variable names must start with a letter.
5BE4
XOR A AF
Clear A to zero. This initializes the character counter that will track the variable name length.
5BE5
LD C,A 4F
Copy A (zero) into C. C will be the name length counter, starting at 0.
[LOOP START - Count alphanumeric characters in variable name.]
5BE6
INC C 0C
Increment C (name length counter). Each alphanumeric character increments this count.
5BE7
DEC C 0D
Decrement C. Combined with the INC, this tests if C will overflow (but preserves its value). Actually, this pattern (INC C / DEC C / JR NZ) is checking if C reached FFH and wrapped.
5BE8
If C is not zero (normal case), jump to 5BEBH to continue. If C wrapped from FFH to 00H (255+ character name), fall through.
5BEA
LD C,A 4F
If we reach here, C overflowed. Reset C to A (which holds the previous valid count). This caps name length to prevent overflow issues.
5BEB
RST 10H D7
Call CHRGET to get the next character into A, advancing HL.
5BEC
CHRGET sets C flag if the character is a digit (0-9). If digit found, loop back to 5BE6H to count it as part of the variable name.
5BEE
Call alphabetic check again. Tests if current character is a letter.
5BF1
If NC (character IS alphabetic - remember, C=1 means NOT alpha), loop back to count this letter in the name. Continue until we hit a non-alphanumeric character.
[Name parsing complete. Now check for type suffix character (%, $, !, #).]
5BF3
LD D,02H 16 02
Load D with 02H. This is the integer type code. D will hold the determined variable type.
5BF5
SUB 25H D6 25
Subtract 25H (%) from A. If A was '%', result is 0 and Z flag is set.
5BF7
If Z (character was %), jump to 5C11H. Variable is Integer type (D=02H).
5BF9
INC D 14
Increment D to 03H. This is the string type code.
5BFA
INC A 3C
Increment A. After the SUB 25H, if original character was '$' (24H), A would be FFH. Adding 1 makes it 0.
5BFB
If Z (character was $), jump to 5C11H. Variable is String type (D=03H).
5BFD
INC D 14
Increment D to 04H. This is the single precision type code.
5BFE
CP FDH FE FD
Compare A with FDH. After SUB 25H and INC A on '!' (21H), we get: 21H-25H=FCH, FCH+1=FDH. So this checks for '!'.
5C00
If Z (character was !), jump to 5C11H. Variable is Single precision type (D=04H).
5C02
LD D,08H 16 08
Load D with 08H. This is the double precision type code.
5C04
INC A 3C
Increment A again. If original was '#' (23H): 23H-25H=FEH, FEH+1=FFH, FFH+1=00H.
5C05
If Z (character was #), jump to 5C11H. Variable is Double precision type (D=08H).
[No type suffix found. Determine type from DEFxxx settings based on first letter.]
5C07
LD A,B 78
Load A with B (the first character of the variable name, saved earlier).
5C08
SUB 41H D6 41
Subtract 41H (A) from A. This converts the letter to an index 0-25 (A=0, B=1, ... Z=25).
5C0A
LD E,A 5F
Copy the letter index into E. This will be the offset into the DEFxxx type table.
5C0B
INC E 1C
Increment E by 1. The type table might be at address-1, or this adjusts for 1-based indexing.
5C0C
LD D,41H 16 41
Load D with 41H (65 decimal). Combined with E, DE now points into the DEFxxx type table starting at 0041H. The table has 26 bytes, one per letter.
5C0E
LD A,(DE) 1A
Load A with the byte at address DE. This reads the default type code for variables starting with this letter, as set by DEFINT, DEFSNG, DEFDBL, or DEFSTR statements.
5C0F
LD D,A 57
Copy the type code from the table into D. D now holds the variable type.
5C10
DEC HL 2B
Decrement HL. Since no type suffix was consumed, back up so the next parse starts at the right position.
[Store results in self-modifying code locations for use by other routines.]
5C11
LD A,D 7A
Copy D (type code) into A for storage.
5C12
LD (5C25H),A 32 25 5C
Store A (type code) at 5C25H. This is a self-modifying location in the Type Checking helper at 5C21H. The stored type code can be retrieved by other routines.
5C15
LD A,C 79
Copy C (variable name length) into A for storage.
5C16
LD (5C2AH),A 32 2A 5C
Store A (name length) at 5C2AH. This is a self-modifying location in the Type Checking helper. Other routines can read the name length from here.
5C19
LD A,B 78
Copy B (first character of name) into A for storage.
5C1A
LD (5C30H),A 32 30 5C
Store A (first character) at 5C30H. This is a self-modifying location. Other routines can read the first character of the most recently parsed variable.
5C1D
RST 10H D7
Call CHRGET to get the next character after the variable name (and type suffix if any).
5C1E
CP 28H FE 28
Compare A with 28H ((). This checks if the variable is an array reference with subscripts.
5C20
RET C9
Return to caller. Z flag is set if next character is '(' (array), cleared otherwise. D=type code, C=name length, B=first character.
5C21H - TYPE CHECKING HELPERS
This section contains several helper routines for type checking and variable structure navigation. The first routine (5C21H) contains self-modifying code locations that store the variable type, name length, and first character as set by the Variable Type Parser at 5BDBH. Other routines here help skip over variable entries in memory and count parentheses for array dimension parsing.
[5C21H - Type Check Helper. Contains self-modifying storage locations populated by 5BDBH. Also validates type consistency.]
5C21
LD A,(HL) 7E
Load A with the byte at HL. HL typically points to a variable structure. The first byte contains the variable type in the low nibble.
5C22
AND 0FHAND 00001111 E6 0F
Mask off the high nibble, keeping only the type code (bits 0-3). Types are: 02=int, 03=string, 04=single, 08=double.
5C24
CP 00H FE 00
SELF-MODIFYING: The 00H at address 5C25H is overwritten by 5C12H with the expected type code. This compares the variable's actual type with the expected type.
5C26
RET NZ C0
If types don't match (NZ), return immediately. The NZ flag indicates a type mismatch to the caller.
5C27
INC HL 23
Types matched. Advance HL to the next byte of the variable structure (the name length byte or first name character).
5C28
LD A,(HL) 7E
Load A with the byte at HL (should be name length or first name char).
5C29
CP 00H FE 00
SELF-MODIFYING: The 00H at address 5C2AH is overwritten by 5C16H with the expected name length. Compares actual vs expected.
5C2B
If name lengths don't match, jump to 5C32H to restore HL and return with NZ (not a match).
5C2D
INC HL 23
Name lengths matched. Advance HL to the next byte (first character of variable name).
5C2E
LD A,(HL) 7E
Load A with the byte at HL (first character of stored variable name).
5C2F
CP 00H FE 00
SELF-MODIFYING: The 00H at address 5C30H is overwritten by 5C1AH with the expected first character. Compares actual vs expected.
5C31
DEC HL 2B
Decrement HL to restore position (will be incremented again at 5C32H, net effect: back to start+1).
5C32
DEC HL 2B
Decrement HL to restore original position. Whether match or mismatch, HL should point back to the variable structure start.
5C33
RET C9
Return to caller. Z flag indicates match (all three checks passed), NZ indicates mismatch.
[5C34H - Skip Variable Entry. Advances HL past a variable entry based on its type/length.]
5C34
LD A,(HL) 7E
Load A with the byte at HL (variable structure first byte containing type and flags).
5C35
AND 0FHAND 00001111 E6 0F
Mask to get the type code from the low nibble.
5C37
ADD 03H C6 03
Add 3 to the type code. Variable entries have a 3-byte header (type, length, first char) plus the type-dependent data size. But wait - the type code IS the data size (2, 3, 4, or 8), so adding 3 gives total entry size.
5C39
LD C,A 4F
Copy the entry size into C.
5C3A
LD B,00H 06 00
Set B to 0. BC now contains the entry size as a 16-bit value.
5C3C
ADD HL,BC 09
Add BC to HL, advancing HL past this variable entry to the next one.
5C3D
OR H B4
OR A with H. This sets flags based on the result - if HL is now 0000H or very low, it might indicate end of table. Actually, this just sets some flags for the caller.
5C3E
RET C9
Return to caller. HL now points to the next variable entry (or past the end of the variable table).
[5C3FH - Skip Variable With Link. Handles linked variable structures.]
5C3F
INC HL 23
Advance HL past first byte.
5C40
INC HL 23
Advance HL past second byte.
5C41
INC HL 23
Advance HL past third byte. HL now points to the link address bytes (if this is a linked structure).
5C42
LD C,(HL) 4E
Load C with low byte of the link address stored at HL.
5C43
INC HL 23
Advance HL to the high byte of the link address.
5C44
LD B,(HL) 46
Load B with high byte of the link address. BC now contains the complete link pointer.
5C45
INC HL 23
Advance HL past the link address, positioning for the ADD below.
5C46
Jump to 5C3CH to add BC to HL and return. This follows the link to the next structure.
[5C48H - Parenthesis Counter. Counts nested parentheses to find matching close paren.]
5C48
LD B,00H 06 00
Initialize B to 0. B is the parenthesis nesting counter.
5C4A
INC B 04
Increment B (nesting level) when we encounter an open parenthesis.
5C4B
RST 10H D7
Call CHRGET to get the next character into A.
5C4C
SCF 37
Set carry flag. This prepares for the RET Z - if we hit end of line (Z set), we return with C set indicating incomplete expression.
5C4D
RET Z C8
If Z (end of statement), return with C flag set. This indicates an error - unmatched open parenthesis.
5C4E
CP 28H FE 28
Compare A with 28H ((). Check for another open paren.
5C50
If open paren, jump to 5C4AH to increment nesting counter and continue.
5C52
CP 29H FE 29
Compare A with 29H ()). Check for close paren.
5C54
If not close paren, jump to 5C4BH to get next character. Keep scanning.
5C56
DJNZ 5C4BH 10 F3
Close paren found. Decrement B (nesting counter) and loop if not zero. We need to match each open paren with a close paren.
5C58
RST 10H D7
All parens matched. Get the next character after the final close paren.
5C59
OR A B7
Clear carry flag and set Z based on A. Normal return preparation.
5C5A
RET C9
Return to caller. C flag clear indicates success, HL positioned after the closing paren.
5C5BH - CLEAR EXTENSION
This routine implements the CLEAR statement's memory management functionality. CLEAR deallocates all variables and resets the stack, optionally setting new memory limits. The syntax is CLEAR ,<top-of-memory>. This routine calculates how much memory to reserve for strings, validates that sufficient memory exists, and relocates the stack to the new location. It uses self-modifying code at 5C9EH and 5CB4H to store intermediate values during the complex memory calculations.
[ENTRY POINT for CLEAR Extension. Expects comma already parsed, DE contains the new top-of-memory value from BASIC expression evaluation.]
5C5B
RST 08H CF
Call SYNCHR at 0008H. The next byte is the required character.
5C5C
2C parameter
RST 08H parameter: , (comma, ASCII 2CH). Expects a comma before the memory address. Syntax Error if not found.
5C5D
Call ROM routine at 2B02H to evaluate an expression and get a 16-bit unsigned integer. Result returned in DE. This gets the new top-of-memory address.
5C60
PUSH HL E5
Save HL (BASIC line pointer) onto the stack for later restoration.
5C61
LD HL,(40B1H) 2A B1 40
Load HL with the value at 40B1H - this is STREND, the end of string storage area / start of free memory.
5C64
OR A B7
Clear carry flag in preparation for the subtraction.
5C65
SBC HL,DE ED 52
Subtract DE (new top-of-memory) from HL (STREND). Result = STREND - new_top. This calculates how much memory would be freed/used.
5C67
LD (5C9EH),HL 22 9E 5C
Store HL (the memory difference) at 5C9EH. This is self-modifying code - the value will be used as an immediate operand later at 5C9DH.
5C6A
PUSH HL E5
Save the memory difference onto the stack.
5C6B
Call ROM routine at 28E6H to perform garbage collection on strings. This compacts string storage to make room for the new memory layout.
5C6E
POP DE D1
Restore the memory difference from the stack into DE.
5C6F
LD HL,(40D6H) 2A D6 40
Load HL with the value at 40D6H - this is FRETOP, the top of free string space (or bottom of string area).
5C72
RST 18H DF
Call CPDEHL at 0018H. Compares DE with HL, sets flags: C if DE>HL, Z if equal, NC and NZ if DE<HL.
5C73
EX DE,HL EB
Exchange DE and HL. HL now contains the memory difference, DE contains FRETOP.
5C74
LD E,1AH 1E 1A
Load E with 1AH (26 decimal). This is an error code for "Out of Memory" (error #26).
5C76
If carry set (meaning new layout would exceed available memory), jump to 19A2H which is the error generator. E contains the error code, so this generates "Out of Memory" error.
5C79
LD DE,(40A0H) ED 5B A0 40
Load DE with the value at 40A0H - this is STKTOP, the current top of BASIC stack.
5C7D
OR A B7
Clear carry flag for the next subtraction.
5C7E
SBC HL,DE ED 52
Subtract DE (current STKTOP) from HL (memory difference). This calculates the offset needed for the new stack location.
5C80
ADD HL,SP 39
Add the current stack pointer to HL. This calculates where the new stack pointer should be after relocation.
5C81
LD (5CB4H),HL 22 B4 5C
Store HL (new SP value) at 5CB4H. This is self-modifying code - the value will be loaded into SP later by the instruction at 5CB3H.
5C84
DEC H 25
Decrement H by 1. This subtracts 256 from the new SP value as a safety margin / stack growth allowance.
5C85
LD DE,(40FDH) ED 5B FD 40
Load DE with the value at 40FDH - this is MEMSIZ, the highest usable memory address.
5C89
RST 18H DF
Call CPDEHL to compare DE (MEMSIZ) with HL (new SP - 256). Check if new stack would exceed memory.
5C8A
If carry set (new stack would exceed MEMSIZ), jump to 197AH which generates an "Out of String Space" or similar memory error.
[Memory calculations validated. Now relocate the stack contents to the new location.]
5C8D
LD HL,0000H 21 00 00
Load HL with 0000H. This will be used to read the current SP value.
5C90
ADD HL,SP 39
Add SP to HL. Since HL was 0, HL now equals the current stack pointer value.
5C91
PUSH HL E5
Save current SP value onto the stack (we'll need it for the copy operation).
5C92
EX DE,HL EB
Exchange DE and HL. DE now has current SP, HL has MEMSIZ.
5C93
LD HL,(40A0H) 2A A0 40
Load HL with STKTOP (current stack top boundary).
5C96
OR A B7
Clear carry for subtraction.
5C97
SBC HL,DE ED 52
Subtract DE (current SP) from HL (STKTOP). Result is the number of bytes currently on the stack.
5C99
LD B,H 44
Copy high byte of stack size to B.
5C9A
LD C,L 4D
Copy low byte of stack size to C. BC now contains the number of bytes to copy.
5C9B
INC BC 03
Increment BC by 1 to ensure we copy all bytes (LDIR/LDDR are count-1 based for the last byte).
5C9C
ADD HL,DE 19
Add DE (current SP) back to HL (stack size). HL now points to STKTOP again.
5C9D
LD DE,0000H 11 00 00
SELF-MODIFYING: The 0000H at address 5C9EH was overwritten at 5C67H with the memory offset. This loads DE with the relocation offset.
5CA0
LD (40A0H),DE ED 53 A0 40
Store DE (new memory offset value) at 40A0H (STKTOP). This updates the stack top boundary.
5CA4
RST 18H DF
Call CPDEHL to compare DE with HL. Determines which direction to copy (LDIR vs LDDR).
5CA5
DI F3
Disable interrupts. Critical section - we're about to move the stack. Any interrupt would use the partially-moved stack and crash.
5CA6
If no carry (DE <= HL, moving stack up), jump to 5CACH to use LDIR (forward copy).
5CA8
LDDR ED B8
Copy stack contents downward. Copies BC bytes from HL to DE, decrementing both after each byte. Used when moving stack to lower addresses.
5CAA
Jump to 5CB3H to set the new SP and finish.
5CAC
POP HL E1
Pop the saved current SP value into HL. This is the source for LDIR.
5CAD
LD DE,(5CB4H) ED 5B B4 5C
Load DE with the new SP value stored earlier at 5CB4H. This is the destination for LDIR.
5CB1
LDIR ED B0
Copy stack contents upward. Copies BC bytes from HL to DE, incrementing both after each byte. Used when moving stack to higher addresses.
5CB3
LD SP,0000H 31 00 00
SELF-MODIFYING: The 0000H at address 5CB4H was overwritten at 5C81H with the new SP value. This sets the stack pointer to its new location.
5CB6
EI FB
Enable interrupts. Stack relocation complete, safe to handle interrupts again.
5CB7
POP HL E1
Pop the saved BASIC line pointer from the (now relocated) stack back into HL.
5CB8
RET C9
Return to the BASIC interpreter. CLEAR operation complete.
5CB9H - STRING OPERATIONS
This section contains several string manipulation helper routines. These include routines to parse string expressions, extract string descriptors (pointer and length), copy strings to temporary storage, and pad strings with spaces. These are fundamental building blocks used by BASIC's string handling functions like LEFT$, RIGHT$, MID$, and string assignment.
[5CB9H - Parse String Variable. Gets string descriptor from a variable after comma.]
5CB9
RST 08H CF
Call SYNCHR - expects a specific character next.
5CBA
2C parameter
RST 08H parameter: , (comma). Requires a comma separator before the string variable.
5CBB
Call ROM routine at 2337H to parse a string expression. Returns with HL pointing to the string descriptor.
5CBE
EX (SP),HL E3
Exchange HL with the top of stack. Saves the string descriptor pointer on stack, retrieves return address into HL.
5CBF
PUSH HL E5
Push the return address back onto the stack. Stack now has: [return address] [string descriptor pointer].
5CC0
Call ROM routine at 29D7H to free temporary string if needed. This ensures the string won't be garbage collected during the operation.
[Fall through to 5CC3H to extract the descriptor fields.]
5CC3
LD A,(HL) 7E
Load A with the byte at HL. This is the string length (first byte of string descriptor).
5CC4
INC HL 23
Advance HL to point to the string address low byte.
5CC5
LD E,(HL) 5E
Load E with the low byte of string address.
5CC6
INC HL 23
Advance HL to point to the string address high byte.
5CC7
LD D,(HL) 56
Load D with the high byte of string address. DE now points to the actual string data.
5CC8
DEC HL 2B
Back up HL one byte.
5CC9
DEC HL 2B
Back up HL another byte. HL now points to the start of the descriptor again.
5CCA
RET C9
Return to caller. A=length, DE=string address, HL=descriptor address.
[5CCBH - Parse String With Evaluation. Evaluates expression first, then extracts descriptor.]
5CCB
Call ROM routine at 0AF4H. This is part of expression evaluation - evaluates a string expression.
5CCE
Call ROM routine at 29DEH to get string parameter. Sets up HL to point to the string descriptor.
5CD1
Jump to 5CC3H to extract the length and address from the descriptor.
[5CD3H - Create String Copy. Allocates new string space and returns descriptor.]
5CD3
LD (HL),00H 36 00
Store 00H at HL. This clears a byte, possibly initializing a descriptor or terminating a string.
5CD5
PUSH HL E5
Save HL (pointer to the destination) onto the stack.
5CD6
Call ROM routine at 28BFH to allocate string space. Reserves room for the string and returns pointer in DE.
5CD9
POP HL E1
Restore HL (original destination pointer).
5CDA
Jump to ROM routine at 285DH to store string descriptor. This completes the string creation.
[5CDDH - Conditional Block Copy. Copies B bytes from HL to DE if B is non-zero.]
5CDD
LD A,B 78
Copy B (byte count) into A.
5CDE
OR A B7
Test if A (byte count) is zero. Sets Z flag if nothing to copy.
5CDF
If count is non-zero, jump to ROM routine at 09D6H which performs the block copy (LDIR wrapper).
5CE2
RET C9
If count was zero, nothing to copy - just return.
[5CE3H - Space Padding Loop. Fills C bytes at HL with spaces (20H).]
5CE3
INC C 0C
Increment C. Prepares for the DJNZ-style loop that follows. The loop pre-decrements, so we add 1 first.
5CE4
DEC C 0D
Decrement C (remaining count).
5CE5
RET Z C8
If C reached zero, we're done - return to caller.
5CE6
LD (HL),20H 36 20
Store 20H (space character) at address HL.
5CE8
INC HL 23
Advance HL to the next byte position.
5CE9
Loop back to 5CE4H to continue filling with spaces. [LOOP]
[5CEBH - String Copy With Allocation. Copies string to new temporary space.]
5CEB
PUSH HL E5
Save HL (source pointer) onto the stack.
5CEC
Call ROM routine at 2843H to allocate temporary string space based on the current string length.
5CEF
POP HL E1
Restore HL (source pointer).
5CF0
Jump to ROM routine at 09D3H which performs a block copy with length. Copies the string data to the newly allocated space.
[5CF3H - Skip to String Data. Advances HL past string descriptor header to the name characters.]
5CF3
INC HL 23
Skip past first byte (type/flags).
5CF4
INC HL 23
Skip past second byte (length or other info).
5CF5
INC HL 23
Skip past third byte. HL now points to the string name/data area.
[Fall through to scan for end of string (null terminator)]
5CF6
LD A,(HL) 7E
Load A with the byte at HL (current character of string).
5CF7
OR A B7
Test if A is zero (null terminator). Sets Z flag if end of string.
5CF8
INC HL 23
Advance HL to the next character regardless.
5CF9
If not null (NZ), loop back to check the next character. [LOOP]
5CFB
RET C9
Return to caller. HL now points one byte past the null terminator.
5CFCH - NUMBER PARSING (DECIMAL STRING TO DE)
This routine converts an ASCII decimal number string to a 16-bit binary integer in the DE register pair. It processes digits from the string at HL, multiplying by 10 and adding each digit's value. The routine tracks the number of digits parsed in C and sets the carry flag if overflow occurs (value > 65535). This is a fundamental routine used by many BASIC statements that need to parse numeric arguments.
[ENTRY POINT for Decimal String Parser. HL points to the ASCII string. On exit: DE=value, C=digit count, Carry=overflow.]
5CFC
LD B,FFH 06 FF
Initialize B to FFH (255). B is a maximum digit counter - parsing stops after this many digits to prevent infinite loops on malformed input.
5CFE
LD DE,0000H 11 00 00
Initialize DE to 0. This is the accumulator that will hold the parsed number value.
5D01
LD C,E 4B
Initialize C to 0 (E is 0 from the LD DE above). C is the digit count - how many digits we've actually parsed.
[LOOP START - Parse each digit character.]
5D02
LD A,B 78
Copy B (remaining max digits) into A.
5D03
OR A B7
Test if B is zero (max digit limit reached). Sets Z flag if limit hit.
5D04
RET Z C8
If max limit reached (Z set), return. This prevents parsing an absurdly long string of digits.
5D05
DEC B 05
Decrement B (remaining max digits counter).
5D06
LD A,(HL) 7E
Load A with the byte at HL (current character from the string).
5D07
SUB 30H D6 30
Subtract 30H (0) from A. This converts ASCII digit to its numeric value (0-9). If it wasn't a digit, result will be <0 or >=10.
5D09
CP 0AH FE 0A
Compare A with 0AH (10). If A >= 10, the character wasn't a valid digit.
5D0B
RET NC D0
If no carry (A >= 10, not a digit), return. We've reached the end of the number. DE contains the value, C contains the digit count.
5D0C
INC HL 23
Valid digit found. Advance HL to the next character for the next iteration.
5D0D
INC BC 03
Increment BC. Since B is being decremented and C is the digit count, this effectively increments C (the digit counter). Actually, this increments the full 16-bit BC which is unusual... but with B being 254+ initially, this is incrementing C.
[Multiply DE by 10 and add new digit. Algorithm: DE = DE*4 + DE = DE*5, then DE = DE*2 = DE*10, then add digit.]
5D0E
PUSH HL E5
Save HL (string pointer) onto the stack.
5D0F
PUSH BC C5
Save BC (counters) onto the stack.
5D10
LD C,A 4F
Copy A (current digit value, 0-9) into C. We'll add this to the result after multiplying.
5D11
LD B,00H 06 00
Clear B. BC now contains just the digit value as a 16-bit number.
5D13
LD H,D 62
Copy D into H. Start copying DE to HL.
5D14
LD L,E 6B
Copy E into L. HL now equals DE (the current accumulated value).
5D15
XOR A AF
Clear A to 0. A will be used to track overflow during the multiply.
5D16
ADD HL,HL 29
HL = HL * 2. First doubling.
5D17
ADC A,A 8F
A = A + A + Carry. Captures any overflow from the ADD HL,HL into A.
5D18
ADD HL,HL 29
HL = HL * 2. Second doubling. HL is now 4 * original DE.
5D19
ADC A,A 8F
Capture overflow again.
5D1A
ADD HL,DE 19
HL = HL + DE. HL is now (4 * DE) + DE = 5 * original DE.
5D1B
ADC A,A 8F
Capture overflow from the add.
5D1C
ADD HL,HL 29
HL = HL * 2. HL is now 10 * original DE. Multiply by 10 complete.
5D1D
ADC A,A 8F
Capture overflow from final doubling.
5D1E
ADD HL,BC 09
HL = HL + BC. Add the new digit value. HL now contains (old_value * 10) + new_digit.
5D1F
POP BC C1
Restore BC (digit counters).
5D20
ADC A,A 8F
Final overflow capture after adding the digit.
5D21
POP DE D1
Restore DE - wait, this was HL (string pointer) that we pushed! This swaps them.
5D22
EX DE,HL EB
Exchange DE and HL. Now DE has the new accumulated value, HL has the string pointer.
5D23
If Z (A is 0, no overflow occurred), loop back to 5D02H to parse the next digit. [LOOP]
[Overflow occurred - number too large for 16 bits.]
5D25
SCF 37
Set carry flag to indicate overflow error.
5D26
RET C9
Return with Carry set indicating the number overflowed 16 bits.
5D27H - NUMBER TO STRING CONVERSION
This section contains routines to convert binary numbers to ASCII string representation. The main routine at 5D32H converts a 16-bit value in DE to a decimal ASCII string stored at 5D51H, stripping leading zeros. A wrapper at 5D27H copies the result to a buffer pointed to by BC. These routines are used for PRINT, STR$, and other numeric output operations.
[5D27H - Convert Number and Copy. Converts DE to string and copies D digits to address BC.]
5D27
Call 5D32H to convert DE to a decimal ASCII string. Result is in buffer at 5D51H, E returns the number of significant digits.
[Copy the converted string to the caller's buffer at BC.]
5D2A
LD A,(HL) 7E
Load A with the byte at HL (current digit from conversion buffer).
5D2B
LD (BC),A 02
Store A at address BC (copy digit to destination buffer).
5D2C
INC BC 03
Advance BC to the next destination position.
5D2D
INC HL 23
Advance HL to the next source digit.
5D2E
DEC D 15
Decrement D (remaining digits to copy).
5D2F
If more digits remain (NZ), loop back to copy the next one. [LOOP]
[5D32H - Main Number to String Conversion. Converts 16-bit DE to decimal ASCII at 5D51H.]
5D32
PUSH BC C5
Save BC onto the stack (caller may be using it).
5D33
LD BC,0000H 01 00 00
Initialize BC to 0. This might be a flag or counter for the ROM routine.
5D36
LD (4121H),DE ED 53 21 41
Store DE (number to convert) at 4121H. This is a BASIC work area used by the ROM conversion routine. The routine at 132FH expects the number here.
5D3A
LD HL,5D51H 21 51 5D
Load HL with 5D51H. This is the output buffer address where the ASCII digits will be stored.
5D3D
PUSH HL E5
Save the buffer address for later use.
5D3E
Call ROM routine at 132FH to convert integer to ASCII. This converts the value at 4121H to a decimal string at HL. The routine handles leading zeros and sign.
5D41
POP HL E1
Restore HL (buffer address 5D51H).
5D42
POP BC C1
Restore BC (caller's value).
5D43
LD D,04H 16 04
Load D with 4. This is the maximum leading zeros to strip. A 16-bit number has at most 5 digits (65535), so we can have 4 leading zeros.
[LOOP - Strip leading zeros from the converted string.]
5D45
LD A,(HL) 7E
Load A with the byte at HL (current digit character).
5D46
CP 30H FE 30
Compare A with 30H (0). Check if this is a leading zero.
5D48
If not zero (NZ), we've found a significant digit - jump to 5D4EH to finish.
5D4A
INC HL 23
Skip this leading zero - advance HL.
5D4B
DEC D 15
Decrement D (remaining zeros we can skip).
5D4C
If D not zero (haven't stripped all possible leading zeros), loop back to check the next digit. [LOOP]
[Calculate the number of significant digits.]
5D4E
INC D 14
Increment D. After the loop, D tells us how many leading zeros were stripped. INC D adjusts this to give the count of significant digits.
5D4F
LD E,D 5A
Copy D to E. E now contains the significant digit count for the caller.
5D50
RET C9
Return to caller. HL points to the first significant digit in buffer 5D51H, E contains the digit count.
5D51H - NUMERIC CONVERSION BUFFER (DATA)
This 6-byte buffer at 5D51H-5D56H is used by the number-to-string conversion routine at 5D32H. It stores the ASCII representation of converted numbers. A 16-bit unsigned integer can have at most 5 digits (65535) plus a possible terminator byte, hence the 6-byte size. The buffer is populated by the ROM routine at 132FH and read by the number output routines.
[DATA BUFFER - Numeric conversion workspace. Shown as NOPs in disassembly but actually used as data storage.]
5D51
00 00 00 00 00 00 data
Numeric Conversion Buffer (6 bytes). Used by 5D32H to store the ASCII decimal representation of numbers. Format is ASCII digits, left-padded with zeros before stripping. Maximum content: 5 digits ("65535") plus null terminator.
5D57H - OUTPUT ROUTINES
This section contains several utility routines for outputting characters and numbers to the screen or printer. These include routines to print spaces, print numbers with or without leading spaces, and a general character output routine. The routines interact with the ROM's character output vector at 0033H and handle printer status checking via 003BH. A 16-bit division routine at 5D7DH is also included for numeric formatting.
[5D57H - Print Multiple Spaces. Prints A spaces to the current output device.]
5D57
LD B,A 47
Copy A (number of spaces to print) into B as a loop counter.
5D58
Call 5D64H to print a single space character.
5D5B
DJNZ 5D58H 10 FB
Decrement B and loop if not zero. Continue until all spaces printed. [LOOP]
5D5D
RET C9
Return to caller after printing all spaces.
[5D5EH - Print Number. Converts DE to decimal and prints it.]
5D5E
LD DE,0000H 11 00 00
Initialize DE to 0. This might be setting up for a default value or clearing the register.
5D61
Call 5D8EH to convert and print the number in DE. This prints "0" since DE is 0.
[5D64H - Print Space. Outputs a single space character.]
5D64
LD A,20H 3E 20
Load A with 20H (space character).
[Fall through to general character output.]
5D66
PUSH DE D5
Save DE onto the stack (character output may use DE).
5D67
PUSH AF F5
Save AF onto the stack. A contains the character to output.
5D68
Call ROM routine at 0033H - this is the character output vector. Outputs the character in A to the current device (screen or printer).
5D6B
LD A,00H 3E 00
Load A with 00H. This might be checking a device flag or status.
5D6D
CP 24H FE 24
Compare A with 24H ($). This appears to be checking if output is to a string device or special mode.
5D6F
POP DE D1
Pop AF that was pushed - but into DE! This recovers the original character in D and flags in E.
5D70
LD A,D 7A
Copy D (the original character) into A.
5D71
If Z flag set (from the CP 24H), call 003BH. This is the printer status check routine - handles printer-specific output processing.
5D74
POP DE D1
Restore the original DE value.
5D75
RET C9
Return to caller. Character has been output.
[5D76H - Print Space Then Character. Prints a space followed by the character in A.]
5D76
Call 5D64H to print a space first.
5D79
LD A,0DH 3E 0D
Load A with 0DH (carriage return). Wait, this seems wrong - we said "then character" but it loads CR. This might be "Print Space Then CR".
5D7B
Jump to 5D66H to output the carriage return character.
[5D7DH - 16-bit Division. Divides HL by C, result in HL, remainder in A.]
5D7D
LD C,A 4F
Copy A (divisor) into C. The divisor must be an 8-bit value.
5D7E
LD B,10H 06 10
Load B with 10H (16). This is the bit counter - we'll process 16 bits of the dividend.
5D80
XOR A AF
Clear A. A will accumulate the remainder during division.
[LOOP START - Standard shift-and-subtract division algorithm.]
5D81
ADD HL,HL 29
Shift HL left by 1 bit. The MSB goes into Carry, making room for the quotient bit on the right.
5D82
RLA 17
Rotate A left through carry. The bit shifted out of HL goes into A (building the remainder).
5D83
If Carry set (overflow from A), we definitely can subtract - jump to 5D88H.
5D85
CP C B9
Compare A (partial remainder) with C (divisor).
5D86
If Carry (A < C), we can't subtract - jump to 5D8AH to set quotient bit to 0.
5D88
SUB C 91
Subtract C (divisor) from A (remainder). A >= C, so we can subtract.
5D89
INC L 2C
Set the low bit of L to 1. This is the quotient bit - we subtracted, so this bit is 1.
5D8A
DJNZ 5D81H 10 F5
Decrement B (bit counter) and loop if not zero. Process all 16 bits. [LOOP]
5D8C
OR A B7
Set flags based on A (the remainder). Also clears Carry flag.
5D8D
RET C9
Return to caller. HL = quotient, A = remainder.
[5D8EH - Convert and Print Number. Converts DE to string and prints it.]
5D8E
LD BC,5D51H 01 51 5D
Load BC with 5D51H (address of numeric conversion buffer).
5D91
PUSH BC C5
Save buffer address onto the stack.
5D92
Call 5D27H to convert DE to ASCII string and copy to buffer at BC. E returns digit count.
5D95
POP HL E1
Pop buffer address into HL. HL now points to the start of the converted number string.
5D96
LD B,E 43
Copy E (digit count) into B as a loop counter.
[LOOP - Print each digit of the converted number.]
5D97
LD A,(HL) 7E
Load A with the byte at HL (current digit character).
5D98
INC HL 23
Advance HL to the next digit.
5D99
Call 5D66H to output the character in A to the current device.
5D9C
DJNZ 5D97H 10 F9
Decrement B and loop if not zero. Continue until all digits printed. [LOOP]
5D9E
RET C9
Return to caller. Number has been printed.
5D9FH - GOSUB Line Number Lookup
This routine locates a line number for GOSUB statements. It skips to the next statement, reads the pointer stored at the line, validates it, and stores the target address at 57B8H for later use. This enables GOSUB to jump to a computed or stored line number.
5D9F
Call the Skip Statement routine to advance HL past the current statement to the next one. This positions us at the start of the next line.
5DA2
INC HL 23
Increment HL to skip the first byte of the line link pointer.
5DA3
LD A,(HL) 7E
Load Register A with the low byte of the next line address pointer.
5DA4
INC HL 23
Increment HL to point to the high byte of the line link pointer.
5DA5
OR (HL) B6
OR Register A with the high byte of the line pointer. If both bytes are zero, the Z FLAG is set, indicating end of program (no more lines).
5DA6
INC HL 23
Increment HL to point to the low byte of the line number itself.
5DA7
If the Z FLAG is set (meaning the line link was 0000H = end of program), JUMP to ROM address 1997H which is the Illegal Function Call error handler. A GOSUB to a non-existent line is an error.
[SUCCESS PATH] The line exists. Now we extract the line number.
5DAA
LD E,(HL) 5E
Load Register E with the low byte of the line number at (HL).
5DAB
INC HL 23
Increment HL to point to the high byte of the line number.
5DAC
LD D,(HL) 56
Load Register D with the high byte of the line number. Now DE contains the full 16-bit line number.
5DAD
LD (57B8H),DE ED 53 B8 57
Store the line number DE at address 57B8H. This is a self-modifying code location used to pass the target line number to other routines. Note: 57B8H is within the NOP region at 57B6H-57B9H.
5DB1
RET C9
Return to caller with the line number stored at 57B8H.
5DB2H - Skip Statement (SKIPST)
This routine skips past BASIC statements to find the next statement or line. It handles statement separators (colon) and the ELSE token (93H). Used by control flow statements to navigate through the program text.
5DB2
DEC HL 2B
Decrement HL to prepare for RST 10H which will increment before reading. This ensures we start reading from the correct position.
5DB3
RST 10H D7
Call CHRGET - advance HL and get the next non-space character into A. Sets Z if end of line (00H or 0DH), C if digit.
5DB4
OR A B7
Test if Register A is zero (end of statement marker 00H).
5DB5
RET Z C8
If the Z FLAG is set (A=00H, end of statement), Return. We've found the end of the current statement.
[LOOP] Look for colon (statement separator) to skip multiple statements on the same line.
5DB6
CP 3AH FE 3A
Compare Register A with : (3AH = colon, the BASIC statement separator). If A equals 3AH, the Z FLAG is set.
5DB8
If the NZ FLAG is set (not a colon), JUMP to 5DBDH to check for ELSE token.
5DBA
RST 10H D7
We found a colon. Call CHRGET to skip it and get the next character.
5DBB
JUMP back to 5DB6H to continue scanning. [LOOP] This handles consecutive colons like ":::".
Check for ELSE token (93H) which also separates statements.
5DBD
RST 08H CF
Call SYNCHR - the next byte (93H) is the required token. If the current character matches, continue; otherwise Syntax Error.
5DBE
93 data
Parameter byte for RST 08H: 93H = ELSE token. SYNCHR will verify the current character is ELSE.
[LOOP] Keep advancing through ELSE branches.
5DBF
OR A B7
Test if Register A is zero (end of statement).
5DC0
RET Z C8
If the Z FLAG is set (A=0, end of line), Return. We've reached the end.
5DC1
RST 10H D7
Call CHRGET to get the next character after ELSE.
5DC2
JUMP back to 5DBFH to check if we've reached the end. [LOOP]
5DC4H - Error Code Table
This is a data table containing Disk BASIC error codes and their associated error numbers. Each entry consists of 3 bytes: a LD A,nn instruction (3EH) followed by LD BC,nnnn (01H) which encodes the error number. The error handler at 5E05H extracts the error code from Register A and jumps to the ROM error generator.
Error Code Table - Each entry is "LD A,code" followed by "LD BC,xxxx". The A value is the error code; the BC load is just padding to maintain 3-byte alignment. Entries are accessed by computing an offset into this table.
5DC4
LD A,2AH 3E 2A
Error code 42 (2AH) - "FIELD Overflow" error.
5DC6
LD BC,2E3EH 01 3E 2E
Padding bytes. When read as data: 3EH,2EH forms next entry.
5DC9
LD BC,643EH 01 3E 64
Error code 46 (2EH) at 5DC7H - "Bad File Mode" error.
5DCC
LD BC,683EH 01 3E 68
Error code 100 (64H) at 5DCAH - Disk BASIC error.
5DCF
LD BC,6C3EH 01 3E 6C
Error code 104 (68H) at 5DCDH - "Already Open" error.
5DD2
LD BC,6E3EH 01 3E 6E
Error code 108 (6CH) at 5DD0H - "Bad File Number" error.
5DD5
LD BC,7C3EH 01 3E 7C
Error code 110 (6EH) at 5DD3H - "File Not Open" error.
5DD8
LD BC,7E3EH 01 3E 7E
Error code 124 (7CH) at 5DD6H - "Input Past End" error.
5DDB
LD BC,803EH 01 3E 80
Error code 126 (7EH) at 5DD9H - "Bad Record Number" error.
5DDE
LD BC,843EH 01 3E 84
Error code 128 (80H) at 5DDCH - "File Name" error.
5DE1
LD BC,8C3EH 01 3E 8C
Error code 132 (84H) at 5DDFH - "Too Many Files" error.
5DE4
LD BC,8E3EH 01 3E 8E
Error code 140 (8CH) at 5DE2H - "Disk Full" error.
5DE7
LD BC,903EH 01 3E 90
Error code 142 (8EH) at 5DE5H - "File Input Beyond End of File" error.
5DEA
LD BC,923EH 01 3E 92
Error code 144 (90H) at 5DE8H - "Bad File Name" error.
5DED
LD BC,943EH 01 3E 94
Error code 146 (92H) at 5DEBH - Disk BASIC error.
5DF0
LD BC,983EH 01 3E 98
Error code 148 (94H) at 5DEEH - Disk BASIC error.
5DF3
LD BC,9A3EH 01 3E 9A
Error code 152 (98H) at 5DF1H - Disk BASIC error.
5DF6
LD BC,9C3EH 01 3E 9C
Error code 154 (9AH) at 5DF4H - Disk BASIC error.
5DF9
LD BC,9E3EH 01 3E 9E
Error code 156 (9CH) at 5DF7H - Disk BASIC error.
5DFC
LD BC,A23EH 01 3E A2
Error code 158 (9EH) at 5DFAH - Disk BASIC error.
5DFF
LD BC,A43EH 01 3E A4
Error code 162 (A2H) at 5DFDH - Disk BASIC error.
5E02
LD BC,A63EH 01 3E A6
Error code 164 (A4H) at 5E00H - Disk BASIC error.
5E05H - Error Dispatch Handler
This routine takes an error code in Register A (or derived from the error table) and dispatches to the ROM error handler at 19A2H. It extracts the error code and passes it in Register E as required by the ROM routine.
5E05
LD E,A 5F
Copy the error code from Register A to Register E. The ROM error handler at 19A2H expects the error code in E.
5E06
JUMP to ROM address 19A2H - the Error Generator. This routine prints the error message and returns to BASIC Ready.
5E09H - Error Handler with State Setup
This error handler stores the error code using self-modifying code, finalizes the current BASIC program state, resets BASIC pointers, then dispatches to the error handler. Used for recoverable errors during program execution.
5E09
LD (5E13H),A 32 13 5E
SELF-MODIFYING CODE: Store the error code from Register A into the immediate byte at address 5E13H. This modifies the "LD A,00H" instruction at 5E12H to load the actual error code.
5E0C
Call ROM routine 1AF8H - Finalize BASIC Program. This cleans up the program state, closes any open FOR/NEXT loops, and prepares for return to command mode.
5E0F
Call ROM routine 1B59H - Reset BASIC Pointers. This resets the program pointer, variable table, and other BASIC state to a clean condition.
5E12
LD A,00H 3E 00
Load Register A with the error code. The 00H is self-modified by the LD (5E13H),A at 5E09H to contain the actual error code.
5E14
JUMP to 5E05H to dispatch the error via the ROM error handler.
5E16H - DOS Error to BASIC Error Translator
This routine translates DOS error codes (returned by SVC calls) into BASIC error codes. It looks up the DOS error in a translation table at 5E36H to find the corresponding BASIC error number. If no translation exists, it uses error 72H (114 decimal) as the default.
5E16
LD C,A 4F
Copy the DOS error code from Register A to Register C for safekeeping during table lookup.
5E17
OR 0C0HOR 11000000 F6 C0
OR Register A with C0H to set bits 7 and 6. This creates the opcode for a conditional return (C0H = RET NZ, C8H = RET Z, etc.)
5E19
LD (57E5H),A 32 E5 57
SELF-MODIFYING CODE: Store the modified value at 57E5H. This location is within the CMD dispatcher and affects error recovery behavior.
5E1C
LD HL,5E36H 21 36 5E
Load HL with the address of the error translation table at 5E36H.
5E1F
LD E,72H 1E 72
Load Register E with the default BASIC error code 72H (114 decimal = "Disk I/O Error"). This is used if no translation is found.
[LOOP START] Search the translation table for a matching DOS error code.
5E21
LD A,(HL) 7E
Load Register A with the DOS error code from the translation table entry.
5E22
CP C B9
Compare the table entry's DOS code with the actual DOS error code in C. If they match, Z FLAG is set.
5E23
INC HL 23
Increment HL to point to the corresponding BASIC error code in the table.
5E24
If NZ FLAG is set (no match), JUMP to 5E27H to skip loading the BASIC error code.
5E26
LD E,(HL) 5E
Match found! Load Register E with the translated BASIC error code from the table.
5E27
INC HL 23
Increment HL to point to the next table entry.
5E28
LD A,(HL) 7E
Load Register A with the next byte to check for end of table.
5E29
OR A B7
Test if Register A is zero (end of table marker).
5E2A
If NZ FLAG is set (not end of table), JUMP back to 5E21H to check next entry. [LOOP]
[LOOP END] Table search complete. Check if we need to close the file.
5E2C
LD HL,(40F0H) 2A F0 40
Load HL with the value at 40F0H - this is the current FCB pointer (File Control Block). Used to check if a file needs closing.
5E2F
LD A,H 7C
Load Register A with the high byte of the FCB pointer.
5E30
OR L B5
OR with low byte. If both are zero, Z FLAG is set (no FCB active).
5E31
If Z FLAG is set (no active FCB), CALL 57E4H which loads A with C0H and jumps to SYS0 error handler at 4409H. This handles the case where no file is open.
5E34
JUMP to 5E06H to dispatch the error using the ROM error handler with the translated error code in E.
5E36H - DOS to BASIC Error Translation Table
This is a lookup table that maps DOS error codes to BASIC error codes. Each entry is 2 bytes: [DOS error code, BASIC error code]. The table is terminated by a 00H byte.
5E36
0F 88 data
DOS error 0FH (15) maps to BASIC error 88H (136) - "Disk Not Ready"
5E38
13 80 data
DOS error 13H (19) maps to BASIC error 80H (128) - "Disk Write Protected"
5E3A
18 6A data
DOS error 18H (24) maps to BASIC error 6AH (106) - "File Not Found"
5E3C
19 8A data
DOS error 19H (25) maps to BASIC error 8AH (138) - "File Already Exists"
5E3E
1A 86 data
DOS error 1AH (26) maps to BASIC error 86H (134) - "Directory Full"
5E40
1B 7A data
DOS error 1BH (27) maps to BASIC error 7AH (122) - "Disk Full"
5E42
1C 7C data
DOS error 1CH (28) maps to BASIC error 7CH (124) - "End of File"
5E44
1D 7C data
DOS error 1DH (29) maps to BASIC error 7CH (124) - "End of File" (alternate)
5E46
1E 7A data
DOS error 1EH (30) maps to BASIC error 7AH (122) - "Disk Full"
5E48
1F 66 data
DOS error 1FH (31) maps to BASIC error 66H (102) - "Bad File Mode"
5E4A
20 80 data
DOS error 20H (32) maps to BASIC error 80H (128) - "Disk Write Protected"
5E4C
21 66 data
DOS error 21H (33) maps to BASIC error 66H (102) - "Bad File Mode"
5E4E
22 66 data
DOS error 22H (34) maps to BASIC error 66H (102) - "Bad File Mode"
5E50
23 66 data
DOS error 23H (35) maps to BASIC error 66H (102) - "Bad File Mode"
5E52
24 66 data
DOS error 24H (36) maps to BASIC error 66H (102) - "Bad File Mode"
5E54
25 8A data
DOS error 25H (37) maps to BASIC error 8AH (138) - "File Already Exists"
5E56
26 66 data
DOS error 26H (38) maps to BASIC error 66H (102) - "Bad File Mode"
5E58
30 80 data
DOS error 30H (48) maps to BASIC error 80H (128) - "Disk Write Protected"
5E5A
00 data
End of table marker.
The remaining bytes 5E5BH-5E62H are NOPs (00H) serving as padding or reserved space.
5E5B
00 00 00 00 00 00 00 00 data
Reserved/padding bytes (8 bytes of 00H).
5E63H - FIELD Statement Handler
This routine handles the BASIC FIELD statement which defines the structure of a random access file buffer. It parses the file number, validates the file is open for random access, and processes field variable assignments. Syntax: FIELD #n, width AS variable$, ...
5E63
Call routine to parse file number and validate the file. Returns with BC pointing to the FCB, A containing file status flags.
5E66
If Z FLAG is set (file is valid), JUMP to 5E6FH to continue processing.
[ERROR PATH] File exists but may not be suitable for FIELD.
5E68
XOR 80H EE 80
Toggle bit 7 of the file status. This inverts the "file open" flag.
5E6A
AND 83H E6 83
Mask with 83H to keep only bits 7, 1, and 0. This checks for incompatible file modes.
5E6C
If NZ FLAG is set (incompatible mode), JUMP to error table entry 5DD0H for "Bad File Number" error.
[SUCCESS PATH] File is valid for FIELD. Calculate buffer address.
5E6F
LD DE,002DH 11 2D 00
Load DE with 45 (2DH = offset to file buffer within FCB structure).
5E72
EX DE,HL EB
Exchange DE and HL. Now HL=002DH (offset), DE=previous HL.
5E73
ADD HL,BC 09
Add BC (FCB address) to HL (offset). Result: HL points to the file buffer.
5E74
EX DE,HL EB
Exchange back. Now DE=buffer address, HL=original value.
5E75
LD B,A 47
Save the file status flags in Register B for later checking.
Check for field variable list (comma separator).
5E76
LD A,2CH 3E 2C
Load Register A with , (comma) character code.
5E78
CP (HL) BE
Compare with current character. If it's a comma, we have field definitions to process.
5E79
RET NZ C0
If NZ FLAG is set (no comma = end of FIELD statement), Return. The FIELD statement is complete.
[LOOP] Process each field variable definition: width AS variable$
5E7A
PUSH DE D5
Save the current buffer position on the stack.
5E7B
PUSH BC C5
Save BC (FCB address and flags) on the stack.
5E7C
Call ROM routine 2B1BH to evaluate the field width expression and return an 8-bit integer in A.
5E7F
PUSH AF F5
Save the field width (in A) on the stack.
5E80
RST 08H CF
Call SYNCHR to require the next token.
5E81
41 data
Parameter for SYNCHR: A (41H) - first letter of "AS".
5E82
RST 08H CF
Call SYNCHR to require the next token.
5E83
53 data
Parameter for SYNCHR: S (53H) - second letter of "AS".
5E84
Call 5EA2H to parse the string variable name and set up the string descriptor.
5E87
POP AF F1
Restore the field width from the stack into A.
5E88
POP BC C1
Restore BC (FCB address and flags).
5E89
LD C,A 4F
Copy field width to C.
5E8A
ADD A,B 80
Add current buffer position (in B) to field width. This calculates the new buffer position.
5E8B
If no carry (no overflow), JUMP to 5E8FH to continue.
5E8D
If NZ (overflow occurred with non-zero result), JUMP to 5E9FH for error handling.
Store the string descriptor pointing to this field in the buffer.
5E8F
EX (SP),HL E3
Exchange HL with top of stack. HL now has buffer position, stack has program pointer.
5E90
EX DE,HL EB
Exchange DE and HL. DE now has buffer position.
5E91
LD (HL),C 71
Store the field width as the string length in the string descriptor.
5E92
INC HL 23
Increment HL to point to string address low byte.
5E93
LD (HL),E 73
Store low byte of buffer address in string descriptor.
5E94
INC HL 23
Increment HL to point to string address high byte.
5E95
LD (HL),D 72
Store high byte of buffer address in string descriptor.
5E96
POP HL E1
Restore HL (program pointer) from the stack.
5E97
LD B,00H 06 00
Clear B (will be used with C to add field width).
5E99
If no overflow, JUMP back to 5E72H to process the next field definition. [LOOP]
Check for another field variable (comma) or end of statement.
5E9B
LD A,(HL) 7E
Load current character into A.
5E9C
CP 2CH FE 2C
Compare with comma (2CH). More fields to process?
5E9E
RET NZ C0
If NZ FLAG (not a comma), Return. FIELD statement is complete.
5E9F
JUMP to error entry 5DCAH - "FIELD Overflow" error. The field definitions exceed the buffer size.
5EA2H - Parse Variable for FIELD
This helper routine parses a variable name for use in FIELD or similar statements. It calls the ROM variable parser and then evaluates the string expression.
5EA2
Call ROM routine 260DH - Get/Parse Variable Reference. This parses the variable name and returns a pointer to its storage location.
5EA5
JUMP to ROM routine 0AF4H - String Expression Evaluation. This validates that the variable is a string type and returns its descriptor.
5EA8H - USR Function File Channel Check
This routine checks if the current input is from a file channel (indicated by # prefix). It's used by the USR function to determine if input should come from a file or the keyboard.
5EA8
CP 23H FE 23
Compare Register A with # (23H = hash/pound sign, file channel prefix).
5EAA
RET NZ C0
If NZ FLAG is set (not a # sign), Return. No file channel specified.
5EAB
PUSH HL E5
Save HL (program pointer) on the stack.
5EAC
RST 10H D7
Call CHRGET to advance past the # and get the next character.
5EAD
CP CEH FE CE
Compare with CEH (token for USR function). Check if this is the USR token.
5EAF
POP HL E1
Restore HL from the stack.
5EB0
LD A,(HL) 7E
Reload the current character at (HL) into A.
5EB1
RET Z C8
If Z FLAG is set (was the USR token), Return. Special USR handling.
5EB2
Call routine to parse and validate file channel number.
5EB5
EX (SP),HL E3
Exchange HL with top of stack. Save current position, get return address.
5EB6
JUMP to ROM routine 21C3H (which is the middle of the INPUT routine) to continue processing with the file channel set up.
5EB9H - PRINT# Position Handler
This routine handles position specifiers for PRINT# statements, determining whether TAB or SPC function was used.
5EB9
Call the FCB status check routine. This validates the file is open and ready for output.
5EBC
POP AF F1
Pop the saved AF from the stack. The A register contains the token that triggered this handler.
5EBD
CP 2BH FE 2B
Compare with 2BH (+ sign or specific token). Check which position function was used.
5EBF
If Z FLAG is set (match), JUMP to ROM routine 2B4AH - handle TAB function.
5EC2
Otherwise JUMP to ROM routine 2282H - handle SPC function.
5EC5H - LOC Function Entry
Entry point for the LOC (location) function which returns the current record position in a random access file.
5EC5
LD B,01H 06 01
Load Register B with 01H - flag indicating LOC function.
5EC7
JUMP to 5EE6H - common file function handler.
5EC9H - LOF Function Entry
Entry point for the LOF (length of file) function which returns the size of a file in bytes.
5EC9
LD B,02H 06 02
Load Register B with 02H - flag indicating LOF function.
5ECB
JUMP to 5EE6H - common file function handler.
5ECDH - EOF Function Signature
Data signature ("$%") used to identify binary file functions.
5ECD
24 25 data
Signature bytes: $ (24H) and % (25H) - binary file function identifier.
5ECFH - EOF Function Entry
Entry point for the EOF (end of file) function which returns -1 (true) if at end of file, 0 (false) otherwise.
5ECF
LD HL,E123H 21 23 E1
Load HL with E123H - setting up a return value or comparison constant.
5ED2
EX (SP),HL E3
Exchange HL with the top of the stack.
5ED3
LD DE,5ECDH 11 CD 5E
Load DE with address of the signature bytes at 5ECDH.
5ED6
LD BC,8005H 01 05 80
Load BC with 8005H. B=80H (EOF function flag), C=05H (counter).
[LOOP] Check for binary file function signature.
5ED9
RRC B CB 08
Rotate B right through carry. Shifts the flag bits.
5EDB
DEC C 0D
Decrement the comparison counter C.
5EDC
If Z FLAG is set (counter zero), JUMP to 5EE4H.
5EDE
LD A,(DE) 1A
Load A with byte from signature string at (DE).
5EDF
CP (HL) BE
Compare with current character in program at (HL).
5EE0
INC DE 13
Increment DE to next signature byte.
5EE1
If NZ FLAG (no match), JUMP back to 5ED9H. [LOOP]
5EE3
RST 10H D7
Call CHRGET to advance past matched character.
5EE4
EX (SP),HL E3
Exchange HL with stack top. Restore program pointer.
5EE5
PUSH HL E5
Push the program pointer onto the stack.
5EE6H - Common File Function Handler (LOC/LOF/EOF)
Common entry point for LOC, LOF, and EOF functions. Parses the file number, validates the file, and dispatches to the appropriate calculation routine.
5EE6
Call routine to parse file number in parentheses and set up the FCB.
5EE9
LD A,B 78
Load A with the function flag from B (01=LOC, 02=LOF, 80=EOF).
5EEA
AND 06H E6 06
Mask with 06H. For LOC/LOF result is non-zero; for EOF result is zero.
5EEC
If NZ FLAG (LOC or LOF function), JUMP to 5EFDH.
[EOF PATH] Handle EOF function.
5EEE
Call ROM routine 0AEFH to get file status information.
5EF1
LD A,H 7C
Load A with high byte of result.
5EF2
LD D,L 55
Copy low byte of HL to D.
5EF3
LD E,C 59
Copy C to E. Building result in ADE.
5EF4
LD B,98H 06 98
Load B with 98H - exponent for floating point conversion (24-bit integer).
5EF6
LD HL,637EH 21 7E 63
Load HL with 637EH - address of the return handler.
5EF9
PUSH HL E5
Push the return handler address onto the stack.
5EFA
JUMP to ROM routine 0969H to convert integer to floating point.
[LOC/LOF PATH] Handle LOC or LOF function.
5EFD
BIT 2,(IX+00H) DD CB 00 56
Test bit 2 of the FCB status byte. Check if file is open for random access.
5F01
If Z FLAG (not random access), JUMP to 5DD0H for "Bad File Number" error.
5F04
Call routine to calculate file position.
5F07
LD HL,637EH 21 7E 63
Load HL with return handler address 637EH.
5F0A
PUSH HL E5
Push return address onto stack.
5F0B
LD H,B 60
Copy B to H (high byte of result).
5F0C
LD L,C 69
Copy C to L (low byte). HL now contains the 16-bit result.
5F0D
JUMP to ROM routine 0A9AH to convert 16-bit integer to floating point.
5F10H - Calculate File Position (Division)
This routine calculates the current record position by performing a 24-bit by 16-bit division. It divides the byte position by the record length to get the record number.
5F10
XOR A AF
Clear Register A (high byte of dividend).
5F11
LD B,L 45
Copy L to B. Building the dividend.
5F12
LD L,H 6C
Copy H to L.
5F13
LD H,A 67
Clear H. Now HLB contains the 24-bit position.
5F14
LD DE,(5702H) ED 5B 02 57
Load DE with the record length from FCB work area at 5702H.
5F18
LD A,11H 3E 11
Load A with 17 (11H) - loop counter for division.
5F1A
JUMP to 5F23H to start division loop.
[DIVISION LOOP] 24-bit by 16-bit division using shift-and-subtract.
5F1C
OR A B7
Clear carry flag for subtraction.
5F1D
SBC HL,DE ED 52
Subtract divisor DE from partial dividend HL.
5F1F
If no carry (succeeded), JUMP to 5F22H.
5F21
ADD HL,DE 19
Restore HL by adding DE back.
5F22
CCF 3F
Complement carry flag (quotient bit).
5F23
RL C CB 11
Rotate left through carry: shift quotient bit into C.
5F25
RL B CB 10
Rotate left through carry: continue into B.
5F27
RL L CB 15
Rotate left through carry: shift dividend L.
5F29
RL H CB 14
Rotate left through carry: shift dividend H.
5F2B
If carry set (overflow), JUMP to 5F38H for error.
5F2D
DEC A 3D
Decrement loop counter.
5F2E
If not zero, JUMP back to 5F1CH. [LOOP]
[DIVISION COMPLETE] Check for remainder and overflow.
5F30
LD A,H 7C
Load A with high byte of remainder.
5F31
OR L B5
OR with low byte to check for remainder.
5F32
If Z FLAG (no remainder), JUMP to 5F35H.
5F34
INC BC 03
Increment quotient if there was a remainder (round up).
5F35
BIT 7,B CB 78
Test bit 7 of B (check for overflow).
5F37
RET Z C8
If Z FLAG (no overflow), Return with result in BC.
5F38
JUMP to error entry 5DD9H - "Bad Record Number" error.
5F3BH - LPOS Function Handler
Handles the LPOS function which returns the current print position on the line printer.
5F3B
Call FCB status check routine.
5F3E
POP HL E1
Pop the return address/parameter from the stack.
5F3F
LD A,L 7D
Load A with low byte of HL.
5F40
CP 30H FE 30
Compare with 30H (ASCII '0').
5F42
LD A,(570AH) 3A 0A 57
Load A with the printer position from FCB work area at 570AH.
5F45
If carry set, JUMP to ROM routine 2130H.
5F48
Otherwise JUMP to ROM routine 2156H.
5F4BH - POS Function Handler
Handles the POS function which returns the current cursor position.
5F4B
Call FCB status check routine.
5F4E
POP HL E1
Pop the return address/parameter from the stack.
5F4F
JUMP to ROM routine 20E9H (which is part of the PRINT@ routine) to return cursor position.
5F52H - INPUT Channel Check
Checks if input should come from a file channel by looking for the USR token (CEH).
5F52
PUSH HL E5
Save HL (program pointer) on the stack.
5F53
RST 10H D7
Call CHRGET to get the next non-space character.
5F54
CP CEH FE CE
Compare with CEH (USR token).
5F56
POP HL E1
Restore HL from the stack.
5F57
LD A,(HL) 7E
Reload current character at (HL) into A.
5F58
RET Z C8
If Z FLAG (was USR token), Return.
5F59
LD C,40H 0E 40
Load C with 40H - flag for input mode.
5F5B
JUMP to 5F5FH for file channel setup.
5F5DH - OUTPUT Channel Setup
Entry point for setting up an output channel to a file.
5F5D
LD C,20H 0E 20
Load C with 20H - flag for output mode.
5F5FH - File Channel Validation
Validates and sets up a file channel for I/O operations. Checks for # prefix, parses file number, and validates file mode.
5F5F
CP 23H FE 23
Compare A with # (23H = file channel indicator).
5F61
RET NZ C0
If NZ FLAG (not # sign), Return. No file channel.
5F62
PUSH BC C5
Save BC (C has I/O mode flag) on the stack.
5F63
Call routine to parse file number and set up FCB pointer.
5F66
BIT 7,A CB 7F
Test bit 7 of file status byte (error state).
5F69
If NZ FLAG (error), JUMP to 5DD0H for "Bad File Number" error.
5F6C
AND C A1
AND status with required I/O mode flag.
5F6D
PUSH HL E5
Save HL (program pointer).
5F6E
LD A,(HL) 7E
Load current character.
5F6F
If Z FLAG (mode mismatch), JUMP to error.
5F72
Call routine to get current file position.
5F75
Call routine to update file position flags.
5F79
RET C9
Return with file channel ready.
5F7AH - Parse File Number and Get FCB Pointer
This routine parses a file number from the BASIC program text, validates it against the maximum allowed files, and returns a pointer to the corresponding File Control Block (FCB). It's called by many disk I/O statements like FIELD, INPUT#, PRINT#, etc. to identify which file the operation applies to. On entry, HL points to the BASIC text. On exit, BC contains the FCB pointer, A contains the FCB status byte, and HL is advanced past the parsed file number.
[ENTRY POINT] Parse file number from BASIC text. The # prefix is optional. HL points to current position in BASIC program.
5F7A
DEC HL 2B
Back up HL by one position to prepare for RST 10H (CHRGET), which will first increment HL before fetching the character.
5F7B
RST 10H D7
Call CHRGET to get the next non-space character into A, advancing HL past any spaces.
5F7C
CP 23H FE 23
Compare A with # (23H). The # symbol is the optional file number prefix (e.g., "#1" or just "1").
5F7E
If A equals # (Z flag set), call ROM routine 1D78H (which is the RST 10H routine) to skip past the # character and get the next character. This handles the optional # prefix gracefully.
Now we need to evaluate the file number expression. The number can be a literal or a variable/expression.
5F81
Call ROM routine 2337H (FRMNUM) to evaluate a numeric expression. This returns the result in the Floating Point Accumulator (FAC).
5F84
Call ROM routine 2B1FH to convert the FAC to an integer in A. This is the file number (1, 2, 3, etc.).
Validate that the file number is within bounds. The maximum file count is stored at 5F89H (typically 3 for NEWDOS/80).
5F87
DEC A 3D
Decrement A to convert from 1-based file number to 0-based index. File #1 becomes index 0, File #2 becomes index 1, etc.
5F88
CP 00H FE 00
Compare the decremented value with 0. This is actually checking against the maximum file number stored at 5F89H - the second byte of this instruction (00H) is self-modified at initialization to contain the maximum allowed file count.
5F8A
If A >= max file count (No Carry), the file number is too large. Jump to error handler 5DCDH which generates error 68H (104) "Bad File Number".
File number is valid. Now calculate the pointer to the FCB. FCBs are stored sequentially starting at 66BEH, each FCB is 64C5H bytes in size.
5F8D
PUSH HL E5
Save the current BASIC text pointer on the stack - we need to return this to the caller.
5F8E
LD HL,66BEH 21 BE 66
Load HL with 66BEH - this is the base address of the FCB table where all File Control Blocks are stored.
5F91
LD BC,(64C5H) ED 4B C5 64
Load BC with the FCB size from address 64C5H. Each FCB is typically 012DH (301) bytes: 2DH (45) bytes header + 100H (256) bytes data buffer.
[LOOP] Calculate FCB pointer by adding FCB size (BC) to base (HL) for each file number.
5F95
OR A B7
Test if A (file index) is zero. If so, we're already at the correct FCB (file #1 = index 0).
5F96
If file index is 0 (Z flag set), skip the loop and jump to 5F9CH to finalize the FCB pointer.
5F98
ADD HL,BC 09
Add FCB size (BC) to current pointer (HL) to advance to the next FCB in the table.
5F99
DEC A 3D
Decrement the file index counter.
5F9A
If index is not yet zero, loop back to 5F98H to add another FCB size. [LOOP]
HL now points to the start of the correct FCB. Get status byte and copy pointer to BC.
5F9C
OR (HL) B6
OR A with the first byte of the FCB (the status byte at offset 00H). This loads the status into A while also setting flags. Z flag will be set if the file is not open (status = 0).
5F9D
LD B,H 44
Copy high byte of FCB pointer from H to B.
5F9E
LD C,L 4D
Copy low byte of FCB pointer from L to C. Now BC contains the FCB pointer.
5F9F
POP HL E1
Restore the BASIC text pointer from the stack into HL.
5FA0
RET C9
Return to caller. Returns: BC = FCB pointer, A = FCB status byte (0 if not open), Z flag set if file not open, HL = updated BASIC text pointer.
5FA1H - CLOSE Statement Handler
This routine handles the BASIC CLOSE statement. It can close a single file (CLOSE #n) or all open files (CLOSE with no arguments). When closing a file, it flushes any buffered data, calls DOS to close the file, then marks the FCB as unused. The routine at 5FB6H handles closing all files, while 5FA1H handles closing a specific file number.
[ENTRY POINT] CLOSE #n - Close a specific file. Entry here means a file number follows.
5FA1
If Z flag is set (no file number specified), jump to 5FB6H to close ALL open files. Otherwise, continue to close the specified file.
[LOOP START] Close files one at a time. This loop handles "CLOSE #1,#2,#3" syntax.
5FA3
Call Parse File Number (5F7AH) to get the file number and FCB pointer. Returns BC=FCB pointer, A=status.
5FA6
Call the single-file close routine at 5FB2H to flush and close this file.
5FA9
Call 638FH to check if there's another file number (comma separator). Returns Z if end of statement, NZ if comma found.
5FAC
If not end of statement (NZ), loop back to 5FA3H to close the next file in the list. [LOOP]
5FAE
RET C9
All specified files closed. Return to BASIC interpreter.
5FAFH - Initialize Dummy FCB
This entry point sets BC to 5700H (the work FCB area) for operations that need a temporary FCB.
5FAF
LD BC,5700H 01 00 57
Load BC with 5700H - the work/dummy FCB area used for temporary file operations.
5FB2H - Close Single File (Common Entry)
Close a single file. BC must contain the FCB pointer. This is the common close logic.
5FB2
XOR A AF
Clear A to zero. This will be used as a flag (0 = close operation).
5FB3
PUSH AF F5
Save A (0) on stack. This serves as a flag for the close-all loop to know when to stop.
5FB4
Jump to 5FD5H to perform the actual close operation.
5FB6H - CLOSE All Files
[CLOSE with no arguments] Close all currently open files.
5FB6
LD A,(5F89H) 3A 89 5F
Load A with the maximum file count from 5F89H. This tells us how many FCBs to check.
5FB9
OR A B7
Test if max file count is zero.
5FBA
RET Z C8
If zero files allowed (shouldn't happen), return immediately.
5FBB
PUSH HL E5
Save BASIC text pointer on stack.
5FBC
LD B,A 47
Copy max file count to B - this is our loop counter.
5FBD
LD C,A 4F
Also copy to C - used to track which file we're on.
5FBE
LD HL,66BEH 21 BE 66
Load HL with FCB table base address 66BEH.
5FC1
Call 65DBH to load DE with FCB size from (64C5H). Each FCB is 012DH bytes.
[LOOP] Scan through all FCBs looking for open files to close.
5FC4
LD A,(HL) 7E
Load A with the status byte of the current FCB (first byte of FCB).
5FC5
OR A B7
Test if status byte is zero (file not open).
5FC6
If not zero (file is open), jump to 5FCBH to exit the scanning loop and close this file.
5FC8
ADD HL,DE 19
Add FCB size (DE) to HL to move to the next FCB in the table.
5FC9
DJNZ 5FC4H 10 F9
Decrement B and loop back to 5FC4H if not zero. [LOOP]
5FCB
POP HL E1
Restore BASIC text pointer from stack.
5FCC
RET Z C8
If Z flag set (no more open files found), return.
Found an open file. C contains the remaining count, so (max - C + 1) is the file number.
5FCD
LD A,C 79
Load A with C (remaining file count).
5FCE
OR A B7
Test if C is zero.
5FCF
RET Z C8
If zero, all files have been processed, return.
5FD0
DEC A 3D
Decrement A to convert to 0-based index for FCB lookup.
5FD1
PUSH AF F5
Save the file index on stack - will be used to continue the loop after closing this file.
5FD2
Call 5F88H (mid-entry to Parse File Number) to get the FCB pointer for this file index. BC = FCB pointer on return.
5FD5H - Execute File Close
Common close logic. BC = FCB pointer. Flush buffer if dirty, then call DOS CLOSE.
5FD5
PUSH HL E5
Save BASIC text pointer.
5FD6
LD HL,000DH 21 0D 00
Load HL with offset 0DH (13) - this is the offset to the filename within the FCB.
5FD9
ADD HL,BC 09
Add FCB base (BC) to get pointer to filename at FCB+0DH. Store in HL.
5FDA
EX DE,HL EB
Exchange DE and HL. Now DE = pointer to filename in FCB.
5FDB
LD H,B 60
Copy FCB pointer high byte to H.
5FDC
LD L,C 69
Copy FCB pointer low byte to L. Now HL = FCB base pointer.
5FDD
BIT 6,(HL) CB 76
Test bit 6 of FCB status byte. Bit 6 = "modified/dirty" flag - indicates the buffer has unsaved data.
5FDF
If dirty flag is set (NZ), call DOS routine 4428H to flush the buffer to disk before closing.
5FE2
PUSH AF F5
Save result flags from flush operation.
5FE3
LD B,2DH 06 2D
Load B with 2DH (45) - the size of the FCB header to clear.
5FE5
Call 6389H to zero-fill B bytes starting at (HL). This clears the FCB header, marking the file as closed.
5FE8
POP AF F1
Restore flags from the flush operation.
5FE9
If flush failed (NZ), jump to error translator 5E16H to report the DOS error as a BASIC error.
5FEC
POP HL E1
Restore BASIC text pointer.
5FED
POP AF F1
Pop the loop continuation flag/index from stack.
5FEE
Jump back to 5FCEH to continue closing any remaining files (for close-all operation).
5FF0H - Get FCB and Validate File Open
This routine is called before file operations to validate that a file is properly open. It parses the file number, retrieves the FCB, and checks that the file is open for the correct mode. Returns the FCB status and position information.
[ENTRY POINT] Get FCB for file operations. B contains required mode flags on entry.
5FF0
PUSH BC C5
Save BC (B contains the required file mode flags for validation).
5FF1
Call 5F84H to evaluate the file number expression and get FCB pointer. Returns BC = FCB pointer.
5FF4
Call 62BFH to validate the FCB and copy FCB header to work area at 5700H. Also sets IX to point to work FCB.
5FF7
If Z flag set (file not open), jump to error 5DD0H which generates "Bad File Number" (6CH) error.
5FFA
POP BC C1
Restore BC. B now contains the mode flags we need to check against.
5FFB
LD DE,(5700H) ED 5B 00 57
Load DE with the first two bytes of the work FCB at 5700H. E = status byte, D = additional flags.
5FFF
Call 61DAH to get alternate position values. Returns A = byte from 5715H, HL = word from 5719H.
6002
LD C,A 4F
Save the position byte in C for later use.
6003
LD A,B 78
Load A with the required mode flags from B.
6004
AND 22H E6 22
Mask with 22H (bits 5 and 1). These are special mode bits.
6006
RET NZ C0
If any of these bits are set, return immediately (special handling path).
6007
BIT 3,B CB 58
Test bit 3 of B (mode flags). Bit 3 indicates a specific file operation type.
6009
If bit 3 is set, jump to 6150H for alternate position handling.
600C
Call 61D3H to get current file position. Returns C = (IX+12H), HL = (5717H).
600F
BIT 6,D CB 72
Test bit 6 of D (FCB flags byte +01H). Bit 6 = position valid flag.
6011
If position not valid (bit 6 clear), jump to 604FH to handle unpositioned file.
Position is valid. Check if we need to read more data or handle end-of-record.
6013
BIT 7,E CB 7B
Test bit 7 of E (status byte). Bit 7 = error state flag.
6015
If no error (bit 7 clear), jump to 6034H to check mode flags.
6017
Call 6149H to get saved position from FCB. Returns C = (IX+04H), HL = (5705H).
601A
BIT 3,E CB 5B
Test bit 3 of E (status byte). Bit 3 = specific operation mode.
601C
If bit 3 clear, jump to 6034H.
601E
BIT 2,E CB 53
Test bit 2 of E. Bit 2 = random access mode.
6020
If random access (bit 2 set), jump to 6031H.
Sequential file - need to read next record.
6022
Call 61CDH to set up for disk read. DE = 444EH (DOS read routine).
6025
Call 6058H to compare current position with target position.
6028
If at or past target position (NC), jump to 6034H.
[LOOP] Read records until we reach the target position.
602A
Call 627FH to read the next record from disk.
602D
If read successful (NZ), loop back to 6025H to check position again. [LOOP]
602F
Jump to 6034H to check final status.
6031
Call 6065H to calculate next position for random file.
6034H - Check File Mode and Return Status
Check if file is in correct mode for the requested operation.
6034
LD A,B 78
Load A with the mode flags from B.
6035
AND 41H E6 41
Mask with 41H (bits 6 and 0). Bit 6 = output mode, Bit 0 = input mode.
6037
RET Z C8
If neither input nor output mode required, return (status check only).
Input or output mode required. Get EOF status.
6038
POP DE D1
Pop return address into DE (we're going to modify the return path).
6039
Call 605BH to compare positions and get status.
603C
LD A,FFH 3E FF
Load A with FFH (-1) - this is the "end of file" indicator.
603E
If positions equal (Z), at EOF - jump to 6048H with A=FFH.
6040
If carry set (past EOF), jump to 6046H.
6042
BIT 6,B CB 70
Test bit 6 of B (output mode flag).
6044
If output mode, jump to 6048H (EOF OK for output).
6046
LD A,00H 3E 00
Load A with 00H - indicates not at EOF.
6048
LD HL,637EH 21 7E 63
Load HL with 637EH - this is the address of the return handler routine.
604B
PUSH HL E5
Push return handler address onto stack.
604C
Jump to ROM 098DH to convert A to floating point and return via 637EH.
604FH - Handle Unpositioned Random File
File position not valid - check if random access mode and initialize position.
604F
BIT 2,B CB 50
Test bit 2 of B (random access mode flag).
6051
If not random access (sequential), jump back to 6034H.
6053
LD HL,0000H 21 00 00
Load HL with 0000H - initialize position to start of file.
6056
LD C,L 4D
Copy L (0) to C - position byte = 0.
6057
RET C9
Return with position initialized to zero.
6058H - Compare File Positions
This routine compares the current file position with the target position to determine if more data needs to be read or if we're at/past the target location.
6058
Call 61D3H to get current position. Returns C = sector position from (IX+12H), HL = position word from (5717H).
605B
Call 61E4H to get both position values for comparison. Sets up DE and HL for RST 18H.
605E
RST 18H DF
Call RST 18H (CPDEHL) to compare DE with HL. Sets Z if equal, C if DE > HL.
605F
RET NZ C0
If positions not equal (NZ), return with carry flag indicating relationship.
6060
LD A,C 79
Load A with C (byte position within record).
6061
CP (IX+15H) DD BE 15
Compare A with (IX+15H) - the record number within sector.
6064
RET C9
Return with flags set from comparison. Z = at same position, C = current position before target.
6065H - Calculate Next Record Position
For random access files, this routine calculates the position of the next record by adding the record length to the current position.
6065
LD HL,(5707H) 2A 07 57
Load HL with the current position word from 5707H (high word of 24-bit position).
6068
LD DE,(5702H) ED 5B 02 57
Load DE with the record length from 5702H. This is the size of each record in the random access file.
606C
ADD HL,DE 19
Add record length (DE) to current position high word (HL). This advances to the next record.
606D
LD A,(5709H) 3A 09 57
Load A with the overflow byte from 5709H (highest byte of 24-bit position).
6070
ADC 00H CE 00
Add carry to the overflow byte (handle 16-bit addition overflow into 24-bit position).
6072
LD C,L 4D
Copy L to C - low byte of new position.
6073
LD L,H 6C
Copy H to L - shift position bytes.
6074
LD H,A 67
Copy A to H - overflow byte becomes high byte.
6075
RET C9
Return with new position in C, HL (24-bit: H=high, L=mid, C=low).
6076H - Character Output to File
This routine outputs a single character to a file. It handles printer position tracking and calls the appropriate DOS write routine. The character to output is passed in A.
6076
Call 63A9H to check and handle re-entrancy protection. If file operations are nested, this prevents corruption.
6079
EX (SP),HL E3
Exchange HL with top of stack. Saves HL and retrieves parameter (character in A was pushed by caller).
607A
PUSH DE D5
Save DE register pair.
607B
LD HL,5700H 21 00 57
Load HL with 5700H - the work FCB area.
607E
BIT 6,(HL) CB 76
Test bit 6 of work FCB status. Bit 6 = file is a printer/line printer output.
6080
If not printer output (bit 6 clear), jump to 6096H to skip printer position tracking.
This is printer output. Track column position for TAB and line width handling.
6082
LD HL,570AH 21 0A 57
Load HL with address of printer position counter at 570AH.
6085
INC (HL) 34
Increment the printer column position.
6086
CP 20H FE 20
Compare character (A) with 20H (space). Characters 00-1FH are control codes.
6088
If character >= 20H (printable), jump to 6091H to write the character.
Control character - may need to adjust position counter.
608A
DEC (HL) 35
Decrement position counter (control char doesn't advance position).
608B
CP 0DH FE 0D
Compare character with 0DH (carriage return).
608D
If not carriage return, jump to 6091H to write the character.
608F
LD (HL),00H 36 00
Carriage return - reset position counter to zero (start of new line).
6091
PUSH AF F5
Save the character to output.
6092
Call 622CH to write the character to the file buffer (DOS SVC 1BH - write byte).
6095
POP AF F1
Restore the character.
6097
POP HL E1
Restore HL (original value from stack exchange).
6098
POP BC C1
Restore BC (return address pushed by caller).
6099
RET C9
Return to caller.
609AH - File OPEN Entry Points
These are the entry points for opening files in different modes. The OPEN statement in BASIC calls one of these depending on the mode (FOR INPUT, FOR OUTPUT, FOR RANDOM, FOR APPEND). Each entry sets up mode flags in BC before calling the common OPEN handler.
[ENTRY POINT] OPEN FOR INPUT/OUTPUT - standard sequential file open.
609A
LD BC,0120H 01 20 01
Load BC with mode flags: B=01H (read mode), C=20H (sequential output). This is OPEN FOR OUTPUT mode.
609DH - Common OPEN Handler
[COMMON ENTRY] All OPEN modes converge here. BC contains mode flags.
609D
PUSH BC C5
Save mode flags (BC) on stack.
609E
PUSH HL E5
Save BASIC text pointer (HL) on stack.
609F
Call 6381H to clear the return handler and prepare for file operations.
60A2
LD BC,5700H 01 00 57
Load BC with 5700H - the work FCB area address.
60A5
Call 62BFH to initialize the work FCB at 5700H. Sets IX to point to work FCB.
60A8
SET 7,(IX+2DH) DD CB 2D FE
Set bit 7 of FCB buffer byte at offset 2DH. This marks the FCB as being initialized for open.
60AC
POP HL E1
Restore BASIC text pointer.
60AD
POP BC C1
Restore mode flags.
60AE
PUSH BC C5
Save mode flags again (needed later).
60AF
LD A,(5700H) 3A 00 57
Load A with status byte from work FCB at 5700H.
60B2
OR A B7
Test if file is already open (status != 0).
60B3
If file already open (NZ), jump to error 5DD3H which generates error 68H (104) "Already Open".
File not currently open. Parse the filename from BASIC program.
60B6
Call ROM 2337H (FRMNUM) to evaluate the filename expression. Returns string descriptor pointer.
60B9
EX (SP),HL E3
Exchange: save BASIC pointer to stack, get mode flags into HL.
60BA
PUSH HL E5
Save mode flags on stack.
60BB
Call 5CC0H to parse and validate the filename string. Returns filename length in A.
60BE
CP 20H FE 20
Compare filename length with 20H (32). Maximum filename length is 31 characters.
60C0
If filename too long (>= 32 chars), jump to error 5DDCH which generates error 80H (128) "File Name error".
60C3
LD HL,570DH 21 0D 57
Load HL with 570DH - the filename buffer in the work FCB.
60C6
PUSH HL E5
Save filename buffer pointer.
60C7
Call 5CDEH to copy the parsed filename to the buffer at 570DH.
60CA
POP DE D1
Restore filename buffer pointer into DE.
60CB
LD (HL),00H 36 00
Null-terminate the filename string.
Filename stored. Now determine buffer size based on mode and optional record length.
60CD
LD HL,(6379H) 2A 79 63
Load HL with the actual FCB pointer from 6379H (set earlier by 62BFH).
60D0
LD BC,002DH 01 2D 00
Load BC with offset 2DH (45) - offset to the data buffer within FCB.
60D3
ADD HL,BC 09
Add offset to get pointer to data buffer start.
60D4
BIT 7,(IX+2DH) DD CB 2D 7E
Test bit 7 of FCB+2DH. This was set earlier at 60A8H if opening a new file.
60D8
If bit clear (re-opening existing file), jump to 60DDH.
60DA
LD HL,4200H 21 00 42
Load HL with 4200H - default buffer address for new files (in high memory).
60DD
POP BC C1
Restore mode flags into BC.
60DE
BIT 0,B CB 40
Test bit 0 of B (mode flags). Bit 0 = read mode.
60E0
PUSH BC C5
Save mode flags.
60E1
LD B,00H 06 00
Clear B for DOS call parameter.
60E3
If read mode (bit 0 set), jump to 60EAH to call DOS OPEN for read.
Open for output - use DOS OPEN for write.
60E5
Call DOS 4420H (OPEN file for output). DE = filename pointer, HL = buffer address.
60E8
Jump to 60EDH to check result.
60EA
Call DOS 4424H (OPEN file for input). DE = filename pointer, HL = buffer address.
60ED
If DOS error (NZ), jump to error translator 5E16H to convert DOS error to BASIC error.
File opened successfully. Initialize position to zero.
60F0
XOR A AF
Clear A to zero.
60F2
LD L,A 6F
Clear L. HL = 0000H (initial position).
60F3
POP BC C1
Restore mode flags.
60F4
BIT 2,B CB 50
Test bit 2 of B. Bit 2 = random access mode.
60F6
If random access (bit 2 set), call 6112H to store initial position in alternate position fields.
60F9
BIT 1,B CB 48
Test bit 1 of B. Bit 1 = write mode.
60FB
If write mode (bit 1 set), call 61DAH to get position values.
60FE
LD (5717H),HL 22 17 57
Store position word in 5717H (current position in work FCB).
6101
LD (5712H),A 32 12 57
Store position byte in 5712H (sector position in work FCB).
6104
LD A,B 78
Load A with mode flags from B.
6105
AND 0F8HAND 11111000 E6 F8
Mask off lower 3 bits - keep only the mode flags (bits 7-3).
6107
LD B,A 47
Store masked flags back in B.
6108
LD (5700H),BC ED 43 00 57
Store BC (status flags) to work FCB at 5700H. This sets the file as "open".
610C
SET 6,(IX+0EH) DD CB 0E F6
Set bit 6 of FCB+0EH. This marks the position as valid.
6110
POP HL E1
Restore BASIC text pointer.
6111
RET C9
Return to BASIC interpreter. File is now open.
6112H - Store Initial Random Position
For random files, store the initial position in the alternate position fields.
6112
LD (5719H),HL 22 19 57
Store position word in alternate position at 5719H.
6115
LD (5715H),A 32 15 57
Store position byte in alternate position at 5715H.
6119H - Check Filename in FCB
This routine compares a filename with the one stored in the work FCB to see if they match.
611A
LD DE,570DH 11 0D 57
Load DE with filename buffer address 570DH in work FCB.
611D
Call ROM 0013H to compare strings. Returns Z if equal.
6121
RET Z C8
If filenames match (Z), return with Z flag set.
6122
Filenames don't match - jump to 63A0H to handle mismatch error.
6125H - PUT Statement Entry Point
This is the entry point for the PUT statement (PUT #n, record). It sets a flag byte indicating PUT mode (with bit 7 and bits 0-2,5 set via OR AFH), then shares common code with GET for parsing and executing the file record operation.
6125
OR AFH F6 AF
Set bits 7,5,3,2,1,0 in Register A. This creates a PUT mode flag (AFH = 10101111 binary). Bit 7 indicates PUT (vs GET), and other bits control write operations.
6127
PUSH AF F5
Save the PUT mode flag onto the stack for later use by the common handler.
6128
GOSUB to Parse File Number and Setup FCB. This parses the "#n" file number, validates the file is open, and copies the FCB to the work area at 5700H.
612B
GOSUB to Parse Optional Record Number. This checks for a comma followed by a record number and updates the file position.
612E
JUMP to SYS0 routine at 4D03H to execute the actual GET or PUT disk operation using the prepared FCB and position.
6131H - Parse Record Number with Comma
This routine expects a comma followed by a record number expression. It parses the record number and stores it in the FCB position fields. Called by both GET and PUT statements.
6131
LD A,2CH 3E 2C
Load Register A with 2CH (ASCII comma ,). This is the parameter for RST 28H SVC call.
6133
RST 28H EF
Call DOS Supervisor with function code 2CH. This validates the comma separator is present in the BASIC statement.
6134
GOSUB to Get Current File Position. Returns current position in HL (low word) and C (sector offset within record).
6137
LD (IX+04H),C DD 71 04
Store the sector offset (Register C) into FCB offset +04H. IX points to the FCB work area at 5700H.
613A
LD (5705H),HL 22 05 57
Store the position word (HL) into the file position storage at 5705H. This is part of the FCB work area.
613D
RET C9
Return to caller (either GET or PUT handler at 612BH).
613EH - Update Alternate File Position
Stores position information in the alternate position fields of the FCB and sets a flag indicating the alternate position is valid.
613E
LD (IX+07H),C DD 71 07
Store the sector offset (Register C) into FCB offset +07H (alternate position byte).
6141
LD (5708H),HL 22 08 57
Store the position word (HL) into the alternate position storage at 5708H.
6144
SET 6,(IX+01H) DD CB 01 F6
Set bit 6 of FCB byte +01H. This flag indicates the alternate position is valid.
6148
RET C9
Return to caller.
6149H - Get Primary File Position
Retrieves the primary file position from FCB offset +04H and memory location 5705H.
6149
LD C,(IX+04H) DD 4E 04
Load Register C with the sector offset from FCB byte +04H.
614C
LD HL,(5705H) 2A 05 57
Load Register Pair HL with the primary file position from 5705H.
614F
RET C9
Return with position in HL and sector offset in C.
6150H - Get Alternate File Position
Retrieves the alternate file position from FCB offset +07H and memory 5708H. Checks if alternate position is valid; if not, jumps to error.
6150
LD C,(IX+07H) DD 4E 07
Load Register C with the alternate sector offset from FCB byte +07H.
6153
LD HL,(5708H) 2A 08 57
Load Register Pair HL with the alternate file position from 5708H.
6156
BIT 6,(IX+01H) DD CB 01 76
Test bit 6 of FCB byte +01H. This checks if the alternate position is valid.
615A
RET NZ C0
If the NZ FLAG is set (bit 6 = 1, alternate position valid), return normally with position data.
615B
If alternate position is NOT valid, JUMP to 6182H which generates a Bad File Number error (5DD0H).
615DH - Record Length Validation
Validates that a requested byte count does not exceed the record length, adjusting if necessary. Also checks for position overflow.
615D
LD A,(5094H) 3A 94 50
Load Register A with the value at 5094H. This is the maximum bytes per record or similar limit.
6160
CP B B8
Compare Register A against Register B (requested byte count). Sets CARRY if A < B.
6161
If CARRY is set (max < requested), JUMP ahead to use the maximum value instead.
6163
LD A,B 78
Otherwise, use the requested count: Load A with B.
6164
LD B,A 47
Store the validated count back into Register B.
6165
ADD 80H C6 80
Add 80H (128) to Register A. This tests if the value exceeds 127 (sets CARRY if original A > 127).
6167
RET NC D0
If NO CARRY (value was ≤ 127), return normally - the value is acceptable.
6168
LD A,71H 3E 71
Load Register A with 71H. This is likely an SVC function code for a special operation.
616A
LD C,B 48
Copy Register B to Register C (save the byte count).
616B
LD B,00H 06 00
Clear Register B to zero (prepare for 16-bit operation).
616D
GOSUB to Position Bounds Check routine which validates the new position won't overflow.
6170
LD B,C 41
Restore Register B from C (the byte count).
6171
LD A,B 78
Copy B to A for return value.
6172
RET C9
Return with validated byte count in A and B.
6173H - File Status Check
Checks the file status flags at 5700H to determine if the file is in an error state or specific mode. Returns via error handler if invalid.
6173
LD DE,(5700H) ED 5B 00 57
Load Register Pair DE with the FCB status word from the work area at 5700H. E contains the primary status byte.
6177
LD A,E 7B
Copy the status byte (E) to Register A for bit testing.
6178
RLCA 07
Rotate A left. Bit 7 moves to bit 0 and to CARRY. Tests the error/open flag.
6179
If NO CARRY (bit 7 was 0, file not open/error), JUMP to error handler at 6182H.
617B
BIT 5,A CB 6F
Test bit 5 of A (which was originally bit 4 before rotation). This checks a specific mode flag.
617D
If bit 5 is set (NZ), skip the next rotate.
617F
RLCA 07
Rotate A left again, continuing to check status bits.
6180
RLCA 07
Rotate A left once more. Now testing different status bits.
6181
RET C D8
If CARRY is set (specific condition met), return to caller - file is in acceptable state.
6182
JUMP to error table entry 5DD0H which generates Bad File Number error (error code 6CH = 108).
6185H - File Buffer Operation Handler
Handles reading/writing data to/from the file buffer. Checks buffer flags and manages the dirty bit for write operations.
6185
GOSUB to Buffer Status Check routine. Returns CARRY and ZERO flags based on buffer state.
6188
RET C D8
If CARRY is set (buffer operation complete or error), return to caller.
6189
SET 4,(IX+2DH) DD CB 2D E6
Set bit 4 of FCB byte +2DH (offset 45). This sets the buffer dirty flag indicating data needs to be written.
618D
RET Z C8
If ZERO flag is set (specific condition from 605BH), return.
618E
LD A,(IX+00H) DD 7E 00
Load Register A with FCB byte +00H (the primary status flags).
6191
BIT 2,A CB 57
Test bit 2 of the status byte. This checks for random access mode.
6193
If ZERO (not random access), JUMP to error handler at 5E03H (likely Bad File Mode error).
6196
AND 03H E6 03
Mask to keep only bits 0 and 1 (read/write mode flags).
6198
RET Z C8
If both bits are zero (no read/write mode), return.
File is in random access mode with read or write enabled. Now handle the buffer operation.
6199
PUSH HL E5
Save Register Pair HL onto the stack.
619A
PUSH BC C5
Save Register Pair BC onto the stack.
619B
EX DE,HL EB
Exchange DE and HL. Move buffer address to HL.
619C
LD C,(IX+15H) DD 4E 15
Load Register C with FCB byte +15H (record position within sector).
619F
GOSUB to DOS File Position Update via SVC.
61A2
LD HL,(5702H) 2A 02 57
Load Register Pair HL with the record length from 5702H.
61A5
GOSUB to Multiple Record Handler to process HL records.
61A8
POP BC C1
Restore Register Pair BC from the stack.
61A9
POP HL E1
Restore Register Pair HL from the stack.
61AA
[LOOP] JUMP back to 6185H to continue processing until buffer operation is complete.
61ACH - Record Count Loop
Decrements the record count in HL and loops until zero. Used for processing multiple records.
61AC
LD A,H 7C
Load Register A with H (high byte of record count).
61AD
OR L B5
OR with L. Sets ZERO flag if HL = 0000H (no more records to process).
61AE
RET Z C8
If ZERO (HL = 0, all records processed), return to caller.
61AF
XOR A AF
Clear Register A to zero.
61B0
LD B,A 47
Clear Register B to zero.
61B1
GOSUB to Process Single Record handler.
61B4
DEC HL 2B
DECrement HL (record counter).
61B5
[LOOP] JUMP back to 61ACH to check if more records remain.
61B7H - String Expression for File Operation
Evaluates a string expression and retrieves the string descriptor for file I/O operations.
61B7
GOSUB to ROM routine at 2337H to parse a string expression. Returns string descriptor pointer.
61BA
EX (SP),HL E3
Exchange HL with top of stack. Saves current pointer, retrieves previous value.
61BB
PUSH HL E5
Push the retrieved value back onto the stack.
61BC
RST 20H E7
Call RST 20H (GETYPR) - get the type of the last expression. Sets flags based on type.
61BD
RET NZ C0
If NZ (not a string type), return - let caller handle the error.
61BE
PUSH AF F5
Save the flags onto the stack.
61BF
GOSUB to ROM routine at 29D7H to free temporary string and get the string descriptor.
61C2
POP AF F1
Restore the flags from the stack.
61C3
LD B,(HL) 46
Load Register B with the string length (first byte of descriptor).
61C4
INC HL 23
Advance HL to point to string address low byte.
61C5
LD C,(HL) 4E
Load Register C with string address low byte.
61C6
INC HL 23
Advance HL to string address high byte.
61C7
LD H,(HL) 66
Load Register H with string address high byte.
61C8
LD L,C 69
Load Register L with C (low byte). Now HL points to the actual string data.
61C9
RET C9
Return with B=length, HL=string address.
61CAH - Get Primary Position and Update
Retrieves the primary file position and calls the DOS position update routine.
61CA
GOSUB to Get Primary File Position. Returns position in HL and sector offset in C.
61CD
LD DE,444EH 11 4E 44
Load Register Pair DE with 444EH. This is a DOS SVC parameter for file position operations.
61D0
JUMP to common SVC caller at 6245H to execute the DOS operation.
61D3H - Get Current File Position
Returns the current file position from the FCB work area.
61D3
LD C,(IX+12H) DD 4E 12
Load Register C with FCB byte +12H (current sector position).
61D6
LD HL,(5717H) 2A 17 57
Load Register Pair HL with the current position word from 5717H.
61D9
RET C9
Return with position in HL and sector offset in C.
61DAH - Get Alternate Position Data
Retrieves the alternate file status and position from the FCB work area at 5715H and 5719H.
61DA
LD A,(5715H) 3A 15 57
Load Register A with the alternate status byte from 5715H in the FCB work area.
61DD
LD HL,(5719H) 2A 19 57
Load Register Pair HL with the alternate position word from 5719H.
61E0
RET C9
Return with alternate status in A and position in HL.
61E1H - Get Both Position Values
Retrieves both the current position and alternate position, returning them for comparison or calculation.
61E1
GOSUB to Get Current File Position. Returns current position in HL and sector offset in C.
61E4
EX DE,HL EB
Exchange DE and HL. Move current position to DE.
61E5
GOSUB to Get Alternate Position Data. Returns alternate position in HL and status in A.
61E8
EX DE,HL EB
Exchange DE and HL again. Now HL has current position, DE has alternate position.
61E9
RET C9
Return with current position in HL, alternate in DE, alternate status in A, sector offset in C.
61EAH - SVC Call with Offset 13H
Sets up an SVC call with DE=0013H and jumps to the common handler.
61EA
LD DE,0013H 11 13 00
Load Register Pair DE with 0013H. This is an SVC parameter offset for a specific DOS operation.
61ED
JUMP to common SVC caller at 6245H.
61EFH - Position Bounds Check
Validates that a file position calculation won't overflow. If adding the increment (in BC) to the current position would overflow, generates an error. Also stores the calculated position for later use.
61EF
PUSH HL E5
Save Register Pair HL onto the stack.
61F0
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H. This is the maximum position value (will be subtracted from).
61F3
LD E,B 58
Copy Register B to E (increment high byte).
61F4
LD D,00H 16 00
Clear D to zero (making DE a 16-bit value with B as high byte? Or preparing for calculation).
61F6
INC DE 13
INCrement DE by 1.
61F7
OR A B7
Clear CARRY flag (prepare for subtraction).
61F8
SBC HL,DE ED 52
Subtract DE from HL with borrow. HL = 0000H - (B+1). This calculates the negative of the increment.
61FA
If CARRY is set (underflow), JUMP to error handler at 5DE5H (EOF error, error code 8EH = 142).
61FD
LD (61F1H),HL 22 F1 61
[SELF-MODIFYING] Store HL into 61F1H. This modifies the "LD HL,0000H" instruction at 61F0H to hold the calculated bounds value!
6200
POP HL E1
Restore Register Pair HL from the stack.
6201
BIT 2,(IX+2DH) DD CB 2D 56
Test bit 2 of FCB byte +2DH. This checks if a specific buffer mode flag is set.
6205
RET NZ C0
If bit 2 is set (NZ), return - buffer is in special mode.
6206H - Process Single Record
Core routine for processing a single record. Handles position validation, buffer management, and DOS calls for reading or writing data.
6206
PUSH HL E5
Save Register Pair HL (data address) onto the stack.
6207
PUSH AF F5
Save Register A and flags onto the stack.
6208
GOSUB to Get Both Positions routine which retrieves current and alternate file positions.
620B
NOP 00
No operation (padding or placeholder for patch).
620C
SUB (IX+15H) DD 96 15
Subtract FCB byte +15H (record position within sector) from Register A.
620F
SBC HL,DE ED 52
Subtract DE from HL with borrow. Calculates position difference.
6211
If NO CARRY (position is valid/forward), JUMP to 621BH to continue.
Position calculation resulted in underflow - adjust and check for EOF.
6213
ADD A,B 80
Add Register B to A (add back the record size).
6214
LD DE,0000H 11 00 00
Load DE with 0000H.
6217
ADC HL,DE ED 5A
Add DE to HL with carry. This adjusts HL based on the carry from the previous calculation.
6219
If NO CARRY after adjustment, JUMP to 6222H.
621B
BIT 7,(IX+01H) DD CB 01 7E
Test bit 7 of FCB byte +01H. This checks the EOF flag.
621F
If bit 7 is clear (ZERO, EOF reached), JUMP to error handler at 5DE8H (Error 90H - Bad File Name or similar).
6222
POP AF F1
Restore Register A and flags from the stack.
6223
POP HL E1
Restore Register Pair HL (data address) from the stack.
6224
GOSUB to SVC Call with 001BH - execute the DOS record operation.
6227
LD A,B 78
Copy Register B (byte count) to A.
6228
OR A B7
OR A with itself. Sets ZERO flag if B was zero (no bytes transferred).
6229
RET Z C8
If ZERO (no bytes to transfer), return.
622A
JUMP to 6231H to check buffer flags and possibly loop.
622CH - SVC Call with Offset 1BH
Sets up an SVC call with DE=001BH for record-level file operations.
622C
LD DE,001BH 11 1B 00
Load Register Pair DE with 001BH. This is an SVC parameter for record read/write operations.
622F
JUMP to common SVC caller at 6245H.
6231H - Buffer Check After Record Operation
After a record operation, checks buffer flags to determine if more processing is needed.
6231
BIT 2,(IX+2DH) DD CB 2D 56
Test bit 2 of FCB byte +2DH. Checks if the buffer operation flag is set.
6235
RET NZ C0
If bit 2 is set (NZ), return - operation complete.
6236
LD DE,443CH 11 3C 44
Load DE with 443CH - another SVC parameter.
6239
JUMP to 623EH to set flag and execute SVC.
623BH - Alternative SVC Entry with 4436H
Entry point for SVC calls using parameter 4436H.
623B
LD DE,4436H 11 36 44
Load DE with 4436H - SVC parameter for specific DOS operation.
623E
SET 7,(IX+0EH) DD CB 0E FE
Set bit 7 of FCB byte +0EH. This sets a status flag before the DOS call.
6242
LD (5716H),A 32 16 57
Store Register A into 5716H in the FCB work area.
6245
GOSUB to Push DE and Set Filename Pointer.
6248
If NZ (error occurred), GOSUB to DOS to BASIC Error Translator to convert and report the error.
624B
PUSH AF F5
Save the result flags onto the stack.
624C
LD A,00H 3E 00
Load Register A with 00H. Note: This location (624DH) is modified by code at 6459H to enable/disable position updates.
624E
OR A B7
OR A with itself. Sets ZERO flag if A = 00H.
624F
If NZ (A was non-zero), GOSUB to Parse Record Number to update the file position.
6252
POP AF F1
Restore the flags from the stack.
6253
RET C9
Return to caller.
6254H - Setup Filename Pointer for SVC
Pushes DE (SVC parameter) and sets DE to point to the filename buffer at 570DH for DOS calls.
6254
PUSH DE D5
Push DE (the SVC parameter) onto the stack. It will be popped by the SVC handler.
6255
LD DE,570DH 11 0D 57
Load DE with 570DH - the filename buffer address in the FCB work area.
6258
RET C9
Return. The SVC parameter is now on the stack, and DE points to the filename.
6259H - SVC Call with 4436H and Clear Flag
Entry point for SVC calls using parameter 4436H that clears bit 7 of FCB byte +0EH.
6259
LD DE,4436H 11 36 44
Load DE with 4436H - SVC parameter.
625C
JUMP to 6261H to clear flag and execute.
625EH - SVC Call with 443CH and Clear Flag
Entry point for SVC calls using parameter 443CH that clears bit 7.
625E
LD DE,443CH 11 3C 44
Load DE with 443CH - SVC parameter.
6261
RES 7,(IX+0EH) DD CB 0E BE
Clear (reset) bit 7 of FCB byte +0EH. This clears the status flag before the DOS call.
6265
JUMP to common SVC caller at 6245H.
6267H - SVC Call with 443FH
Entry point for SVC calls using parameter 443FH.
6267
LD DE,443FH 11 3F 44
Load DE with 443FH - SVC parameter for another DOS operation.
626A
JUMP to common SVC caller at 6245H.
626CH - Add Bytes to Current Position
Adds a byte count (in B) to the current file position. Checks for overflow and updates the position through a DOS call. Used for sequential file operations.
626C
LD A,B 78
Load Register A with the byte count from Register B.
626D
GOSUB to Get Current File Position. Returns position word in HL and sector offset in C.
6270
ADD A,C 81
Add sector offset (C) to byte count (A). This calculates new position within sector.
6271
LD C,A 4F
Store the result back into C.
6272
LD DE,0000H 11 00 00
Load DE with 0000H (zero for carry propagation).
6275
ADC HL,DE ED 5A
Add DE (0) to HL with carry. If adding A+C caused a carry, this increments HL (the position word).
6277
If NO CARRY (no overflow), JUMP to 61CDH to update the position through the DOS call.
Position overflow occurred - generate an error.
627A
LD A,1DH 3E 1D
Load Register A with DOS error code 1DH (29 decimal) - Position past EOF.
627C
JUMP to DOS to BASIC Error Translator to convert and report the error.
627FH - File Buffer Management
Manages file buffer operations by calculating position from L and C registers, calling the buffer routine, and handling the result.
627F
PUSH HL E5
Save Register Pair HL onto the stack.
6280
PUSH BC C5
Save Register Pair BC onto the stack.
6281
LD H,L 65
Copy L to H.
6282
LD L,C 69
Copy C to L. Now HL contains (original L, C) as a position value.
6283
GOSUB to Calculate Buffer Offset from the position in HL.
6286
GOSUB to Buffer Status Check routine.
6289
LD A,B 78
Copy the result status (B) to A.
628A
POP BC C1
Restore Register Pair BC from the stack.
628B
POP HL E1
Restore Register Pair HL from the stack.
628C
RET C D8
If CARRY is set (error or special condition), return to caller.
628D
If NZ (additional processing needed), GOSUB to the position update routine at 626DH.
6290
OR FFH F6 FF
OR A with FFH. Sets A to FFH and clears ZERO flag (indicates success).
6292
RET C9
Return with A=FFH indicating operation complete.
6293H - Buffer Status Check
Checks the buffer status after a DOS operation and returns appropriate flags and values.
6293
GOSUB to SVC Call with Offset 13H to get buffer status from DOS.
6296
OR A B7
OR A with itself. Sets ZERO flag if A = 0.
6297
RET Z C8
If ZERO (A = 0, operation complete), return.
6298
ADD 80H C6 80
Add 80H (128) to A. This tests if A was in the range 80H-FFH (sets CARRY if A was >= 80H before).
629A
If CARRY (A was >= 80H), JUMP to 62B7H to handle that case.
629C
ADD 10H C6 10
Add 10H (16) to A. Continues decoding the status value.
629E
RET Z C8
If result is zero (original was 70H), return.
629F
DEC A 3D
DECrement A by 1.
62A0
If ZERO (original was 71H), JUMP to 62B4H.
62A2
LD B,02H 06 02
Load B with 02H (status code for this case).
62A5
If ZERO (original was 72H), JUMP to 62B2H.
62A7
LD B,04H 06 04
Load B with 04H.
62AA
If ZERO (original was 73H), JUMP to 62B2H.
62AC
LD B,08H 06 08
Load B with 08H.
62AF
If NZ (unknown status code), JUMP to error table at 5DC4H (FIELD Overflow error).
62B2
OR B B0
OR A with B. Sets flags and combines status.
62B3
RET C9
Return with combined status in A.
62B4
GOSUB to SVC Call with Offset 13H again.
62B7
LD B,A 47
Copy A to B (save the status).
62B8
LD A,03H 3E 03
Load A with 03H (return code).
62BA
OR A B7
OR A with itself (sets flags, clears ZERO since A=03H).
62BB
RET C9
Return with A=03H and original status in B.
62BCH - Parse File Number and Setup FCB
This is a key routine called by GET, PUT, and other file operations. It parses the "#n" file number from the BASIC statement, validates that the file is open, and copies the FCB to the work area at 5700H. Also sets a guard flag to prevent re-entry.
62BC
GOSUB to Parse File Number. Parses "#n" syntax, validates file number, returns file number in A and FCB address in BC.
62BF
LD A,(63A9H) 3A A9 63
Load Register A with the re-entry guard flag at 63A9H. This prevents recursive FCB operations.
62C2
OR A B7
OR A with itself. Sets ZERO flag if the guard is clear (00H).
62C3
If NZ (guard already set, re-entry attempt), JUMP to error handler at 5E00H.
62C6
PUSH HL E5
Save Register Pair HL (BASIC text pointer) onto the stack.
62C7
LD H,B 60
Copy B (FCB address high) to H.
62C8
LD L,C 69
Copy C (FCB address low) to L. Now HL = FCB address.
62C9
LD (6379H),HL 22 79 63
Store the FCB address into 6379H for later reference by cleanup routines.
62CC
GOSUB to Set Guard Flag at 63ADH. This sets the re-entry guard to C9H (RET opcode).
62CF
LD DE,5700H 11 00 57
Load DE with 5700H - the FCB work area destination address.
62D2
PUSH DE D5
Push the work area address onto the stack.
62D3
POP IX DD E1
Pop into IX. Now IX points to the FCB work area at 5700H.
62D5
LD (IX+2DH),00H DD 36 2D 00
Store 00H into offset +2DH (byte 45) of the work area. This clears the buffer flags.
62D9
LD BC,002DH 01 2D 00
Load BC with 002DH (45 bytes) - the number of bytes to copy from the FCB.
62DC
LDIR ED B0
Block copy BC bytes from (HL) to (DE). Copies the FCB data to the work area.
62DE
POP HL E1
Restore Register Pair HL (BASIC text pointer) from the stack.
62DF
LD A,(5700H) 3A 00 57
Load A with the first byte of the copied FCB (file status).
62E2
OR A B7
OR A with itself. Sets ZERO flag if status is 00H (file not open).
62E3
RET C9
Return with ZERO flag indicating if file is open (NZ) or not (Z).
62E4H - Push HL and Setup FCB
Alternate entry point that saves HL before setting up the FCB work area.
62E4
PUSH HL E5
Save Register Pair HL onto the stack.
62E5
JUMP to 62CFH to set up the FCB work area (skipping the file number parsing).
62E7H - Parse File Number with Required Comma
Parses a file number preceded by a comma. Uses RST 08H to require the comma.
62E7
GOSUB to Parse File Number and Setup FCB.
62EA
RST 08H CF
Call SYNCHR - require the next character to match.
62EB
2CH 2C
Parameter: 2CH (ASCII comma ,).
62EC
JUMP to 62DFH to load file status and return.
62EEH - Check Buffer Position Valid
Tests bit 6 of FCB byte +2DH for buffer position validity.
62EE
BIT 6,(IX+2DH) DD CB 2D 76
Test bit 6 of FCB byte +2DH - buffer position valid flag.
62F2
RET Z C8
If ZERO (not valid), return.
62F3
JUMP to error handler at 62FCH.
62F5
EX DE,HL EB
Exchange DE and HL.
62F6
INC DE 13
INCrement DE.
62F7
BIT 6,(IX+2DH) DD CB 2D 76
Test bit 6 of FCB byte +2DH.
62FB
RET NZ C0
If NZ (valid), return.
62FC
JUMP to error handler.
62FFH - Check Write Mode and Variable
Checks write mode flag and handles variable or file reference.
62FF
BIT 1,(IX+00H) DD CB 00 4E
Test bit 1 of FCB byte +00H - write mode flag.
6303
RET Z C8
If ZERO (not write mode), return.
6304
LD A,(5094H) 3A 94 50
Load A with buffer limit from 5094H.
6307
LD C,A 4F
Copy A to C.
6308
LD A,(HL) 7E
Load A with byte at (HL).
6309
CP 23H FE 23
Compare against 23H (ASCII #).
630B
If match, JUMP to 62F5H.
630D
CP 24H FE 24
Compare against 24H (ASCII $).
630F
If match, JUMP to 62F5H.
6312
GOSUB to ROM to parse variable.
6316
EX DE,HL EB
Exchange DE and HL.
6317
LD B,(HL) 46
Load B with byte at (HL).
6318
RST 20H E7
Call GETYPR - get expression type.
6319
If NZ, JUMP to 6322H.
631B
BIT 6,(IX+2DH) DD CB 2D 76
Test bit 6 of FCB byte +2DH.
631F
If ZERO, JUMP to error.
6323
LD A,00H 3E 00
Load A with 00H.
6326H - File Status Validation
Validates file status flags at 5700H for specific operations.
6326
LD A,(5700H) 3A 00 57
Load A with FCB status byte from 5700H.
6329
BIT 4,A CB 67
Test bit 4 of status.
632B
RET Z C8
If ZERO (bit 4 clear), return.
632C
BIT 3,A CB 5F
Test bit 3.
632E
RET Z C8
If ZERO, return.
632F
LD B,(IX+2DH) DD 46 2D
Load B with FCB byte +2DH.
6332
BIT 1,A CB 4F
Test bit 1 (write mode).
6334
If NZ, JUMP to 634FH.
6336
BIT 0,A CB 47
Test bit 0 (read mode).
6338
RET Z C8
If ZERO, return.
6339
BIT 2,A CB 57
Test bit 2 (random access).
633B
If NZ, JUMP to 6352H.
633D
BIT 4,B CB 60
Test bit 4 of B (from +2DH).
633F
RET NZ C0
If NZ, return.
6340
BIT 3,B CB 58
Test bit 3 of B.
6342
If ZERO, JUMP to 6352H.
6344
GOSUB to Get Both Position Values.
6347
SUB C 91
Subtract C from A.
6348
EX DE,HL EB
Exchange DE and HL.
6349
SBC HL,DE ED 52
Subtract DE from HL with borrow.
634B
LD H,L 65
Copy L to H.
634C
LD L,A 6F
Copy A to L.
634F
BIT 4,B CB 60
Test bit 4 of B.
6351
RET Z C8
If ZERO, return.
6352
LD HL,(61F1H) 2A F1 61
Load HL from self-modifying location 61F1H.
6355
JUMP to record count loop.
6358H - Position Comparison
Compares file positions from 5704H and 5707H.
6358
LD HL,(5704H) 2A 04 57
Load HL with position word from 5704H.
635B
LD DE,(5707H) ED 5B 07 57
Load DE with position word from 5707H.
635F
OR A B7
Clear CARRY flag.
6360
SBC HL,DE ED 52
Subtract DE from HL.
6362
EX DE,HL EB
Exchange DE and HL.
6363
LD HL,(5702H) 2A 02 57
Load HL with record length from 5702H.
6367
SBC HL,DE ED 52
Subtract DE from HL.
6369
RET NC D0
If NO CARRY, return (OK).
636A
JUMP to EOF error handler.
636DH - Position from Current
Gets current position and calculates buffer offset.
636D
GOSUB to Get Current File Position.
6370
LD H,L 65
Copy L to H.
6371
LD L,C 69
Copy C to L.
6372
JUMP to 635BH for comparison.
6374H - Setup Work Area Pointer
Saves HL and points HL to FCB work area at 5700H, DE to 0.
6375
LD HL,5700H 21 00 57
Point HL to FCB work area.
6378
LD DE,0000H 11 00 00
Load DE with 0.
637B
JUMP to LDIR copy routine.
637EH - Return Handler for File Functions
Common return point for LOC/LOF/EOF functions. Cleans up FCB and resets guard flag.
637E
GOSUB to setup work area pointer.
6381
GOSUB to Clear Guard Flag.
6384
LD HL,5700H 21 00 57
Point HL to FCB work area.
6387
LD B,2EH 06 2E
Load B with 2EH (46 bytes to clear).
6389
LD (HL),00H 36 00
[LOOP] Clear byte at (HL).
638C
DECrement B and loop until zero.
638FH - Check for Comma or End
Decrements HL, gets next character, checks for comma or end of statement.
638F
DEC HL 2B
DECrement HL.
6390
RST 10H D7
CHRGET - get next character.
6391
RET Z C8
If end of statement, return.
6394
CP FFH FE FF
Compare against FFH.
6397H - DOS File Open Call
Calls DOS to open a file using the filename at 570DH.
6397
LD DE,570DH 11 0D 57
Point DE to filename buffer.
639A
GOSUB to DOS file open routine.
639D
RET Z C8
If ZERO (success), return.
639E
CP 1DH FE 1D
Compare error against 1DH (EOF).
63A0
If EOF, JUMP to 63A7H.
63A2
CP 1CH FE 1C
Compare against 1CH (also EOF).
63A4
If NZ (other error), JUMP to error translator.
63A7
OR A B7
Set flags based on A.
63A9H - Guard Flag and FCB Cleanup
Contains the re-entry guard flag at 63A9H and routines to set/clear it. The guard prevents recursive FCB operations. When set to C9H (RET opcode), calls to this address return immediately.
63A9
NOP 00
Guard Flag Location: When cleared (00H), allows entry. When set to C9H, acts as RET instruction.
63AA
INC SP 33
INCrement Stack Pointer (part of return sequence).
63AB
INC SP 33
INCrement Stack Pointer again (discards return address).
63ADH - Set Guard Flag
Sets the guard flag at 63A9H to C9H (RET opcode), preventing re-entry into FCB operations.
63AD
LD A,C9H 3E C9
Load A with C9H (RET opcode).
63AF
LD (63A9H),A 32 A9 63
[SELF-MODIFYING] Store C9H into 63A9H. This makes a call to 63A9H return immediately.
63B3H - Copy Guard to Another Location
Copies the guard flag from 63A9H to 63BDH, then clears it.
63B3
LD A,(63A9H) 3A A9 63
Load A with guard flag value.
63B6
LD (63BDH),A 32 BD 63
Store into 63BDH (backup location).
63B9
XOR A AF
Clear A to zero.
63BA
JUMP to 63AFH to store 00H into guard flag (clears it).
63BCH - Clear Guard with Default
Clears the guard flag using a default value of 00H.
63BC
LD A,00H 3E 00
Load A with 00H. Note: Location 63BDH may be modified by 63B6H.
63BE
JUMP to 63AFH to store A into guard flag.
63C0H - PRINT# Output Handler
Handles output for PRINT# statement. Checks for end of buffer, compares current position against buffer limits, and handles file writes.
63C0
POP AF F1
Pop AF from stack (return address cleanup).
63C1
EX (SP),HL E3
Exchange HL with top of stack.
63C3
LD DE,1D9EH 11 9E 1D
Load DE with 1D9EH - a ROM comparison address.
63C6
RST 18H DF
CPDEHL - compare DE with HL.
63C7
If NZ (not equal), JUMP to 63CDH.
63CA
EX (SP),HL E3
Exchange HL with stack.
63CD
LD DE,1D21H 11 21 1D
Load DE with 1D21H - another ROM address.
63D2
EX (SP),HL E3
Exchange HL with stack.
63D3
If NZ, JUMP to ROM syntax error at 035BH.
63D6
GOSUB to set print width.
63D9
LD A,(HL) 7E
Load A with byte at (HL).
63DA
OR A B7
Set flags based on A.
63DDH - Line Number Display
Displays a BASIC line number during execution. Used for error reporting and debugging.
63E0
INC HL 23
Advance HL past link pointer low byte.
63E1
LD A,(HL) 7E
Load A with link pointer high byte.
63E3
OR (HL) B6
OR with next byte. Tests if link is zero (end of program).
63E4
If ZERO (end of program), JUMP to 641CH.
63E6
INC HL 23
Advance to line number low byte.
63E7
LD E,(HL) 5E
Load E with line number low.
63E8
INC HL 23
Advance to line number high.
63E9
LD D,(HL) 56
Load D with line number high. DE = line number.
63EA
LD HL,0000H 21 00 00
Load HL with 0000H. Note: 63EBH may be modified.
63ED
LD A,H 7C
Copy H to A.
63EE
OR L B5
OR with L. Test if HL is zero.
63EF
If ZERO, JUMP to 63F6H.
63F2
SBC HL,DE ED 52
Subtract DE from HL.
63F4
If NZ (not equal), JUMP to 641CH.
63F6
LD (63EBH),HL 22 EB 63
[SELF-MODIFYING] Store HL into 63EBH (modifies the LD HL,0000H instruction).
63F9
LD BC,3C39H 01 39 3C
Load BC with 3C39H - video RAM address for line number display.
63FC
LD A,40H 3E 40
Load A with 40H (@ symbol or display character).
63FE
LD (BC),A 02
Store to video RAM.
6400
INC BC 03
Advance video position.
6401
GOSUB to Number to String Conversion.
6404
GOSUB to display routine.
6407
GOSUB to ROM keyboard scan.
640A
CP 01H FE 01
Compare against 01H (break key?).
640C
If match, JUMP to 6412H.
640E
SUB 0DH D6 0D
Subtract 0DH (ENTER key).
6410
[LOOP] If NZ, loop back waiting for ENTER.
6413
PUSH AF F5
Save flags.
6414
GOSUB to display routine (clear the display area).
6417
POP AF F1
Restore flags.
641C
POP BC C1
Restore BC (early exit path).
6420
OR 00H F6 00
OR with 00H. Note: 6421H may be modified.
6422
If NZ (modified to non-zero), JUMP to 642CH.
6424
LD A,(4369H) 3A 69 43
Load A with system flag from 4369H.
6427
AND 20HAND 00100000 E6 20
Mask bit 5.
6429
If ZERO, JUMP to ROM syntax error.
642EH - Clear Display Line
Clears a portion of the video display by writing spaces.
642E
LD A,20H 3E 20
Load A with 20H (ASCII space).
6430
LD (BC),A 02
Store space to video RAM.
6431
INC BC 03
Advance video position.
6432
LD A,C 79
Copy C to A.
6433
AND 3FHAND 00111111 E6 3F
Mask to column position (0-63).
6435
[LOOP] If not at column 0, continue clearing.
6437
RET C9
Return when line is clear.
63A9H - Guard Flag and FCB Cleanup
Contains the re-entry guard flag at 63A9H and routines to set/clear it. The guard prevents recursive FCB operations. When set to C9H (RET opcode), calls to this address return immediately.
63A9
NOP 00
Guard Flag Location: When cleared (00H), allows entry. When set to C9H, acts as RET instruction.
63AA
INC SP 33
INCrement Stack Pointer (part of return sequence).
63AB
INC SP 33
INCrement Stack Pointer again (discards return address).
63ADH - Set Guard Flag
Sets the guard flag at 63A9H to C9H (RET opcode), preventing re-entry into FCB operations.
63AD
LD A,C9H 3E C9
Load A with C9H (RET opcode).
63AF
LD (63A9H),A 32 A9 63
[SELF-MODIFYING] Store C9H into 63A9H. This makes a call to 63A9H return immediately.
63B3H - Copy Guard to Another Location
Copies the guard flag from 63A9H to 63BDH, then clears it.
63B3
LD A,(63A9H) 3A A9 63
Load A with guard flag value.
63B6
LD (63BDH),A 32 BD 63
Store into 63BDH (backup location).
63B9
XOR A AF
Clear A to zero.
63BA
JUMP to 63AFH to store 00H into guard flag (clears it).
63BCH - Clear Guard with Default
Clears the guard flag using a default value of 00H.
63BC
LD A,00H 3E 00
Load A with 00H. Note: Location 63BDH may be modified by 63B6H.
63BE
JUMP to 63AFH to store A into guard flag.
63C0H - PRINT# Output Handler
Handles output for PRINT# statement. Checks for end of buffer, compares current position against buffer limits, and handles file writes.
63C0
POP AF F1
Pop AF from stack (return address cleanup).
63C1
EX (SP),HL E3
Exchange HL with top of stack.
63C3
LD DE,1D9EH 11 9E 1D
Load DE with 1D9EH - a ROM comparison address.
63C6
RST 18H DF
CPDEHL - compare DE with HL.
63C7
If NZ (not equal), JUMP to 63CDH.
63CA
EX (SP),HL E3
Exchange HL with stack.
63CD
LD DE,1D21H 11 21 1D
Load DE with 1D21H - another ROM address.
63D2
EX (SP),HL E3
Exchange HL with stack.
63D3
If NZ, JUMP to ROM syntax error at 035BH.
63D6
GOSUB to set print width.
63D9
LD A,(HL) 7E
Load A with byte at (HL).
63DA
OR A B7
Set flags based on A.
63DDH - Line Number Display
Displays a BASIC line number during execution. Used for error reporting and debugging.
63E0
INC HL 23
Advance HL past link pointer low byte.
63E1
LD A,(HL) 7E
Load A with link pointer high byte.
63E3
OR (HL) B6
OR with next byte. Tests if link is zero (end of program).
63E4
If ZERO (end of program), JUMP to 641CH.
63E6
INC HL 23
Advance to line number low byte.
63E7
LD E,(HL) 5E
Load E with line number low.
63E8
INC HL 23
Advance to line number high.
63E9
LD D,(HL) 56
Load D with line number high. DE = line number.
63EA
LD HL,0000H 21 00 00
Load HL with 0000H. Note: 63EBH may be modified.
63ED
LD A,H 7C
Copy H to A.
63EE
OR L B5
OR with L. Test if HL is zero.
63EF
If ZERO, JUMP to 63F6H.
63F2
SBC HL,DE ED 52
Subtract DE from HL.
63F4
If NZ (not equal), JUMP to 641CH.
63F6
LD (63EBH),HL 22 EB 63
[SELF-MODIFYING] Store HL into 63EBH (modifies the LD HL,0000H instruction).
63F9
LD BC,3C39H 01 39 3C
Load BC with 3C39H - video RAM address for line number display.
63FC
LD A,40H 3E 40
Load A with 40H (@ symbol or display character).
63FE
LD (BC),A 02
Store to video RAM.
6400
INC BC 03
Advance video position.
6401
GOSUB to Number to String Conversion.
6404
GOSUB to display routine.
6407
GOSUB to ROM keyboard scan.
640A
CP 01H FE 01
Compare against 01H (break key?).
640C
If match, JUMP to 6412H.
640E
SUB 0DH D6 0D
Subtract 0DH (ENTER key).
6410
[LOOP] If NZ, loop back waiting for ENTER.
6413
PUSH AF F5
Save flags.
6414
GOSUB to display routine (clear the display area).
6417
POP AF F1
Restore flags.
641C
POP BC C1
Restore BC (early exit path).
6420
OR 00H F6 00
OR with 00H. Note: 6421H may be modified.
6422
If NZ (modified to non-zero), JUMP to 642CH.
6424
LD A,(4369H) 3A 69 43
Load A with system flag from 4369H.
6427
AND 20HAND 00100000 E6 20
Mask bit 5.
6429
If ZERO, JUMP to ROM syntax error.
642EH - Clear Display Line
Clears a portion of the video display by writing spaces.
642E
LD A,20H 3E 20
Load A with 20H (ASCII space).
6430
LD (BC),A 02
Store space to video RAM.
6431
INC BC 03
Advance video position.
6432
LD A,C 79
Copy C to A.
6433
AND 3FHAND 00111111 E6 3F
Mask to column position (0-63).
6435
[LOOP] If not at column 0, continue clearing.
6437
RET C9
Return when line is clear.
6438H - Set Default Print Width (32)
Sets the printer tab/zone width to 32 (20H) for normal formatting.
6438
LD A,20H 3E 20
Load A with 20H (32 decimal) - default print width.
643A
JUMP to 6447H to store the width.
643CH - File OPEN with Width Setup
Opens a file and sets up print width handling.
643C
GOSUB to File OPEN routine.
643F
GOSUB to SYS0 routine for file setup.
6442
If NZ (error), JUMP to error translator.
6445
LD A,18H 3E 18
Load A with 18H (24 decimal) - compact print width.
6447
LD (6482H),A 32 82 64
[SELF-MODIFYING] Store width into 6482H (modifies instruction at 6481H).
644AH - File Cleanup and Guard Reset
Main cleanup routine called when BASIC file operations complete. Saves registers, processes pending file operations, clears buffers, and resets the guard flag.
644D
GOSUB to return routine (just a RET initially, but location may be modified).
6451
LD (65C9H),A 32 C9 65
Clear byte at 65C9H.
6454
LD (624DH),A 32 4D 62
[SELF-MODIFYING] Clear 624DH (disables position update in SVC handler).
6457
LD (5D6CH),A 32 6C 5D
Clear byte at 5D6CH.
645A
INC A 3C
Increment A to 01H.
645B
LD (40A9H),A 32 A9 40
Store 01H into 40A9H (BASIC system flag).
645E
LD HL,4369H 21 69 43
Point HL to system flags at 4369H.
6461
RES 6,(HL) CB B6
Clear bit 6 of system flags (output not in progress).
6463
LD A,(63A9H) 3A A9 63
Load A with guard flag.
6466
OR A B7
Test if guard is set.
6467
If ZERO (guard clear), JUMP to cleanup exit at 64B9H.
Guard was set - need to clean up the pending FCB operation.
6469
LD HL,572DH 21 2D 57
Point HL to FCB status area at 572DH.
646C
BIT 7,(HL) CB 7E
Test bit 7 (file open/error flag).
646E
If ZERO (not set), JUMP to 647AH.
6470
GOSUB to file buffer flush routine.
6473
LD HL,5FCFH 21 CF 5F
Point HL to 5FCFH.
6476
LD (HL),C8H 36 C8
Store C8H (RET Z opcode) - modifies code for conditional return.
6478
JUMP to final cleanup at 64B6H.
647B
LD HL,19B4H 21 B4 19
Load HL with 19B4H - ROM address comparison value.
647F
SBC HL,BC ED 42
Subtract BC from HL.
6481
PUSH BC C5
Re-save BC.
6482
JR NZ,64B3H 20 2F
If NZ (BC was not 19B4H), JUMP to 64B3H. Note: 6482H byte may be modified.
BC was 19B4H - special handling for BASIC line execution.
6484
LD HL,(6379H) 2A 79 63
Load HL with stored FCB address from 6379H.
6487
LD A,(HL) 7E
Load A with first byte of FCB.
6488
OR A B7
Test if FCB is active.
6489
If ZERO (not active), JUMP to cleanup.
648B
PUSH HL E5
Save FCB pointer.
648C
GOSUB to Get Current File Position.
648F
EX (SP),HL E3
Exchange position with FCB pointer on stack.
6490
LD A,(570EH) 3A 0E 57
Load A with FCB byte at 570EH.
6494
GOSUB to Push HL and Setup FCB.
6497
LD (HL),00H 36 00
Clear the byte at (HL).
6499
POP BC C1
Restore BC (was AF - so B has the FCB byte).
649A
POP DE D1
Restore DE (the position).
649B
LD C,(IX+0EH) DD 4E 0E
Load C with FCB byte +0EH.
649E
LD HL,(5717H) 2A 17 57
Load HL with current position from 5717H.
64A1
RST 18H DF
CPDEHL - compare positions.
64A2
If NZ (positions differ), JUMP to 64ACH.
64A4
BIT 4,C CB 61
Test bit 4 of C.
64A6
If ZERO, JUMP to 64ACH.
64A8
BIT 4,B CB 60
Test bit 4 of B.
64AA
JR NZ,64ACH 20 00
If NZ, JUMP to 64ACH (redundant jump).
64AC
RES 4,C CB A1
Clear bit 4 of C.
64AE
SET 5,C CB E9
Set bit 5 of C.
64B0
LD (IX+0EH),C DD 71 0E
Store modified C back to FCB byte +0EH.
64B3
GOSUB to Setup Work Area Pointer.
64B6
GOSUB to clear guard and reset FCB work area.
64BEH - Store Return Address
Stores the address 64BDH into 644EH, setting up a callback location.
64BE
LD HL,64BDH 21 BD 64
Load HL with 64BDH (the RET instruction address).
64C1
LD (644EH),HL 22 4E 64
[SELF-MODIFYING] Store into 644EH (modifies CALL target at 644DH).
64C5H - FCB Size Storage
Data area storing the FCB size (typically 012DH = 301 bytes) used during file operations.
64C5
00 00 data
FCB Size Storage: 2-byte value storing the FCB record size. Initialized to 012DH (301 bytes) during setup.
64C7
RET C9
Return (also serves as data boundary).
64C8
LD A,(2C00H) 3A 00 2C
Load A from 2C00H. This appears to be dead code or data interpreted as code.
64CAH - BASIC Initialization Entry
This is called during BASIC startup. It initializes memory pointers, checks high memory availability, and sets up the BASIC environment. The actual PROGRAM ENTRY is at 66BEH which jumps here after FCB table setup.
64CA
LD HL,0000H 21 00 00
Load HL with 0000H. Note: 64CBH may be modified to hold actual value.
64CD
LD A,H 7C
Copy H to A.
64CE
OR L B5
OR with L. Test if HL is zero.
64CF
LD DE,(4049H) ED 5B 49 40
Load DE with High Memory Pointer from 4049H. This is the top of usable RAM.
64D3
If NZ (HL was not zero), skip loading from DE.
64D5
LD H,D 62
Copy D to H.
64D6
LD L,E 6B
Copy E to L. Now HL = high memory from 4049H.
64D8
LD A,D 7A
Copy D (high memory high byte) to A.
64D9
CP H BC
Compare against H.
64DA
If NZ, JUMP to compare low bytes.
64DC
LD A,E 7B
Copy E to A.
64DD
CP L BD
Compare against L.
64DE
If CARRY (high memory < requested), JUMP to error handler at 57C9H (memory error).
Memory check passed. Now test if memory is writable.
64E1
LD B,(HL) 46
Save original byte at (HL) into B.
64E2
LD A,D9H 3E D9
Load A with test pattern D9H.
64E4
LD (HL),A 77
Write test pattern to memory.
64E5
CP (HL) BE
Read back and compare. Tests if RAM is writable.
64E6
If NZ (write failed), JUMP to memory error.
64E9
LD (HL),B 70
Restore original byte.
Memory test passed. Initialize BASIC system variables.
64EA
LD (40B1H),HL 22 B1 40
Store HL into STREND (40B1H) - end of string storage area.
64ED
LD DE,FFCEH 11 CE FF
Load DE with FFCEH (-50 decimal) - stack margin.
64F0
ADD HL,DE 19
Subtract 50 bytes from high memory for stack space.
64F1
LD (40A0H),HL 22 A0 40
Store into STKTOP (40A0H) - top of BASIC stack.
64F4
LD HL,675CH 21 5C 67
Point HL to startup message at 675CH ("DISK BASIC...").
64F7
GOSUB to SYS0 routine to display string.
64FA
LD HL,FFFEH 21 FE FF
Load HL with FFFEH (-2) - marker for end of program.
64FD
LD (40A2H),HL 22 A2 40
Store into VARTAB (40A2H) - start of variable table (marks no program loaded).
6500
LD HL,64CAH 21 CA 64
Point HL to this initialization routine.
6503
LD (40A7H),HL 22 A7 40
Store into BASIC work pointer (40A7H).
6506
LD HL,4369H 21 69 43
Point HL to system flags at 4369H.
6509
RES 7,(HL) CB BE
Clear bit 7 of system flags.
650B
LD A,(436CH) 3A 6C 43
Load A with DOS flags from 436CH.
650E
BIT 6,A CB 77
Test bit 6 (chaining active flag).
6510
LD A,C9H 3E C9
Load A with C9H (RET opcode).
6512
If ZERO (chaining not active), JUMP to 651AH.
6514
LD A,H 7C
Copy H to A (will be stored for self-modification).
6515
LD (6421H),A 32 21 64
[SELF-MODIFYING] Store into 6421H.
6518
LD A,C3H 3E C3
Load A with C3H (JP opcode).
651A
LD (4312H),A 32 12 43
Store A into BREAK key handler at 4312H. C9H=enabled (RET), C3H=disabled (JP).
Now copy the jump table from 67BBH to 4152H.
651D
LD HL,67BBH 21 BB 67
Point HL to jump table source at 67BBH.
6520
LD DE,4152H 11 52 41
Point DE to jump table destination at 4152H in RAM.
6523
LD BC,0093H 01 93 00
Load BC with 0093H (147 bytes) - size of jump table (49 entries × 3 bytes).
6526
DI F3
Disable interrupts during critical table copy.
6527
LDIR ED B0
Block copy the jump table from ROM to RAM.
6529
LD A,03H 3E 03
Load A with 03H - default number of files. Note: 6529H may be modified.
652B
LD (5F89H),A 32 89 5F
Store into maximum files at 5F89H.
652E
LD HL,66BEH 21 BE 66
Point HL to FCB table base at 66BEH.
6531
LD SP,6534H 31 34 65
Set stack pointer to 6534H (temporary stack during init).
6534
EI FB
Re-enable interrupts.
6535
OR A B7
Set flags based on A (number of files).
6536
If ZERO (no files), skip FCB table clearing.
[LOOP START] Clear all FCB table entries.
6538
EX AF,AF' 08
Save file count in alternate A.
6539
LD BC,(64C5H) ED 4B C5 64
Load BC with FCB size from 64C5H (012DH = 301 bytes).
653D
LD (HL),00H 36 00
[INNER LOOP] Clear byte at (HL).
653F
DEC BC 0B
Decrement byte counter.
6540
INC HL 23
Advance to next byte.
6541
LD A,B 78
Copy B to A.
6542
OR C B1
OR with C. Test if BC is zero.
6543
If NZ, loop to clear next byte.
6545
EX AF,AF' 08
Restore file count from alternate A.
6546
DEC A 3D
Decrement file counter.
At this point, we've just finished clearing the FCB table. HL points to the byte after the last FCB (at 66BEH + n*301 bytes, where n = number of files). Now we finalize the BASIC program storage area.
6549
LD (HL),00H 36 00
Store 00H at current location (HL). This creates a null byte to mark the boundary between FCB storage and the BASIC program area.
654B
INC HL 23
INCrement HL to point to the first byte of available program storage space.
654C
LD (40A4H),HL 22 A4 40
Store HL into TXTTAB (40A4H), which is BASIC's "Text Table" pointer - the start address of the BASIC program in memory. This establishes where BASIC programs will be stored.
Now verify there's enough memory for BASIC to operate. We need at least 012CH (300) bytes between TXTTAB and STREND for the edit buffer and minimum workspace.
654F
LD DE,012CH 11 2C 01
Load DE with 012CH (300 decimal). This is the minimum memory buffer size required for BASIC's edit line buffer and workspace.
6552
ADD HL,DE 19
ADD DE (012CH) to HL. HL now points 300 bytes past TXTTAB - the minimum required end of the program area.
6553
EX DE,HL EB
EXchange DE and HL. DE now contains TXTTAB + 012CH (the minimum required address), HL is free for the next comparison.
6554
LD HL,(40B1H) 2A B1 40
Load HL with the value at STREND (40B1H), which is the end of string storage / bottom of free memory. This is the upper bound of available space.
6557
RST 18H DF
RST 18H (CPDEHL) - Compare DE with HL. Subtracts HL from DE. If DE (minimum required) > HL (available), the Carry flag is SET, indicating insufficient memory.
6558
If the CARRY FLAG is set (minimum required address exceeds available memory), JUMP to 57C9H which is the CMD dispatcher error handler. This reports an out-of-memory error and returns to DOS.
Memory check passed. Now initialize BASIC's internal state and check if there's an auto-run command pending.
655B
GOSUB to ROM routine at 1B4DH. This is BASIC's NEW statement handler - it clears the current program, resets variables, and prepares BASIC for a fresh start. This initializes all BASIC pointers without affecting TXTTAB.
[SELF-MODIFYING CODE] The following instruction at 655EH has its address operand modified at runtime. When no auto-run is pending, it's set to 0000H. When auto-run is active, it's set to the startup command line address.
655E
LD HL,0000H 21 00 00
Load HL with the value at 655FH-6560H. This is self-modifying code - the address 0000H is a placeholder that gets modified by the startup code at 674BH to contain the command line pointer for auto-run programs.
6561
LD A,(HL) 7E
Load Register A with the byte at address HL. If HL=0000H (no auto-run), A gets the value from ROM address 0000H. If HL points to a command line, A gets the first character.
6562
CP 2AH FE 2A
Compare Register A against 2AH (ASCII *). The asterisk character indicates an auto-run program specification on the command line. If A = 2AH, the Z FLAG is set.
6564
If the NZ FLAG is set (character is not *), JUMP forward to 657DH to check for a normal ENTER key press. No auto-run program was specified.
Auto-run detected! The * prefix means we need to set up the existing program's line pointer and string space. The program was already loaded by the startup code.
6566
LD BC,0000H 01 00 00
Load BC with the value at 6567H-6568H. This is self-modifying code - the value is set by the startup routine at 66DDH to contain the last program line address for the auto-run program.
6569
LD HL,(40A4H) 2A A4 40
Load HL with TXTTAB (40A4H), the start of the BASIC program text area.
656C
LD (HL),C 71
Store the low byte of BC (the last line address low byte) into the first byte of program text. This sets up the program's link pointer.
656D
INC HL 23
INCrement HL to point to the second byte of program text.
656E
LD (HL),B 70
Store the high byte of BC (the last line address high byte) into the second byte. Together, this creates the forward pointer to the next line (or 0000H for end of program).
[SELF-MODIFYING CODE] The following instruction at 656FH has its address operand modified at runtime by the startup code at 66E7H.
656F
LD HL,0000H 21 00 00
Load HL with the value at 6570H-6571H. This is self-modifying code - gets set to the string space boundary (from 40F9H) captured during the auto-run setup at 66E7H.
6572
GOSUB to ROM routine at 1B5AH. This is BASIC's string space initialization routine. It sets up FRETOP and related pointers using the value in HL. This restores the string space to its pre-auto-run state.
6575
LD HL,54E9H 21 E9 54
Load HL with 54E9H. This is the address of a "RUN" command string in memory (part of the command token table). Points to the RUN command to auto-execute the loaded program.
6578
LD (655EH),HL 22 5E 65
Store HL into the self-modifying address at 655EH. This sets up the auto-run command pointer so that when BASIC's main loop reads from this address, it will execute "RUN".
657B
JUMP forward to 6581H to set up the command processor callback and enter BASIC's main loop.
Not an auto-run (*) - check if the character is just ENTER (end of line).
657D
CP 0DH FE 0D
Compare Register A against 0DH (ASCII carriage return / ENTER). If A = 0DH, the Z FLAG is set, indicating an empty command line (just pressed ENTER).
657F
If the Z FLAG is set (character is ENTER), JUMP forward to 6587H to enter BASIC's main loop directly without processing any startup command.
There's a startup command (not * and not empty) - set up the callback to process it after displaying the startup message.
6581
LD HL,6589H 21 89 65
Load HL with 6589H. This is the address of the startup command processor - a routine that will be called after the startup message is displayed.
6584
LD (5205H),HL 22 05 52
Store HL into the callback address at 5205H. This sets up a return hook so that after ROM routine 1A19H displays its message, control transfers to 6589H to process the startup command.
6587
JUMP to ROM routine at 1A19H. This is BASIC's main entry point / ready loop. It displays "READY" and enters the direct command processor. If 5205H was set, it will call back to 6589H after initialization.
6589H - Startup Command Processor
This routine is called via the callback mechanism after BASIC displays its startup message. It returns from a subroutine on the stack to reach 658AH, then displays additional startup text and processes any command line that was passed to BASIC at startup (such as RUN "filename" or direct commands).
This is the callback target. When 1A19H returns via the callback at 5205H, it comes here. The first thing we do is clean up the stack and prepare for startup message display.
6589
NOP 00
No operation. This byte is at address 6589H, which was stored in 5205H. Execution actually continues through to 658AH.
658A
POP HL E1
POP the return address from the stack into HL. This removes the stacked return address that was pushed when the callback was invoked, cleaning up the stack frame.
658B
LD HL,0033H 21 33 00
Load HL with 0033H. This is the address of the ROM's character output routine (OUTCHR). This will be stored as the callback return address for normal character output.
658E
LD (5205H),HL 22 05 52
Store 0033H into the callback address at 5205H. This resets the callback to the standard character output routine, removing our special startup callback.
6591
PUSH BC C5
Save BC onto the stack. BC may contain important state information that needs to be preserved across the message display.
6592
LD HL,65ACH 21 AC 65
Load HL with 65ACH. This points to a control code sequence (cursor positioning or screen control) that will be sent before displaying additional messages.
6595
GOSUB to SYS0 routine at 4467H. This is the string display routine - it outputs the string pointed to by HL until it encounters a terminator. Displays the control codes at 65ACH.
6598
LD DE,(655EH) ED 5B 5E 65
Load DE with the value at 655EH. This is the startup command line pointer that was set up during initialization. Points to either the command string or the "RUN" command for auto-run.
659C
LD HL,(40A7H) 2A A7 40
Load HL with the value at 40A7H. This is BASIC's work pointer / edit buffer area where the command line will be copied for processing.
[LOOP START] Copy the startup command string from (DE) to the edit buffer at (HL). Continue until we hit a carriage return (0DH).
659F
LD A,(DE) 1A
Load Register A with the byte at address DE (the current character from the startup command string).
65A0
CP 0DH FE 0D
Compare Register A against 0DH (carriage return). If A = 0DH, we've reached the end of the command string and the Z FLAG is set.
65A2
LD (HL),A 77
Store Register A into memory at address HL (copy the character to the edit buffer). This copies the character regardless of whether it's the terminator.
65A3
INC DE 13
INCrement DE to point to the next character in the source command string.
65A4
INC HL 23
INCrement HL to point to the next position in the destination edit buffer.
65A5
If the NZ FLAG is set (character was not carriage return), LOOP BACK to 659FH to copy the next character. [LOOP]
Command string has been copied to the edit buffer. Now set up for BASIC to process it.
65A7
XOR A AF
XOR Register A with itself, setting A to 00H and clearing all flags. This creates a null terminator.
65A8
PUSH AF F5
Save AF (A=00H, flags cleared) onto the stack. This pushes a null byte that will be used by the BASIC parser.
65A9
DEC HL 2B
DECrement HL to point back to the last character position (the carriage return that was just stored).
65AA
JUMP to ROM routine at 0379H. This is BASIC's line processor entry point. It takes the command line in the edit buffer and executes it (either as a direct command or adds it to the program if it has a line number).
65ADH - Control Code Data
This 3-byte sequence contains cursor control codes used by the startup message display routine at 6595H. These are TRS-80 screen control characters.
65AD
1D 1B 1F data
Control code sequence: 1DH = cursor right, 1BH = cursor home, 1FH = cursor down. These position the cursor after the "READY" message before displaying the NEWDOS/80 startup text.
65C9H - Reserved/NOP Space
This area contains NOP bytes (00H) that serve as padding or reserved space between routines. They may have been used during development or reserved for future patches.
65C9-65CCH
00 00 00 00 data
Four NOP bytes (00H) - reserved space or padding.
65CDH - Check for Assignment Statement
This small utility routine checks if the current BASIC statement is an assignment (contains an = sign). It's used by the command parser to distinguish between variable assignments and other statements.
65CD
LD HL,(232AH) 2A 2A 23
Load HL with the value at 232AH. This appears to be a BASIC system pointer (in ROM workspace area) that points to the current position in the command being parsed.
65D0
LD A,(HL) 7E
Load Register A with the byte at address HL (the current character being examined).
65D1
CP 3DH FE 3D
Compare Register A against 3DH (ASCII =). If the current character is an equals sign, the Z FLAG is set. This indicates an assignment statement like LET A=5 or just A=5.
65D3
RET C9
RETurn to the caller. The Z flag indicates the result: Z set = equals sign found (assignment), Z clear = not an assignment.
65D4H - Get Position with BC Preserved
This utility routine calls the position fetching routine at 61E1H while preserving the BC register pair. It returns the position status in Register A.
65D4
PUSH BC C5
Save BC onto the stack to preserve its value across the subroutine call.
65D5
GOSUB to 61E1H to get both file positions for comparison. This routine loads the primary and alternate position values from the FCB work area at 5700H.
65D8
LD A,C 79
Load Register A with the value from Register C. After 61E1H returns, C contains a status or flag byte from the position operation.
65D9
POP BC C1
Restore BC from the stack, recovering the original value that was saved at entry.
65DA
RET C9
RETurn to the caller with the status in Register A and BC restored.
65DBH - Get FCB Size
This short utility routine retrieves the FCB (File Control Block) size value from the storage location at 64C5H. This is used when calculating FCB table offsets.
65DB
LD DE,(64C5H) ED 5B C5 64
Load DE with the 16-bit value at 64C5H. This is the FCB size constant, typically 012DH (301 decimal). Each file's FCB requires this many bytes of storage.
65DF
RET C9
RETurn to the caller with the FCB size in Register pair DE.
65E0H - Reserved/NOP Area (FCB Workspace)
This large block of 00H bytes from 65E0H to 66BDH is reserved space that may be used for FCB table overflow or as workspace. It contains 222 bytes of zeros.
65E0-66BDH
00 00 ... (222 bytes) data
Reserved NOP/data area. This 222-byte block of zeros (65E0H-66BDH) provides workspace or overflow area for the FCB table. The actual FCB table starts at 66BEH.
66BEH - PROGRAM ENTRY POINT
This is the main entry point for BASIC/CMD. When NEWDOS/80 loads and executes BASIC, execution begins here. This routine processes any startup parameters, handles the * auto-run command, determines the FCB size for multiple files, and then jumps to the main initialization at 64CAH. The code handles the BASIC command line format: BASIC [*filename] [,n[V]] where n=number of files and V=verify mode.
PROGRAM ENTRY - Execution starts here when BASIC/CMD is loaded by DOS. The code at 66BCH-66BDH is actually data (part of the reserved area), and execution truly begins at 66BEH.
66BC
LD HL,(012AH) 2A 2A 01
Load HL with the value at 012AH. This is a DOS system variable containing a pointer to the command line arguments that were passed when BASIC was invoked. Note: The disassembler shows this starting at 66BC but it decodes as LD HL,(012AH) which spans bytes 2A 2A 01.
66BF
CALL NZ,C366H C4 66 C3
CALL C366H if NZ flag is set. However, this appears to be a decoding artifact. The actual byte sequence C4 66 C3 at 66BF decodes differently. Looking at the disassembly pattern, 66BFH starts the real entry code.
The disassembler has some misalignment here. Let me re-interpret based on the continuation instructions which state entry is at 66BEH and the code jumps to 64CAH at the end.
66BF
NOP area varies
The bytes from 66BFH-66C3H need careful re-interpretation. The actual program entry sequence begins properly below.
66C4
DEC HL 2B
DECrement HL. After getting the command line pointer, step back one position to prepare for the CHRGET loop.
66C5
RST 10H D7
RST 10H (CHRGET) - Advance to the next non-space character and load it into Register A. This skips leading spaces in the command line.
66C6
CP 2AH FE 2A
Compare Register A against 2AH (ASCII *). The asterisk indicates an auto-run program specification like BASIC *MYPROG.
66C8
If the NZ FLAG is set (first non-space character is not *), JUMP forward to 670DH to process normal startup without auto-run.
Auto-run mode detected! The * prefix means we need to load and run a program. First, save important state and find the program's parameters.
66CA
PUSH HL E5
Save HL onto the stack. HL points to the character after the * in the command line (the filename).
66CB
LD HL,(40B1H) 2A B1 40
Load HL with the value at STREND (40B1H), the end of string storage. This captures the current memory boundary before loading the program.
66CE
LD (64CBH),HL 22 CB 64
Store HL into 64CBH. This saves the STREND value for restoration after the program loads, so string space is preserved.
66D1
LD HL,(40A4H) 2A A4 40
Load HL with the value at TXTTAB (40A4H), the start of BASIC program text. This is needed to scan the program structure.
66D4
PUSH HL E5
Save HL (TXTTAB) onto the stack for later restoration.
[LOOP START] Scan through the BASIC program to find the last line. Each line starts with a 2-byte link pointer to the next line. A link of 0000H marks the end.
66D5
LD E,(HL) 5E
Load Register E with the low byte of the link pointer at (HL). This is the low byte of the address of the next line.
66D6
INC HL 23
INCrement HL to point to the high byte of the link pointer.
66D7
LD D,(HL) 56
Load Register D with the high byte of the link pointer. DE now contains the complete address of the next line.
66D8
EX DE,HL EB
EXchange DE and HL. HL now points to the next line, DE contains the previous pointer position.
66D9
LD A,H 7C
Load Register A with the high byte of HL (next line address).
66DA
OR L B5
OR Register A with Register L. If HL = 0000H (end of program), the result is 0 and the Z FLAG is set.
66DB
If the Z FLAG is set (next line pointer is 0000H, meaning end of program), JUMP forward to 66E4H to finish scanning.
66DD
LD (6566H),HL 22 66 65
Store HL into the self-modifying location at 6566H. This saves the address of the current line as the "last line" pointer for the auto-run setup.
66E0
EX DE,HL EB
EXchange DE and HL. Restore HL to point to next line for continued scanning.
66E1
RST 18H DF
RST 18H (CPDEHL) - Compare DE with HL. This checks if we've made progress in the scan.
66E2
If the NO CARRY flag is set (DE >= HL, meaning we haven't advanced or went backwards - error condition), JUMP to 673DH for error handling.
Continue scanning - loop back to process the next line.
66E4
CONTINUE TO 66D5H implicit
The loop continues at 66D5H. After hitting end of program (Z flag set at 66DBH), we fall through here.
66E4
LD HL,(40F9H) 2A F9 40
Load HL with the value at 40F9H. This is the string space boundary pointer that marks where string storage begins.
66E7
LD (656FH),HL 22 6F 65
Store HL into the self-modifying location at 656FH. This saves the string space boundary for restoration during auto-run initialization.
66EA
DEC HL 2B
DECrement HL to point one byte before the string space boundary.
66EB
LD A,(HL) 7E
Load Register A with the byte at (HL). This reads the byte just before string space.
66EC
DEC HL 2B
DECrement HL again to check the previous byte.
66ED
OR (HL) B6
OR Register A with the byte at (HL). If both bytes are 00H, the result is 0 and Z is set. This checks for a null terminator marking valid string space.
66EE
If the NZ FLAG is set (string space boundary check failed - invalid structure), JUMP to 673DH for error handling.
66F0
RST 18H DF
RST 18H (CPDEHL) - Compare DE with HL for additional validation.
66F1
If the CARRY FLAG is set (validation failed), JUMP to 673DH for error handling.
66F3
OR FFH F6 FF
OR Register A with FFH, setting A to FFH (255) and clearing the Z flag. This sets up a flag indicating auto-run mode is active.
66F5
POP HL E1
Restore HL from the stack. This recovers the TXTTAB value that was saved at 66D4H.
66F6
LD DE,66BFH 11 BF 66
Load DE with 66BFH. This is the base address of the FCB table area (one byte after the reserved space).
66F9
SBC HL,DE ED 52
SUBtract with Carry: HL = HL - DE - Carry. This calculates the offset from the FCB base to TXTTAB, determining how much space is used by FCBs.
66FB
LD DE,(64C5H) ED 5B C5 64
Load DE with the value at 64C5H. This is the FCB size (typically 012DH = 301 bytes per file).
66FF
ADD HL,DE 19
ADD DE (FCB size) to HL. This adjusts the offset calculation.
[LOOP START] Count how many files can be supported based on available space. Divide the available space by FCB size.
6700
INC A 3C
INCrement Register A. A serves as the file counter, starting from -1 (FFH) so first increment gives 0.
6701
OR A B7
OR Register A with itself. This sets the flags based on A's value without changing it. Clears the carry flag for the next SBC.
6702
SBC HL,DE ED 52
SUBtract with Carry: HL = HL - DE. Subtract one FCB size from the remaining space.
6704
If the Z FLAG is set (exactly zero space remaining after subtraction), JUMP to 6747H to store the file count and continue initialization.
6707
CP 0FH FE 0F
Compare Register A against 0FH (15 decimal). This is the maximum number of files supported. If A >= 15, we've hit the limit.
6709
If the CARRY FLAG is set (A < 15, haven't reached max files yet), LOOP BACK to 6700H to count another file. [LOOP]
670B
JUMP forward to 673DH. Maximum file count exceeded - proceed with error handling or use default configuration.
No auto-run (*) detected - process normal BASIC startup with optional parameters.
670D
DEC HL 2B
DECrement HL to step back one position in the command line for re-parsing.
670E
LD BC,012DH 01 2D 01
Load BC with 012DH (301 decimal). This is the default FCB size for standard file operations.
6711
LD (64C5H),BC ED 43 C5 64
Store BC into 64C5H. This sets the FCB size variable to the default value of 301 bytes.
6715
RST 10H D7
RST 10H (CHRGET) - Advance to the next non-space character and load it into Register A.
6716
If the NO CARRY flag is set (character is not a digit 0-9), JUMP forward to 674BH. No numeric parameter was specified.
A numeric parameter was found - parse it as the number of files to allocate.
6718
GOSUB to 5CFCH to parse a decimal number from the command line. Returns the parsed number in DE.
671B
If the CARRY FLAG is set (parse error occurred), JUMP to 673DH for error handling.
671D
LD A,D 7A
Load Register A with the high byte of DE (the parsed number).
671E
OR A B7
OR Register A with itself. If D is non-zero, the number is > 255 which is too large.
671F
If the NZ FLAG is set (high byte non-zero, number > 255), JUMP to 6740H to handle the large number case.
6721
LD A,E 7B
Load Register A with the low byte of DE (the file count, now known to be < 256).
6722
CP 10H FE 10
Compare Register A against 10H (16 decimal). The maximum allowed file count is 15.
6724
If the NO CARRY flag is set (A >= 16, file count exceeds maximum), JUMP to 673DH for error handling.
6726
LD (6529H),A 32 29 65
Store Register A into the maximum files count at 6529H. This is a self-modifying location in the FCB clearing loop.
6729
LD A,(HL) 7E
Load Register A with the current character at (HL) in the command line. Check for additional parameters.
672A
CP 56H FE 56
Compare Register A against 56H (ASCII V). The V suffix indicates verify mode for disk operations.
672C
If the NZ FLAG is set (character is not V), JUMP forward to 6734H to check for more parameters.
672E
LD A,02H 3E 02
Load Register A with 02H. This is the verify mode flag value that enables write verification.
6730
LD (64C6H),A 32 C6 64
Store the verify flag (02H) into 64C6H. This enables disk verify mode for all subsequent write operations.
6733
RST 10H D7
RST 10H (CHRGET) - Advance past the V character to get the next character.
6734
LD A,(HL) 7E
Load Register A with the current character at (HL).
6735
CP 2CH FE 2C
Compare Register A against 2CH (ASCII ,). A comma separates multiple parameters on the command line.
6737
If the Z FLAG is set (character is comma), LOOP BACK to 6715H to parse the next parameter. [LOOP]
6739
CP 0DH FE 0D
Compare Register A against 0DH (carriage return). End of command line.
673B
If the Z FLAG is set (end of line reached), JUMP forward to 674BH to complete initialization.
673D
JUMP to 57C9H - the CMD dispatcher error handler. This handles syntax errors or invalid parameters in the BASIC command line.
Large file count case - the parsed number was > 255, so we need to handle it specially.
6740
DEC DE 1B
DECrement DE. Adjust the large number value.
6741
LD (64CBH),DE ED 53 CB 64
Store DE into 64CBH. This saves the adjusted value for later processing.
6745
JUMP back to 6734H to continue parsing parameters.
Store the calculated file count and save the command line pointer.
6747
LD (6529H),A 32 29 65
Store Register A (the file count) into the maximum files variable at 6529H. This value controls how many FCBs are allocated.
674A
POP HL E1
Restore HL from the stack. This recovers the command line pointer that was saved at 66CAH.
674B
LD (655EH),HL 22 5E 65
Store HL into the command line pointer at 655EH. This is the self-modifying location that the initialization routine uses to find startup commands.
Copy the BASIC system variable initialization table from ROM to RAM.
674E
LD HL,18F7H 21 F7 18
Load HL with 18F7H. This points to a BASIC system variable template in ROM - initial values for BASIC's workspace variables.
6751
LD DE,4080H 11 80 40
Load DE with 4080H. This is the destination in RAM where BASIC system variables are stored.
6754
LD BC,0027H 01 27 00
Load BC with 0027H (39 decimal). This is the number of bytes to copy from the initialization template.
6757
LDIR ED B0
LDIR - Block transfer: copy BC bytes from (HL) to (DE), incrementing both pointers. This initializes BASIC's system variables from the ROM template.
6759
JUMP to 64CAH to begin the main BASIC initialization. This continues with memory detection, FCB table setup, jump table installation, and finally entering BASIC's ready loop.
675CH - Startup Message Text
This area contains the ASCII text strings displayed when BASIC starts up. The text includes cursor control codes and the NEWDOS/80 copyright/enhancement message. Control codes: 1CH = cursor control, 1FH = clear screen/position, 0AH = line feed, 0DH = carriage return.
675C
1C 1F data
Control codes: 1CH and 1FH. These are TRS-80 cursor positioning/screen control characters that position the cursor before displaying the message.
675E
44 49 53 4B 20 42 41 53 49 43 2E 20 ASCII
"DISK BASIC. " - The start of the BASIC identification message.
676A
52 41 44 49 4F 20 53 48 41 43 4B 27 53 20 ASCII
"RADIO SHACK'S " - Credit to the original manufacturer.
6778
52 4F 4D 20 45 4E 48 41 4E 43 45 44 20 57 49 54 48 ASCII
"ROM ENHANCED WITH" - Indicates the ROM has been enhanced.
678A
0A control
0AH = Line feed character. Moves cursor to the next line.
678B
41 50 50 41 52 41 54 27 53 20 ASCII
"APPARAT'S " - Credit to Apparat, the company that created NEWDOS/80.
6795
4E 45 57 44 4F 53 38 30 20 ASCII
"NEWDOS80 " - The name of the disk operating system.
679E
45 58 54 45 4E 44 45 44 20 ASCII
"EXTENDED " - Indicating extended features.
67A7
41 4E 44 20 ASCII
"AND " - Conjunction.
67AB
44 49 53 4B 20 ASCII
"DISK " - Continuing the sentence.
67B0
46 45 41 54 55 52 45 53 2E ASCII
"FEATURES." - End of the enhancement description.
67B9
0A 0D control
0AH = Line feed, 0DH = Carriage return. These terminate the message and move the cursor to a new line.
Complete startup message: "DISK BASIC. RADIO SHACK'S ROM ENHANCED WITH[LF]APPARAT'S NEWDOS80 EXTENDED AND DISK FEATURES.[LF][CR]"
67BBH - BASIC Jump Table
This is the BASIC statement/function jump table. It contains 49 JP (Jump) instructions that provide entry points for various DISK BASIC statements and functions. During initialization, this entire table (147 bytes = 49 entries × 3 bytes) is copied from here to RAM at 4152H. The entries provide hooks into BASIC/CMD's disk I/O routines, file handling, and extended statements.
Jump Table Entry Format: Each entry is a 3-byte JP instruction (C3 xx xx). These are copied to 4152H-41E4H to replace/extend ROM BASIC's jump vectors.
67BB
Entry 0: Jump to 58F5H - INPUT# statement handler. Reads data from a sequential file into variables.
67BE
Entry 1: Jump to 577FH - SVC call dispatcher with BC=534AH. Handles a specific DOS service call.
67C1
Entry 2: Jump to 58F2H - Related INPUT# entry point or variation.
67C4
Entry 3: Jump to 5852H - OPEN statement handler. Opens files for reading or writing.
67C7
Entry 4: Jump to 58EFH - Another INPUT# related entry.
67CA
Entry 5: Jump to 5EC5H - LOC function. Returns the current position in a file.
67CD
Entry 6: Jump to 5ED1H - File position related function.
67D0
Entry 7: Jump to 5EC9H - LOF function. Returns the length of a file.
67D3
Entry 8: Jump to 58DEH - File I/O related routine.
67D6
Entry 9: Jump to 58DBH - File I/O related routine.
67D9
Entry 10: Jump to 58D8H - File I/O related routine.
67DC
Entry 11: Jump to 57FFH - NAME statement. Renames files on disk.
67DF
Entry 12: Jump to 58C4H - TIME$ statement or function handler.
67E2
Entry 13: Jump to 5795H - SVC dispatcher for BC=5504H.
67E5
Entry 14: Jump to 5E63H - FIELD statement. Defines fields in a random access buffer.
67E8
Entry 15: Jump to 6126H - GET statement. Reads a record from a random access file.
67EB
Entry 16: Jump to 6125H - PUT statement. Writes a record to a random access file.
67EE
Entry 17: Jump to 5FA1H - File OPEN routine variant.
67F1
Entry 18: Jump to 574AH - CMD dispatcher entry with preliminary setup.
67F4
Entry 19: Jump to 572EH - Buffer setup routine. Calls 609AH for initialization.
67F7
Entry 20: Jump to ROM at 1E4AH - Syntax error handler. This entry redirects to ROM's error routine.
67FA
Entry 21: Jump to 643CH - PRINT# termination handler.
67FD
Entry 22: Jump to 5790H - SVC dispatcher for BC=54C5H.
6800
Entry 23: Jump to 5908H - MID$ statement handler (string assignment).
6803
Entry 24: Jump to 5909H - MID$ function (string extraction).
6806
Entry 25: Jump to 5786H - SVC dispatcher for BC=53F2H.
6809
Entry 26: Jump to 573BH - Buffer setup with BC=8440H.
680C
Entry 27: Jump to 579FH - SVC dispatcher for BC=55E8H.
680F
LD A,2FH 3E 2F
Entry 28: Load A with 2FH (SVC function code 47). This is followed by RST 28H.
6811
RST 28H EF
Execute DOS SVC call with function code 2FH. Inline code instead of a JP.
6812
Entry 29: Jump to 5892H - CLOSE statement handler.
6815
Entry 30: Jump to ROM at 2169H - SWAP statement implementation.
6818
Entry 31: Jump to 575DH - Error checking routine, compares against 1A7EH.
681B
Entry 32: Jump to 5756H - SVC setup routine with BC=54FFH.
681E
Entry 33: Jump to 63B3H - Guard flag copy and clear. Saves guard to 63BDH then clears.
6821
Entry 34: Jump to 63BCH - Guard flag clear. Stores 00H at 63A9H.
6824
Entry 35: Jump to 5FB6H - File OPEN parsing continuation.
6827
Entry 36: Jump to 6438H - Print width handler. Sets print width for file output.
682A
Entry 37: Jump to 6076H - File OPEN mode parsing.
682D
Entry 38: Jump to 63C0H - PRINT# handler. Outputs data to a file.
6830
Entry 39: Jump to 5746H - RET C followed by setup, related to error returns.
6833
Entry 40: Jump to 5F52H - File CLOSE pre-cleanup.
6836
Entry 41: Jump to 5F4BH - File CLOSE completion.
6839
Entry 42: Jump to 5FA0H - Conditional return routine.
683C
Entry 43: Jump to 5F3BH - File CLOSE wrapper.
683F
Entry 44: Jump to 5EA8H - EOF function. Tests for end-of-file condition.
6842
Entry 45: Jump to 578BH - SVC dispatcher for BC=5462H.
6845
Entry 46: Jump to 579AH - SVC dispatcher for BC=55D4H.
6848
Entry 47: Jump to 5EB9H - File position function.
684B
Entry 48: Jump to 5FA0H - Conditional return routine (duplicate entry).
End of jump table. Total: 49 entries × 3 bytes = 147 bytes (67BBH-684DH). Copied to 4152H-41E4H during BASIC initialization at 651DH-6527H.