4152H (DSKBAS) - DISK BASIC JUMP TABLE
This is the primary dispatch table for Disk BASIC commands. When the BASIC interpreter encounters a disk-related token, it calculates the offset into this table and executes the corresponding JP instruction. Each 3-byte entry redirects to the actual command handler. The table contains 32 entry points covering all file I/O and disk system commands.
4152DSKBAS
Jump to CHR$ function handler - Returns a string containing the character with the specified ASCII code.
4155
Jump to DIM statement handler for string arrays with file buffer - Dimensions a string array for use with file operations.
4158
Jump to MKI$ function handler - Converts an integer to a 2-byte string for random file storage.
415B
Jump to DEFUSR statement handler - Defines a USR function entry point for machine language calls.
415E
Jump to MKS$ function handler - Converts a single-precision number to a 4-byte string for random file storage.
4161
Jump to EOF function handler - Returns -1 (true) if end of file reached, 0 (false) otherwise.
4164
Jump to LOC function handler - Returns the current record number for a random access file.
4167
Jump to LOF function handler - Returns the length of file in bytes (number of records × record length).
416A
Jump to MKD$ function handler - Converts a double-precision number to an 8-byte string for random file storage.
416D
Jump to CVI function handler - Converts a 2-byte string from a random file back to an integer.
4170
Jump to CVS function handler - Converts a 4-byte string from a random file back to single-precision.
4173
Jump to CMD statement handler - Redirects output to a device (printer, comm port, or file).
4176
Jump to ROM routine at 3030H - CVD function handler for double-precision conversion from string.
4179
Jump to OPEN statement handler - Opens a file for input, output, random, or extend access.
417C
Jump to FIELD statement handler - Defines field variables for random access file buffer.
417F
Jump to GET statement handler - Reads a record from a random access file into the buffer.
4182
Jump to PUT statement handler - Writes a record from the buffer to a random access file.
4185
Jump to CLOSE statement handler - Closes one or more open files, flushing buffers to disk.
4188
Jump to LOAD statement handler - Loads a BASIC program from disk into memory.
418B
Jump to MERGE statement handler - Merges an ASCII BASIC program with the current program.
418E
Jump to NAME statement handler - Renames a file on disk.
4191
Jump to KILL statement handler - Deletes a file from disk.
4194
Jump to &H / &O handler - Parses hexadecimal (&H) or octal (&O) number constants.
4197
Jump to LSET statement handler - Left-justifies a string in a random file field buffer.
419A
Jump to RSET statement handler - Right-justifies a string in a random file field buffer.
419D
Jump to FILES statement handler - Displays a directory listing of files on disk.
41A0
Jump to SAVE statement handler - Saves the current BASIC program to disk.
41A3
Jump to LINE INPUT statement handler - Reads an entire line from keyboard or file.
41A6
Jump to ERROR statement handler (in SYS0) - Simulates an error condition.
41A9
Jump to USR function handler - Calls a machine language routine defined by DEFUSR.
41AC
Jump to PRINT# output completion handler - Writes buffered output to file.
41AF
Jump to INPUT# statement handler - Reads formatted data from a sequential file.
41B2
Jump to PRINT# statement handler - Writes formatted data to a sequential file.
41B5
Jump to file buffer save routine - Preserves file state for nested operations.
41B8
Jump to file buffer restore routine - Restores file state after nested operations.
41BB
Jump to close all files routine - Closes all open files (used before LOAD/RUN/SYSTEM).
41BE
Jump to clear file buffer pointer - Resets the active file pointer to indicate no file selected.
41C1
Jump to INPUT# item separator check - Processes comma/newline between INPUT# variables.
41C4
Jump to INPUT handler with file check - Gets input from keyboard or file depending on context.
41C7
Jump to RUN statement handler (file version) - Runs a BASIC program from disk.
41CA
Jump to file mode check for LIST - Checks if output should go to file or screen.
41CD
Jump to simple RET (stub entry) - Placeholder for future expansion or compatibility.
41D0
Jump to print character to file handler - Routes character output to file if file active.
41D3
Jump to PRINT# file number check - Validates file number for output operations.
41D6
Jump to MID$ statement handler - Replaces a portion of a string variable.
41D9
Jump to WRITE# statement handler - Writes comma-delimited data to sequential file.
41DC
Jump to check if output to file active - Returns status of current file output redirection.
41DF
Jump to SYSTEM statement handler - Exits BASIC and returns to TRSDOS Ready prompt.
41E2
Jump to SYSTEM (alternate entry) - Same as 41DFH, possibly for different token.
5200H (DOPROT) - FILE STATE FLAGS AND ARRAY DIMENSION HANDLER
This section contains three flag bytes at 5200H-5202H that track file operation states, followed by the array dimension handler for disk file operations. The routine at 5203H processes DIM statements for arrays that will be used with random access files. It validates the number of dimensions and stores array bounds.
5200DOPROT
NOP 00
File operation active flag - Set to FFH when file operations are in progress, 00H otherwise. Used to track state across LOAD/RUN operations.
5201PROTFL
NOP 00
Verify flag storage - Stores verify mode (from 442BH bit 2) during file operations.
5202
NOP 00
Initialization flag - Non-zero if special initialization routine at 3042H should be called.
The following routine handles array dimensioning for file buffer variables. Entry: HL points to BASIC text after DIM token. The routine checks if array dimensions are valid (1-3 dimensions supported) and creates the array descriptor.
5203PUSVAL
LD A,(40AFH) LD A,(VALTYP)3A AF 40
Load Register A with the variable type flag from 40AFH. This indicates the type of variable being dimensioned: 1=integer, 2=string, 3=single precision, 4=double precision. [src: FIND OUT WHAT TYPE OF VALUE WE ARE SAVING]
5206
DEC A 3D
Decrement Register A by 1, converting type 1-4 to 0-3. [src: SETUP THE CONDITION CODES]
5207
DEC A 3D
Decrement Register A again, now type becomes -1 to 2. [src: WITHOUT AFFECTING CARRY]
5208
DEC A 3D
Decrement Register A again. If original type was 3 (single precision), A is now 0; types 1-2 are now negative (sign flag set). [src: SET ZERO FOR STRING]
5209
OR A B7
OR Register A with itself to set flags. Z flag set if A=0 (single precision), M flag set if A is negative (integer or string). [src: SET THE PARITY FLAG]
520A
SCF 37
Set Carry Flag to 1. This flag will be used to indicate a special array type if we jump.
520B
If Z flag is set (type was single precision = 3), JUMP to 526CH to handle single-precision array with carry set indicating special mode. [src: FOR FRMEVL, GOTO TMERR]
520D
LD C,(HL) 4E
Load Register C with the low byte of the first dimension bound from the array descriptor pointed to by HL.
520E
INC HL 23
Increment HL to point to the high byte of the first dimension.
520F
LD B,(HL) 46
Load Register B with the high byte of the first dimension bound. BC now contains the first dimension size.
5210
PUSH BC C5
Save the first dimension bound onto the stack for later use.
5211
If M flag (Minus/Sign) is set from the OR at 5209H (meaning type was integer=1 or string=2), JUMP to 522BH to handle 1-dimensional array. [src: ALL DONE IF THE DATA WAS AN INTEGER]
5214
INC HL 23
Increment HL to point to the next dimension in the array descriptor.
5215
LD C,(HL) 4E
Load Register C with the low byte of the second dimension bound.
5216
INC HL 23
Increment HL to point to the high byte of the second dimension.
5217
LD B,(HL) 46
Load Register B with the high byte of the second dimension bound. BC now contains the second dimension size.
5218
PUSH BC C5
Save the second dimension bound onto the stack. [src: PUSH FAC-1 ,0 ON THE STACK]
5219
If Parity/Overflow flag is clear (odd parity - type was 4, double precision), JUMP to 522BH. The original type=4 after three decrements = 1, OR 1 = PO flag clear. [src: ALL DONE IF WE HAD A SNG]
521C
INC HL 23
Increment HL to point to a possible third dimension.
521D
If Carry is set (from 520AH, indicating special array handling), JUMP to 5222H to continue reading third dimension. [src: FOR VARIABLES , THE VALUE BYTES ARE]
521F
LD HL,411DH 21 1D 41
Load HL with address 411DH - a default array descriptor location in the BASIC workspace, used when no third dimension specified. [src: WE HAVE A DOUBLE PRECISION NUMBER]
5222PUSDVR
LD C,(HL) 4E
Load Register C with the low byte of the third dimension (or default). [src: WE HAVE A DOUBLE PRECISION NUMBER]
5223
INC HL 23
Increment HL to point to high byte.
5224
LD B,(HL) 46
Load Register B with the high byte of the third dimension. BC now contains the third dimension size.
5225
INC HL 23
Increment HL past this dimension entry.
5226
PUSH BC C5
Save the third dimension bound onto the stack.
5227
LD C,(HL) 4E
Load Register C with the low byte of a possible fourth dimension.
5228
INC HL 23
Increment HL to point to high byte.
5229
LD B,(HL) 46
Load Register B with the high byte of the fourth dimension.
522A
PUSH BC C5
Save the fourth dimension bound onto the stack. [src: USER-DEFINED FUNCTIONS REQUIRE THAT THE]
522BVPUSHD
If Carry flag is set, JUMP to 5276H to process the accumulated dimension values on the stack. [src: GO BACK FOR USER-DEFINED FUNCTIONS]
522EGETFNM
RST 08H CF
Call the SYNCHR routine via RST 08H to verify the next character in BASIC text matches the expected token. [src: MUST START WITH 'FN']
522F
CP (HL) BE
(Token byte BEH follows RST 08H) - Check for token BEH (specific BASIC keyword token).
5230
LD A,80H 3E 80
Load Register A with 80H - the array processing active flag to indicate we're in the middle of dimensioning. [src: DONT ALLOW AN ARRAY]
5232
LD (40DCH),A LD (SUBFLG),A32 DC 40
Store the array flag (80H) into 40DCH (array dimension processing flag) to indicate active array processing. [src: DON'T RECOGNIZE THE "(" AS]
5235
OR (HL) B6
OR Register A with the byte at HL, combining the flag with the current token/value. [src: PUT FUNCTION BIT ON]
5236
LD B,A 47
Copy the combined value from A to Register B for use as a parameter. [src: GET FIRST CHAR INTO B]
5237
JUMP to ROM routine at 2612H to continue array dimensioning with the calculated parameters in B. [src: REALLY GET THE POINTER]
523AH (FNDOER) - DIM STATEMENT DISK HANDLER
This is the main entry point for the DIM statement when disk file support is active. It calls the dimension processor at 522EH, then checks the variable type and sets up the array descriptor pointer. Entry: HL points to BASIC text. Exit: Array is dimensioned, HL points past the dimension specification.
523AFNDOER
GOSUB to 522EH to process the dimension specification via RST 08H synchronization. [src: GET A POINTER TO THE FUNCTION]
523D
LD A,(40AFH) LD A,(VALTYP)3A AF 40
Load Register A with the variable type flag from 40AFH after dimension processing. [src: DEFINITION IN (DE)]
5240
OR A B7
OR Register A with itself to set the Zero flag based on the type value. [src: PUSH THIS A ON WITH A PSW WITH CARRY OFF]
5241
PUSH AF F5
Save AF (type and flags) onto the stack for later comparison. [src: SAE SO THAT THE FINAL RESULT WILL]
5242
LD (40F3H),HL LD (OLDLIN),HL22 F3 40
Store HL (current BASIC text pointer) into 40F3H (saved file pointer) to preserve position. [src: SAVE THE TEX POINTER THAT POINTS PAST]
5245
EX DE,HL EB
Exchange DE and HL. DE now has the text pointer, HL will be used for array descriptor. [src: (H,L) =A POINTER TO THE VALUE OF FUNCTION]
5246
LD A,(HL) 7E
Load Register A with the byte at HL (array descriptor low byte). [src: (H,L)= VALUE OF THE FUNCTION]
5247
INC HL 23
Increment HL to point to high byte.
5248
LD H,(HL) 66
Load Register H with the high byte of the array pointer. [src: WHICH IS A TEXT POINTER AT THE FORMAL]
5249
LD L,A 6F
Load Register L with the low byte (from A). HL now points to the array descriptor.
524A
OR H B4
OR Register A (low byte) with H (high byte) to check if the pointer is zero (null array). [src: A ZERO TEXT POINTER MEAMS THE FUNCTION]
524B
If Z flag is set (pointer is 0000H - undefined array), JUMP to 5363H to handle the "Undefined array" error. [src: IF SO, GIVEN AN "UNDEFINED FUNCTION " ERROR]
524E
LD A,(HL) 7E
Load Register A with the first byte of the array descriptor. [src: SEE IF THERE ARE ANY PARAMETERS]
524F
CP 28H FE 28
Compare Register A with 28H (ASCII ( open parenthesis). This checks if we're at an array element reference. [src: PARAMETER LIST ATARTS WITH "("]
5251
If NZ flag is set (not an open parenthesis), JUMP to 529FH - this is a simple variable, not an array. [src: SKIP OVER PARAMETER SETUP]
5253
RST 10H D7
Call CHRGET via RST 10H to get the next character from BASIC text, advancing past the '('.
5254
LD (40D8H),HL LD (TEMP2),HL22 D8 40
Store the current HL pointer into 40D8H for later restoration during array indexing. [src: SAVE THE TEXT POINTER TO THE START OF THE]
5257
JUMP unconditionally to 525BH to continue processing the array subscripts.
LOOP START
- The following code loops through each array subscript, separated by commas.
5259MORPUS
RST 08H CF
Call SYNCHR via RST 08H to verify expected character. [src: INSURE COMMA FOLLOWS EACH VARIABLE]
525A
INC L 2C
(Token byte 2CH follows RST 08H) - Verify comma (2CH = ASCII ,) between subscripts.
525BFRSPRM
LD C,04H 0E 04
Load Register C with 04H - parameter indicating 4-byte floating point value expected for subscript. [src: ALLOW FOR DOUBLE PRECISION]
525D
GOSUB to ROM routine at 1963H to evaluate the subscript expression. [src: MAKE SURE THERE WILL BE ROOM FOR THE]
5260
LD A,80H 3E 80
Load Register A with 80H - the array processing flag. [src: DON'T ALLOW ARRAYS AS PARAMETERS]
5262
LD (40DCH),A LD (SUBFLG),A32 DC 40
Store the flag into 40DCH to indicate array processing is active. [src: THIS PREVENTS RECURSION DUE TO THIS]
5265
GOSUB to ROM routine at 260DH to process the evaluated subscript value. [src: GET A POINTER TO THE PARAMETER]
5268
EX DE,HL EB
Exchange DE and HL to swap array pointer and text pointer. [src: SAVE THE TEXT POINTER IN (DE)]
5269
SCF 37
Set the Carry Flag to indicate subscript processing continues. [src: THE STACK, VALTYP GIVES ITS VALUE TYPE]
526A
LOOP
- JUMP back to 5203H to process the next subscript or complete array access. [src: SAVE THE VALUE ON THE STACK]
526CPUSSTR
If No Carry flag is set, JUMP to ROM routine at 2423H - single precision array with simple subscript. [src: FRMEVL DOESN'T ALLOW STRINGS TO COME]
526F
PUSH DE D5
Save DE (text pointer) onto the stack. [src: PUT THE POINTER AT THE VARIABLE VALUE]
5270
EX DE,HL EB
Exchange DE and HL. [src: INTO (DE) AS REQUIRED BY PUTTMP]
5271
GOSUB to ROM routine at 2888H to allocate string space for the array element. [src: SET UP A TEMPORARY WITH THE VALUE OF THE]
5274
POP DE D1
Restore DE (text pointer) from the stack.
5275
XOR A AF
Clear Register A to 0 and clear flags (Z flag set). [src: LEAVE A PSW WITH ZERO SET ON THE]
5276H (FINPUS) - ARRAY SUBSCRIPT PROCESSING AND STORAGE
This section processes accumulated array subscripts from the stack and stores dimension bounds into the array descriptor. It handles the closing parenthesis verification and stores subscript values into the appropriate memory locations. Entry: Stack contains dimension values, HL points to array descriptor, DE points to BASIC text.
5276FINPUS
PUSH HL E5
Save HL (array descriptor pointer) onto the stack. [src: SAVE THE POINTER TO THE END OF THE VALUE]
5277
PUSH AF F5
Save AF (flags including Z from XOR A at 5275H) onto the stack. [src: SAVE WHAT TYPE OF VALUE IT WAS]
5278
EX DE,HL EB
Exchange DE and HL. HL now points to BASIC text, DE points to array descriptor. [src: GET THE TEXT POINTER BACK INTO (HL)]
5279
LD A,(HL) 7E
Load Register A with the current character from BASIC text. [src: IS THE PARAMETERE LIST TERMINATION]
527A
CP 29H FE 29
Compare Register A with 29H (ASCII ) closing parenthesis). If equal, Z flag is set. [src: THE END IS MARKED BY ")"]
527C
If NZ flag is set (not a closing parenthesis), JUMP back to 5259H to expect and process another comma-separated subscript. [src: IF NOT ENDING , MAKE SURE THER IS A COMMA]
527E
LD HL,(40F3H) LD HL,(OLDLIN)2A F3 40
Load HL with the saved BASIC text pointer from 40F3H (saved at 5242H). [src: NOW GET THE TEXT-POINTER FROM THE CALL]
5281
RST 08H CF
Call SYNCHR via RST 08H to verify expected token. [src: SEE IF START OF ARG LIST]
5282
(Token byte 28H follows RST 08H) - Verify opening parenthesis (28H). If found (Z set), JUMP to 5269H.
5284
LD HL,(40D8H) LD HL,(TEMP2)2A D8 40
Load HL with the saved array index pointer from 40D8H (saved at 5254H). [src: GET THE POINTER TO THE BEGINNING OF THE]
5287ASGMOR
GOSUB to ROM routine at 260DH to continue processing the array element. [src: READ A PARAMETER ,NO NEED TO OUTLAW]
528A
EX (SP),HL E3
Exchange HL with the value on top of stack. HL gets previous value, stack gets current HL. [src: SAVE THE TEXT POINTER INTO THE PARAMETER]
528B
GOSUB to ROM routine at 1F2BH for additional array processing. [src: LIST]
528E
LD A,(HL) 7E
Load Register A with the byte at current HL position. [src: SEE WHATCOMES AFTER THE ARGUMENT FORMULA]
528F
CP 29H FE 29
Compare Register A with 29H (ASCII )) to check for closing parenthesis. [src: IS THE ARGUMENT LIST ENDING?]
5291
If Z flag is set (found closing parenthesis), JUMP to 529AH to finish subscript processing. [src: MAKE SURE THE ARGUMENT LIST ALSO ENDED]
5293
RST 08H CF
Call SYNCHR via RST 08H to verify expected token. [src: SKIP OVER ARG COMMA]
5294
INC L 2C
(Token byte 2CH follows RST 08H) - Verify comma separator between subscripts.
5295
EX (SP),HL E3
Exchange HL with stack top, rotating pointers. [src: SAVE THE ARGUMENT LIST TEXT POINTER AND GET]
5296
RST 08H CF
Call SYNCHR via RST 08H again. [src: SKIP OVER PARAMETER LIST COMMA]
5297
INC L 2C
(Token byte 2CH follows RST 08H) - Verify another comma.
5298
LOOP
- JUMP back to 5287H to continue processing subscripts. [src: AND BIND THE REST OF THE PARAMETERS]
529AFINASG
RST 10H D7
Call CHRGET via RST 10H to advance past the closing parenthesis. [src: SKIP OVER CLOSING PARENTHESIS]
529B
EX (SP),HL E3
Exchange HL with stack top to restore proper pointer. [src: AND GET THE PARAMETER LIST TEXT POINTER]
529C
RST 08H CF
Call SYNCHR via RST 08H. [src: END OF PARAMETER LIST?]
529D
ADD HL,HL 29
(Token byte 29H follows RST 08H) - Verify closing parenthesis token.
529E
LD A,D5H 3E D5
Load Register A with D5H - a marker value for completed array subscript processing. [src: SKIP THE NEXT BYTE]
529FFINVLS
RST 08H CF
Call SYNCHR via RST 08H to verify next token. [src: HERE WHEN THERE WERE NO ARGUMENTS]
52A0
RST 08H CF
Call SYNCHR again - this is part of inline token verification. [src: SKIP OVER THE '=' IN DEFINITION]
52A1
PUSH DE D5
(Token byte D5H follows RST 08H) - Verify token, then save DE onto stack.
52A2
GOSUB to ROM routine at 2337H for expression evaluation. [src: EVALUATE THE DEFINITRION FORMULA]
52A5
DEC HL 2B
Decrement HL to back up one character in BASIC text.
52A6
RST 10H D7
Call CHRGET via RST 10H to re-fetch current character.
52A7
If NZ flag is set (unexpected character), JUMP to ROM error handler at 1997H for Syntax Error. [src: SEE IF THE STATEMENT ENDED RIGHT]
52AA
RST 20H E7
Call GETYP via RST 20H to determine the result type. [src: IF THE RESULT OF THE FUNCTION]
52AB
If Z flag is set (string type), JUMP to 52DCH to handle string assignment. [src: STORE THE LAST TEMPORARY IN DSCTMP]
52ADMORRV2
POP DE D1
Restore DE from the stack. [src: GET THE TEXT POINTER FROM THE CALLER]
52AEMORRVL
POP AF F1
Restore AF from the stack (flags saved earlier). [src: GET THE TYPE OF VALUE TO BE RESTORED]
52AF
If Z flag is set, JUMP to 52F0H to finalize array element. [src: RESTORE A STRING VALUE]
52B1
If No Carry flag is set, JUMP to 52CFH for different array type handling. [src: IF CARRY IS OFF, WE JUST POPPED OFF]
52B3
POP HL E1
Restore HL (array descriptor pointer) from the stack. [src: GET A POINTER TO THE END OF THE VALUE]
52B4
POP BC C1
Restore BC (dimension value) from the stack. [src: POP OFF THE FIRST PARTOF THE VALUE]
52B5
LD (HL),B 70
Store high byte of dimension (B) into array descriptor at HL. [src: PUT THE VALUE BACK]
52B6
DEC HL 2B
Decrement HL to point to previous byte.
52B7
LD (HL),C 71
Store low byte of dimension (C) into array descriptor.
52B8
If M flag (Minus/Sign) is set, JUMP to 52AEH to continue processing dimensions. [src: INTEGERS ARE FINISHED]
52BB
DEC HL 2B
Decrement HL for next dimension entry.
52BC
POP BC C1
Restore next BC (dimension value) from the stack.
52BD
LD (HL),B 70
Store high byte of this dimension.
52BE
DEC HL 2B
Decrement HL.
52BF
LD (HL),C 71
Store low byte of this dimension.
52C0
If Parity/Overflow flag is clear, JUMP to 52AEH. [src: SINGLE PRECISIONS ARE FINISHED]
52C3
DEC HL 2B
Decrement HL for third dimension entry.
52C4
POP BC C1
Restore BC (third dimension value) from the stack.
52C5
LD (HL),B 70
Store high byte of third dimension.
52C6
DEC HL 2B
Decrement HL.
52C7
LD (HL),C 71
Store low byte of third dimension.
52C8
DEC HL 2B
Decrement HL for fourth dimension entry.
52C9
POP BC C1
Restore BC (fourth dimension value) from the stack.
52CA
LD (HL),B 70
Store high byte of fourth dimension.
52CB
DEC HL 2B
Decrement HL.
52CC
LD (HL),C 71
Store low byte of fourth dimension.
52CD
JUMP to 52AEH to continue processing. [src: DOUBLE PRECISIONS ARE DONE]
52CFDONRVL
PUSH DE D5
Save DE onto the stack. [src: GO RESTORE MORE VALUES]
52D0
PUSH AF F5
Save AF onto the stack. [src: SAVE THE TEXT POINTER]
52D1
RST 20H E7
Call GETYP via RST 20H to get result type. [src: IF THE RESULT IS STRING, WE NEED TO]
52D2
LD DE,40D3H LD DE,DSCTMP11 D3 40
Load DE with address 40D3H (temporary storage for string operations). [src: PLACE TO RESTORE FROM]
52D5
If Z flag is set (string type), GOSUB to ROM routine at 2888H for string allocation. [src: IF STRING, DO THE RESTORE]
52D8
POP AF F1
Restore AF from the stack. [src: GET BAXK THE FUNCTION TYPE]
52D9
JUMP to ROM routine at 281AH to complete the operation. This is in the middle of a routine to convert the result of arithmetic routines to the proper destination type, but not enterest at the top of the routine (at DOCNVF) but after the PUSH HL to skip that.
52DCSTRREL
LD HL,(40B3H) LD HL,(VARPNT)2A B3 40
Load HL with the array variable pointer from 40B3H. [src: SEE IF THE FUNCTION RESULT IS IN A TEMPORARY]
52DF
EX DE,HL EB
Exchange DE and HL. [src: IF NOT, USE STRCPY TO GET IT INTO DSCTMP]
52E0
LD HL,(4121H) LD HL,(FACLO)2A 21 41
Load HL with the variable pointer for DIM from 4121H. [src: (HL) = POINTER AT RESULT DESCRIPTOR]
52E3
RST 18H DF
Call CPDEHL via RST 18H to compare DE with HL. [src: TRMPORARIES ARE BELOW (TEMPPT), VARIAVBLES ARE ABOVE]
52E4
If Carry is set (DE < HL), JUMP to 52EBH. [src: JUST COPY DESCRIPTOR INTO DSCTMP FROM TEMP AND FREE UP TEMP]
52E6
GOSUB to ROM routine at 2843H for string handling. [src: MAKE A COPY OF THE VARIABLE WHICH IS THE RESULT]
52E9
JUMP to 52ADH to continue. [src: RESULT IS NOW IN DSCTMP]
52EBSTRRL2
POP DE D1
Restore DE from the stack. [src: GET THE TEXT POINTER FROM THE CALLER]
52EC
LD HL,40D3H LD HL,DSCTMP21 D3 40
Load HL with address 40D3H (temporary string storage). [src: STORE THE FUNCTION RESULT IN DSCTMP]
52EF
PUSH HL E5
Save HL onto the stack. [src: SO THE OTHER TRMPORARIES CAN BE FREED UP]
52F0POPSTR
GOSUB to ROM routine at 29F5H for final array element processing. [src: FREE UP A TEMPORARY WITHOUT]
52F3
LD A,(HL) 7E
Load Register A with the byte at HL. [src: GET THE LENGTH]
52F4
LD (40B3H),HL LD (VARPNT),HL22 B3 40
Store HL into 40B3H (array variable pointer). [src: UPDATE THE POINTER GIVING THE FIRST]
52F7
POP HL E1
Restore HL from the stack. [src: GET THE PLACE TO RESTORE THE VALUE]
52F8
LD (HL),A 77
Store the value in A at the address pointed to by HL. [src: RESTORE THE LENGTH]
52F9
INC HL 23
Increment HL.
52FA
LD (HL),C 71
Store C at the address pointed to by HL. [src: RESTORE THE POINTER]
52FB
INC HL 23
Increment HL.
52FC
LD (HL),B 70
Store B at the address pointed to by HL.
52FD
JUMP to 52AEH to continue processing. [src: RESTORE MORE VALUES]
52FFH (DEF) - DEFUSR STATEMENT HANDLER
Handles the DEFUSR statement which defines the entry address for a USR machine language function. Syntax: DEFUSR[n]=address where n is 0-9. The address is stored in a lookup table at 5868H.
52FFDEF
CP C1H
Compare Register A with C1H. This checks for a specific token following DEFUSR. [src: DEFINING THE CALL ADDRESS OF USR ROUTINE?]
5301
If Z flag is set (token matches), JUMP to 5354H for alternate DEFUSR handling. [src: YES, DO IT]
5303
GOSUB to 522EH to synchronize with BASIC text via RST 08H. [src: GET A POINTER TO THE FUNCTION NAME]
5306
GOSUB to ROM routine at 2828H to get the address expression value. [src: DEF IS "ILLEGAL DERECT"]
5309
EX DE,HL EB
Exchange DE and HL. DE now has the text pointer, HL has the address value. [src: (DE) = THE TEXT POINTER AFTER THE FUNCTION]
530A
LD (HL),E 73
Store low byte of address (E) at the USR table entry. [src: SAVE THE TEXT POITER AS THE VALUE]
530B
INC HL 23
Increment HL to point to high byte location.
530C
LD (HL),D 72
Store high byte of address (D) at the USR table entry.
530D
EX DE,HL EB
Exchange DE and HL back. HL now has the text pointer. [src: RESTORE THE TEXT POINTER TO (HL)]
530E
LD A,(HL) 7E
Load Register A with the current character from BASIC text. [src: GET NEXT CHAR]
530F
CP 28H FE 28
Compare Register A with 28H (ASCII (). Check if there's a following parameter. [src: DOES THIS FUNCTION HAVE ARGS?]
5311
If NZ flag is set (no open parenthesis), JUMP to ROM at 1F05H to complete the statement. [src: NO]
5314
RST 10H D7
Call CHRGET via RST 10H to advance past the '('.
5315SCNLIS
GOSUB to ROM routine at 260DH to evaluate parameter expression. [src: GET POINER TO DUMMY VAR(CREATE VAR)]
5318
LD A,(HL) 7E
Load Register A with current character. [src: GET TERMINATOR]
5319
CP 29H FE 29
Compare Register A with 29H (ASCII )) checking for closing parenthesis. [src: END OF ARG LIST?]
531B
If Z flag is set (found ')'), JUMP to ROM at 1F05H to finish the statement. [src: YES]
531E
RST 08H CF
Call SYNCHR via RST 08H. [src: COMMA MUST FOLLOW THEN]
531F
INC L 2C
(Token byte 2CH follows RST 08H) - Verify comma separator.
5320
LOOP
- JUMP back to 5315H to process next parameter.
5322H (USROUT) - USR FUNCTION HANDLER
Handles the USR function call which invokes a machine language routine previously defined with DEFUSR. Entry: HL points to text after USR token, optional digit 0-9 specifies which USR slot. Exit: Returns result from machine language routine in the numeric accumulator.
5322USROUT
POP AF
Restore AF from the stack (caller's return info). [src: GET RID OF THE RETURN ADDRESS]
5323USRFN
GOSUB to 5342H to parse the optional USR number (0-9) and get the address table entry. [src: SCAN THE USR#]
5326
PUSH DE D5
Save DE (pointer to USR address table entry) onto the stack. [src: SAVE POINTER]
5327
GOSUB to ROM routine at 252CH to evaluate the argument expression. [src: GET LEFT PAREN AND FORMULA]
532A
EX (SP),HL E3
Exchange HL with stack top. HL gets USR table pointer, stack gets text pointer. [src: SAVE TEXT POINTER & GET INDEX INTO USRTAB]
532B
LD C,(HL) 4E
Load Register C with the low byte of the USR address. [src: GET DISPATCH ADDRESS]
532C
INC HL 23
Increment HL to point to high byte.
532D
LD B,(HL) 46
Load Register B with the high byte of the USR address. BC now contains the USR entry point.
532E
LD HL,26E7H 21 E7 26
Load HL with address 26E7H - the return address for after the USR call completes.
5331
PUSH HL E5
Push the return address onto the stack. [src: PUSH IT ON]
5332
PUSH BC C5
Push the USR address onto the stack (will be used as call target via RET). [src: SAVE ADDRESS OF USER ROUTINE]
5333
LD A,(40AFH) LD A,(VALTYP)3A AF 40
Load Register A with the variable type flag from 40AFH. [src: GET ARGUMENT TYPE IN (A)]
5336
PUSH AF F5
Save the type flag onto the stack for the USR routine to access. [src: SAVE VALTYP]
5337
CP 03H FE 03
Compare Register A with 03H (single precision type). [src: STRING?]
5339
If Z flag is set (single precision), GOSUB to ROM routine at 29DAH to prepare the single-precision value in registers. [src: FREE IT UP]
533C
POP AF F1
Restore AF (type flag) from the stack. This will be available to the USR routine. [src: GET BACK VALTYP]
533D
EX DE,HL EB
Exchange DE and HL. Sets up registers for USR routine parameter passing. [src: MOVE POSSIBLE DESC. POINTER TO (DE)]
533E
LD HL,4121H LD HL,FACLO21 21 41
Load HL with address 4121H - pointer to variable storage area for USR to return value. [src: POINTER TO FAC IN (HL)]
5341
RET C9
RETurn - This pops the USR address from stack and jumps to the user's machine language routine. When USR routine executes RET, control returns to 26E7H.
5342H (SCNUSR) - USR NUMBER PARSER
Parses the optional digit (0-9) after USR to determine which USR slot to use. If no digit follows, defaults to USR0. Returns pointer to the 2-byte address entry in the USR table at 5868H. Entry: HL points to BASIC text. Exit: DE = pointer to USR table entry, HL = updated text pointer.
5342SCNUSR
RST 10H D7
Call CHRGET via RST 10H to get the next character (possibly a digit 0-9). [src: GET A CHARACTER]
5343
LD BC,0000H LD BC,RST0001 00 00
Load BC with 0000H - default offset (USR0) if no digit follows. [src: ASSUME USR 0]
5346
If No Carry (character is not a digit 0-9), JUMP to 534DH to use default USR0. [src: NOT NUMERIC , MUST BE SO]
5348
SUB 30H D6 30
Subtract 30H (ASCII '0') from A to convert digit character to numeric value 0-9. [src: MAKE AN OFFSET]
534A
RLCA 07
Rotate A left (multiply by 2) since each USR entry is 2 bytes. [src: MULTIPLY BY 2]
534B
LD C,A 4F
Load Register C with the calculated offset (0, 2, 4, 6, ... 18 for USR0-USR9). [src: SAVE OFFSET IN (C)]
534C
RST 10H D7
Call CHRGET via RST 10H to advance past the digit. [src: GET FOLLOWING CHAR]
534DNOARGU
EX DE,HL EB
Exchange DE and HL. DE now has the text pointer. [src: SAVE TEXT POINER IN (DE)]
534E
LD HL,5868H LD HL,USRTAB21 68 58
Load HL with 5868H - base address of the USR address table (10 entries × 2 bytes). [src: GET STARTOF TABLE]
5351
ADD HL,BC 09
Add BC (offset 0-18) to HL to point to the specific USR entry. [src: ADD ON OFFSET]
5352
EX DE,HL EB
Exchange DE and HL. DE now has pointer to USR entry, HL has text pointer. [src: RETURN FROM SCAN ROUTINE]
5353
RET C9
RETurn to caller with DE = USR table entry pointer, HL = text pointer.
5354H (DEFUSR) - ALTERNATE DEFUSR HANDLER
Alternate entry for DEFUSR when preceded by token C1H. Parses the USR number and stores the address value into the USR table.
5354DEFUSR
GOSUB to 5342H to parse the USR number and get table entry pointer in DE. [src: SCAN THE USER NAME]
5357
PUSH DE D5
Save DE (USR table entry pointer) onto the stack. [src: SAVE POINTER TO USRTAB ENTRY]
5358
RST 08H CF
Call SYNCHR via RST 08H to verify next token. [src: MUST HAVE '=' SIGN]
5359
PUSH DE D5
(Token byte D5H follows RST 08H) - Verify token D5H (likely '=' assignment).
535A
GOSUB to ROM routine at 2B02H to evaluate the address expression. [src: GET THE ADDRESS]
535D
EX (SP),HL E3
Exchange HL with stack top. HL gets USR table pointer, stack gets text pointer. [src: TEXT POINTER TO STACK, GET ADDRESS]
535E
LD (HL),E 73
Store low byte of address (E) into the USR table entry. [src: SAVE USR CALL ADDRESS]
535F
INC HL 23
Increment HL to point to high byte location. [src: BUMP POINRER]
5360
LD (HL),D 72
Store high byte of address (D) into the USR table entry. [src: SAVE HIGH BYTE OF ADDRESS]
5361
POP HL E1
Restore HL (text pointer) from the stack. [src: RESTORE TEXT POINTER]
5362
RET C9
RETurn to caller - DEFUSR statement complete.
5363H (UFERR) - UNDEFINED ARRAY ERROR HANDLER
Generates error code 2EH (Undefined array) when an array is referenced that hasn't been dimensioned. Jumps to the standard BASIC error handler.
5363UFERR
LD E,2EH 1E 2E
Load Register E with error code 2EH - "Undefined array" error number.
5365
JUMP to ROM error handler at 19A2H to display error message and return to READY.
5368H (FILGTO) - CMD Statement Pre-Check Routine
This routine is called before processing CMD statements that require a file number. It checks if the next token is the USING keyword (token CEH) and if so, returns immediately with Z flag set. Otherwise, it validates that the current variable contains a valid file number and jumps to the file number validation routine at 5A46H.
5368FILGTO
PUSH HL E5
Save HL (current BASIC line pointer) on stack [src: ALLOW CASSETTE STUFF TO GO BACK]
5369
RST 10H D7
Call CHRGET - get next character from BASIC line, skip spaces [src: SEE WHAT NEXT CHAR IS]
536A
CP CEH FE CE
Compare with CEH (USING keyword token). If match, Z flag is set
536C
POP HL E1
Restore HL (BASIC line pointer)
536D
LD A,(HL) 7E
Load Register A with byte at current BASIC line position [src: GET BACK THE CHAR]
536E
RET Z C8
If Z flag set (USING keyword found), RETURN - let caller handle PRINT USING [src: RETURN IF ZERO]
Not USING keyword - this is a PRINT# or CMD requiring a file number. Continue to validate.
536F
LD C,02H 0E 02
Load Register C with 02H (file access mode = output)
5371
JUMP to 5A46H to validate file number and set up for output
5374H (CMD) - CMD Statement Main Handler (Device Dispatcher)
This is the main entry point for the CMD statement. It evaluates a string expression to get the device/option code, then dispatches to the appropriate handler based on the first character. CMD supports: D (DOS directory), L (LOAD command string), P (PRINT# position), J (JKL system), Z (ZONE settings), C (cassette options), O (file rename), X (DOS exit), B (BREAK on/off), E (video enable), T (tape operations), R (cassette read), S (SYSTEM), A (SYSTEM with carry), & (debug/special), and I (immediate DOS command).
5374CMD
Call ROM routine to skip spaces and set up expression evaluation [src: SEE WHAT FLAVOR OF "CMD" IT IS]
5377
PUSH HL E5
Save HL (BASIC line pointer after expression) on stack [src: SAVE THE TEXT POINTER]
5378
Call ROM routine to evaluate string expression - returns string descriptor in HL [src: RELEASE THE SPACE AND TEMP]
537B
LD A,(HL) 7E
Load Register A with string length from descriptor [src: GET THE LENGHT]
537C
OR A B7
Test if string length is zero
537D
If string empty (Z set), JUMP to Illegal Function Call error at 1E4AH
String is not empty. Get pointer to actual string data from descriptor bytes 2-3.
5380
INC HL 23
Point to low byte of string address in descriptor [src: GET A POINTER AT THE DATA]
5381
LD E,(HL) 5E
Load Register E with low byte of string data address
5382
INC HL 23
Point to high byte of string address
5383
LD D,(HL) 56
Load Register D with high byte of string data address. DE now points to string
5384
LD A,(DE) 1A
Load Register A with first character of CMD string (the command letter)
Now dispatch based on the command letter. Each letter has a specific handler.
5385
CP 44H FE 44
Compare with D (44H) - DOS directory listing command
5387
If D, JUMP to 541AH - CMD "D" handler (directory with options) [src: DO DIRECTORY]
538A
CP 4CH FE 4C
Compare with L (4CH) - LOAD command handler [src: LOAD MACHINE LANGUAGE PGM]
538C
If L, JUMP to 54F3H - CMD "L" handler (load program via string)
538F
CP 50H FE 50
Compare with P (50H) - PRINT# position handler [src: RETURN PRINTER STATUS]
5391
If P, JUMP to 552DH - CMD "P" handler (set print position)
5394
CP 4AH FE 4A
Compare with J (4AH) - JKL system command [src: RETURN JULIAN DATE]
5396
If J, JUMP to 557CH - CMD "J" handler (execute JKL system routine)
5399
CP 5AH FE 5A
Compare with Z (5AH) - ZONE settings (ROUTE/DUAL) [src: TOGGLE DUAL?]
539B
If Z, JUMP to 559FH - CMD "Z" handler (zone/route/dual settings)
539E
CP 43H FE 43
Compare with C (43H) - Cassette options (R/S) [src: COMPRESS?]
53A0
If C, JUMP to 55F4H - CMD "C" handler (cassette read/save options)
53A3
CP 4FH FE 4F
Compare with O (4FH) - File rename operation [src: SORT?]
53A5
If O, JUMP to 5610H - CMD "O" handler (rename old file to new)
53A8
CP 58H FE 58
Compare with X (58H) - DOS exit command [src: CROSS REFERENCE?]
53AA
If X, JUMP to 5594H - CMD "X" handler (exit to TRSDOS)
53AD
CP 42H FE 42
Compare with B (42H) - BREAK on/off command [src: BREAK KEY OFF?]
53AF
If B, JUMP to 564BH - CMD "B" handler (enable/disable BREAK key)
53B2
CP 45H FE 45
Compare with E (45H) - Video enable command
53B4
If E, JUMP (relative) to 5410H - CMD "E" handler (video output control)
53B6
CP 54H FE 54
Compare with T (54H) - Tape operations
53B8
If T, JUMP (relative) to 53DAH - CMD "T" handler (tape motor control)
53BA
CP 52H FE 52
Compare with R (52H) - Cassette read mode
53BC
If R, JUMP (relative) to 53D5H - CMD "R" handler (cassette read)
53BE
CP 53H FE 53
Compare with S (53H) - SYSTEM command
53C0
If S, JUMP to 59C9H - CMD "S" handler (SYSTEM command)
53C3
CP 41H FE 41
Compare with A (41H) - SYSTEM with carry set
53C5
SCF 37
Set Carry Flag (will be passed to SYSTEM handler as mode indicator)
53C6
If A, JUMP to 59C9H - CMD "A" handler (SYSTEM with special flag)
53C9
CP 26H FE 26
Compare with & (26H) - Debug/special command
53CB
If &, JUMP to 5487H - CMD "&" handler (special debug/poke operations)
53CE
CP 49H FE 49
Compare with I (49H) - Immediate DOS command
53D0
If I, JUMP (relative) to 53E0H - CMD "I" handler (immediate DOS command)
No valid command letter matched - this is an invalid CMD option.
53D2
JUMP to Illegal Function Call error at 1E4AH
53D5H (TIMEN) - CMD "R" Handler (Cassette Read Mode)
This handler activates cassette read mode by calling the ROM cassette initialization routine at 0298H. After setup, it re-enables interrupts and returns to BASIC.
53D5TIMEN
Call ROM cassette read initialization routine at 0298H [src: TURN THE CLOCK ON]
53D8
JUMP (relative) to 53DDH - common exit (restore HL, enable interrupts, return)
53DAH (OFTIM) - CMD "T" Handler (Tape Motor Control)
This handler controls the cassette tape motor by calling the ROM routine at 02A1H. This allows BASIC programs to start/stop the tape motor programmatically.
53DAOFTIM
Call ROM tape motor control routine at 02A1H [src: TURN THE CLOCK OFF]
53DDCOMMON
POP HL E1
Restore HL (BASIC line pointer saved at 5377H)
53DE
EI FB
Enable interrupts (cassette routines may have disabled them)
53DF
RET C9
RETURN to BASIC interpreter
53E0H (CMDUUO) - CMD "I" Handler (Immediate DOS Command)
This handler executes an immediate TRSDOS command from a string. It expects the syntax CMD "I,command" where "command" is the DOS command string. The routine copies the command to the DOS command buffer at 4225H and calls the $COMDOS routine at 4299H to execute it.
53E0CMDUUO
POP HL E1
Restore HL (BASIC line pointer) [src: GET BACK THE TEXT POINTER]
53E1
RST 08H CF
SYNCHR - verify next character matches inline byte
53E2
DEFB 2CH 2C
Inline byte: require , (comma) separator
53E3
Call ROM routine to skip spaces and prepare for expression
53E6
PUSH HL E5
Save HL (BASIC line pointer after comma) on stack
53E7
Call ROM routine to evaluate string expression - get DOS command string
53EA
LD A,(HL) 7E
Load Register A with string length from descriptor
53EB
OR A B7
Test if string length is zero [src: NULL STRINGS NOT ALLOWED]
53EC
If string empty, JUMP to Illegal Function Call error
String has content. Extract address and length for copying to DOS buffer.
53EF
INC HL 23
Point to low byte of string address [src: GET POINTER AT DATA INTO (DE)]
53F0
LD E,(HL) 5E
Load Register E with low byte of string address
53F1
INC HL 23
Point to high byte of string address
53F2
LD D,(HL) 56
Load Register D with high byte. DE now points to command string
53F3
LD C,A 4F
Copy string length to Register C [src: GET THE COUNT IN BC]
53F4
LD B,00H 06 00
Clear Register B - BC now holds string length (0-255)
53F6
INC BC 03
Increment BC to include terminating CR in copy count [src: INC FOR THE CR]
53F7
LD L,A 6F
Load Register L with string length
53F8
LD H,00H 26 00
Clear Register H - HL now holds string length
53FA
ADD HL,DE 19
Add string base to length - HL points past end of string
53FB
LD A,(HL) 7E
Load Register A with byte after string (save it)
53FC
PUSH AF F5
Save original byte on stack (will restore after command execution)
53FD
LD (HL),0DH 36 0D
Store 0DH (CR) as terminator after string
53FF
PUSH HL E5
Save terminator position on stack
5400
EX DE,HL EB
Exchange: HL = source string address, DE = terminator position [src: HL => FRONT OF COMMAND]
5401
LD DE,4225H 11 25 42
Load DE with DOS command line buffer address (4225H) [src: DE => DOS COMMAND LINE]
5404
PUSH DE D5
Save buffer address on stack (for COMDOS call) [src: SAVE IT]
5405
LDIR ED B0
Block copy: copy BC bytes from (HL) to (DE) - command string to DOS buffer [src: MOVE THE OPERATION TO THE COMMAND LINE]
5407
POP HL E1
Restore HL = 4225H (DOS command buffer address) [src: HL => COMMAND TO EXECUTE]
5408
Call $COMDOS at 4299H - execute DOS command, returns to BASIC READY on completion
After DOS command completes, restore the original byte we overwrote with CR.
540B
POP HL E1
Restore HL = position where we put CR terminator
540C
POP AF F1
Restore original byte in Register A
540D
LD (HL),A 77
Restore original byte after string (remove our CR)
540E
POP HL E1
Restore HL (BASIC line pointer)
540F
RET C9
RETURN to BASIC interpreter
5410H (DERGO) - CMD "E" Handler (Video Enable Control)
This handler controls video output by calling DOS function at 4409H. It reads the last DOS error code from 63BCH, ORs it with C0H (setting bits 6 and 7), and passes this value to the video control routine. This enables or configures video display output.
5410DERGO
LD A,(63BCH) LD A,(DSKERR)3A BC 63
Load Register A with last DOS error code from 63BCH
5413
OR C0H F6 C0
OR with C0H - set bits 6 and 7 (video enable flags) [src: SET BITS 6 & 7]
5415
Call DOS video control routine at 4409H
5418
POP HL E1
Restore HL (BASIC line pointer)
5419
RET C9
RETURN to BASIC interpreter
541AH (DODIR) - CMD "D" Handler (DOS Directory with Options)
This handler processes the CMD "D" command which displays a directory listing with optional filtering. The rest of the CMD string contains filter options that are passed to the DOS directory display routine at 4419H. The format is CMD "D:filter" where filter specifies what files to list.
541ADODIR
EX DE,HL EB
Exchange DE and HL - HL now points to CMD string data [src: POINTER TO HL]
541B
INC HL 23
Skip past the 'D' character to point to filter options [src: BUMP TO NEXT CHAR]
541C
SYNCHR: Verify next char [src: MUST BE FOLLOWED BY ':']
541D
DEFB 3AH 3A
Expected: ':' (colon)
541E
LD A,(HL) 7E
Get character from HL [src: GET THE DRIVE NUMBER]
541F
LD (4271H),A 32 71 42
Store to 4271H [src: SET IT IN DOS]
5422
DOS call [src: GET THE DIRECTORY]
5425
POP HL E1
Restore HL (BASIC line pointer) [src: GET TEXT POINTER OFF STACK]
5426
RET C9
RETURN to BASIC interpreter [src: EXIT]
5427H (LINE) - LINE INPUT Statement Handler
This is the entry point for the LINE INPUT statement. It handles both LINE INPUT# (file input) and LINE INPUT (keyboard input). The statement reads an entire line of text into a string variable without parsing. If a # symbol follows, it redirects to the LINE INPUT# handler at 5AC9H.
5427LINE
RST 08H CF
SYNCHR - verify next character matches inline byte
5428
DEFB 89H 89
Inline byte: require INPUT token (89H) after LINE keyword
5429
Call ROM routine to handle LINE INPUT prompt string if present
542C
LD A,(HL) 7E
Load Register A with current character from BASIC line
542D
CP 23H FE 23
Compare with # (23H) - check for file number prefix
542F
If # found, JUMP to 5AC9H - LINE INPUT# file handler
No # symbol - this is keyboard LINE INPUT. Get variable to store result.
5432
Call ROM routine to get/create string variable - returns address in DE [src: PRINT QUOTED STRING IF ONE]
5435
Call ROM routine to verify it's a string variable (error if not) [src: READ STRING TO STORE INTO]
5438
Call ROM routine to finalize variable setup [src: MAKE SURE ITS A STRING]
543B
PUSH DE D5
Save DE (variable address) on stack [src: SAVE POINTER AT VARIABLE]
543C
PUSH HL E5
Save HL (BASIC line pointer) on stack [src: SAVE (HL)]
543D
Call ROM keyboard input routine - read line from keyboard [src: READ A LINE OF INPUT]
5440
POP DE D1
Restore DE (now holds BASIC line pointer) [src: GET DESC. OFF STACK]
5441
POP BC C1
Restore BC (now holds variable address) [src: GET TEXT POINTER OFF TEMP]
5442
If Carry set (BREAK pressed), JUMP to BREAK handler at 1DBEH [src: IF CONTROL-C, STOP]
Input completed successfully. Copy input line to string variable.
5445
PUSH BC C5
Save BC (variable address) on stack [src: SAVE BACK TEXT POINTER]
5446
PUSH DE D5
Save DE (BASIC line pointer) on stack [src: SAVE DESC. BACK]
5447
LD B,00H 06 00
Clear Register B (string processing flag = 0) [src: SETUP ZERO AS ONLY TERMINATOR]
5449
Call ROM routine to process input buffer into string [src: LITERALIZE THE INPUT]
544C
POP HL E1
Restore HL (BASIC line pointer) [src: RESTORE (HL) = TEXT POINTER]
544D
XOR A AF
Clear Register A (success indicator = 0) [src: SET ZERO FOR STRING]
544E
JUMP to ROM routine at 1F32H to complete string assignment and continue execution [src: DO THE ASSIGNMENT]
5451H (FINDRT) - Clear File Buffer Pointer Routine
This utility routine clears the current FCB (File Control Block) pointer at 63BEH to indicate no file is currently active. It's called when closing files or when file operations complete.
5451FINDRT
PUSH HL E5
Save HL on stack [src: ZERO OUT PTRFIL AND SAVE (HL)]
5452
LD L,A 6F
Load Register L with A (which is 0 from caller) [src: (A) = 0]
5453
LD H,A 67
Load Register H with A (also 0) - HL = 0000H
5454
LD (63BEH),HL LD (PTRFIL),HL22 BE 63
Store 0000H at 63BEH - clear current FCB pointer (no file active)
5458
RET C9
RETURN to caller
5459H (FILSTI) - PRINT# File Number Check Routine
This routine validates the file number for PRINT# statements. It expects A to contain '#' (23H) when called. If '#' is present, it advances to get the file number and validates it for output. If not '#', it returns to normal PRINT handling.
5459FILSTI
PUSH HL E5
Save HL (BASIC line pointer) on stack [src: SAVE THE TEXT POINTER]
545A
CP 23H FE 23
Compare Register A with # (23H) [src: IS THERE A NUMBER]
545C
If not '#', JUMP to ROM PRINT continuation at 26E7H [src: IF NOT , DONE]
'#' found - this is PRINT# (output to file). Check for USING keyword.
545F
RST 10H D7
CHRGET - get next character after '#' [src: IS IT NEGATIVE?]
5460
CP CEH FE CE
Compare with USING token (CEH)
5462
POP HL E1
Restore HL (BASIC line pointer) [src: FETCH BACK THE ORIGINAL TEXT POINTER]
5463
LD A,(HL) 7E
Reload Register A with current character [src: GET THE CHARACTER]
5464
RET Z C8
If USING keyword found (Z set), RETURN - caller handles PRINT# USING [src: LET CASSETTE I/O GO BACK]
Not USING - this is plain PRINT#. Set up file for output.
5465
POP BC C1
Pop return address into BC (discard - we'll jump elsewhere) [src: GETRID OF THE RETURN ADDRESS]
5466
Call file number validation routine at 5A44H
5469
PUSH HL E5
Save HL (BASIC line pointer after file number)
546A
LD HL,(40A7H) LD HL,(TEMPPT)2A A7 40
Load HL with input buffer pointer from 40A7H
546D
DEC HL 2B
Decrement to point to last valid position
546E
JUMP to ROM routine at 21EBH to continue PRINT# processing
5471H (EXCHDS) - Check if Output to File Active
This routine checks whether output is currently being directed to a file (vs console). It examines the FCB pointer at 63BEH - if it's zero, no file output is active. If non-zero, it checks if the return address indicates we're coming from the right place in the PRINT routines and redirects accordingly.
5471EXCHDS
PUSH HL E5
Save HL on stack [src: SEE IF ITS A DISK FILE]
5472
LD HL,(63BEH) LD HL,(PTRFIL)2A BE 63
Load HL with current FCB pointer from 63BEH
5475
LD A,H 7C
Load Register A with high byte of FCB pointer
5476
OR L B5
OR with low byte - test if FCB pointer is zero
5478
RET Z C8
If FCB pointer is zero (no file active), RETURN - normal output [src: IF NOT, IGNORE IT]
File output is active. Check where we came from and redirect.
5479
EX (SP),HL E3
Exchange HL with top of stack - get return address into HL [src: SEE WHO IS CALLING]
547A
PUSH DE D5
Save DE on stack
547B
LD DE,2B2EH 11 2E 2B
Load DE with ROM address 2B2EH (PRINT routine boundary) [src: BEFORE OR AFTER LIST?]
547E
RST 18H DF
CPDEHL - compare DE with HL (return address)
5480
POP HL E1
Restore HL (original value)
5481
If return address >= 2B2EH, JUMP to 2B4AH (alternate PRINT path)
5484
Otherwise JUMP to 2282H (standard PRINT path with file output)
5487H (MICPRT) - CMD "&" Handler (Debug/Special Operations)
This handler processes the CMD "&" command which provides special debug and memory poke operations. The format is CMD "&&" (double ampersand required). It then calls a data table interpreter at 563FH with a pointer to the operation table at 549BH. This allows direct memory manipulation and system control.
5487MICPRT
POP HL E1
Restore HL (BASIC line pointer) [src: GET VACK THE TEXT POINTER]
5488
LD A,(HL) 7E
Load Register A with current character (should be '&')
5489
CP 26H FE 26
Compare with & (26H) - verify double ampersand
548B
If not '&', JUMP to Illegal Function Call error
548E
RST 10H D7
CHRGET - get next character (skip second '&')
548F
If not end of statement (NZ), JUMP to Illegal Function Call error
Valid CMD "&&" - execute debug table operations.
5492
PUSH HL E5
Save HL (BASIC line pointer) on stack
5493
LD HL,549BH LD HL,MESMIC21 9B 54
Load HL with address of operation table at 549BH
5496
Call table interpreter routine at 563FH [src: UNSCRAMBLE THE TEXT AND DISPLAY IT]
5499
POP HL E1
Restore HL (BASIC line pointer)
549A
RET C9
RETURN to BASIC interpreter
549BH (MESMIC) - CMD "&" Operation Data Table
This is a data table used by the CMD "&" debug handler. It contains encoded operations for memory manipulation, system control, and special functions. The data is interpreted by the routine at 563FH. Each entry specifies a memory address and operation to perform. The table is XOR-encoded with 55H for obfuscation.
Data table: 88 bytes of encoded debug operation definitions from 549BH to 54F2H. Format is interpreted by routine at 563FH - XOR 55H decoding applied to each byte.
549BMESMIC
DEFB 35H,01H,3DH,3CH,26H,75H 35 01 3D 3C 26 75
Encoded operation entry 1
54A1
DEFB 17H,34H,26H,3CH,36H,75H 17 34 26 3C 36 75
Encoded operation entry 2
54A7
DEFB 3CH,26H,75H,16H,1AH,05H 3C 26 75 16 1A 05
Encoded operation entry 3
54AD
DEFB 0CH,07H,1CH,12H,1DH,01H 0C 07 1C 12 1D 01
Encoded operation entry 4
54B3
DEFB 10H,11H,75H,37H,2CH,75H 10 11 75 37 2C 75
Encoded operation entry 5
54B9
DEFB 01H,14H,1BH,11H,0CH,75H 01 14 1B 11 0C 75
Encoded operation entry 6
54BF
DEFB 16H,1AH,07H,05H,1AH,07H 16 1A 07 05 1A 07
Encoded operation entry 7
54C5
DEFB 14H,01H,1CH,1AH,1BH,79H 14 01 1C 1A 1B 79
Encoded operation entry 8
54CB
DEFB 75H,64H,6CH,6DH,65H,58H 75 64 6C 6D 65 58
Encoded operation entry 9 (contains "dlme" text?)
54D1
DEFB 01H,1FH,58H,05H,27H,3AH 01 1F 58 05 27 3A
Encoded operation entry 10
54D7
DEFB 21H,30H,36H,21H,3CH,3AH 21 30 36 21 3C 3A
Encoded operation entry 11
54DD
DEFB 3BH,75H,3DH,34H,26H,75H 3B 75 3D 34 26 75
Encoded operation entry 12
54E3
DEFB 16H,19H,10H,14H,07H,10H 16 19 10 14 07 10
Encoded operation entry 13
54E9
DEFB 11H,75H,18H,30H,38H,3AH 11 75 18 30 38 3A
Encoded operation entry 14
54EF
DEFB 27H,2CH,58H,01H 27 2C 58 01
Encoded operation entry 15 (final entry marker)
54F3H (LOADPG) - CMD "L" Handler (LOAD Program from String)
This handler processes the CMD "L,filename" command which loads a program file. The filename is taken from a BASIC string expression following the comma. The routine copies the filename to the DOS command buffer at 4465H (with CR terminator) and calls the DOS $LOAD routine at 4430H.
54F3LOADPG
POP HL E1
Restore HL (originally points to CMD string - but we discard this) [src: GET TEXT POINTER BACK]
54F4
RST 08H CF
SYNCHR - verify next character matches inline byte [src: MUST HAVE COMMA]
54F5
DEFB 2CH 2C
Inline byte: require , (comma) separator after 'L'
54F6
Call ROM routine to skip spaces and prepare for expression [src: CONVERT THE NAME INTO STRING]
54F9
PUSH HL E5
Save HL (BASIC line pointer after comma) on stack [src: SAVE POINTER]
54FA
Call ROM routine to evaluate string expression - get filename string
54FD
LD A,(HL) 7E
Load Register A with string length from descriptor [src: GET 1ST CHAR]
54FE
OR A B7
Test if string length is zero [src: NULL STRINGS NOT ALLOWED]
54FF
If Carry set (error condition), JUMP to Illegal Function Call [src: EXIT IF ERROR]
Get string address and calculate position for CR terminator.
5502
INC HL 23
Point to low byte of string address [src: GET POINTER AT DATA INTO (DE)]
5503
LD E,(HL) 5E
Load Register E with low byte of string address
5504
INC HL 23
Point to high byte of string address
5505
LD D,(HL) 56
Load Register D with high byte. DE = filename string address
5506
LD L,A 6F
Load Register L with string length [src: PUT THE LENGTH INTO HL]
5507
LD H,00H 26 00
Clear Register H - HL = string length
5509
ADD HL,DE 19
Add base to length - HL points past end of filename string [src: HL => END OF FILESPEC]
550A
LD A,(HL) 7E
Load Register A with byte after filename (save for restoration)
550B
PUSH AF F5
Save original byte on stack
550C
LD (HL),0DH 36 0D
Store 0DH (CR) as filename terminator [src: SET CR AT END]
550E
PUSH HL E5
Save terminator position on stack [src: SAVE POINTER]
550F
EX DE,HL EB
Exchange: HL = source filename, DE = terminator position [src: FRONT POINTER TO HL]
5510
LD DE,4465H 11 65 44
Load DE with DOS command buffer address at 4465H [src: DE => INTERNAL DCB]
[LOOP START] Copy filename character by character to DOS buffer until CR found.
5513LOADP1
LD A,(HL) 7E
LOOP
Load Register A with character from source filename [src: MOVE IT TO INTERNAL DCB]
5514
LD (DE),A 12
Store character to DOS command buffer
5515
CP 0DH FE 0D
Compare with CR (0DH) - end of filename? [src: END OF NAME?]
5517
If CR (Z set), JUMP to 551DH - done copying [LOOP END] [src: YES, EXIT]
5519
INC HL 23
Advance source pointer [src: NO, BUMP POINTERS]
551A
INC DE 13
Advance destination pointer
551B
JUMP back to 5513H - continue copying [LOOP] [src: LOOP TILL END]
Filename copied. Now call DOS to load the program.
551DLOADP2
LD DE,4465H 11 65 44
Load DE with DOS command buffer address (filename location) [src: DE => INTERNAL DCB]
5520
Call DOS $LOAD routine at 4430H to load program file [src: LOAD IN THE PROGRAM]
5523
If NZ (DOS error), JUMP to error handler at 6113H [src: TRAP ANY ERRORS]
Load successful. Restore the byte we overwrote with CR.
5526
POP HL E1
Restore HL = terminator position [src: GET END POINTER BACK]
5527
POP AF F1
Restore original byte in Register A [src: GET VALUE BACK]
5528
LD (HL),A 77
Restore original byte (remove our CR terminator) [src: RESTORE IT]
5529BEXIT
POP HL E1
Restore HL (BASIC line pointer) [src: GET TEXT POINTER BACK]
552A
RET C9
RETURN to BASIC interpreter [src: DONE]
552BDOFORM
Alternate entry - JUMP to 5529H (cleanup and return)
552DH (RETPRT) - CMD "P" Handler (PRINT# Position)
This handler processes the CMD "P,expression" command which sets the print position for subsequent PRINT# output. It evaluates a string expression and stores the position information in a string variable descriptor, then formats the memory size value in a specific format for display purposes.
552DRETPRT
POP HL E1
Restore HL (discard CMD string pointer) [src: GET TEXT POINTER BACK]
552E
RST 08H CF
SYNCHR - verify next character matches inline byte [src: MUST HAVE COMMA]
552F
DEFB 2CH 2C
Inline byte: require , (comma) separator
5530
Call ROM routine to get string variable address in DE [src: GET A POINTER TO THE VARIABLE]
5533
Call ROM routine to finalize variable setup [src: FORCE THE FAC TO STRING VARIABLE]
5536
PUSH HL E5
Save HL (BASIC line pointer) on stack [src: SAVE TEXT POINTER]
5537
LD A,(DE) 1A
Load Register A with string length from variable descriptor [src: GET THE LENGTH OF STRING]
5538
OR A B7
Test if string length is zero [src: NEW STRING?]
5539
If string empty (Z set), JUMP to 5544H - create new string space [src: YES, GET SOME STRING SPACE]
Existing string - get its address from descriptor.
553B
PUSH DE D5
Save DE (variable descriptor address) on stack [src: SAVE THE VARIABLE POINTER]
553C
EX DE,HL EB
Exchange: HL = descriptor address [src: MOVE POINTER TO HL]
553D
INC HL 23
Point to low byte of string address [src: BUMP TO ADDRESS OF STRING]
553E
LD E,(HL) 5E
Load Register E with low byte of string address [src: GET THE ADDRESS OF STRING]
553F
INC HL 23
Point to high byte of string address
5540
LD D,(HL) 56
Load Register D with high byte. DE = string data address
5541
POP HL E1
Restore HL (was DE = descriptor address) [src: GET VARIABLE POINTER BACK]
5542
JUMP to 554FH - continue with string setup [src: AND ADD THE NEW STRING]
Empty string - allocate 3 bytes of string space.
5544RETPR0
PUSH DE D5
Save DE (variable descriptor address) on stack [src: SAVE POINTER TO VARIABLE]
5545
LD A,03H 3E 03
Load Register A with 03H (need 3 bytes for position string) [src: CLEAR 3 SPACES]
5547
Call ROM routine to allocate A bytes of string space [src: GET US SOME STRING SPACE]
554A
LD HL,(40D4H) LD HL,(DSCPNT)2A D4 40
Load HL with string descriptor pointer from 40D4H [src: GET THE ADDRESS OF THE NEW SPACE]
554D
POP DE D1
Restore DE (variable descriptor address) [src: GET THE VARIABLE POINTER BACK]
554E
EX DE,HL EB
Exchange: HL = variable descriptor, DE = new string space [src: PUT THE POINTER INTO HL]
Set up string descriptor: length=3, address=DE.
554FRETP00
LD (HL),03H 36 03
Store 03H as string length in descriptor [src: SET NUMBER OF BYTES OF THE STRING]
5551
INC HL 23
Point to low byte of address in descriptor
5552
LD (HL),E 73
Store low byte of string address [src: SET THE ADDRESS OF THE STRING]
5553
INC HL 23
Point to high byte of address in descriptor
5554
LD (HL),D 72
Store high byte of string address
5555
EX DE,HL EB
Exchange: HL = string data area [src: STORAGE POINTER INTO HL]
Read memory size from port F8H and format as 2-digit number with prefix.
5556
IN A,(F8H) DB F8
Read port F8H - memory configuration/size register [src: GET THE PRINTER VALUE]
5558
CP C8H FE C8
Compare with C8H (200 decimal) - 48K+? [src: DO WE NEED A '2']
555A
LD B,32H 06 32
Load Register B with 2 (32H) - first digit for >=200 [src: (IN CASE)]
555C
LD C,C8H 0E C8
Load Register C with C8H (200) - subtractor for >=200 [src: AMOUNT TO SUBTRACT FROM VALUE (IN CASE)]
555E
If A >= 200 (NC), JUMP to 556CH - use '2' prefix [src: YES, DO IT]
5560
CP 64H FE 64
Compare with 64H (100 decimal) - 32K-48K range? [src: HOW ABOUT A '1']
5562
LD B,31H 06 31
Load Register B with 1 (31H) - first digit for 100-199
5564
LD C,64H 0E 64
Load Register C with 64H (100) - subtractor for 100-199
5566
If A >= 100 (NC), JUMP to 556CH - use '1' prefix [src: YES, DO IT]
5568
LD B,20H 06 20
Load Register B with (20H space) - first digit for <100 [src: NO, IS 99 OR LESS, USE A SPACE]
556A
LD C,00H 0E 00
Load Register C with 00H - no subtraction needed
Store first character and calculate remaining 2-digit number.
556CRETPR1
LD (HL),B 70
Store first character (hundreds digit or space) in string [src: SET THE 1ST BYTE VALUE]
556D
INC HL 23
Advance to next position in string
556E
SUB C 91
Subtract C from A - remove hundreds [src: RELEASE THE DIFFERENCE]
556F
LD (HL),2FH 36 2F
Store 2FH ('0'-1) - will be incremented to get tens digit [src: START WITH 0]
[LOOP START] Divide by 10 to get tens digit.
5571RETPR2
INC (HL) 34
LOOP
Increment tens digit character [src: BUMP THE 10'S DIGIT]
5572
SUB 0AH D6 0A
Subtract 10 from A [src: SUBTRACT FROM UNITS]
5574
If still >= 0 (NC), JUMP back to 5571H - keep counting tens [LOOP] [src: LOOP TILL FOUND]
Remainder is units digit. Convert to ASCII.
5576
ADD 3AH C6 3A
Add 3AH to remainder (compensates for extra SUB 0AH, converts to '0'-'9') [src: BRING TO POSITIVE AND MAKE ASCII]
5578
INC HL 23
Advance to units position in string [src: BUMP TO NEXT VALU]
5579
LD (HL),A 77
Store units digit character
557A
POP HL E1
Restore HL (BASIC line pointer) [src: GET THE TEXT POINTER BACK]
557B
RET C9
RETURN to BASIC interpreter [src: EXIT]
557CH (RETJUL) - CMD "J" Handler (JKL System)
Executes the TRSDOS JKL system routine. The JKL system provides keyboard macro capabilities in TRSDOS.
The JKL system allows users to define keyboard macros. This handler preserves the return address around the DOS call to ensure proper continuation of BASIC command processing.
557CRETJUL
POP HL E1
Restore return address from CMD parser [src: GET TEXT POINTER]
557D
LD (4272H),HL LD (BASIC1),HL22 72 42
Save return address to temporary storage [src: SAVE IT FOR OVERLAY]
5580
Call DOS JKL system routine [src: BRING IN THE OVERLAY]
5583
LD HL,(4272H) LD HL,(BASIC1)2A 72 42
Restore return address [src: GET THE TEXT POINTER BACK]
5586
RET C9
Return to BASIC [src: EXIT]
5594H (GETREF) - CMD "X" Handler (Exit to TRSDOS)
Exits BASIC and returns to TRSDOS operating system prompt.
The EXIT command terminates BASIC and returns control to TRSDOS. The code after the CALL at 5598H is never executed since the DOS exit routine transfers control directly to the operating system. However, it's included for consistency with other handlers.
5594GETREF
POP HL E1
Restore return address from CMD parser [src: GET TEXT POINTER]
5595
LD (4272H),HL LD (BASIC1),HL22 72 42
Save return address to temporary storage [src: SAVE IT FOR THE OVERLAY]
5598
Call DOS exit routine (does not return) [src: BRING IN THE OVERLAY]
559B
LD HL,(4272H) LD HL,(BASIC1)2A 72 42
Restore return address (never executed) [src: GET THE TEXT POINTER BACK]
559E
RET C9
Return (never executed) [src: EXIT]
559FH (DODUAL) - CMD "Z" Handler (ZONE N/F - ROUTE/DUAL Settings)
Controls printer output routing: ZONE "N" enables ROUTE mode (duplicate output to printer), ZONE "F" disables it. The "Z" command syntax is: CMD "Z","N" or CMD "Z","F"
559FDODUAL
POP HL E1
Restore return address from CMD parser [src: GET THE TEXT LINE POINTER BACK]
55A0
SYNCHR: Verify next char is comma [src: MUST HAVE COMMA]
55A1
DEFB 2CH 2C
Expected character: comma
55A2
SYNCHR: Verify next char is quote [src: MUST HAVE DOUBLE QUOTES]
55A3
DEFB 22H 22
Expected character: quote
55A4
LD (4FCFH),HL 22 CF 4F
Save HL (parser position) to temporary storage [src: MUST START WITH 'O']
55A7
DEC HL 2B
Back up to quote character [src: GET THE NEXT CHARACTER]
55A8
CHRGET: Get next character (skip quote)
55A9
INC HL 23
Move to character after quote [src: ON?]
55AA
CP 4EH FE 4E
Is it 'N' (eNable ROUTE/DUAL)?
55AC
If not 'N', check for 'F'
55ADH - Enable ROUTE/DUAL Mode (CMD "Z","N")
Enables printer output duplication - all screen output is also sent to the printer.
The DUAL mode works by redirecting both output vectors to a special handler at 4CE1H that duplicates all output to both the screen and printer. The original vectors are saved so they can be restored when DUAL mode is disabled.
55AD
PUSH HL E5
Save parser position [src: SAVE THE TEXT POINTER]
55AE
LD A,(442FH) LD A,(DUALIT)3A 2F 44
Get current ROUTE/DUAL flag [src: GET THE DUAL FLAG]
55B1
OR A B7
Check if already enabled (FFH) [src: IS DUAL ALREADY ON?]
55B2
If already on, skip to exit [src: YES, JUST EXIT]
55B4
DEC A 3D
Set A = FFH (enable flag) [src: MAKE IT 'NZ']
55B5
LD (442FH),A LD (DUALIT),A32 2F 44
Enable ROUTE/DUAL mode
55B8
LD HL,(401EH) 2A 1E 40
Get primary output vector [src: GET THE DRIVER ADDR]
55BB
LD (4CE7H),HL 22 E7 4C
Save original primary vector [src: SAVE IT IN 'RES' DUAL ROUTINE]
55BE
LD HL,(4026H) 2A 26 40
Get secondary output vector [src: GET THE DRIVER ADDR]
55C1
LD (4CF8H),HL 22 F8 4C
Save original secondary vector [src: SAVE IT IN DUAL ROUTINE]
55C4
LD HL,4CE1H 21 E1 4C
Point to DUAL output handler routine [src: ADDRESS OF THE DUAL ROUTINE]
55C7
LD (401EH),HL 22 1E 40
Set primary output vector to DUAL handler [src: INTO VIDEO]
55CA
LD (4026H),HL 22 26 40
Set secondary output vector to DUAL handler [src: INTO PRINTER]
55CDH (DUALON) - ZONE Command Exit Handler
Common exit point for ZONE command - checks for closing quote and returns.
55CDDUALON
POP HL E1
Restore parser position [src: GET TEXT POINTER BACK]
55CE
LD A,(HL) 7E
Get current character [src: PICK UP THE LAST CHAR ON LINE]
55CF
CP 22H FE 22
Is it closing quote? [src: ENDING QUOTE?]
55D1
RET NZ C0
Return if not (syntax error will follow) [src: NO, EXIT]
55D2
INC HL 23
Skip past closing quote [src: YES, BUMP PAST IT]
55D3
RET C9
Return to command processor
55D4H (DULOFF) - Check for 'F' (Disable ROUTE/DUAL)
Handles CMD "Z","F" to disable printer output duplication.
Disabling DUAL mode restores the original output vectors from their saved locations. This returns output routing to normal screen-only operation. The ROUTE/DUAL flag at 442FH is set to 00H to indicate disabled state.
55D4DULOFF
CP 46H FE 46
Is it 'F' (disable)? [src: OFF?]
55D6
If not 'F', syntax error [src: NO, ERROR]
55D9
SYNCHR: Verify next char [src: MUST HAVE 2ND 'F']
55DA
DEFB 46H 46
Expected character: 'F'
55DBDUALOF
PUSH HL E5
Save parser position [src: SAVE THE TEXT POINTER]
55DC
LD A,(442FH) LD A,(DUALIT)3A 2F 44
Get current ROUTE/DUAL flag [src: GET THE DUAL FLAG]
55DF
OR A B7
Check if enabled (00H = off) [src: DUAL ALREADY OFF?]
55E0
If already off, skip to exit [src: YES, EXIT]
55E2
LD HL,(4CE7H) 2A E7 4C
Get saved primary output vector [src: GET THE SAVED VIDEO DRIVER ADDR]
55E5
LD (401EH),HL 22 1E 40
Restore original primary vector [src: RESTORE]
55E8
LD HL,(4CF8H) 2A F8 4C
Get saved secondary output vector [src: GET THE SAVED PRINTER DRIVER ADDR]
55EB
LD (4026H),HL 22 26 40
Restore original secondary vector [src: RESTORE]
55EE
XOR A AF
Set A = 00H (disable flag) [src: CLEAR THE DUAL FLAG]
55EF
LD (442FH),A LD (DUALIT),A32 2F 44
Disable ROUTE/DUAL mode
55F2
Jump to exit handler [src: AND EXIT]
55F4H (CMPRES) - CMD "C" Handler (Cassette R/S Options)
Controls cassette tape operations: CMD "C" (read mode, E=02) or CMD "C","R" (read mode, E=02) or CMD "C","S" (write mode, E=00). This sets up the cassette system for either reading or writing.
NOTE: There's a bug in this code. When "R" is specified, E should be 02H (read mode), but the code path leaves E=01H. However, at 5602H it jumps to 560AH which calls 4281H. The cassette control routine at 4281H may handle E=01H as read mode, or this might be a minor bug that doesn't affect functionality. The correct values should be: E=02H for read, E=00H for write.
55F4CMPRES
POP HL E1
Restore return address from CMD parser [src: GET THE TEXT POINTER BACK]
55F5
LD A,(HL) 7E
Get next character from command line [src: GET THE NEXT CHAR]
55F6
CP 2CH FE 2C
Is it a comma? [src: COMMA?]
55F8
LD E,02H 1E 02
Default mode = 02H (Read mode) [src: SET FLAG FOR 'BOTH' REM & SPACES]
55FA
If no comma, use default read mode [src: NO, DO BOTH]
55FC
INC HL 23
Skip past comma [src: BUMP TO NEXT CHAR]
55FD
DEC E 1D
E = 01H (intermediate value) [src: DEC THE FLAG]
55FE
LD A,(HL) 7E
Get option character [src: GET THE LETTER]
55FF
INC HL 23
Move to next position [src: BUMP PAST LETTER]
5600
CP 52H FE 52
Is it 'R' (Read)? [src: REMARK?]
5602
If 'R', E=01H is incorrect; jump to call [src: YES, DO IT]
5604
DEC E 1D
E = 00H (Write mode for 'S') [src: DEC THE FLAG]
5605
CP 53H FE 53
Is it 'S' (Save/Write)? [src: SPACES?]
5607
If not 'S', syntax error [src: NO, ERROR]
560AH (CMPRE1) - Execute Cassette Control
Calls the DOS cassette control routine with the mode in register E.
560ACMPRE1
PUSH HL E5
Save parser position [src: SAVE TEXT POINTER]
560B
Call cassette control (E = mode) [src: DO THE COMPRESS]
560E
POP HL E1
Restore parser position [src: GET THE POINTER BACK]
560F
RET C9
Return to BASIC [src: EXIT]
5610H (DOSORT) - CMD "O" Handler (Rename File)
Renames a disk file. Syntax: CMD "O", oldname$, newname$ - The "O" command provides file renaming capability from BASIC.
The rename operation requires two string parameters. The DOS routine at 4284H expects the old filename pointer at 4272H and the new filename pointer at 4274H. Both filenames must be valid strings; empty strings cause a Type Mismatch error.
5610DOSORT
POP HL E1
Restore return address from CMD parser [src: GET THE COMMAND POINTER BACK]
5611
SYNCHR: Verify next char is comma [src: MUST HAVE COMMA]
5612
DEFB 2CH 2C
Expected character: comma
5613
Evaluate expression (old filename) [src: GET A POINTER TO THE VARIABLE]
5616
LD A,(40AFH) LD A,(VALTYP)3A AF 40
Get variable type flag [src: GET THE TYPE OF EXPRESSION]
5619
CP 02H FE 02
Is it a string (type 2)? [src: INTEGER?]
561B
If not string, "Type Mismatch" error [src: NO, ERROR]
561E
PUSH HL E5
Save parser position [src: SAVE TEXT POINTER]
561F
EX DE,HL EB
DE = parser position, HL = string descriptor [src: MOVE THE POINTER TO HL]
5620
LD E,(HL) 5E
E = string length [src: PICK UP THE VALUE]
5621
INC HL 23
Point to address low byte
5622
LD D,(HL) 56
D = string address low byte
5623
POP HL E1
Restore parser position [src: GET THE TEXT POINTER BACK]
5624
LD (4272H),DE LD (BASIC1),DEED 53 72 42
Save old filename pointer to 4272H [src: SAVE NUMBER OF VARIABLES]
5628
SYNCHR: Verify next char is comma [src: MUST HAVE COMMA]
5629
DEFB 2CH 2C
Expected character: comma
562A
Evaluate expression (new filename) [src: GET A POINTER TO THE LAST VARIABLE]
562D
Get string address in DE, length in A [src: FORCE FAC TO STRING]
5630
PUSH HL E5
Save parser position [src: SAVE THE TEXT POINTER]
5631
LD A,(DE) 1A
Get first character of new filename [src: GET THE LENGTH OF THE STRING]
5632
OR A B7
Check if null (empty string) [src: ANYTHING?]
5633
If empty, "Type Mismatch" error [src: NO, ERROR]
5636
LD (4274H),DE LD (BASIC2),DEED 53 74 42
Save new filename pointer to 4274H [src: SAVE THE POINTER FOR SORT]
563A
Call DOS rename file routine [src: DO THE SORT]
563D
POP HL E1
Restore parser position [src: GET TEXT POINTER BACK]
563E
RET C9
Return to BASIC
563FH (SCRMBL) - XOR-Encoded Table Interpreter
Processes XOR 55H encoded command tables. Used by CMD "&" handler to interpret encoded operation data. This routine reads a count byte, then XOR-decodes and outputs each subsequent byte.
This routine is used to decode the CMD "&" operation data table at 549BH-54F2H. Each byte in the table is XOR'd with 55H to produce the actual character to output. This simple encoding may have been used to avoid conflicts with special characters or control codes in the source file.
563FSCRMBL
LD B,(HL) 46
B = byte count from table [src: GET THE COUNT]
5640
INC HL 23
Point to next data byte [LOOP START]
5641SCRMB1
LD A,(HL) 7E
Get encoded byte [LOOP] [src: GET A BYTE]
5642
XOR 55H EE 55
Decode by XOR with 55H [src: UNSCRAMBLE IT]
5644
Output character in A to current device [src: DISPLAY IT]
5647
INC HL 23
Point to next encoded byte [src: BUMP TO NEXT CHAR]
5648
Repeat for all B bytes [LOOP END] [src: LOOP FOR COUNT]
564A
RET C9
Return to caller
564BH (KILBRK) - CMD "B" Handler (BREAK ON/OFF)
Controls CTRL+C break handling. CMD "B","N" enables breaks (stores C9H=RET at 42AEH). CMD "B","F" disables breaks (stores C3H=JP at 42AEH). This uses self-modifying code to enable/disable the break check.
564BKILBRK
POP HL E1
Restore return address from CMD parser [src: GET THE TEXT LINE POINTER BACK]
564C
SYNCHR: Verify next char is comma [src: MUST HAVE COMMA]
564D
DEFB 2CH 2C
Expected character: comma
564E
SYNCHR: Verify next char is quote [src: MUST HAVE DOUBLE QUOTES]
564F
DEFB 22H 22
Expected character: quote
5650
LD (4FCFH),HL 22 CF 4F
Save parser position [src: MUST START WITH 'O']
5653
DEC HL 2B
Back up to quote [src: GET THE NEXT CHARACTER]
5654
CHRGET: Get next char (skip quote)
5655
INC HL 23
Move to character after quote [src: ON?]
5656
CP 4EH FE 4E
Is it 'N' (eNable breaks)?
5658
If not 'N', check for 'F'
565A
LD A,C9H 3E C9
A = C9H (RET opcode - enables breaks)
565C
Jump to store break enable byte
565DH (KILBR1) - Check for 'F' (Disable Breaks)
565DKILBR1
CP 46H FE 46
Is it 'F' (disable breaks)? [src: OFF?]
565F
If not 'F', syntax error [src: NO, ERROR]
5662
SYNCHR: Verify next char is 'F' [src: MUST HAVE 2ND 'F']
5663
DEFB 46H 46
Expected character: 'F'
5664
LD A,C3H 3E C3
A = C3H (JP opcode - disables breaks) [src: SET A 'JP' INSTRUCIONT]
5666H (KILBR2) - Store Break Control Byte and Exit
The BREAK control mechanism uses self-modifying code. Location 42AEH contains either RET (C9H) which allows breaks, or JP (C3H) which bypasses the break check. When breaks are disabled, the break handler immediately jumps past the break detection code. This is an efficient way to enable/disable a feature without conditionals in the time-critical break check routine.
5666KILBR2
LD (42AEH),A LD (BREAKK),A32 AE 42
Store opcode at break check location [src: SET THE INSTRUCTION IN DOS]
5669
LD A,(HL) 7E
Get current character [src: PICK UP THE LAST CHAR ON LINE]
566A
CP 22H FE 22
Is it closing quote? [src: ENDING QUOTE?]
566C
RET NZ C0
Return if not (error will follow) [src: NO, EXIT]
566D
INC HL 23
Skip past closing quote [src: YES, BUMP PAST IT]
566E
RET C9
Return to BASIC [src: DONE, EXIT]
566FH (RENUMB) - NAME Statement Handler
Implements the NAME statement for renaming files. Syntax: NAME oldname$ AS newname$. This provides an alternative syntax to CMD "O" for file renaming.
The NAME statement closes all files before attempting the rename operation. This ensures that neither the old nor new filename is currently in use by an open file buffer. The actual rename processing is handled by the DOS routine at 427EH.
566FRENUMB
PUSH BC C5
Save registers [src: SAVE ALL REGISTER AND POINTERS]
5670
PUSH DE D5
Save registers
5671
PUSH HL E5
Save parser position
5672
Close all open files [src: CLOSE ALL FILES]
5675
POP HL E1
Restore parser position [src: RESTORE ALL POINTERS]
5676
POP DE D1
Restore registers
5677
POP BC C1
Restore registers
5678
Jump to DOS NAME handler [src: DO THE RENUMBER]
567BH (INSTR) - FILES Statement Handler
Implements the FILES statement for displaying disk directory. Syntax: FILES [filespec$] - If no filespec is provided, displays all files. This provides directory listing capability from BASIC programs.
567BINSTR
CHRGET: Get next character from command
567C
Evaluate expression (optional filespec) [src: EAT FIRST CHAR]
567F
GETYP: Check variable type
5680
LD A,01H 3E 01
A = 01H (numeric type flag) [src: IF SO, ASSUME SEARCH START AT FIRST CHAR]
5682
PUSH AF F5
Save type indicator [src: SAVE OFFSET IN CASE STRING]
5683
If string (Z=1), jump to process filespec [src: WAS A STRING]
5685
POP AF F1
Restore type (numeric) [src: GET RID OF SAVED OFFSET]
5686
Convert numeric to integer in HL [src: FORCE ARG1 (I%) TO BE INTEGER]
5689
OR A B7
Check if result is zero [src: DONT ALLOW ZERO OFFSET]
568A
If zero, "Type Mismatch" error [src: KILL HIM]
568D
PUSH AF F5
Save numeric value (now type=numeric confirmed) [src: SAVE FOR LATER]
568E
SYNCHR: Verify next char is comma [src: EAT THE COMMA]
568F
DEFB 2CH 2C
Expected character: comma
5690
Evaluate string expression (filespec) [src: EAT FIRST STRING ARG]
5693
Get string address in DE [src: BLOW UP IF NOT STRING]
5696H (WUZSTR) - Process FILES Command Parameters
This is a complex routine that appears to handle multiple parameter formats for the FILES command. The exact behavior continues in the next section starting at 56C8H. The routine manages string allocation and type checking for the directory listing parameters.
5696WUZSTR
SYNCHR: Verify next char is comma [src: EAT COMMA AFTER ARG]
5697
DEFB 2CH 2C
Expected character: comma
5698
PUSH HL E5
Save parser position [src: SAVE THE TEXT POINTER]
5699
LD HL,(4121H) LD HL,(FACLO)2A 21 41
Get variable pointer [src: GET DESCRIPTOR POINTER]
569C
EX (SP),HL E3
Save var ptr, restore parser pos [src: PUT ON STACK & GET BACK TEXT PNT.]
569D
Evaluate string expression [src: GET LAST ARG]
56A0
SYNCHR: Verify next char [src: EAT RIGHT PAREN]
56A1
DEFB 29H 29
Expected character: ')' (close paren)
56A2
PUSH HL E5
Save parser position [src: SAVE TEXT POINTER]
56A3
Allocate string space [src: FREE UP TEMP & CHECK STRING]
56A6
EX DE,HL EB
DE = allocated space address [src: SAVE 2ND DESC, POINTER IN (DE)]
56A7
POP BC C1
BC = parser position [src: GET TEXT POINTER IN BC]
56A8
POP HL E1
HL = variable pointer [src: DESC. POINTER FOR S1$]
56A9
POP AF F1
A = type flag (01H=numeric, other=string) [src: OFFSET]
56AA
PUSH BC C5
Save parser position [src: PUSH TEXT POINTER ON BOTTON]
56AB
LD BC,26E7H 01 E7 26
Return address for completion [src: PUT ADDRESS OF POP HL RET ON]
56AE
PUSH BC C5
Push return address [src: PUSH IT]
56AF
LD BC,27F8H 01 F8 27
Secondary return address [src: NO2W ADDRESS OF (A) RETURNER]
56B2
PUSH BC C5
Push secondary return [src: ONTO STACK]
56B3
PUSH AF F5
Save type flag again [src: SAVE OFFSET BACK]
56B4
PUSH DE D5
Save destination pointer [src: SAVE DESC. OF S2]
56B5
String manipulation routine [src: FREE UP S1 DESC.]
56B8
POP DE D1
Restore destination pointer [src: RESTORE DESC, S2]
56B9
POP AF F1
Restore type flag [src: GET BACK OFFSET]
56BA
LD B,A 47
B = type flag [src: SAVE UNMODIFIED OFFSET]
56BB
DEC A 3D
Adjust for zero-based index [src: MAKE OFFSET OK]
56BC
LD C,A 4F
C = adjusted type [src: SAVE IN C]
56BD
CP (HL) BE
Compare with actual type [src: IS IT BEYOND LENGTH OF S1?]
56BE
LD A,00H 3E 00
Prepare return value = 0 [src: IF SO, RETURN ZERO. (ERROR)]
56C0
RET NC D0
Return if type mismatch
56C1
LD A,(HL) 7E
Get actual string length [src: IS S1$ NULL?]
56C2
OR A B7
Check if zero length [src: SET CC'S]
56C3
RET Z C8
Return if empty string [src: RETURN IF ZERO]
56C4
LD A,(DE) 1A
Get first char of destination [src: GET LENGH OF S1$]
56C5
OR A B7
Check if null [src: NULL?]
56C6
LD A,B 78
A = original type flag [src: GET OFFSET BACK]
56C7
RET Z C8
Return if destination empty [src: ALLIF S2 NULL, RETURN OFFSET]
56C8H - FILES Handler String Comparison Loop
Continuation of FILES statement handler - performs string comparison and manipulation for directory filtering.
56C8
LD A,(HL) 7E
Get length byte from source string [src: GET LENGTH OF S1$]
56C9
INC HL 23
Point to low address byte
56CA
LD B,(HL) 46
B = address low byte
56CB
INC HL 23
Point to high address byte [src: BUMP POINTER]
56CC
LD H,(HL) 66
H = address high byte [src: GET 2ND BYTE]
56CD
LD L,B 68
HL = string address [src: GET 1ST BYTE SET UP]
56CE
LD B,00H 06 00
B = 00H (prepare for 16-bit add) [src: GET READ FOR ADD]
56D0
ADD HL,BC 09
HL = string start + length offset [src: NOW INDEXING INTO STRING]
56D1
SUB C 91
A = remaining length [src: MAKE LENGTH OF STRING S1$ RIGHT]
56D2
LD B,A 47
B = remaining length [src: SAVE LRNGTH OF 1ST STRING IN (B)]
56D3
PUSH BC C5
Save remaining length [src: SAVE COUNTER , OFFSET]
56D4
PUSH DE D5
Save destination pointer [src: PUT 2ND DESC. (S2$) ON STACK]
56D5
EX (SP),HL E3
HL=dest, save source on stack [src: GET 2ND DESC. POINTER]
56D6
LD C,(HL) 4E
C = dest string length [src: SET UP LENGTH]
56D7
INC HL 23
Point to address low byte [src: BUMP POINTER]
56D8
LD E,(HL) 5E
E = address low byte [src: GET FIRST BYTE OF ADDRESS]
56D9
INC HL 23
Point to address high byte [src: BUMP POINTER AGAIN]
56DA
LD D,(HL) 56
DE = destination string address [src: GET 2ND BYTE]
56DB
POP HL E1
HL = source string address [src: RESTORE POINTER FOR 1ST STRING]
56DCCHK1
PUSH HL E5
Save source address again [src: SAVE POSITION IN SEARCH STRING]
56DD
PUSH DE D5
Save dest address [src: SAVE START OF SUBSTRING]
56DE
PUSH BC C5
Save dest length [src: SAVE WHERE WE STARTED SEARCH]
56DFH (CHK) - Character-by-Character Comparison Loop
Compares source and destination strings character by character.
56DFCHK
LD A,(DE) 1A
Get char from destination [LOOP START] [src: GET CHAR FROM SUBSTRING]
56E0
CP (HL) BE
Compare with source char [src: = CHAR POINTER TO BY (HL)]
56E1
If different, handle mismatch [src: NO]
56E3
INC DE 13
Next dest character [MATCH PATH] [src: BUMP COMPARE POINTER]
56E4
DEC C 0D
Decrement dest length counter [src: END OF SEARCH STRING?]
56E5
If dest exhausted, complete match [src: WE FOUND IT!]
56E7
INC HL 23
Next source character [src: DECREMENT LENGHT OF SEARCH STRING]
56E8
DEC B 05
Decrement source length counter
56E9
Continue if source not exhausted [LOOP] [src: END OF STRING ,YOU LOSE]
56EBRETZER
POP DE D1
Clean up stack (dest length) [src: GET RID OF POINTERS]
56EC
POP DE D1
Clean up stack (dest address) [src: GET RID OF GARB]
56ED
POP BC C1
Clean up stack (source address) [src: LIKE SO]
56EERETZR1
POP DE D1
Clean up stack (remaining length)
56EF
XOR A AF
A = 0 (no match found) [src: GOTO SNGFLT.]
56F0
RET C9
Return with no match [src: RET]
56F1H (GOTSTR) - Complete Match Found
Destination string completely matched against source - return position in source.
56F1GOTSTR
POP HL E1
HL = dest length (discard) [src: GET RID OF GARB]
56F2
POP DE D1
DE = dest address (discard) [src: GET RID OF EXCESS STACK]
56F3
POP DE D1
DE = source address (discard) [src: GET COUNTER]
56F4
POP BC C1
BC = remaining length
56F5
LD A,B 78
A = remaining source length [src: GET ORIGINAL SOURCE COUNTER]
56F6
SUB H 94
Calculate match position [src: SUBTRACT FINAL COUNTER]
56F7
ADD A,C 81
Adjust with matched length [src: ADD ORIGINAL OFFSET (N1%)]
56F8
INC A 3C
Make 1-based position [src: MAKE OFFSET OF ZERO = POSIT 1]
56F9
RET C9
Return position in A [src: DONE]
56FAH (OHWELL) - Character Mismatch - Try Next Position
Characters didn't match - advance source position and retry.
This is a substring search routine used by the FILES statement to filter directory listings. It searches for a match of the destination string within the source string, returning the 1-based position if found, or 0 if not found. The algorithm tries every possible starting position in the source string.
56FAOHWELL
POP BC C1
BC = dest length (discard)
56FB
POP DE D1
DE = dest address (restore) [src: GET BACK WHERE WE STARTED TO COMPARE]
56FC
POP HL E1
HL = source address [src: AND POINT TO NEXT CHATR]
56FD
INC HL 23
Advance to next source position [src: ;]
56FE
DEC B 05
Decrement remaining source length [src: DECR. # CHAR LEFT IN SOURCE STRING]
56FF
If source exhausted, no match [src: END FO STRING, RETURN 0]
5701
Retry comparison at new position [LOOP END] [src: TRY SEARCHING SOME MORE]
5703H (OCTCNS) - &H/&O Number Parser (Hexadecimal and Octal Literals)
Parses hexadecimal (&H) and octal (&O) number literals. Returns 16-bit value in DE. Used by BASIC to support &H and &O number formats.
The parser recognizes three formats: &H for hexadecimal (base 16), &O for octal (base 8), and a bare & followed by digits which defaults to octal. This provides compatibility with various BASIC dialects.
5703OCTCNS
LD DE,0000H LD DE,RST0011 00 00
Initialize result to 0 [src: INITIALIZE TO ZERO AND IGNORE OVERFLOW]
5706
CHRGET: Get next character after '&' [src: GET FIRST CHAR]
5707
CP 4FH FE 4F
Is it 'O' (octal)? [src: OCTAL]
5709
If 'O', process octal number [src: IF SO, DO IT]
570B
CP 48H FE 48
Is it 'H' (hexadecimal)? [src: HEX?]
570D
If neither H nor O, treat as octal [src: THEN DO IT]
570FH - Hexadecimal Number Parser (&H)
Parses up to 5 hexadecimal digits (supports 0-9, A-F). Result accumulated in HL, then moved to DE.
570F
LD B,05H 06 05
Max 5 hex digits (20 bits, but we use 16) [src: INIT ORG COUNT]
5711LOPHEX
INC HL 23
Move to next character [HEX LOOP START] [src: BUMP POINTER]
5712
LD A,(HL) 7E
Get next character [HEX LOOP] [src: GET CHAR]
5713
Check if character is letter (A-Z) [src: FETCH CHAR , SEE IF ALPHA]
5716
EX DE,HL EB
Save parser pos in DE, result in HL [src: SAVE (HL)]
5717
If letter (carry clear), handle A-F [src: YES,MAKE SURE LEGAL HEC]
5719
CP 3AH FE 3A
Is it >= ':' (after '9')? [src: IS IT BIGGER THAN LARGEST DIGIT?]
571B
If >= ':', invalid hex [ERROR PATH] [src: BE FORGIVING IF NOT HEX DIGIT]
571D
SUB 30H D6 30
Convert '0'-'9' to 0-9 [src: MASK OFF ASCII]
571F
If < '0', invalid hex [ERROR PATH] [src: BE FORGIVING IF NOT HEX DIGIT]
5721
Jump to shift and add digit [src: ADD IN OFFSET]
5723H (ALPTST) - Process Hex Letter (A-F)
5723ALPTST
CP 47H FE 47
Is it >= 'G'? [src: IS THIS LEGAL HEX?]
5725
If >= 'G', invalid hex [ERROR PATH] [src: YES,TERMINATE]
5727
SUB 37H D6 37
Convert 'A'-'F' to 10-15 (41H-37H=0AH) [src: MAKE BINARY VALUE]
5729H (NXTHEX) - Shift and Add Hex Digit
5729NXTHEX
ADD HL,HL 29
Multiply result by 16 (shift left 4 bits) [src: SHIFT RIGHT FOUR BITS]
572C
ADD HL,HL 29
Shift 4 (×16 complete)
572D
OR L B5
Combine digit with result [src: OR ON NEW DIGIT]
572E
LD L,A 6F
Store in low byte [src: SAVE BACK]
572F
DEC B 05
Decrement digit counter [src: TOO MANY DIGITS?]
5730
If 5 digits processed, finish [SUCCESS PATH] [src: YUP]
5733
EX DE,HL EB
Restore parser pos to HL, result to DE [src: GET TEXT POINTER BACK IN (HL)]
5734
Get next hex digit [HEX LOOP END] [src: KEEP EATING]
5736H (LOPOC2) - Prepare for Octal Parse (No 'O' Specified)
5736LOPOC2
DEC HL 2B
Back up to character after '&' [src: REGET LAST CHAR]
5737H (LOPOCT) - Octal Number Parser (&O or bare &)
Parses octal digits (0-7). Result accumulated in HL, then moved to DE.
5737LOPOCT
CHRGET: Get next character [OCTAL LOOP START] [src: READ A DIGIT]
5738
EX DE,HL EB
DE=parser pos, HL=result [src: RESULT INTO (HL)]
5739
If carry clear (not digit), finish [LOOP] [src: OUT OF DIGITS MEANS DONE]
573B
CP 38H FE 38
Is it >= '8'? [src: IS THIS AN OCTAL DIGIT]
573D
If >= '8', syntax error (invalid octal) [src: NO, TOO BAD YOU WILL LOSE]
5740
LD BC,07B2HLD BC,OVERR 01 B2 07
BC = return address after conversion [src: WHERE TO GO ON OVERFLOW ERROR]
5743
PUSH BC C5
Push return address [src: SAVE ADDR ON STACK]
5744
ADD HL,HL 29
Multiply by 8 (shift left 3 bits) [src: MULTIPLY BY 8]
5745
RET C D8
If overflow, return [ERROR PATH] [src: RETURN IF CARRY]
5747
RET C D8
If overflow, return [ERROR PATH] [src: OVERFLOW ERROR]
5748
ADD HL,HL 29
Shift 3 (×8 complete)
5749
RET C D8
If overflow, return [ERROR PATH] [src: OVERFLOW ERROR]
574A
POP BC C1
Remove return address (no overflow) [src: GET RID OF OVERR ADDR]
574B
LD B,00H 06 00
B = 0 for 16-bit add [src: SET UP TO ADD (BC)]
574D
SUB 30H D6 30
Convert '0'-'7' to 0-7 [src: MASK OFF ASCII]
574F
LD C,A 4F
C = digit value
5750
ADD HL,BC 09
Add digit to result [src: ADD IN THE DIGIT]
5751
EX DE,HL EB
HL=parser pos, DE=result [src: PUTTEXT POINTER BACK IN (HL)]
5752
Get next octal digit [OCTAL LOOP END] [src: SCAN MORE DIGITS]
5754H (HEXFIN) - Finalize Number and Return
Common exit point for both hex and octal parsers. Converts result and returns.
The number parsers support hexadecimal (&H) and octal (&O or bare &) literals in BASIC expressions. Hexadecimal numbers can be up to 5 digits (though only 4 digits = 16 bits are typically used), and octal numbers can be any length until overflow. Invalid digits for the selected base cause appropriate errors. The final result is converted to BASIC's internal floating-point format before returning.
5754HEXFIN
Convert HL to floating point [src: SAVE AS AN INTEGER]
5757
EX DE,HL EB
HL = parser position [src: (HL) - TEXT POINTER]
5758
RET C9
Return to caller
5759H (DLHSMD) - MID$ Statement Handler
Implements the MID$ statement for modifying a substring within a string variable. Syntax: MID$(string$, position [, length]) = replacement$. This allows in-place modification of strings.
The MID$ statement requires careful handling because it modifies strings in place. The code checks whether the string is in the string space (above memory top) or in the program area, as different handling is needed for each case. Strings in program space are literals and should not normally be modified.
5759DLHSMD
INC HL 23
Skip past MID$ token [src: POINT TO NEXT CHAR]
575A
SYNCHR: Verify next char is '(' [src: MUST HAVE '(']
575B
DEFB 28H 28
Expected character: '(' (open paren)
575C
Evaluate expression (string variable) [src: GET A STRING VAR]
575F
Get string descriptor [src: MAKE SURE IT WAS A STRING]
5762
PUSH HL E5
Save parser position [src: SAVE TEXT POINTER]
5763
PUSH DE D5
Save string descriptor pointer [src: SAVE DESC. POINTER]
5764
EX DE,HL EB
HL = string descriptor pointer [src: PUT DESC. POINTER IN (HL)]
5765
INC HL 23
Skip length byte [src: MOVE TO ADDRESS FIELD]
5766
LD E,(HL) 5E
E = string address low byte [src: GET ADDR OF LHS IN (DE)]
5767
INC HL 23
Point to high byte [src: BUMP DESC. POINTER]
5768
LD D,(HL) 56
DE = string address [src: PICK UP HIGH BYTE OF ADDRESS]
5769
LD HL,(40A0H) LD HL,(STKTOP)2A A0 40
HL = memory top pointer [src: SEE IF LHS STRING IS IN STRING SPACE]
576C
CPDEHL: Compare DE with HL [src: BY COMPARING IT WITH STKTOP]
576D
If string in string space, OK [src: IF ALREADY IN STRING SPACE]
576F
POP HL E1
Restore string descriptor [src: GET BACK DESC. POINTER]
5770
PUSH HL E5
Save it again [src: SAVE BACK ON STACK]
5771
Check string in program area [src: COPY TH STRING LITERALINTO STRING SPACE]
5774
POP HL E1
Restore string descriptor [src: GET BACK DESC.POINTER]
5775
PUSH HL E5
Save it again [src: BACK ON STACK AGAIND]
5776
String assignment check [src: MOVE NEW DESC. INTO OLD SLOT.]
5779H (NCPMID) - Parse Position, Length Parameters, and Replacement String
5779NCPMID
POP HL E1
Restore string descriptor [src: GET DESC. POINTER]
577A
EX (SP),HL E3
HL=parser pos, save descriptor [src: GET TEXT POINTER TO (HL) DESC. TO STACK]
577B
SYNCHR: Verify next char is comma [src: MUST HAVE COMMA]
577C
DEFB 2CH 2C
Expected character: comma
577D
Evaluate integer expression (position) [src: GET ARG2 (OFFSET INTO STRING]
5780
OR A B7
Check if position is zero [src: MAKE SURE NOT ZERO]
5781
If zero, "Type Mismatch" error [src: BLOW HIM UP IF ZERO]
5784
PUSH AF F5
Save position [src: SAVE ARG#2 ON STACK]
5785
LD A,(HL) 7E
Get next character [src: RESTORE CURRENT CHAR]
5786
Parse optional length parameter [src: USR MID CODE TO EVALUATE POSIBLE THIRD ARG.]
5789
PUSH DE D5
Save length (in E) [src: SAVE THIRD ARG(E) ON STACK]
578A
SYNCHR: Verify next char [src: MUST HAVE = SIGN]
578B
DEFB D5H D5
Expected character: D5H (PUSH DE opcode as delimiter)
578C
Evaluate string expression (replacement) [src: EVALUATE RHS OF THING]
578F
PUSH HL E5
Save parser position [src: SAVE TEXT POINTER]
5790
Allocate string space [src: FREE UP TEMP RHS IF ANY.]
5793
EX DE,HL EB
DE = allocated space [src: PUT RHS DESC. POINTER IN (DE)]
5794
POP HL E1
Restore parser position [src: TEXT POINTER TO (HL)]
5795
POP BC C1
BC = previous stack entry [src: ARG#3 TO C]
5796
POP AF F1
A = position parameter [src: ARG#2 TO A]
5797
LD B,A 47
B = position [src: AND (B)]
5798
EX (SP),HL E3
HL=string descriptor, save parser [src: GET LHS DESC. POINTER TO (HL)]
5799
PUSH HL E5
Save descriptor again [src: SAVE TEXT POINTER]
579A
LD HL,26E7H 21 E7 26
Return address for completion [src: GET ADDR TO RETURN TO]
579D
EX (SP),HL E3
Push return addr, restore descriptor [src: SAVE ON STACK & GET BACK TXT PTR]
579E
LD A,C 79
A = length (from earlier) [src: GET ARG#3]
579F
OR A B7
Check if zero [src: SET CC]
57A0
RET Z C8
If no characters to replace, done [src: IF ZERO , DO NOTHING]
57A1
LD A,(HL) 7E
A = target string length [src: GET LENGTH OF LHS]
57A2
SUB B 90
A = length - position [src: SEE HOW MANY CHARS IN EMAINDER OF STRING]
57A3
If position beyond string, error [src: CANT ASSIGN PAST LEN(LHS)!]
57A6
INC A 3C
Adjust for inclusive range [src: MAKE PROPER COUNT]
57A7
CP C B9
Compare with requested length [src: SEE IF # OF CHARS IS .GT. THIRD ARG]
57A8
If less available, use available [src: IF SO , DONT TRUNCATE]
57AA
LD A,C 79
Use requested length [src: TRUNCATE BY USING ARG#3]
57ABH (BIGLEN) - Perform String Replacement
Copies replacement characters into the target string at the specified position.
57ABBIGLEN
LD C,B 48
C = position [src: GET OFFSET OF STRING IN (C)]
57AC
DEC C 0D
Make 0-based offset [src: MAKE PROPER OFFSET]
57AD
LD B,00H 06 00
B = 0 for 16-bit add [src: SET UYP (BC) FOR LATER ADD]
57AF
PUSH DE D5
Save replacement string pointer [src: SAVE DE]
57B0
INC HL 23
Skip target length byte [src: POINTER TO ADDRESS FIELD]
57B1
LD E,(HL) 5E
E = target address low [src: GET LOW BYTE IN (E)]
57B2
INC HL 23
Point to high byte [src: BUMP POINTER]
57B3
LD H,(HL) 66
H = target address high [src: GET HIGH BYTE IN (H)]
57B4
LD L,E 6B
HL = target string start [src: NOW COPY LOW BYTE BACK TO L]
57B5
ADD HL,BC 09
HL = target position to replace [src: ADD OFFSET]
57B6
LD B,A 47
B = number of chars to replace [src: SET COUNT OF LHS IN (B)]
57B7
POP DE D1
DE = replacement string pointer [src: RESTORE (DE)]
57B8
EX DE,HL EB
HL=replacement, DE=target [src: MOVE RHS. DESC. POINTER TO (HL)']
57B9
LD C,(HL) 4E
C = replacement string length [src: GET LEN(RHS) TO C]
57BA
INC HL 23
Point to address low [src: MOVE POINTER TO]
57BB
LD A,(HL) 7E
A = address low byte [src: GET LOW BYTE OF ADDR IN A]
57BC
INC HL 23
Point to high byte [src: BUMP POINTER]
57BD
LD H,(HL) 66
H = address high byte [src: GET HIGH BYTE OF ADDR IN (H)]
57BE
LD L,A 6F
HL = replacement string address [src: COPY LOW BYTE TO (L)]
57BF
EX DE,HL EB
HL=target, DE=replacement source [src: ADDR OF RHS NOW IN (DE)]
57C0
LD A,C 79
A = replacement length [src: IS RHS NULL?]
57C1
OR A B7
Check if zero [src: TEST]
57C2
RET Z C8
If no replacement chars, done [src: THEN ALL DONE]
57C3H (MIDLP) - Character Copy Loop
The MID$ statement replaces up to the specified number of characters in the target string with characters from the replacement string. If the replacement string is longer than the specified length or available space, it's truncated. If the replacement string is shorter, only those characters are replaced.
57C3MIDLP
LD A,(DE) 1A
Get char from replacement [LOOP START] [src: GET BYTE FROM RHS.]
57C4
LD (HL),A 77
Store in target [LOOP] [src: STORE IN LHS]
57C5
INC DE 13
Next replacement char [src: BUMP RHS POINTER]
57C6
INC HL 23
Next target position [src: BUMP LHS POINTER]
57C7
DEC C 0D
Decrement replacement counter [src: BUMP DOWN COUNT OF RHS]
57C8
RET Z C8
If done with replacement, return [src: IF ZERO , ALL DONE]
57C9
Continue if target space remains [LOOP END] [src: IF NOT DONE, MORE COPYING]
57CB
RET C9
Return to caller
57CCH (MIDRST) - Parse Optional Length Parameter
Helper routine to parse the optional length parameter in MID$ statement. Sets E to FFH if no length specified, otherwise evaluates the length expression.
57CCMIDRST
LD E,FFH 1E FF
Default length = FFH (maximum) [src: IF TWO ARG GUY, TRUNCATE]
57CE
CP 29H FE 29
Is next char ')' (no length)?
57D0
If ')', use default length [src: (E) SAYS USE ALL CHARS]
57D2
SYNCHR: Verify comma [src: COMMA? MUST DELINEATE ARG #3]
57D3
DEFB 2CH 2C
Expected character: comma
57D4
Evaluate integer expression (length) [src: GET ARGUMENT IN E]
57D7H (MID2) - Verify Closing Parenthesis
57D7MID2
SYNCHR: Verify ')' [src: MUST BE FOLLOWED BY ')']
57D8
DEFB 29H 29
Expected character: ')' (close paren)
57D9
RET C9
Return to caller [src: ALL DONE]
57DAH (INLINE) - INPUT# Statement Handler
Reads data from a file using INPUT# statement. Checks if a file is open and routes to appropriate input handler.
57DAINLINE
PUSH HL E5
Save parser position
57DB
LD HL,(63BEH) LD HL,(PTRFIL)2A BE 63
Get current FCB pointer
57DE
LD A,H 7C
Check if file open
57DF
OR L B5
Is FCB pointer zero?
57E0
POP HL E1
Restore parser position
57E1
If no file, use regular INPUT
57E4ISFILE
POP AF F1
Remove return address (change flow) [src: GET RID OF RETURN ADDR]
57E5
PUSH BC C5
Save BC [src: SAVE THE OLD (BC)]
57E7
LD B,F0H 06 F0
B = 240 chars max per read [src: SETUP THE MAXIMUM CHAR COUNT]
57E9
LD D,7FH 16 7F
D = 7FH (mask for high bit clear) [src: AT START TURN OFF HIGH BITS]
57EB
LD HL,(40A7H) LD HL,(TEMPPT)2A A7 40
HL = input buffer pointer [src: PLACE WE ARE GOING TOSTORE THE LINE]
57EEH - Read Characters from File Loop
Reads characters from file into input buffer, processing special characters.
57EE
Read character from file [LOOP START]
57F1LOPBUF
LD E,A 5F
Save character in E [LOOP] [src: GET CHAR FROM FILE]
57F2
SUB 80H D6 80
Test high bit
57F4
SBC A,A 9F
A = FFH if high bit was set, 00H if clear [src: SAVE THE CHAR]
57F5
OR D B2
Combine with mask (7FH)
57F7
LD A,E 7B
Restore character [src: (A)= 255 IF CHAR HAD HIGH BIT]
57F8
AND D A2
Apply mask (clear high bit if needed) [src: SET TO 127 OR 255]
57F9
LD (HL),A 77
Store in input buffer [src: AFTER FIRST CHAR WO/HIGH BIT NO MORE MASKING]
57FA
CP 0DH FE 0D
Is it CR (carriage return)? [src: GET BACK THE CHAR]
57FC
If CR, finish line [src: STORE THE CHAR]
57FE
CP 0AH FE 0A
Is it LF (line feed)?
5800
If not LF, store and continue
5802
LD A,B 78
Check if first character
5803
CP F0H FE F0
Is counter still at F0H?
5805
If first char is LF, skip it [LOOP] [src: CHECK TO SEE IF AT ATART]
5807H - Continue Reading Characters
5807
INC HL 23
Advance buffer pointer
5808
Continue if space remains [LOOP END]
580AH (INOTLF) - 580AH (FINLIN) - Terminate Input Line
580AFINLIN
XOR A AF
A = 00H (null terminator) [src: MAKE THE TERMINATOR 0]
580B
LD (HL),A 77
Terminate string
580D
POP BC C1
Restore BC [src: RESTORE THE OLD (BC)]
580E
LD HL,(40A7H) LD HL,(TEMPPT)2A A7 40
HL = input buffer start [src: POINT AT BUFMIN]
5811
DEC HL 2B
Back up one position
5812
RET C9
Return to caller
5813H (EXOUTC) - INPUT# Separator Check
Checks for field separators (comma, colon) when reading from a file with INPUT#.
The INPUT# handler reads up to 240 characters (F0H) from a file, stopping at CR (0DH). It masks the high bit of characters and skips leading LF characters. The data is placed in the input buffer at 40A7H and null-terminated.
5813EXOUTC
PUSH HL E5
Save position [src: OUTPUT CHAR TO DISK FILE?]
5814
LD HL,(63BEH) LD HL,(PTRFIL)2A BE 63
Get current FCB pointer
5817
LD A,H 7C
Check if file open
5818
OR L B5
Is FCB pointer zero?
5819
POP HL E1
Restore position
581A
LD A,C 79
A = separator character [src: RESTORE THE CHAR]
581B
RET Z C8
If no file, return (use keyboard) [src: GO AWAY IF NOT DISK OUTPUT]
581C
POP AF F1
Remove return address [src: GET RID OF THE RETURN ADDR]
581D
LD A,C 79
A = separator again [src: GET THE CHAR TO SEND]
581E
POP BC C1
Restore BC [src: RESTORE (BC) (SAVED AT OUTDO)]
581F
Jump to file character output routine
5822H (EXINC) - INPUT with File Check
Checks whether INPUT should read from a file or keyboard, and routes accordingly.
5822EXINC
INC SP 33
Remove two bytes from stack [src: WE KNOW WHO CALLED US]
5823
INC SP 33
(Clean up stack) [src: WE WANT TO SEE WHO CALLED HIM]
5824
EX (SP),HL E3
HL=top of stack, save original HL [src: SINCE IT COULD BE POLL FOR CHAR OR INCHR]
5825
PUSH DE D5
Save DE [src: SAVE REGISTER IN IN COMPARE]
5826
LD DE,0387H 11 87 03
DE = comparison value
5829
CPDEHL: Compare DE with HL
582B
EX (SP),HL E3
Restore stack, get HL back [src: GET BACK OLD (HL) RESTORE RETURN ADDR]
582C
If not file input, use normal INPUT [src: MUST BE POLL CALL - DO BACK]
582E
PUSH HL E5
Save HL [src: SAVE OLD (HL) AGAIN]
582F
LD HL,(63BEH) LD HL,(PTRFIL)2A BE 63
Get current FCB pointer
5832
LD A,H 7C
Check if file open
5833
OR L B5
Is FCB pointer zero? [src: SEE IF DOING DISK I/O]
5835
If no file, keyboard input [src: NOT DISK SO RETURN]
5838
PUSH HL E5
Save HL again [src: SAVE OLD (HL) AGAIN]
5839
Read character from file [src: READ A CHARACTER]
583C
If no carry, normal return [src: ALL DONE IF NO END OF FILE]
583F
PUSH BC C5
Save BC [src: SAVE CONTEXT]
5842
Complete PRINT# output [src: ZERO PTRFIL AND CLOSE FILE 0]
5848
LD A,(63E2H) LD A,(LSTFRE)3A E2 63
Get EOF flag [src: DO WE RUN NOW?]
584B
OR A B7
Check if EOF [src: NO ZERO IF SO]
584C
LD HL,1D1EH LD HL,NEWSTT21 1E 1D
HL = error handler address [src: PLACE TO GO TO START]
584F
EX (SP),HL E3
Replace return with error handler [src: PUT ON AS RETURN ADDRESS]
5850
If EOF, trigger INPUT PAST END error [src: GO RUN]
5853
EX (SP),HL E3
Restore original return address [src: GET VACK ILD (HL)]
5856
LD HL,1929H 21 29 19
HL = string handling routine [src: PRINT PREMATURE MESSAGE]
585E
LD A,0DH 3E 0D
A = CR character [src: FORCE OUT OF DISK LINE INPUT LOOP]
5861
RET C9
Return to caller
5862H (FIXCAS) - Use Normal Keyboard INPUT
This section provides complex logic to determine whether INPUT should read from a file or the keyboard. It checks the FCB pointer at 63BEH to determine if a file is currently open for input operations. The code handles EOF conditions and routes to appropriate error handlers.
5862FIXCAS
LD (40A9H),A 32 A9 40
Store character [src: FIX THE CASSETTE BUG]
5865
Jump to keyboard INPUT handler in the middle of the INKEY$ routine "ISCHAR"
5868H (USRTAB) - USR Function Address Table
Table of 10 addresses for USR(0) through USR(9) functions. All initialized to 1E4AH (Type Mismatch error handler). Users can POKE new addresses to redirect USR functions to custom machine language routines.
5868USRTAB
DEFW 1E4AH 4A 1E
USR(0) default address - Type Mismatch error [src: REPEAT 10 MACRO]
586A
DEFW 1E4AH 4A 1E
USR(1) default address
586C
DEFW 1E4AH 4A 1E
USR(2) default address
586E
DEFW 1E4AH 4A 1E
USR(3) default address
5870
DEFW 1E4AH 4A 1E
USR(4) default address
5872
DEFW 1E4AH 4A 1E
USR(5) default address
5874
DEFW 1E4AH 4A 1E
USR(6) default address
5876
DEFW 1E4AH 4A 1E
USR(7) default address
5878
DEFW 1E4AH 4A 1E
USR(8) default address
587A
DEFW 1E4AH 4A 1E
USR(9) default address
587CH - INPUT Statement Entry Point (No File)
Main entry point for INPUT statement when no file is open. Checks if this is a special editing command (LIST, EDIT, AUTO, DELETE) or regular INPUT.
This routine detects special editing keys: LF (line feed), '[', '.', and ',' all trigger line number input for editing commands. ESC cancels input. ^Z (1AH) is used for special commands. Regular characters go through the normal INPUT buffer processing.
587C
POP HL E1
Get return address from stack
587D
PUSH HL E5
Put it back (peek at return)
587E
LD DE,1A7EH 11 7E 1A
DE = comparison address
5881
CPDEHL: Compare return address
5882
If not special case, normal INPUT. Note, this jumps into the middle of an opcode.7
5885
LD A,0EH 3E 0E
A = 0EH (shift out control code)
5887
Output shift-out character
588A
Get character from keyboard
588D
CP 0AH FE 0A
Is it line feed?
588F
If LF, get line number
5891
CP 5BH FE 5B
Is it '[' key?
5893
If '[', get line number
5895
CP 2EH FE 2E
Is it '.' (period)?
5897
If period, get line number
5899
CP 2CH FE 2C
Is it ',' (comma)?
589B
If comma, get line number
589D
LD HL,(40A4H) LD HL,(TXTTAB)2A A4 40
HL = string space pointer
58A0
CP 1BH FE 1B
Is it ESC key?
58A2
If ESC, handle cancel
58A4
LD DE,FFFFH 11 FF FF
DE = -1 (default increment)
58A7
CP 1AH FE 1A
Is it ^Z (Ctrl-Z)?
58A9
If ^Z, process editing command
58AC
LD HL,5938H 21 38 59
HL = command processing routine
58AF
PUSH HL E5
Push return address
58B0
LD HL,(40A7H) LD HL,(TEMPPT)2A A7 40
HL = input buffer pointer
58B3
PUSH HL E5
Save buffer pointer
58B4
LD B,F0H 06 F0
B = 240 chars max input
58B6
LD C,B 48
C = same (F0H)
58B7
Jump to the middle of the keyboard input routine. This enters 1 instruction after KLNNXT which was a call to fetch a key. This jump goes to the area which starts testing Register A against different chaaracters (Space, Carriage Return, Clear, Break, etc) and jumps accordingly.
58BBH - Get Current Line Number for Editing
Retrieves the current line number from system variable for use in LIST, EDIT, AUTO commands.
58BB
LD DE,(40ECH) LD DE,(CURLIN)ED 5B EC 40
DE = current line number
58BFH - Process Editing Command
Processes special editing commands like AUTO, EDIT, LIST, DELETE. Parses optional line number and validates the command.
58BF
PUSH AF F5
Save command character
58C0
Get line number from input
58C3
POP DE D1
D = command character
58C4
NOP 00
(Padding or remnant)
58C5
LD A,D 7A
A = command character
58C6
If no carry (valid number), continue
58C8
CP 2EH FE 2E
Was command '.' (period)?
58CA
If period, handle special case
58CC
CP 2CH FE 2C
Was command ',' (comma)?
58CE
If comma, handle special case
58D0
CP 0AH FE 0A
Was it line feed?
58D2
If not LF, check for '['
58D4
LD A,(HL) 7E
Get low byte of line number
58D5
INC HL 23
Point to high byte
58D6
OR (HL) B6
OR with high byte (test if zero)
58D7
DEC HL 2B
Restore pointer
58D8
If line number nonzero, cancel
58DCH - Check for Carry Flag from Line Number Parse
58DC
If zero result, handle specially
58DEH - Check for '[' Key
58DE
CP 5BH FE 5B
Is it '[' key?
58E2H - Validate String Space Pointer
Checks if string space pointer has moved during command processing.
58E2
LD HL,(40A4H) LD HL,(TXTTAB)2A A4 40
Get current string space pointer
58E5
OR A B7
Clear carry for subtraction
58E6
SBC HL,BC ED 42
HL = current - saved
58E8
If unchanged, continue
58EA
ADD HL,BC 09
Restore HL [LOOP START]
58EB
PUSH BC C5
Save BC [LOOP]
58EF
LD A,(HL) 7E
Get low byte of address
58F0
INC HL 23
Point to high byte
58F1
LD H,(HL) 66
H = high byte
58F2
LD L,A 6F
HL = string address
58F3
CPDEHL: Compare with saved
58F4
If not match, keep searching [LOOP END]
58F6H - Transfer Parsed Values
58F8H - Setup Command Parameters
Prepares registers for command execution - BC contains line number, DE contains next line pointer.
58F8
NOP 00
(Padding or alignment)
58F9
POP BC C1
Restore BC (original value)
58FB
POP BC C1
BC = HL (line number)
58FC
INC HL 23
Skip past length byte
58FD
INC HL 23
Skip past another byte
58FE
LD E,(HL) 5E
E = low byte of next pointer
58FF
INC HL 23
Point to high byte
5900
LD D,(HL) 56
DE = next line pointer
5901
CP 2CH FE 2C
Is command ','?
5903
If comma, handle renumber?
5906
PUSH DE D5
Save next line pointer
5907
PUSH BC C5
Save line number
5908
LD A,0FH 3E 0F
A = 0FH (shift in control code)
590A
Output shift-in character
590D
LD A,1DH 3E 1D
A = 1DH (cursor right)
5912
LD HL,(4020H) 2A 20 40
HL = cursor position pointer
5915
LD DE,FFC0H 11 C0 FF
DE = -64 (back one line on screen)
5918
ADD HL,DE 19
HL = cursor position - 64
5919
LD A,H 7C
Get high byte of position
591A
CP 3CH FE 3C
Compare with screen start (3C00H)
591C
If below screen, skip READY check
591E
LD B,0AH 06 0A
B = 10 (length of "READY ")
5920
LD DE,59BEH 11 BE 59
DE = "READY" string address
5923H - Compare Screen with "READY" String
Checks if "READY" appears on screen at the cursor position.
5923
LD A,(DE) 1A
Get char from READY string [LOOP START]
5924
CP (HL) BE
Compare with screen [LOOP]
5925
If mismatch, skip erase
5927
INC DE 13
Next char in READY
5928
INC HL 23
Next screen position
5929
Continue for all 10 chars [LOOP END]
592B
LD A,1BH 3E 1B
A = 1BH (ESC - erase to end of line)
592D
Erase "READY" from screen
5930H - Restore Cursor and Execute Command
5930
LD A,1EH 3E 1E
A = 1EH (cursor home)
5932
Move cursor to home position
5935
Jump to command executor
This section handles the interactive editing features. It detects "READY" on the screen and erases it before executing LIST, EDIT, AUTO, or DELETE commands. The cursor positioning code ensures clean display output. The routine at 2B33H handles the actual command execution based on the parsed parameters in BC (line number) and DE (next line pointer).
5938H - Command Keyword Detection (LIST/EDIT/DELETE/AUTO)
Identifies which editing command (LIST, EDIT, DELETE, AUTO) was entered and sets up parameters for execution.
5939
If carry set, skip keyword check
593B
PUSH HL E5
Save input pointer
593C
LD A,(HL) 7E
Get first character of command
593D
LD HL,59A8H 21 A8 59
Point to "LIST" keyword
5940
CP 4CH FE 4C
Is it 'L' (LIST)?
5944
LD HL,59ADH 21 AD 59
Point to "EDIT" keyword
5947
CP 45H FE 45
Is it 'E' (EDIT)?
594B
LD HL,59B9H 21 B9 59
Point to "AUTO" keyword
594E
CP 41H FE 41
Is it 'A' (AUTO)?
5952
LD HL,59B2H 21 B2 59
Point to "DELETE" keyword
5955
CP 44H FE 44
Is it 'D' (DELETE)?
5957
If not 'D', not a keyword
5959H - Process Recognized Keyword
Keyword was recognized - extract length and setup for comparison.
5959
LD A,(HL) 7E
Get keyword length byte
595A
LD (5992H),A 32 92 59
Store length for LDIR
595E
LD (5975H),A 32 75 59
Store for ADD instruction **SELF-MODIFY**
5961
INC HL 23
Skip past length byte
5962
LD (598FH),HL 22 8F 59
Store keyword text address **SELF-MODIFY**
5965
POP HL E1
Restore input pointer
5966
PUSH HL E5
Save it again
5967
CHRGET: Get next character
596A
CP 2EH FE 2E
Is it '.' (period)?
596EH - Validate Complete Keyword Match
This routine uses SELF-MODIFYING CODE at three locations: 5975H (ADD nn), 598FH (LD HL,nnnn), and 5992H (LD C,nn). It expands abbreviated keywords (L, E, D, A) to their full forms (LIST, EDIT, DELETE, AUTO) by copying the full keyword text into the input buffer. The LDDR backwards copy prevents overwriting source data when the destination overlaps.
596E
Check for end of keyword
5971
If at end, not valid keyword
5973
LD A,B 78
A = B (start position)
5974
ADD 00H C6 00
Add keyword length **SELF-MODIFIED at 5975H**
5976
CP C B9
Compare with end position
5977
If beyond end, syntax error
597A
POP HL E1
Restore input pointer
597B
PUSH HL E5
Save it again
597D
LD E,B 58
E = start position
597E
LD B,A 47
B = end position
597F
SUB E 93
A = bytes to move
5981
LD B,00H 06 00
B = 0 for 16-bit add
5983
LD C,E 4B
BC = start offset
5984
ADD HL,BC 09
HL = source + offset
5985
ADD A,L 85
Calculate destination low
5986
LD E,A 5F
E = dest low byte
5987
LD A,H 7C
Get source high byte
5988
ADC 00H CE 00
Add carry to high byte
598A
LD D,A 57
DE = destination address
598B
LDDR ED B8
Copy backwards (overlap safe)
598D
EX DE,HL EB
HL = destination
598E
LD HL,0000H LD HL,RST0021 00 00
HL = keyword source **SELF-MODIFIED at 598FH**
5991
LD C,00H 0E 00
C = keyword length **SELF-MODIFIED at 5992H**
5993
LDIR ED B0
Copy keyword into input buffer
5997H - Exit Keyword Processing
5997
POP HL E1
Restore input pointer
5998H - Jump to Command Processor
5998
Jump to the middle of the INPUT routine in ROM.
599BH - Check for End of Keyword
Verifies that keyword is followed by valid delimiter (=, (, or CR).
599B
CHRGET: Get next character [LOOP START]
599C
CP 3DH FE 3D
Is it '=' (assignment)? [LOOP]
599E
RET Z C8
If '=', valid end (Z set)
599F
CP 28H FE 28
Is it '(' (function call)?
59A1
RET Z C8
If '(', valid end (Z set)
59A2
CP 0DH FE 0D
Is it CR (end of line)?
59A4
If not CR, keep checking [LOOP END]
59A6
OR A B7
Clear Z flag (not valid delimiter)
59A7
RET C9
Return (Z clear = not at end)
59A8H - Keyword String Table (DATA)
Length-prefixed keyword strings for LIST, EDIT, DELETE, and AUTO commands.
59A8
DEFB 04H 04
"LIST" keyword length
59A9
DEFM "LIST" 4C 49 53 54
"LIST" keyword text
59AD
DEFB 04H 04
"EDIT" keyword length
59AE
DEFM "EDIT" 45 44 49 54
"EDIT" keyword text
59B2
DEFB 06H 06
"DELETE" keyword length
59B3
DEFM "DELETE" 44 45 4C 45 54 45
"DELETE" keyword text
59B9
DEFB 04H 04
"AUTO" keyword length
59BA
DEFM "AUTO" 41 55 54 4F
"AUTO" keyword text
59BEH - "READY" String (DATA)
10-byte string displayed at BASIC ready prompt: "READY" followed by 5 spaces.
The "READY" string is exactly 10 bytes to fill a line on the TRS-80 screen. It's used by the code at 5923H to detect and erase the READY prompt when executing editing commands.
59BE
DEFM "READY " 52 45 41 44 59 20 20 20 20 20
READY prompt string (10 bytes)
59C8H (SYSOUT) - End of READY String / Code Boundary
59C8SYSOUT
RET C9
Return (boundary marker) [src: USE NORMAL SYSTEM CODE]
59C9H (SYSGO) - SYSTEM Statement Handler
Exits BASIC and returns to TRSDOS operating system. Closes all files and restores DOS environment before exit.
The SYSTEM statement performs a clean exit from BASIC. It sets the SYSTEM active flag to prevent re-entry, restores the original DOS state saved at initialization (5200H), sets up an error handler, closes all files to flush buffers and release resources, then transfers control back to TRSDOS. The carry flag determines which DOS entry point to use.
59C9SYSGO
PUSH AF F5
Save flags [src: REMEMBER IF "SYS" OR "ABORT"]
59CA
LD A,FFH 3E FF
A = FFH (SYSTEM active flag) [src: RESET THE 'BASIC' FLAG]
59CC
LD (427AH),A LD (ABRTFL),A32 7A 42
Set SYSTEM active flag
59CF
LD HL,(5200H) LD HL,(DOPROT)2A 00 52
Get original state from 5200H [src: GET THE PROTECTION FLAGS]
59D2
LD (426FH),HL 22 6F 42
Restore saved state to 426FH [src: SAVE THEM]
59D5
LD HL,4030H 21 30 40
HL = error handler address [src: RESET THE CASSETTE/PRINTER 'BREAK']
59D8
LD (4204H),HL LD (BREAK),HL22 04 42
Set error handler vector
59DB
Close all open files [src: SHUT DOWN ALL OPEN FILES]
59DE
POP AF F1
Restore flags [src: DISPATCH TO CORRECT EXIT POINT]
59DF
If no carry, exit via DOS vector [src: RETURN TO NORMAL DOS]
59E2SSYSGO
Exit to TRSDOS (warm boot) [src: RETURN TO ABORT IN DOS]
59E5H (EXDPOS) - Check File Open and Process
Validates that a file is open and processes file operations. Used by various file I/O statements.
59E5EXDPOS
LD HL,(63BEH) LD HL,(PTRFIL)2A BE 63
Get current FCB pointer [src: SEE IF DISK IS BEING USED]
59E8
LD A,H 7C
Check if file open [src: IF NOT JUST RETURN BACK]
59E9
OR L B5
Is FCB pointer zero?
59EA
RET Z C8
If no file open, return
59EB
INC HL 23
Point to FCB+1 (mode byte) [src: PICK UP TERMINAL POSITION]
59EC
LD A,(HL) 7E
Get file mode
59ED
POP HL E1
Get return address [src: GET RID OF THE RETURN ADDRESS]
59EE
PUSH DE D5
Save DE [src: COMPARE TO SEE WHERE CAME FROM TO]
59EF
PUSH AF F5
Save file mode [src: SAVE THE CHARACTER POSITION]
59F0
LD DE,2130H 11 30 21
DE = comparison value [src: DIVIDING LABELBETWEEN TWO CALLS]
59F3
CPDEHL: Compare return address
59F4
POP DE D1
D = file mode [src: GET BACK THE POSITION]
59F5
LD A,D 7A
A = file mode [src: WITHOUT CHANGING THE CONDITION CODES]
59F6
POP DE D1
Restore DE [src: RESTORE (DE)]
59F7
If carry, jump to handler
59FA
Jump to alternate handler
59FDH (EXFIND) - File Buffer Save Routine
Saves the current file FCB pointer and buffer pointer for later restoration.
59FDEXFIND
LD HL,(63BEH) LD HL,(PTRFIL)2A BE 63
Get current FCB pointer [src: CALL HERE WHEN ABOUT TO INSERT LINE. MUST SAVE]
5A00
LD (40F3H),HL LD (OLDLIN),HL22 F3 40
Save FCB pointer to 40F3H [src: ACTIVE FILE POINTER BECAUSE MAY BE DOING AS]
5A03
LD HL,6250H LD HL,DIRTMP21 50 62
HL = default buffer address [src: MAKE FILE 0 LOOK ALREADY CLOSED WITH MODE 0]
5A06
LD (HL),00H 36 00
Initialize buffer (clear first byte) [src: SO ASCII LOAD DILE IS NOT CLOSED]
5A08
LD (63C0H),HL LD (FILPTR),HL22 C0 63
Set current buffer pointer [src: POINT IT AT THE DUMMY FCB]
5A0B
RET C9
Return to caller
5A0CH (EXFIN2) - File Buffer Restore Routine
Restores previously saved FCB and buffer pointers.
5A0CEXFIN2
LD HL,(40F3H) LD HL,(OLDLIN)2A F3 40
Get saved FCB pointer [src: HAVING RETURNED FROM RUNC NOW]
5A0F
LD (63BEH),HL LD (PTRFIL),HL22 BE 63
Restore current FCB pointer [src: WE RESTORE PTRFIL AND FILPTR]
5A12
LD HL,(63E0H) LD HL,(FILPT1)2A E0 63
Get last allocated buffer end [src: SAVED COPY OF TRUE FILPTR]
5A15
LD (63C0H),HL LD (FILPTR),HL22 C0 63
Restore current buffer pointer
5A18EXDSCR
RET C9
Return to caller
5A19H (EXDSKL) - LIST File Mode Check
Checks if a file is open for LIST output. If file is open, redirects to file output instead of screen.
This routine intercepts LIST commands when a file is open. Instead of displaying to the screen, it redirects the LIST output to the open file by removing the normal return address and jumping to a file-specific LIST handler.
5A19EXDSKL
LD HL,(63BEH) LD HL,(PTRFIL)2A BE 63
Get current FCB pointer [src: SEE IF LINE POSITION IS IMPORTANT]
5A1C
LD A,H 7C
Check if file open [src: IT NEVER IS IN DISK FILES FOR FORCING A CRLF]
5A1D
OR L B5
Is FCB pointer zero? [src: SINCE FILES HAVE INFINITE WIDTH]
5A1E
RET Z C8
If no file, return (use screen) [src: IF NOT DISK JUST GO BACK]
5A1F
POP HL E1
Remove return address [src: OTHERWISE GET RID OF THE RETURN ADDR]
5A20
Jump to file LIST handler [src: AND DONT EVER DO CRLF CHECK]
5A23H (ASCII) - Memory Calculation Routine
Converts floating point value to integer and performs memory-related calculation. Used by file buffer allocation routines.
This routine multiplies the input value by 192 (C0H), which is the size of file buffer structures. This is used to calculate memory requirements for file buffers. The result is converted to a format suitable for memory allocation.
5A23ASCII
Convert FP to integer in HL
5A26ASCII1
LD A,C0H 3E C0
A = C0H (192 decimal)
5A30
Jump to conversion routine
5A33H (XOPEN) - Open File for Output Helper
Opens a file for output and saves the DOS state.
5A33XOPEN
DOS: Open file for output [src: DO OPEN IN DOS]
5A36
Jump to common save routine [src: SET THE FLAGS]
5A38H (XINIT) - Open File for Input Helper
Opens a file for input and saves the DOS state.
5A38XINIT
DOS: Open file for input [src: DO INIT IN DOS]
5A3BH (ZOPEN) - Save DOS State After File Open
Common routine to save DOS state after opening a file.
5A3BZOPEN
PUSH HL E5
Save HL register [src: SAVE ANY POINTER]
5A3C
LD HL,(5200H) LD HL,(DOPROT)2A 00 52
Get original state from 5200H [src: GET THE PROTECTION FLAGS]
5A3F
LD (426FH),HL 22 6F 42
Save state to 426FH [src: SAVE THEM 'DOWNSTAIRS']
5A42
POP HL E1
Restore HL [src: GET ANY POINTER BACK]
5A43
RET C9
Return to caller [src: EXIT BACK TO CALLER]
5A44H (FILINP) - File # Validation Helper (Expects '#')
Sets C=1 and falls through to check for '#' character.
5A44FILINP
LD C,01H 0E 01
C = 1 (file number expected flag) [src: MUST BE SEQUENTIAL INPUT]
5A46H (FILGET) - File # Validation (Called from 5371H)
Checks if next character is '#', returns if not. Used by PRINT#, INPUT#, etc.
5A46FILGET
CP 23H FE 23
Is it '#' character? [src: NUMBER SIGN THERE]
5A48
RET NZ C0
If not '#', return [src: NO, NOT DISK READER]
5A49
PUSH BC C5
Save BC [src: SAVE EXPECTED MODE]
5A4A
Parse file number [src: READ AND GET POINTER]
5A4D
POP DE D1
D = saved C (expected flag) [src: (E)= FILE MODE]
5A4E
CP E BB
Compare file # with expected [src: IS IT RIGHT]
5A4F
If mismatch, error [src: IF NOT , 'BAD FILE MODE']
5A52GDFILM
SYNCHR: Verify comma follows [src: GO PAST THE COMMA]
5A53
DEFB 2CH 2C
Expected character: comma
5A54FILSET
LD (63BEH),BC LD (PTRFIL),BCED 43 BE 63
Store file control block pointer
5A58
RET C9
Return to caller
5A59H (FILSCN) - File # Parser
Parses file number after '#' character, validates range, and returns FCB pointer in BC.
The file number table at 63C0H contains 16 word pointers (32 bytes total) to FCB structures. Each file number (0-15) has a 2-byte pointer. The routine multiplies the file number by 2 (two ADD HL,DE) to index into this table. The FCB's first byte is the status: 00H=closed, non-zero=open.
5A59FILSCN
DEC HL 2B
Back up to '#' character
5A5A
CHRGET: Get next char (skip '#')
5A5B
CP 23H FE 23
Is it '#'? [src: MAKE NUMBER SIGN OPTIONAL]
5A5D
If '#', handle special case [src: BY SKIPPONG IT IF THERE]
5A60
Evaluate expression (file number) [src: READ THE FILE NUMBER INTO THE FAC]
5A63FILFRM
Convert to integer in A [src: GET THE FILE NUMBER INTO THE (A)]
5A66FILIDX
LD E,A 5F
E = file number [src: GET FILE NUMBER INTO (E)]
5A67FILID2
LD A,(426DH) LD A,(MAXFIL)3A 6D 42
Get maximum file number allowed [src: IS THIS FILE # LEGAL?]
5A6A
CP E BB
Compare max with requested
5A6B
If requested > max, error [src: IF NOT , 'BAD FILE NUMBER]
5A6E
LD D,00H 16 00
D = 0 (DE = file number) [src: SETUP DOUBLE - BYTE OFFSET TO GET]
5A70
PUSH HL E5
Save parser position [src: SAVE HL]
5A71
LD HL,63C0H LD HL,FILPTR21 C0 63
HL = file pointer table base [src: POINT AT POINTER TABLE]
5A74
ADD HL,DE 19
Add file number (×1) [src: ADD ON OFFSET TWICE FOR DOUBLE BYTE]
5A75
ADD HL,DE 19
Add again (×2 for word pointers) [src: ENTRIES]
5A76
LD C,(HL) 4E
C = FCB pointer low byte [src: PICK UP POINTER IN (BC)]
5A77
INC HL 23
Point to high byte
5A78
LD B,(HL) 46
BC = FCB pointer
5A79
LD A,(BC) 0A
Get first byte of FCB (status) [src: GET MODE OF FILE INTO (A)]
5A7A
OR A B7
Check if file is open (0=closed) [src: SET ZERO IF FILE NOT OPEN]
5A7B
POP HL E1
Restore parser position [src: RETRIEVE (HL)]
5A7C
RET C9
Return (Z set if closed)
5A7DH (MKI) - MKD$ Function Handler
Converts double-precision floating point to 8-byte string representation.
5A7DMKI
LD A,02H 3E 02
A = 2 (MKD$ type code) [src: VALUE TYPE FOR INTEGER AND NUMBER]
5A7F
LD BC,043EH 01 3E 04
BC = double-precision size params
5A80H (MKS) - CVI Function Handler
Converts 2-byte string to integer value.
5A80MKS
LD BC,083EH 01 3E 08
BC = integer conversion params [src: OF CHARACTERS RESULT WILL NEED]
5A83H (MKD) - CVS Function Handler (and common MKx$ processing)
Converts 4-byte string to single-precision value. Also serves as common code for MKI$/MKS$/MKD$.
5A83MKD
PUSH AF F5
Save type code [src: VALUE TYPE OF DOUBLE -PRECISION]
5A87
POP AF F1
Restore type code
5A88
Convert string to numeric
5A8B
LD HL,(40D4H) LD HL,(DSCPNT)2A D4 40
Get string descriptor pointer
5A91
Return with converted value
5A96H (CVI) - CHR$ Function Handler (Disk Version)
Extended CHR$ function supporting additional parameters for disk BASIC.
5A96CVI
LD A,01H 3E 01
A = 1 (CHR$ type) [src: SET A TO BE VALTYP-1]
5A98
LD BC,033EH 01 3E 03
BC = single byte params [src: SKIP THE NEXT TWO BYTES WITH "LXI B"]
5A99H (CVS) - MKI$ Function Handler
Converts integer to 2-byte string representation.
5A99CVS
LD BC,073EH 01 3E 07
BC = integer size params [src: ALSO SET (A) TO NUMBER OF CHAR REQUIRED-1]
5A9CH (CVD) - MKS$ Function Handler (and common CVx processing)
Converts single-precision to 4-byte string. Also common code for CVI/CVS/CVD functions.
The MKI$/MKS$/MKD$ functions convert numeric values to binary string representations, while CVI/CVS/CVD convert binary strings back to numbers. These are used for binary file I/O. The type codes are: 1=integer (2 bytes), 2=single (4 bytes), 3=double (8 bytes). The string length must be exact for the type being converted.
5A9CCVD
PUSH AF F5
Save type code [src: DOUBLE PRECISION VALUE TYPE-1]
5A9D
Allocate string space
5AA0
POP AF F1
Restore type code
5AA1
CP (HL) BE
Compare type with string length
5AA2
If type >= length, Type Mismatch [src: GET BACK NUMBER OF CHAR REQUIRED-1]
5AA5
INC A 3C
Adjust type code
5AA6
INC HL 23
Skip length byte
5AA7
LD C,(HL) 4E
C = string address low [src: (A)=TRUE VALUE TYPE]
5AA8
INC HL 23
Point to high byte
5AA9
LD H,(HL) 66
H = string address high [src: (HL)=POINTER AT STRING DATA]
5AAA
LD L,C 69
HL = string data address [src: TO BE MOVED INTO THE FAC]
5AAB
LD (40AFH),A LD (VALTYP),A32 AF 40
Store type in variable type flag
5AAE
Complete conversion and return
5AB3H (FILIND) - WRITE# Statement Handler
Implements WRITE# for formatted output to sequential files. Automatically adds delimiters (commas) between fields and quotes around strings. Syntax: WRITE# filenumber, expression [, expression...]
WRITE# uses specific delimiters: strings are enclosed in quotes (22H) and fields are separated by commas (2CH). Numeric values use space (20H) delimiter. This differs from PRINT# which doesn't add quotes or commas automatically.
5AB3FILIND
LD DE,(63BEH) LD DE,(PTRFIL)ED 5B BE 63
Get current FCB pointer [src: SEE IF ITS A DISK FILE]
5AB7
LD A,D 7A
Check if file open [src: SAVE THE TEXT POINTER IN (DE)]
5AB8
OR E B3
Is FCB pointer zero?
5AB9
RET Z C8
If no file, return (use PRINT) [src: RETURN IF NOT]
5ABA
POP AF F1
Remove return address (change flow) [src: GET RID OF RETURN ADDR]
5ABB
GETYP: Get variable type [src: SEE IF INPUT IS STRING OR NUMBER]
5ABC
LD BC,2243H 01 43 22
BC = delimiters: B=22H (quote), C=43H [src: RETURN ADDRESS TO SETUP (FAC)]
5ABF
LD DE,2C20H 11 20 2C
DE = delimiters: D=20H (space), E=2CH (comma) [src: SET UP TERMINATORS SPACE AND COMMA]
5AC2
If not string (Z=0), numeric output [src: IF NUMERIC, GO READ THE FILE]
5AC5
LD E,D 5A
E = D = 20H (space delimiter for string) [src: MAKE BOTH TERMINATORS COMMA]
5AC6
Jump to WRITE output routine [src: GO READ THE FILE]
5AC9H (DLINE) - LINE INPUT# Statement Handler
Reads an entire line from a file into a string variable. Syntax: LINE INPUT# filenumber, string$. Unlike regular INPUT#, this reads the complete line including commas and quotes as literal characters.
5AC9DLINE
Validate '#' character present [src: GET FILE NUMBER SET UP]
5ACC
Evaluate expression (file number) [src: READ STRING TO STORE INTO]
5ACF
Get string address in DE [src: MAKE SURE IT WAS A STRING]
5AD2
LD BC,2169H LD BC,CONOUT01 69 21
BC = return address [src: RESET TO CONSOLE WHEN DONE READING]
5AD5
PUSH BC C5
Push return address [src: SAVE ON STACK]
5AD6
PUSH DE D5
Save string descriptor [src: SAVE POINTER AT VARIABLE]
5AD7
LD BC,1F31H 01 31 1F
BC = parameters for line input [src: GOOD RETURN ADDRESS FOR ASSIGNMENT]
5ADA
XOR A AF
A = 0 [src: SET A=0 FOR STRING VALUE TYPE]
5ADB
LD D,A 57
D = 0 (quote state) [src: ZERO OUT BOTH TERMINATORS]
5ADC
LD E,A 5F
E = 0 (delimiter state)
5ADDH (INPDOR) - WRITE# Main Processing Loop
Core routine for reading and processing file data for WRITE# or LINE INPUT#. Handles quotes, delimiters, and special characters.
5ADDINPDOR
PUSH AF F5
Save A register [src: SAVE VALUE TYPE]
5ADE
PUSH BC C5
Save delimiters (B=quote, C=field) [src: SAVE RETURN ADDR]
5ADF
PUSH HL E5
Save parser position [src: SAVE POINTER AT DATA COMING IN]
5AE0NOTNWT
Read character from file [LOOP START] [src: READ A CHAR]
5AE3
If carry (EOF), error [ERROR PATH] [src: READ PAST END ERROR IF EOF]
5AE6
CP 20H FE 20
Is it space? [LOOP] [src: SKIP LEADING SPACES]
5AE8
If not space, process normally [src: SKIP ANY NUMBER]
5AEA
INC D 14
Test D (quote state flag)
5AEB
DEC D 15
Restore D (sets Z if was 0)
5AEC
If in quotes (D≠0), skip space [LOOP]
5AEEH (NOTSPC) - Check for Quote Character
5AEENOTSPC
CP 22H FE 22
Is it quote (")? [src: QUOTED STRING COMING IN]
5AF0
If not quote, continue processing
5AF2
LD B,A 47
B = quote character (save it) [src: SAVE THE QUOTE]
5AF3
LD A,E 7B
A = delimiter state [src: MUST BE INPUT OF A STRING]
5AF4
CP 2CH FE 2C
Was last delimiter comma? [src: WHICH WAS (E)=44]
5AF6
LD A,B 78
Restore A = quote [src: QUOTE BACK INTO (A)]
5AF7
If not after comma, process normally
5AF9
LD D,B 50
D = quote (mark in-quote state) [src: TERMINATORS ATE QUOTES ONLY]
5AFA
LD E,B 58
E = quote (delimiter state)
5AFB
Read next character (skip opening quote) [src: READ PAST QUOTATION]
5AFE
If EOF, finish [ERROR PATH] [src: IF EOF, ALL DONE]
5B00H (NOTQTE) - Character Processing Main Logic
5B00NOTQTE
LD HL,(40A7H) LD HL,(TEMPPT)2A A7 40
HL = input buffer pointer
5B03
LD B,FFH 06 FF
B = max chars remaining (255) [src: MAXIMUN NUMBER OF CHAR (255)]
5B05LOPCRS
LD C,A 4F
C = current character [src: SAVE CHAR IN (C)]
5B06
LD A,D 7A
A = quote state [src: CHECK FOR QUOTED STRING]
5B07
CP 22H FE 22
Are we in quoted string?
5B09
LD A,C 79
Restore A = current char [src: RESTORE CHAR]
5B0A
If in quotes, store character [src: DONT IGNORE CR OR STOP ON LF]
5B0C
CP 0DH FE 0D
Is it CR (end of line)? [src: CR?]
5B0E
PUSH HL E5
Save buffer pointer [src: SAVE POINTER ON STACK]
5B0F
If CR, finalize input [src: EAT LINE FEED IF ONE]
5B11
POP HL E1
Restore buffer pointer [src: RESTORE DEST. PTR]
5B12
CP 0AH FE 0A
Is it LF (line feed)? [src: LF?]
5B14
If not LF, store character [src: NO,TEST OTHER TERMINATORS]
5B16
LD C,A 4F
C = LF character [src: SAVE CURRENT CHAR]
5B17
LD A,E 7B
A = last delimiter [src: GET TERMINATOR 2]
5B18
CP 2CH FE 2C
Was last delimiter comma? [src: CHECK FOR COMMA( UNQUOTED STRING]
5B1A
LD A,C 79
Restore A = LF [src: RESTORE ORIG CHAR]
5B1B
If not after comma, write char to buffer [src: IF NOT , STORE LF?]
5B1E
Read next character [src: GET NEXT CHAR]
5B21
If EOF, finish [ERROR PATH] [src: IF EOF, ALL DONE]
5B23
CP 0DH FE 0D
Is next char CR? [src: IS IT A CR ?]
5B25
If not CR, continue [src: IF NOT ,SEE IF STORE NORMALLY]
5B27
LD A,E 7B
A = last delimiter [src: GET TERMINATOR]
5B28
CP 20H FE 20
Was it space? [src: IS IT NUMERIC INPUT?]
5B2A
If space, read more [src: IF SO, IGNORE CR, DONT PUT IN BUFFER]
5B2C
CP 2CH FE 2C
Was it comma? [src: IS IT NON-QUOTED STRING (TERM=,)]
5B2E
LD A,0DH 3E 0D
A = CR [src: GET BACK CR.]
5B30
If comma, read more [src: IF SO , IGNORE CR.]
5B32H (NOTQTL) - Check for Delimiter Match
5B32NOTQTL
OR A B7
Check if char is zero [src: IS CHAR ZERO]
5B33
If zero, read next [src: ALWAYS IGNORE,AS IT IS TERMINATOR]
5B35
CP D BA
Does it match quote state? [src: TERMINATOR ONE?]
5B36
If closing quote, finish field [src: STOP THEN]
5B38
CP E BB
Does it match delimiter? [src: TERMINATOR TWO?]
5B39
If delimiter, finish field
5B3B
Store character in buffer [src: SAVE THE CHAR]
5B3EH (LPCRGT) - Read Next Character
5B3ELPCRGT
Read next character from file [src: READ ANOTHER CHAR]
5B41
If no EOF, continue loop [LOOP END] [src: IF NOT, CHECK AS TERMINATOR]
5B43H (QUITSI) - Field Complete - Process Terminator
5B43QUITSI
PUSH HL E5
Save buffer pointer [src: SAVE PLACE TO STUFF ZERO]
5B44
CP 22H FE 22
Is terminator a quote? [src: STOPPED ON QUOTE?]
5B46
If quote, skip trailing spaces [src: DONT SKIP SPACES THEN]
5B48
CP 20H FE 20
Is terminator a space? [src: STOPPED ON SPACE?]
5B4A
If not space, finalize [src: NO, DONT SKIP SPACES]
5B4CH (MORSPC) - Skip Trailing Spaces/Quotes
5B4CMORSPC
Read next character [SKIP LOOP START] [src: READ SPACES]
5B4F
If EOF, finalize [SKIP LOOP] [src: EOF,ALL DONE/]
5B51
CP 20H FE 20
Is it space?
5B53
If space, keep skipping [SKIP LOOP END]
5B55
CP 2CH FE 2C
Is it comma?
5B57
If comma, finalize [src: IF COMMA SKIP IT]
5B59
CP 0DH FE 0D
Is it CR? [src: CARRIAGE RETURN?]
5B5B
If not CR, check for LF [src: BACK UP PAST THIS CHAR]
5B5DH (ICASLF) - Handle End of Line (CR Found)
5B5DICASLF
Read next character [src: READ ANOTHER]
5B60
If EOF, finalize [src: EOF,ALL DONE]
5B62
CP 0AH FE 0A
Is it LF? [src: LINE FEED?]
5B64
If LF after CR, finalize [src: OK,SKIP IT TOO]
5B66H (BAKUPT) - Decrement Record Counter
5B66BAKUPT
LD HL,(63BEH) LD HL,(PTRFIL)2A BE 63
Get FCB pointer [src: GOTO NUMBER OF CHAR]
5B69
LD BC,0007H 01 07 00
Offset to record counter
5B6C
ADD HL,BC 09
HL = FCB + 7 (record counter)
5B6D
Decrement and check counter
5B72H (BAKCHR) - Decrement Record Counter and Check for Refill
Decrements the record counter at (HL). If counter reaches FFH, reads next record from file. Returns Z flag set if counter is zero.
The record counter at FCB+7 tracks how many characters remain in the current buffer. When it reaches FFH (255), the buffer is exhausted and a new record must be read from disk. This automatic buffering makes sequential file access efficient.
5B72BAKCHR
DEC (HL) 35
Decrement record counter [src: BACKUP BY DECREMENTING POSITION]
5B73
LD A,(HL) 7E
Get new counter value [src: SEE OF WE PAST BOUNDARY]
5B75
RET Z C8
If zero, return (Z set) [src: NO, EXIT]
5B76
CP FFH FE FF
Did it wrap to FFH?
5B78
RET NZ C0
If not FFH, return [src: SEE IF WRAP BACK]
5B79
PUSH HL E5
Save counter address [src: SINCE BUFFER IS 256 MAY HAVE TO BACKUP]
5B7B
LD BC,FFFBH 01 FB FF
BC = -5 (back to FCB start) [src: POINT AT OS DCB]
5B7E
ADD HL,BC 09
HL = FCB + 7 - 5 = FCB + 2
5B7F
EX DE,HL EB
DE = FCB + 2 [src: PASS IT IN (DE)]
5B80
DOS: Read next record [src: BACK UP ONE RECORD]
5B83
If error (NZ), translate DOS error
5B86
POP DE D1
Restore DE [src: RETRIEVE SAVED REGISTER]
5B87
POP HL E1
Restore counter address
5B88
LD (HL),FFH 36 FF
Reset counter to FFH (full buffer) [src: INDICATE ONLY ONE CHAR ACTIVE]
5B8A
RET C9
Return to caller
5B8BH (NOSKCR) - Finalize Field Input
Terminates the input buffer, processes the field data, and returns to caller.
5B8BNOSKCR
POP HL E1
Restore buffer pointer [src: GET BACK PLACE TO STORE TERMINATOR]
5B8CQUIT2B
LD (HL),00H 36 00
Null-terminate buffer [src: STORE THE TERMINATOR]
5B8E
LD HL,(40A7H) LD HL,(TEMPPT)2A A7 40
Get input buffer start
5B91
DEC HL 2B
Back up one position
5B92
LD A,E 7B
A = last delimiter [src: WAS A NUMERIC INPUT]
5B93
SUB 20H D6 20
Check if space (20H) [src: IF SO,(E)=' ']
5B95
If space, special handling [src: USE FIN TO SCAN IT]
5B97
LD B,00H 06 00
B = 0 [src: SCAN STRING LITERAL]
5B99
Process input data [src: TRAILING BLANKS ATE SIGNFIGANTY SINCE B<>44]
5B9C
POP HL E1
Restore HL from stack [src: GET BACK (HL)]
5B9D
RET C9
Return to caller
5B9EH (NUMIMK) - Space Delimiter Special Handling
5B9ENUMIMK
CHRGET: Get next character [src: READ FIRST CHAR]
5B9F
Process numeric input [src: SCAN THE NUMBERS]
5BA2
POP HL E1
Restore HL [src: GET (HL)]
5BA3
RET C9
Return to caller
5BA4H (STRCHR) - Store Character in Input Buffer
Stores character in buffer if non-zero and space remains. Auto-exits if buffer full.
5BA4STRCHR
OR A B7
Check if character is zero [src: TRYING TO STORE NULL BYTE]
5BA5
RET Z C8
If zero, don't store [src: RETURN, DONT STORE IT]
5BA6
LD (HL),A 77
Store character in buffer [src: STORE THE CHAR]
5BA7
INC HL 23
Advance buffer pointer
5BA8
DEC B 05
Decrement chars remaining [src: 128 YET?]
5BA9
RET NZ C0
If space remains, return [src: MORE SPACE IN BUFFER, RETURN]
5BAA
POP BC C1
Clean stack (remove return addr) [src: GET RID OF SUPERFLUOUS STACK ENTRY]
5BAB
Buffer full - finalize input [src: SPECIAL QUIT]
5BADH (PRGFLI) - LOAD/RUN/MERGE Common Entry
Common initialization for LOAD, RUN, and MERGE statements. Sets up parameters and jumps to main OPEN processing.
5BADPRGFLI
LD D,01H 16 01
D = 01H (LOAD/RUN mode) [src: SEQUENTIAL INPUT MODE]
5BAFPRGFL2
XOR A AF
A = 0 [src: INTERNAL FILE NUMBER IS ALWAYS ZERO]
5BB0
Jump to OPEN processing routine [src: SCAN FILE NAME AND DISK NUMBER']
5BB3H (LRUN) - RUN Statement (File Version)
Loads and executes a BASIC program from disk. Syntax: RUN "filename"
The RUN statement accepts optional ",R" parameter to start execution. The RUN mode flag at 5200H is set to FFH to distinguish from LOAD. After loading completes, execution transfers to the newly loaded program.
5BB3LRUN
RET C D8
If carry set, return [src: RETURN IF ITS A LINE NUMBER]
5BB4
POP AF F1
Remove return address (change flow) [src: GET RID OF RETURN ADDR IF NOT]
5BB5
LD A,FFH 3E FF
A = FFH (RUN flag)
5BB7
LD (5200H),A LD (DOPROT),A32 00 52
Set RUN mode flag [src: ALLOW RUNNING IF PROTECTED FILES]
5BBALRUN2
OR AFH F6 AF
Set flags [src: SET NON ZERO TO FLAG "RUN" COMMAND]
5BBC
PUSH AF F5
Save flags [src: SAVE "RUN/LOAD" FLAG]
5BBD
Call LOAD common routine [src: FIND THAT FILE AND SETUP FOR]
5BC0
LD A,(426DH) LD A,(MAXFIL)3A 6D 42
Get max file number [src: SAVE THE NUMBER OF FILES]
5BC3
LD (63E3H),A 32 E3 63
Save to file count storage [src: SINCE WE MAKE IT LOOK LIKE ZERO]
5BC6
DEC HL 2B
Back up parser [src: SO, R OPTION CAN LEAVE FILES OPEN]
5BC7
CHRGET: Get next char
5BC8
If end of statement, execute [src: NO,JUST LOAD]
5BCA
SYNCHR: Verify comma [src: GOTTA HAVE COMMA]
5BCB
DEFB 2CH 2C
Expected character: comma
5BCC
SYNCHR: Verify 'R' [src: ONLY OPTION IS 'RUN']
5BCD
DEFB 52H 52
Expected character: 'R'
5BCE
If not 'R', syntax error [src: AND THAT BETTER BE THE END]
5BD1H - RUN Statement Execution (Continued)
Completes RUN statement by clearing file number, setting EOF flag, and executing the loaded program.
5BD1
POP AF F1
Restore flags [src: GET RID OF "RUN/LOAD" FLAG]
5BD2CHNENT
XOR A AF
A = 0 [src: SO FILE AREN'T CLOSED]
5BD3
LD (426DH),A LD (MAXFIL),A32 6D 42
Clear max file number (no files) [src: PRETEND THERE AREN'T ANY]
5BD6
OR F1H F6 F1
A = F1H (EOF flag value) [src: FLAG NON-RUN WITH ZERO]
5BD8H - LOAD Common Completion
Common exit point for LOAD and RUN. Sets up EOF flag, initializes buffer, and completes the load operation.
5BD8
LD (63E2H),A LD (LSTFRE),A32 E2 63
Set EOF flag to A (F1H)
5BDB
LD HL,6250H LD HL,DIRTMP21 50 62
HL = default buffer address
5BDE
LD (HL),00H 36 00
Initialize buffer (clear first byte)
5BE0
LD (63C0H),HL LD (FILPTR),HL22 C0 63
Set current buffer pointer [src: MESS UP POINTER AT FILE ZERO]
5BE3
Process program in memory
5BE6
LD A,(63E3H) 3A E3 63
Get saved file count [src: RESTORE MAXFI L]
5BE9
LD (426DH),A LD (MAXFIL),A32 6D 42
Restore max file number [src: THAT WAS KLUDGED]
5BEC
LD HL,(63E0H) LD HL,(FILPT1)2A E0 63
Get last buffer end pointer
5BEF
LD (63C0H),HL LD (FILPTR),HL22 C0 63
Restore current buffer pointer
5BF2
LD (63BEH),HL LD (PTRFIL),HL22 BE 63
Restore current FCB pointer [src: PTRFIL FOT ZEROED SO FIS IT TOO]
5BF5NOTINI
Read character from file [src: READ THE FIRST CHAR]
5BF8
If EOF, finish [ERROR PATH] [src: ALL DONE IF NOTHING IN FILE]
5BFBNTPROL
INC A 3C
Increment character [src: IS IT A BINARY FILE?]
5BFC
If not FFH, continue [src: NO,SINCE PTRFIL IS NON-ZERO]
5BFEH (BINLOD) - Load Program Into Memory
Main program loading loop - reads file data into memory until EOF or memory full.
5BFEBINLOD
LD HL,(40A4H) LD HL,(TXTTAB)2A A4 40
HL = string space pointer [LOAD LOOP START] [src: GET PLACE TO START STORING INTO]
5C01LPBLDR
EX DE,HL EB
DE = string space [src: SEE IF THERE IS ROOM TO SPARE]
5C02
LD HL,(40A0H) LD HL,(STKTOP)2A A0 40
HL = memory top [LOAD LOOP]
5C05
LD BC,FFAAH 01 AA FF
BC = -86 (safety margin)
5C08
ADD HL,BC 09
HL = memory top - 86
5C09
CPDEHL: Compare string space with limit
5C0A
EX DE,HL EB
HL = string space
5C0B
If out of memory, finish [ERROR PATH] [src: ERROR AND WIPE OUT PARTIAL GARBAGE]
5C0D
Read character from file [src: UNLINKED!! NO ZEROES AT THE END!!]
5C10
LD (HL),A 77
Store character in memory [src: STORE BYTE]
5C11
INC HL 23
Advance memory pointer [src: INCREMENT POINTER]
5C12
If no EOF, continue loading [LOAD LOOP END] [src: READ TRHE NEXT CHAR]
5C14
Finalize program in memory [src: FIX THE LINKS]
5C17
INC HL 23
Skip terminator byte [src: WHEN LINKER RETURNS, (HL)]
5C18
INC HL 23
Skip second terminator [src: POINTS TO DOUBLE ZEROES]
5C19
LD (40F9H),HL LD (VARTAB),HL22 F9 40
Save end of file buffer [src: UPDATE (VARTAB)]
5C1C
LD HL,426DH LD HL,MAXFIL21 6D 42
HL = max file number address [src: ONLY CLOSE FILE ZERO]
5C1F
LD A,(HL) 7E
Get current max file number
5C20
LD (63E3H),A 32 E3 63
Save to file count storage
5C23
LD (HL),00H 36 00
Clear max file number
5C25
Link program lines [src: SETUP ARYTAB,STREND]
5C28
LD A,(63E3H) 3A E3 63
Get saved file count [src: RESTORE NUMBER OF FILES]
5C2B
LD (426DH),A LD (MAXFIL),A32 6D 42
Restore max file number
5C2E
LD A,(63E2H) LD A,(LSTFRE)3A E2 63
Get EOF flag
5C32
If not EOF, normal return
5C35
If EOF, execute loaded program
The LOAD routine reads the program file byte-by-byte into the string space area, checking memory limits. After loading, it processes the program lines (1AF8H), links them properly (1B5DH), and if this is RUN (EOF flag = F1H), executes the program at 1D1EH.
5C38H (PRGFIN) - PRINT# Output Completion
Finalizes PRINT# statement output. Closes file if requested and cleans up.
5C38PRGFIN
Finalize PRINT output [src: ZERO PTRFIL]
5C3B
Close file helper [src: CLOSE FILE ZERO]
5C3E
POP HL E1
Get return address [src: GET RETURN ADDR]
5C40
LD DE,1A1FH 11 1F 1A
DE = comparison address [src: CALLING FROM READY?]
5C43
CPDEHL: Compare return address
5C44
POP DE D1
Restore DE [src: GET (DE) BACK]
5C45
PUSH HL E5
Push return address back [src: RESTORE RETURN ADDR]
5C46
If match, cleanup file [src: TEST PROTECTION]
5C49
Return to main interpreter [src: REFETCH TEXT POINTER]
5C4CH (OUTLOD) - Out of Memory During LOAD
5C4COUTLOD
Process partial program
5C4F
Trigger Out of Memory error
5C52H (MERGE) - MERGE Statement Handler
Merges program from disk with current program in memory. Syntax: MERGE "filename"
5C52MERGE
POP BC C1
Remove return address [src: ELIMINATE NEWSTT RETURN]
5C53
Call LOAD common routine [src: READ THE NAME AND DISK]
5C56
DEC HL 2B
Back up parser [src: MUST END THERE]
5C57
CHRGET: Get next char
5C58
If end of statement, merge [src: READ THE FILE]
5C5A
Complete PRINT# if needed [src: CLOSE OUT TIME]
5C5D
Syntax error [src: AND 'SYNTAX ERROR]
5C60H (OKGETM) - Execute MERGE Operation
5C60OKGETM
XOR A AF
A = 0 (clear EOF flag) [src: NO RUN OPTION WITH 'MERGE']
5C61
LD (63E2H),A LD (LSTFRE),A32 E2 63
Clear EOF flag (not RUN) [src: SET UP THE FLAG]
5C64
Read first character [src: READ FROM (PTRFIL) FILE]
5C67
If EOF immediately, finish [src: GO BACK IF EOF]
5C6A
INC A 3C
Check for FFH marker [src: IS IT A BINARY FILE?]
5C6B
If FFH (binary), error [src: BINARY IS WRONG FILE MODE]
5C6EH (MAINGO) - MERGE/LOAD Record Processing
5C6EMAINGO
LD HL,(63BEH) LD HL,(PTRFIL)2A BE 63
Get FCB pointer [src: GET FILE POINTER]
5C71
LD BC,0007H 01 07 00
Offset to record counter [src: OFFSET TO NEXT RECORD NUMBER]
5C74
ADD HL,BC 09
HL = FCB + 7 [src: BY ADDING OFFSET]
5C75
Decrement record counter [src: BACK UP ONE CHARACTER]
5C78
Return to interpreter
5C7BH (DIRDO) - PRINT# Statement Handler
Outputs formatted data to a file. Syntax: PRINT# filenumber, expression [; expression...]
5C7BDIRDO
RET C D8
If carry set, return [src: RETURN IF A LINE INPUT]
5C7C
POP AF F1
Remove return address [src: GET RID OF THE RETURN ADDR]
5C7D
PUSH HL E5
Save parser position
5C7E
LD HL,(63BEH) LD HL,(PTRFIL)2A BE 63
Get FCB pointer
5C81
LD A,H 7C
Check if file open
5C82
OR L B5
Is FCB pointer zero? [src: IS PTRFIL ZERO SO NOT FILE READING]
5C83
LD DE,0084H 11 84 00
DE = error code (Bad File Mode) [src: 'DIRECT STATEMENT IN FILE']
5C86
If file open, error [src: NOTE: LXI D IS USED TO]
5C89
POP HL E1
Restore parser position [src: GET BACK POINTER AT BUFMIN]
5C8A
File cleanup routine [src: TEST PROTECTION SWITCH]
5C8D
Jump to PRINT handler [src: EXECUTE DIRECT STATEMENT]
5C90H (SAVE) - SAVE Statement Handler
Saves current BASIC program to disk. Syntax: SAVE "filename" [,A]
5C90SAVE
LD D,02H 16 02
D = 02H (SAVE mode) [src: ELIMINATE EARLIER VERSION]
5C92
Call file open routine [src: READ FILE NAME AND DISK NUMBER AND]
5C95
DEC HL 2B
Back up parser [src: LOOK IT UP]
5C96
CHRGET: Get next char
5C97
If end of statement, save ASCII [src: BINARY SAVE]
5C99
SYNCHR: Verify comma [src: ONLY OPTION IS ',A']
5C9A
DEFB 2CH 2C
Expected character: comma
5C9B
SYNCHR: Verify 'A' [src: FOR ASCII SAVE]
5C9C
DEFB 41H 41
Expected character: 'A' (ASCII)
5C9D
Jump to ASCII save handler. This uses the LIST code, and this is a JUMP directly to the LIST entry point.
5CA0H (BINSAV) - Save Program in Binary Format
Saves program as tokenized binary format (default for SAVE without ,A option).
SAVE writes the program in tokenized binary format by default. The FFH marker at the start indicates binary format. The ",A" option (handled at 2B2EH) saves in ASCII format instead. Binary saves are smaller and faster but not human-readable.
5CA0BINSAV
LD A,FFH 3E FF
A = FFH (binary marker) [src: ALWAYS START WITH 255]
5CA2BINPSV
Write marker to file [src: SEND TO FILE]
5CA5
LD DE,(40F9H) LD DE,(VARTAB)ED 5B F9 40
DE = end of file buffer [src: GET STOP POINT]
5CA9
LD HL,(40A4H) LD HL,(TXTTAB)2A A4 40
HL = string space pointer (program start) [src: GET START POINT]
5CACBSAVLP
CPDEHL: Compare pointers [SAVE LOOP START]
5CAD
If all written, finish [SAVE LOOP END] [src: REACHED TH END?]
5CAF
LD A,(HL) 7E
Get byte from program [SAVE LOOP] [src: GET LINE DATA]
5CB0
INC HL 23
Advance program pointer [src: POINT AT NEXT DATA]
5CB1
PUSH DE D5
Save end pointer [src: SAVE LIMIT]
5CB2
Write byte to file [src: SEND CHAR TO FILE]
5CB5
POP DE D1
Restore end pointer [src: RESTORE LIMIT]
5CB6
Continue saving [LOOP] [src: CONTINUE WITH LINE DATA]
5CB8H (CLOSE) - CLOSE Statement Handler
Closes one or all open files. Syntax: CLOSE [#filenumber] or CLOSE (closes all files)
5CB8CLOSE
LD BC,5E14H LD BC,CLSFIL01 14 5E
BC = file close routine address [src: SERVICE ROUTINE ADDR]
5CBB
LD A,(426DH) LD A,(MAXFIL)3A 6D 42
A = max file number [src: HIGHEST POSSIBLE ARGUMENT]
5CBEPTALLR
If specific file, jump to handler [src: NOT END OF STATEMENT SO SCAN ARGUMENTS]
5CC0H - Close All Files Loop
Iterates through all file numbers and closes each open file.
5CC0
PUSH HL E5
Save parser position [CLOSE ALL LOOP START] [src: SAVE THE TEXT POINTER]
5CC1MRALL
PUSH BC C5
Save close routine address [src: SAVE ROUTINE ADDR]
5CC2
PUSH AF F5
Save file number counter [CLOSE ALL LOOP] [src: SAVE CURRENT VALUE]
5CC3
LD DE,5CC9H LD DE,RETALL11 C9 5C
DE = return address [src: RETURN ADDR]
5CC6
PUSH DE D5
Push return address [src: SAVE IT TO COME BACK WITH]
5CC7
PUSH BC C5
Push close routine address [src: DISPATCH TO SERVICE ROUTINE ADDR]
5CC8
RET C9
Call close routine (RET to BC)
5CC9RETALL
POP AF F1
Restore file number [src: GET BACK OLD ARGUMENT]
5CCA
POP BC C1
Restore close routine [src: GET BACK SERVICE ROUTINE ADDR]
5CCB
DEC A 3D
Decrement file counter [src: DECREMENT ARGUMENT]
5CCC
If more files, continue [CLOSE ALL LOOP END] [src: LOOP ON MORE VALUES]
5CCF
POP HL E1
Restore parser position [src: GET BACK THE TEXT POINTER]
5CD0
RET C9
Return to caller
5CD1H (RETRTS) - Check for Additional Files to Close
5CD1RETRTS
POP BC C1
Remove BC from stack [src: GET BACK SERVICE ROUTINE ADDR]
5CD2
POP HL E1
Get parser position [src: GET BACK THE TEXT POINTER]
5CD3
LD A,(HL) 7E
Get next character [src: SEE IF MORE ARGUMENTS]
5CD4
CP 2CH FE 2C
Is it comma? [src: DELIMITED BY COMMA]
5CD6
RET NZ C0
If not comma, done
5CD7
CHRGET: Skip comma [src: READ FIRST CHAR OF FORMULA]
5CD8H (RTLOOP) - Close Specific File Number
5CD8RTLOOP
PUSH BC C5
Save close routine address [src: SAVE THE SERVICE ROUTINE ADDR]
5CD9
LD A,(HL) 7E
Get next character [src: GET POSSIBLE"#"]
5CDA
CP 23H FE 23
Is it '#'? [src: IS IT?]
5CDC
If '#', skip it [src: SKIP IT ,ITS OPTIONAL]
5CDF
Get file number in A [src: READ THE ARGUMENT]
5CE2
EX (SP),HL E3
HL = close routine, save parser [src: SAVE THE TEXT POINTER ON THE STACK]
5CE3
PUSH HL E5
Push close routine as return [src: SAVE THE SERVICE ADDR]
5CE4
LD DE,5CD1H LD DE,RETRTS11 D1 5C
DE = continuation address [src: PUT A RETURN ADDR ON THE STACK]
5CE7
PUSH DE D5
Push continuation address
5CE8
JP (HL) E9
Jump to close routine [src: DISPATCH TO DO THE FUNCTION]
5CE9H (CLSALL) - Close All Files Routine
Emergency close all files. Called by SYSTEM, errors, and program termination.
5CE9CLSALL
PUSH DE D5
Save DE
5CEA
PUSH BC C5
Save BC [src: SAVE (BC) FOR STKINI]
5CEB
XOR A AF
A = 0 (close all marker) [src: MAKE IT CLOSE ALL DISKS]
5CF0
POP DE D1
Restore DE [src: GET BACK (DE)]
5CF1
XOR A AF
A = 0 (clear flags) [src: RETURN WITH (A)=0 AND Z ON]
5CF2
RET C9
Return to caller
5CF3H (FIELD) - FIELD Statement Handler
Defines field structure for random access files. Syntax: FIELD #n, width AS stringvar [, width AS stringvar...]
5CF3FIELD
Parse file number [src: GET DATA BLOCK POINTER IN (BC)]
5CF6
If file not open, error [src: 'BAD FILE NUMBER ' IF FILE NOT OPEN]
5CF9
SUB 03H D6 03
Check file mode (must be random=3) [src: MAKE SURE ITS A RANDOM FILE]
5CFB
If not random access, error [src: IF NOT ,"BAD FILE MODE"]
5CFE
EX DE,HL EB
DE = parser position [src: SAVE TEXT POINTER]
5CFF
LD HL,000BH 21 0B 00
HL = offset 11 (record length)
5D02
ADD HL,BC 09
HL = FCB + 11
5D03
LD A,(HL) 7E
Get record length [src: GET RECORD SIZE]
5D04
LD (63B6H),A LD (FLRL),A32 B6 63
Save to record length variable
5D07
XOR A AF
A = 0 (field position)
5D08
EX DE,HL EB
HL = parser, DE = FCB+11
5D09
LD DE,0034H 11 34 00
DE = offset 52 (buffer start) [src: OFFSET TO POINT AT DATA]
5D0CH (LOPFLD) - FIELD Definition Loop
Processes each field definition in the FIELD statement.
5D0CLOPFLD
EX DE,HL EB
Swap DE/HL [FIELD LOOP START] [src: SAVE TEXT POINTER IN (DE)]
5D0D
ADD HL,BC 09
HL = FCB + offset [FIELD LOOP] [src: ADD ON DATA POINTER SO (HL) NOW POINTS]
5D0E
LD B,A 47
B = current position [src: SETUP COUNT OF CHAR PAST BY]
5D0F
EX DE,HL EB
Restore HL = parser [src: IN DATA AREA ,SO TOTAL IS NEVER GREATER THAN 128]
5D10
LD A,(HL) 7E
Get next character [src: MORE "AS"S TO SCAN]
5D11
CP 2CH FE 2C
Is it comma? [src: COMMA STARTS THE CLAUSE]
5D13
RET NZ C0
If not comma, done [FIELD LOOP END]
5D14
PUSH DE D5
Save buffer address [src: SAVE THE POINTER INTO THE DATA BLOCK]
5D15
PUSH BC C5
Save position [src: SAVE (B)=NUMBER OF CHAR ALLOCATED]
5D16
Get field width in A [src: READ NUMBER INTO (A) FROM TEXT]
5D19
PUSH AF F5
Save width [src: SAVE THIS NUMBER]
5D1A
SYNCHR: Verify 'A' [src: SCAN THE 'AS']
5D1B
DEFB 41H 41
Expected: 'A' (AS keyword)
5D1D
DEFB 53H 53
Expected: 'S'
5D1E
Evaluate string variable [src: GET A POINTER AT THE STRING DESCRIPTOR]
5D21
Get string descriptor address [src: INTO (DE)]
5D24
POP AF F1
Restore width [src: GET THE NUMBER OF CHAR]
5D25
POP BC C1
Restore position [src: GET THE NUMBER ALREADY USED]
5D26
EX (SP),HL E3
HL = buffer addr, save parser [src: SAVE THE TEXT POINTER AND]
5D27
LD C,A 4F
C = width [src: SAVE # OF CHAR IN (C)]
5D28
ADD A,B 80
A = position + width [src: GET OLDTOTAL + NEW COUNT]
5D29
If no overflow, continue
5D2EH (FEVSOK) - Validate Field Width
5D2EFEVSOK
LD B,A 47
B = new position [src: SAVE FIELD POSITION]
5D2F
LD A,(63B6H) LD A,(FLRL)3A B6 63
A = record length [src: GET RECORD LENGHT]
5D32
CP B B8
Compare with new position [src: ARE WE WITHIN?]
5D33
If within record, OK [src: IF SO, OK]
5D35
OR A B7
Check if record length is zero [src: ALSO OK IF RECORD SIZE IS 0]
5D36
If nonzero and overflow, error
5D39H (GOODFL) - Store Field Descriptor
The FIELD statement maps string variables to sections of a random access file's record buffer. Each field has a width (in bytes) and a string variable name. The statement stores width and buffer address in the string descriptor (3 bytes: length, addr_low, addr_high). The field position is tracked and validated against the record length (63B6H) to prevent buffer overflow.
5D39GOODFL
LD A,B 78
A = new position [src: GET BACK POSITION]
5D3B
EX DE,HL EB
DE = buffer address [src: (HL) POINT TO STRING DESCRIPTOR]
5D3C
LD (HL),C 71
Store width in descriptor [src: STORE THE LENGTH]
5D3E
LD (HL),E 73
Store buffer address low [src: STORE THE POINTER INTO THE DATA BLOCK]
5D40
LD (HL),D 72
Store buffer address high
5D41
LD B,00H 06 00
B = 0 for BC
5D43
POP HL E1
Restore parser position [src: (BC)=DOUBLE BYTE ODDSET FOR DATA POINTER]
5D44
If more fields, continue loop [src: IF TOTAL ADDED UP TO NOT 256 ,GO BACK FOR MORE]
5D46
LD A,C 79
A = width [src: SEE HOW MUCH WE ADDED]
5D47
OR A B7
Check if zero [src: TEST]
5D48
RET NZ C0
If nonzero, return [src: JUST ADDED UP TO 256 ,GIVE SYNTAX ERROR IF MORE]
5D49
Process next field [src: CONTINUE SCANNING "AS" CLAUSES IF MORE]
5D4BH (RSET) - RSET Statement Handler
Right-justify string in field. Syntax: RSET stringvar = expression. Pads left side with spaces.
5D4BRSET
OR 37H F6 37
Set bit 5 and others (RSET flag) [src: ORI <STC>]
5D4DH - LSET Statement Handler
Left-justify string in field. Syntax: LSET stringvar = expression. Pads right side with spaces. RSET falls through to here.
5D4D
PUSH AF F5
Save LSET/RSET flag [src: SAVE LSET/RSET FLAG]
5D4E
Evaluate left side (string variable) [src: GET POINTER TO STRINGVAR]
5D51
Get string descriptor in DE [src: MUST BE A STRING VARIABLE]
5D54
PUSH DE D5
Save descriptor address [src: SAVE POINTER TO DESCRIPTOR]
5D55
SYNCHR: Verify '=' [src: MUST HAVE '=']
5D56
DEFB D5H D5
Expected character: '=' (equals sign, actually D5H is unusual...)
5D57
Evaluate right side (string expression) [src: EVALUATE STRINGEXP]
5D5A
POP BC C1
BC = destination descriptor [src: (BC)= POINTER TO DESCR]
5D5B
EX (SP),HL E3
HL = LSET/RSET flag, save parser [src: TEXT PTR ON VOTTOM OF STACK]
5D5C
PUSH HL E5
Save flag again [src: LSET/RSET FLAG NEXT]
5D5D
PUSH BC C5
Save destination descriptor [src: PUT DESCR.PTR BACK ON]
5D5E
Get source string address in HL [src: ERROR IF NOT STRING FREE TEMP]
5D61
LD B,(HL) 46
B = source string length [src: GETY LENGTH OF STRINGVAR]
5D62
EX (SP),HL E3
HL = dest descriptor, save source [src: (HL)=DESCR. OF VAR,SAVE OTHER]
5D63
LD A,(HL) 7E
A = destination length [src: GET LENGTH OF STRINGVAR]
5D64
LD C,A 4F
C = destination length [src: SAVE IN C]
5D65
PUSH BC C5
Save lengths (B=src, C=dst) [src: SAVE LENGTHS OF VOTH]
5D66
PUSH HL E5
Save dest descriptor [src: SAVE DESCRIPTOR POINTER]
5D67
PUSH AF F5
Save dest length [src: PSW ZERO OF WAS TEMP]
5D68
INC HL 23
Point to address bytes
5D69
LD E,(HL) 5E
E = dest address low
5D6B
LD D,(HL) 56
DE = destination buffer address [src: GET PTR TO STRINGVAR TEXT]
5D6C
OR A B7
Check if dest length is zero [src: STRINGVAR NULL?]
5D6D
If zero length, cleanup and exit [src: YES, DON'T CHANGE]
5D6F
LD HL,(40A4H) LD HL,(TXTTAB)2A A4 40
HL = string space pointer
5D72
CPDEHL: Is dest in string space?
5D73
If not in string space, skip check [src: YES,USE IT]
5D75
LD HL,(40F9H) LD HL,(VARTAB)2A F9 40
HL = end of file buffer
5D78
CPDEHL: Is dest below file buffer? [src: STRING VAR IN PROGRAM (LITERAL) ?]
5D79
If in safe area, proceed [src: NO,IN STRING SPACE SO USE IT]
NOTE: The SYNCHR at 5D56H uses D5H as the expected character. This is unusual - D5H is not the '=' character (which is 3DH). This appears to be an error or the bytes may be misaligned. The hex should be verified against the actual file.
5D7BH - Garbage Collection for Field Assignment
If destination is a temporary string, performs garbage collection to make room.
5D7B
LD E,C 59
E = destination length [src: # BYTES TO ALLOCATE FOR RESULT]
5D7C
LD D,00H 16 00
DE = dest length (16-bit)
5D7E
LD HL,(40A0H) LD HL,(STKTOP)2A A0 40
HL = memory top
5D81
ADD HL,DE 19
HL = top + length
5D82
EX DE,HL EB
DE = required top
5D83
LD HL,(40D6H) LD HL,(TEMP)2A D6 40
HL = temp string pointer
5D86
Perform garbage collection [src: WILL GETSPA GARBAGE COLLECT]
5D89
If carry (error), handle it [src: YES,BETTER HAVE STRINGEXP TEMP]
5D8BMADESC
POP AF F1
Restore dest length
5D8C
LD A,C 79
A = dest length [src: GET LENGTH OF STRINGVAR]
5D8D
Allocate string space [src: GET SPACE FOR RESULT]
5D90
POP HL E1
Restore dest descriptor address [src: GET STRINGVAR]
5D91
POP BC C1
Restore lengths
5D92
EX (SP),HL E3
HL = source string, save dest desc [src: GET WHAT WE WANTED, STRINGEXP DESCR.]
5D93
PUSH DE D5
Save new address
5D94
PUSH BC C5
Save lengths
5D95
Get source string again [src: FREE TEMP IF ANY]
5D98
POP BC C1
Restore lengths
5D99
POP DE D1
Restore new address
5D9A
EX (SP),HL E3
HL = dest descriptor
5D9B
PUSH BC C5
Save lengths [src: RESTORE STACK TO PREVIOUS STATE]
5D9C
PUSH HL E5
Save dest descriptor
5D9D
INC HL 23
Point to address
5D9E
LD (HL),E 73
Store new address low
5DA0
LD (HL),D 72
Store new address high [src: SET POINTER TO STRINGVAR COPY]
5DA2H (OLDSTR) - Get Source and Destination Pointers
5DA2OLDSTR
POP AF F1
Restore A
5DA3
POP HL E1
HL = dest descriptor [src: GET STRINGVAR DESCR.]
5DA4
INC HL 23
Point to address
5DA5
LD E,(HL) 5E
E = dest address low
5DA7
LD D,(HL) 56
DE = dest buffer address
5DA8
POP BC C1
BC = lengths (B=src, C=dst) [src: GET LENGTH OFF STACK]
5DA9
POP HL E1
HL = source descriptor [src: GET POINTER TO STRINGEXP DESCR.]
5DAA
PUSH DE D5
Save dest address
5DAB
INC HL 23
Point to source address
5DAC
LD E,(HL) 5E
E = source address low
5DAE
LD D,(HL) 56
DE = source address
5DAF
EX DE,HL EB
HL = source address [src: GET POINTER TO STRINGEXP TEXT]
5DB0
POP DE D1
DE = dest address
5DB1
LD A,C 79
A = dest length [src: GET LENGTH OF FIELD(STRINGVAR)]
5DB2
CP B B8
Compare dest with source length
5DB3
If dest >= source, use dest length [src: JUMP IF FIELD LARGE ENOUGH FOR RESULT]
5DB5
LD B,A 47
B = dest length (truncate source) [src: SAVE # OF BYTES TO COPY]
5DB6H (FILDOK) - Calculate Padding and Perform Copy
5DB6FILDOK
SUB B 90
A = dest length - copy length
5DB7
LD C,A 4F
C = padding length [src: (C)= # VLANKS TO FILL]
5DB8
POP AF F1
Restore LSET/RSET flag [src: GET LSET/RSET FLAG]
5DB9
If RSET (NC), pad left with spaces [src: FILL LEADING IF RSET]
5DBC
INC B 04
Test B [src: IN CASR ZERO]
5DBDCOPLOP
DEC B 05
Restore B (set Z if was 0) [src: DECR. # TO COPY]
5DBE
If no chars to copy, skip [src: DONE WHEN ALL COPIED]
5DC0H - String Copy Loop
5DC0
LD A,(HL) 7E
Get source character [COPY LOOP START] [src: GET BYTE FROM STRINGEXP]
5DC1
LD (DE),A 12
Store to destination [COPY LOOP] [src: COPY TO STRINGVAR]
5DC3
INC DE 13
Next destination
5DC4
Continue copy [COPY LOOP END]
5DC6H (RETCUR) - Zero-Length Field Cleanup
5DC6RETCUR
POP BC C1
Clean stack (5 values)
5DCBH (LRSTDN) - Pad Right Side (LSET)
5DCBLRSTDN
If LSET (C set), pad right with spaces [src: FILL TRAILING IF LSET]
5DCE
POP HL E1
Restore parser position [src: RESTORE TEXT POINTER]
5DCF
RET C9
Return to caller
5DD0H (BLKFIL) - Fill with Spaces Subroutine
Fills C bytes at (DE) with spaces (20H). Used for padding in LSET/RSET.
5DD0BLKFIL
LD A,20H 3E 20
A = space character [src: FILL EITH SPACES]
5DD2
INC C 0C
Test C [PAD LOOP START] [src: IN CASE ZERO]
5DD3BLKFL1
DEC C 0D
Restore C (set Z if was 0) [PAD LOOP] [src: DECR. # TO FILL]
5DD4
RET Z C8
If no padding needed, return [src: RETURN WHEN DONE]
5DD5
LD (DE),A 12
Store space [src: STORE SPACE]
5DD6
INC DE 13
Next position
5DD7
Continue padding [PAD LOOP END]
5DD9H (MAKDSC) - String Allocation Error Handler
5DD9MAKDSC
POP AF F1
Clean stack [src: GET TEMP FLAG]
5DDC
EX (SP),HL E3
Get source descriptor [src: DIG DOWN TO STRINGEXP DESCR.]
5DDD
EX DE,HL EB
DE = source descriptor [src: FRETMS WANTS (DE)]
5DDE
If error not zero, skip conversion [src: NOT A TEMP, DON'T REALLOCATE]
5DE1
LD A,B 78
A = source length
5DE2
Convert to string type [src: MAKE A TEMP POINT TO STRINGEXP]
5DE5
Process string [src: GET A TEMP TO POINT TO IT]
5DE9H (MAKDS1) - Continue Error Recovery
5DE9MAKDS1
EX (SP),HL E3
Restore stack state
5DEB
PUSH HL E5
Save HL [src: RESTORE STACK TO PREVIOUS STATE]
5DEDAAA
Jump back to retry allocation
5DEFH (EOF) - EOF Function Handler
Tests if end-of-file reached for a file. Syntax: EOF(filenumber). Returns -1 (true) if at EOF, 0 (false) otherwise.
5DEFEOF
Get file number and validate [src: CONVERT ARGUMENT TO FILE NUMBER]
5DF2
CP 02H FE 02
Is it output mode (02H)? [src: IS IT A SEQUENTIAL OUTPUT FILE ?]
5DF4
If output, error (can't EOF on output) [src: IF SO," BAD FILE MODE "]
5DF7
LD HL,000FH 21 0F 00
HL = offset 15 (current record high) [src: COMPARE RECORD NUMBERS]
5DFA
ADD HL,BC 09
HL = FCB + 15
5DFB
LD A,(HL) 7E
A = current record high byte [src: GET INTO (A,E)]
5DFC
DEC HL 2B
HL = FCB + 14
5DFD
LD E,(HL) 5E
E = current record low byte
5DFE
DEC HL 2B
HL = FCB + 13
5DFF
CP (HL) BE
Compare current high with last high [src: HIGH ORDERS MATCH?]
5E00
If different, not at EOF
5E02
DEC HL 2B
HL = FCB + 12
5E03
LD A,E 7B
A = current low byte
5E04
CP (HL) BE
Compare current low with last low [src: COMPARE LOW ORDERS]
5E05
If different, not at EOF
5E07
DEC HL 2B
HL = FCB + 11 (record length)
5E08
DEC HL 2B
HL = FCB + 10 (buffer position) [src: POINT AT EOF BYTE COUNT]
5E09
LD A,(HL) 7E
A = buffer position [src: FETCH FOR COMPARISON]
5E0A
DEC HL 2B
HL = FCB + 9
5E0B
DEC HL 2B
HL = FCB + 8
5E0C
DEC HL 2B
HL = FCB + 7 (chars remaining) [src: BACK UP TO CURRENT BYTE POSITION]
5E0D
SUB (HL) 96
A = position - remaining [src: THE SAME?]
5E0EH (NOEOF) - Return EOF Status
EOF checks if the current record number equals the last record number AND if the buffer position equals or exceeds the characters remaining. This indicates all data has been read. The function returns -1 (true) if at EOF, 0 (false) otherwise.
5E0ENOEOF
SUB 01H D6 01
Set carry if A was 0 [src: MAP 0 TO -1 AND ALL OTHERS TO 0]
5E10
SBC A,A 9F
A = FFH if carry, 00H if no carry
5E11
Convert to floating point and return [src: CONVERT TO AN INTEGER AND RETURN]
5E14H (CLSFIL) - File Close Helper
Internal file close routine. Validates file number and closes the file via DOS.
5E14CLSFIL
Get file number in A, FCB in BC [src: GET POINTER TO DATA]
5E17
RET Z C8
If file not open (Z), return
5E18
CP 01H FE 01
Is it input mode? [src: DON'T NEED TO CLOSE INPUT EITHER]
5E1C
PUSH BC C5
Save FCB pointer [src: SAVE FILE POINTER]
5E1D
XOR A AF
A = 0 (clear flag) [src: CLEAR MODE SO DON'T CLOSE AGAIN IF FAILS]
5E1E
LD (BC),A 02
Clear FCB status byte [src: A MODE OF 0 MEANS NOT OPEN]
5E1F
INC BC 03
BC = FCB + 1 [src: POINT AT OS DCB]
5E20
INC BC 03
BC = FCB + 2
5E22
LD E,C 59
DE = FCB + 2
5E26
If error, translate DOS error [src: NO ERROR VALID]
5E29
POP BC C1
Restore FCB pointer
5E2AH (NTOPNC) - Clear File Buffer
5E2ANTOPNC
LD D,34H 16 34
D = 52 (buffer size to clear) [src: NO. OF BYTES TO ZERO]
5E2C
XOR A AF
A = 0 [CLEAR LOOP START]
5E2DMORCZR
LD (BC),A 02
Clear byte in FCB [CLEAR LOOP]
5E2F
DEC D 15
Decrement counter
5E30
Continue clearing [CLEAR LOOP END]
5E32
RET C9
Return to caller
5E33H (LOC) - LOC Function Handler
Returns current record number for random access file. Syntax: LOC(filenumber)
5E33LOC
Get file number and FCB [src: CONVERT ARGUMENT AND POINT AT DATA BLOCK]
5E36
If file not open, error [src: IF NOT OPEN, "BAD FILE NUMBER]
5E39
SCF 37
Set carry flag [src: SET CARRY. LOC CALLING]
5E3A
LD HL,000CH 21 0C 00
HL = offset 12 (last record low) [src: POINT AT CURLOC HIGH BYTE]
5E3DLOFEND
PUSH AF F5
Save flags [src: SAVE THE FLAGS]
5E3E
ADD HL,BC 09
HL = FCB + 12
5E3F
LD E,(HL) 5E
E = last record low byte [src: GET THE LSB OF THE ERN]
5E40
INC HL 23
HL = FCB + 13 [src: INC TO THE MSB]
5E41
LD D,(HL) 56
DE = last record number [src: GET THE MSB OF ERN]
5E42
LD HL,000BH 21 0B 00
HL = offset 11 (record length) [src: GET THE LRL OF THE FILE]
5E45
ADD HL,BC 09
HL = FCB + 11
5E46
LD A,(HL) 7E
A = record length
5E47
LD (5E69H),A LD (LRL2),A32 69 5E
Store to self-modify location **SELF-MODIFY** [src: SAVE IT]
5E4A
LD HL,000AH 21 0A 00
HL = offset 10 (buffer position) [src: GET THE END OF FILE BYTE]
5E4D
POP AF F1
Restore flags [src: GET THE FLAGS BACK]
5E4E
If no carry, use offset 10 [src: IT'S 'LOF' CALLING]
5E50
LD HL,0007H 21 07 00
HL = offset 7 (chars remaining) [src: USE THE OFFSET FOR LOC]
5E53H (LOFEN1) - Calculate Record Position (LOC/LOF Common)
Calculates record number based on byte position. Uses self-modifying code for record length.
5E53LOFEN1
ADD HL,BC 09
HL = FCB + offset
5E54
LD A,(HL) 7E
A = position or chars remaining
5E55
LD (5E70H),A LD (EOF2),A32 70 5E
Store to self-modify location **SELF-MODIFY** [src: SAVE IT]
5E58
LD A,(5E69H) LD A,(LRL2)3A 69 5E
Get record length **SELF-MODIFIED** [src: GET THE LRL]
5E5B
OR A B7
Check if zero [src: LRL 256?]
5E5C
If nonzero, calculate normally [src: NO, CONTINUE]
5E5E
LD A,(5E70H) LD A,(EOF2)3A 70 5E
Get position **SELF-MODIFIED** [src: GET THE EOF BYTE]
5E61
OR A B7
Check if zero [src: ON SECTOR BOUNDARY?]
5E62
If both zero, return 0 [src: YES, DON'T INC THE RECORD NUMBER]
5E64
INC DE 13
Increment record number [src: CORRECT FOR OFFSET WITHIN SECTOR]
5E67H (LRL256) - Divide by Record Length
LOC uses self-modifying code at 5E69H and 5E70H to store the record length and position for calculation. The routine multiplies the record number by record length and adds the position to get the total byte position, then returns this as a floating point number.
5E67LRL256
EX DE,HL EB
HL = last record number [src: RECORD NUMBER INTO HL]
5E68
LD A,00H 3E 00
A = record length **SELF-MODIFIED at 5E69H** [src: LRL STORED HERE]
5E6A
DOS: Calculate sector (HL = HL * A) [src: DO THE DIVISION]
5E6D
LD H,A 67
H = result high
5E6E
LD D,L 55
D = result low
5E6F
LD L,00H 2E 00
L = 0 [src: EOF/OFFSET STORED HERE]
5E70EOF2
LD A,00H 3E 00
A = position **SELF-MODIFIED at 5E70H**
5E75
LD E,L 5D
E = result low byte
5E76
ADD A,D 82
Add carries
5E77
LD D,A 57
DE = total records [src: INTO E]
5E78H (LRL257) - Convert to Floating Point
5E78LRL257
EX DE,HL EB
HL = record number [src: HL = NUMBER OF RECORDS]
5E79
Convert HL to floating point and return
5E7CH (LOF) - LOF Function Handler
Returns length of file (total number of records). Syntax: LOF(filenumber)
LOF reuses most of LOC's code, but uses offset 14 (file length) instead of offset 12 (current record). Both functions share the calculation routine at 5E53H which handles the self-modifying record length division.
5E7CLOF
Get file number and FCB [src: CONVERT ARGUMENT AND INDEX]
5E7F
If file not open, error [src: "BAD FILE NUMBER IF NOT OPEN]
5E82
LD HL,000EH 21 0E 00
HL = offset 14 (file length low) [src: POINT AT EOF RECORD #]
5E85
OR A B7
Clear carry [src: INSURE CARRY OFF]
5E86
Jump to common calculation routine
5E88H (FILOUT) - Character Output to File Entry (Stack Cleanup)
Prepares for character output to file by cleaning up stack.
5E88FILOUT
POP HL E1
Get return address [src: GET SAVED (HL) OFF STACK]
5E89H (FILOU3) - Character Output to File Routine *** CRITICAL ***
Core routine for writing characters to sequential files. Called by PRINT#, WRITE#, SAVE, and all output statements. Manages output buffer and writes to disk when full.
*** CRITICAL ROUTINE *** This is one of the most important routines in the entire file system. It is called by every file output operation. Understanding this routine is essential to understanding how file output works.
5E89FILOU3
PUSH HL E5
Save HL (return address from stack) [src: SAVE THE (HL)]
5E8A
PUSH AF F5
Save character to write [src: SAVE THE CHAR AGAIN]
5E8B
LD HL,(63BEH) LD HL,(PTRFIL)2A BE 63
HL = current FCB pointer [src: GET THE POINTER TO THE FILE]
5E8E
LD A,(HL) 7E
A = file mode (FCB+0) [src: WHAT IS THE MODE?]
5E8F
CP 01H FE 01
Is it input mode (01H)? [src: MUST BE ECHOING OR "EXTRA IGNORED"]
5E91
If input mode, error (can't write) [src: SO IGNORE THIS OUTCHR]
5E94
POP AF F1
Restore character to write [src: TAKE THE CHAR OFF]
5E95
PUSH DE D5
Save DE [src: SAVE (DE)]
5E96
PUSH BC C5
Save BC [src: SAVE (BC) FOR CALLER]
5E97
INC HL 23
HL = FCB+1 (mode details) [src: POINT AT TERMINAL POSITION]
5E98
LD B,00H 06 00
B = 0 (for 16-bit math)
5E9A
PUSH AF F5
Save character again [src: SAVE THE CHAR AGAIN]
5E9B
LD D,(HL) 56
D = mode byte value [src: GET THE POSITION]
5E9C
CP 0DH FE 0D
Is character CR (carriage return)? [src: TIME TO ZERO]
5E9E
LD (HL),B 70
Clear mode byte temporarily
5E9F
If CR, skip position update
5EA1
ADD E0H C6 E0
Add E0H (adjust position?) [src: SET CARRY FOR SPACES AND HIGHER]
5EA3
LD A,D 7A
A = mode byte
5EA4
ADC A,B 88
Add carry to mode byte [src: ADD IN CARRY]
5EA5
LD (HL),A 77
Restore mode byte
5EA6H (ISCRDS) - Call DOS Write Routine
5EA6ISCRDS
INC HL 23
HL = FCB+2 [src: POINT AT OS DCB]
5EA7
EX DE,HL EB
DE = FCB+2, HL = mode byte val [src: CALL WITH POINTER IN (DE)]
5EA8
POP AF F1
Restore character to write [src: GET BACK THE CHAR]
5EA9
PUSH AF F5
Save it again
5EAB
ROM: Character output to file [src: PUT THE CHAR INTO THE FILE]
5EAE
POP DE D1
Restore FCB+2
5EAF
If error (NZ), handle it [ERROR PATH] [src: NO ERRORS ARE SPECIAL]
5EB1H (NOERRP) - Success Path - Restore and Return
5EB1NOERRP
POP AF F1
Clean stack (character) [SUCCESS PATH]
5EB4
POP HL E1
Restore return address
5EB5
RET C9
Return to caller [SUCCESS] [src: GET BACK SAVED (HL)]
5EB6H (ERRCHK) - Error Path - Check DOS Error Code
The character output routine at 5E89H is the bottleneck for all file output. It calls ROM routine at 001BH which manages the actual character buffering and disk writes. The mode byte at FCB+1 is temporarily cleared and restored - this may be for DOS compatibility. CR (0DH) is handled specially without updating the position counter.
5EB6ERRCHK
LD C,A 4F
C = error code from DOS [ERROR PATH] [src: SEE (A) IN CASE ITS AN ERROR CODE]
5EB7
LD A,(DE) 1A
A = error status byte [src: LOOK AT DCB+0 BIT 7 TO SEE IF DEVICE]
5EB8
OR A B7
Check sign bit [src: IF BIT 7 IS SET ITS A DISK FILE AND]
5EB9
LD A,C 79
Restore error code
5EBA
If negative (M), translate DOS error [src: (A) CONTAINS THE ERROR]
5EBD
Otherwise, treat as success
5EBFH (PUT) - PUT Statement Handler
Writes a record to a random access file. Syntax: PUT #filenumber [, recordnumber]
5EBFPUT
OR AFH F6 AF
Set flags (mark as PUT) [src: "ORI" TO SET NON-ZERO]
5EC1
LD (63BDH),A LD (MAXTRK),A32 BD 63
Store operation flag (write=FFH) [src: SAVE FLAG]
5EC4
XOR A AF
A = 0 [src: CLEAR THE POSITION FLAG]
5EC5
LD (5F01H),A LD (GETX),A32 01 5F
Clear record increment flag **SELF-MODIFY**
5EC8
Parse file number [src: GET POINTER AT FILE BLOCK]
5ECB
CP 03H FE 03
Is file mode random (03H)? [src: MUST BE RANDOM FILE]
5ECD
If not random, error [src: IF NOT, "BAD FILE MODE"]
5ED0
PUSH BC C5
Save FCB pointer [src: SAVE POINTER AT FILE DATA BLOCK]
5ED1
PUSH HL E5
Save parser position [src: SAVE TEXT POINTER]
5ED2
LD HL,000CH 21 0C 00
HL = offset 12 (record number) [src: FETCH CURLOC]
5ED5
ADD HL,BC 09
HL = FCB+12
5ED6
LD E,(HL) 5E
E = current record low
5ED8
LD D,(HL) 56
DE = current record number
5ED9
INC DE 13
DE = next record (default) [src: INCREMENT BY ON TO COMPENSATE]
5EDA
POP HL E1
Restore parser position [src: GET TEXT POINTER]
5EDB
LD A,(HL) 7E
Get next character
5EDC
CP 2CH FE 2C
Is it comma? [src: IS THERE A RECORD NUMBER?]
5EDE
If comma, get explicit record# [src: YES, READ IT IN]
5EE0
LD A,FFH 3E FF
A = FFH (auto-increment flag) [src: SET THE POSITION FLAG]
5EE2
LD (5F01H),A LD (GETX),A32 01 5F
Set auto-increment **SELF-MODIFY**
5EE5
Continue with default record [src: AND CONTINUE]
5EE7H (GET1) - GET/PUT with Explicit Record Number
5EE7GET1
Get integer value (record number) [src: READ IN THE RECORD NUMBER]
5EEAH (GET2) - Validate Syntax and Record Number
5EEAGET2
DEC HL 2B
Back up parser [src: MAKE SURE THE STATEMENT ENDS]
5EEB
CHRGET: Get next char
5EEC
If not end, syntax error
5EEF
EX (SP),HL E3
HL = FCB, save parser on stack [src: SAVE TEXT POINTER GET DCB POINTER]
5EF0
PUSH HL E5
Save FCB again [src: RESAVE THE DCB POINTER]
5EF1
LD A,E 7B
A = record low byte
5EF2
OR D B2
OR with high byte [src: MAKE SURE ITS NOT ZERO]
5EF3
If record 0, error [src: IF SO,"BAD RECORD NUMBER"]
5EF6
DEC DE 1B
DE = record - 1 (0-based) [src: MAKE RECORD COUNT 0 TO N]
5EF7
LD B,D 42
BC = record number - 1 [src: (BC)=RECORD COUNT]
5EF8
LD C,E 4B
BC = 0-based record
5EF9
EX DE,HL EB
HL = record - 1 [src: (DE)= POINT AT DCB]
5EFA
INC DE 13
DE = FCB + 1
5EFB
INC DE 13
DE = FCB + 2
5EFC
LD HL,0032H 21 32 00
HL = 50 (offset to buffer) [src: POINT AT BLOCKING BUFFER IN CASE]
5EFF
ADD HL,DE 19
HL = FCB + 52 (buffer start) [src: THIS IS VARIABLE LENGTH]
5F00
LD A,00H 3E 00
A = auto-increment flag **SELF-MODIFIED at 5F01H** [src: GET THE 'POSITION' FLAG]
5F02
OR A B7
Check auto-increment flag [src: DO A POSITION?]
5F03
If auto-increment, skip DOS position [src: NO, JUST DO NEXT RECORD]
5F05H - Position to Specific Record
5F05
PUSH HL E5
Save buffer address [src: SAVE FOR READ/WRITE CALL]
5F06
DOS: Position to record in BC
5F09
POP HL E1
Restore buffer address [src: GET BACK POINTER AT BLOCKING BUFFER]
5F0A
If success (Z), continue
5F0C
CP 1CH FE 1C
Is error code 1CH? [src: IS IT EOF? ALSO OK]
5F0E
If 1CH, handle specially
5F10
CP 1DH FE 1D
Is error code 1DH? [src: POSITION PAST END?]
5F12
If not 1CH or 1DH, DOS error
5F15H (ENDRND) - Handle Record Not Found (Create New)
5F15ENDRND
LD A,(63BDH) LD A,(MAXTRK)3A BD 63
A = operation flag [src: WAS IT PUT OR GET?]
5F18
OR A B7
Check if PUT (FFH) or GET (00H)
5F19
If GET (0), clear buffer and return [src: JUST ZERO BUFFER IF GET]
5F1BPUTDO
DOS: Write new record [src: SEND THE RECORD]
5F1E
If error, translate DOS error [src: NO ERRORS ARE GOOD]
5F21
POP AF F1
Clean stack [src: GET RID OF DCB POINTER]
5F22
POP HL E1
Restore parser [src: GET TEXT POINTER BACK]
5F23
RET C9
Return to caller
5F24H (SEEKOK) - Read or Write Record
5F24SEEKOK
LD A,(63BDH) LD A,(MAXTRK)3A BD 63
A = operation flag
5F27
OR A B7
Check if write or read [src: PUT OR GET?]
5F28
If PUT (NZ), write record
5F2A
DOS: Read record (GET) [src: READ THE RECORD IN]
5F2D
If success (Z), finish [src: GOOD READ]
5F2F
LD B,A 47
B = error code [src: SAVE THE ERROR CODE]
5F30
AND FEH E6 FE
Mask off low bit [src: FORCE ROR TO EOF]
5F32
CP 1CH FE 1C
Is it 1CH or 1DH? [src: EOF?]
5F34
LD A,B 78
Restore full error code [src: GET ERROR CODE BACK]
5F35
If other error, translate [src: NO, GO TO ERROR TRAP]
5F38
LD A,(426EH) LD A,(VARREC)3A 6E 42
A = verify flag [src: GET THE VARIABLE FILE POINTER]
5F3B
OR A B7
Check if verify enabled [src: VARIABLE RECORDS?]
5F3C
LD A,B 78
Restore error code [src: GET THE ERROR CODE BACK]
5F3D
If verify on, report error [src: YES, EOF NOT ALLOWED]
5F40
Else clear buffer and continue [src: WAS .NOT.VARIABLE.AND.EOF. ZERO BUFFER]
5F42H (SEEKO4) - GET Success - Return
5F42SEEKO4
POP BC C1
Clean stack [src: GET RID OF DCB POINTER]
5F43
POP HL E1
Restore parser [src: GET TEXT POINTER BACK]
5F44
RET C9
Return to caller
5F45H (ZERBUF) - Clear Record Buffer
Clears the record buffer to zeros. Used when GET fails or for new records.
5F45ZERBUF
POP HL E1
HL = FCB pointer [src: TIME TO ZERO BUFFER]
5F46
LD DE,0034H 11 34 00
DE = 52 (offset to buffer)
5F49
ADD HL,DE 19
HL = buffer start [src: POINT TO DATA BUFFER]
5F4A
LD B,00H 06 00
B = 256 (buffer size)
5F4DLOPZRB
LD (HL),A 77
Clear byte [CLEAR LOOP START]
5F4E
INC HL 23
Next byte [CLEAR LOOP]
5F4F
Continue for 256 bytes [CLEAR LOOP END]
5F51
POP HL E1
Restore parser [src: GET TEXT POINTER BACK]
5F52
RET C9
Return to caller
PUT/GET use self-modifying code at 5F01H to store the auto-increment flag. The operation flag at 63BDH distinguishes PUT (FFH) from GET (00H). The verify flag at 426EH controls whether read errors on non-existent records are reported or silently ignored by zeroing the buffer.
5F53H (INDSKB) - Read Character from File *** CRITICAL ***
Core routine for reading characters from sequential files. Called by INPUT#, LINE INPUT#, LOAD, MERGE, and all input statements. Manages input buffer and reads from disk when exhausted.
*** CRITICAL ROUTINE *** This is the mirror of 5E89H for input operations. Every file read operation calls this routine. Understanding this is essential to understanding file input.
The character read routine at 5F53H calls ROM routine 0013H which manages the actual buffer and disk reads. Error codes 1CH and 1DH are treated as EOF conditions and return with carry set. The routine at 5F7BH may retry the read under certain conditions (Z flag set from ROM call).
5F53INDSKB
PUSH BC C5
Save BC [src: SAVE CHAR COUNTER]
5F54
PUSH HL E5
Save HL [src: SAVE (HL)]
5F55INDSK3
LD HL,(63BEH) LD HL,(PTRFIL)2A BE 63
HL = current FCB pointer [src: GET DATA BLOCK POINTER]
5F58
PUSH DE D5
Save DE [src: SAVE (DE)]
5F59
EX DE,HL EB
DE = FCB pointer [src: POINT AT OS DCB]
5F5A
INC DE 13
DE = FCB + 1
5F5B
INC DE 13
DE = FCB + 2
5F5CGETAGN
PUSH DE D5
Save FCB+2 address
5F5D
ROM: Read character from file [src: READ A BYTE]
5F60
POP DE D1
Restore FCB+2 address
5F61
PUSH AF F5
Save character and flags
5F62
LD A,(DE) 1A
A = error status byte
5F63
OR A B7
Check sign bit
5F64
If positive (P), no error
5F67
POP AF F1
Restore character/flags [ERROR PATH]
5F68
If Z (EOF), set carry and return [src: RETURN WITH BYTE]
5F6AREDERR
CP 1CH FE 1C
Is error code 1CH? [src: IS IT END IF FILE?]
5F6C
If 1CH, set carry [src: YES, SET FLAGS]
5F6E
CP 1DH FE 1D
Is error code 1DH? [src: ROR? (EOF)]
5F70
If not 1C/1D, translate DOS error
5F73H (REDER1) - Set EOF Flag and Return
5F73REDER1
SCF 37
Set carry flag (EOF/error) [src: INDICATE EOF]
5F74
LD B,B7H 06 B7
B = B7H (flag value) [src: SKIP NEXT BYTE WITH "MVI B"]
5F75H (OKGET) - Restore and Return with Carry
5F75OKGET
POP DE D1
Restore DE [src: CLEAR CARRY FLAG]
5F78
RET C9
Return (carry=EOF/error)
5F7AH (WC) - Success Path - Character Read OK
5F7AWC
POP AF F1
Restore character (carry clear)
5F7B
If Z set, retry read?
5F7D
Return with character (no carry)
5F7FH (NAMFIL) - Filename Parser *** IMPORTANT ***
Parses filename string, converts to uppercase, validates with DOS. Result stored at 6350H. Called by OPEN, LOAD, SAVE, KILL.
*** IMPORTANT ROUTINE *** Called by all file operations that need filenames.
5F7FNAMFIL
PUSH BC C5
Save BC [src: SAVE POINTER AT FILE INFO']
5F80
Evaluate string expression [src: READ A STRING FORMULA]
5F83
PUSH HL E5
Save parser position [src: SAVE THE TEXT POINTER]
5F84
Get string descriptor [src: MAKE SURE ARG IS A STRING AND]
5F87
LD A,(HL) 7E
A = string length [src: GET LENGTH INTO (A)]
5F88
OR A B7
Check if zero [src: IS IT A NULL STRING?]
5F89
If empty, error [src: IF SO,"BAD FILE NAME]
5F8C
CP 18H FE 18
Is length >= 24? [src: SEE IF NAME IS TOO BIG (.GT. FILLEN CHARS)]
5F8E
If >= 24, too long error [src: YES,ERROR]
5F91
INC HL 23
Point to address low [src: (BC)= POINTER AT NAME DATA]
5F92
LD C,(HL) 4E
C = address low
5F93
INC HL 23
Point to address high
5F94
LD B,(HL) 46
BC = source string address
5F95
LD HL,6350H LD HL,FILNAM21 50 63
HL = filename buffer destination
5F98
LD E,A 5F
E = length (counter) [src: (E)=LENGTH OF NAME GIVEN]
5F99H (MVFLNM) - Filename Copy and Uppercase Conversion Loop
5F99MVFLNM
LD A,(BC) 0A
Get char from source [LOOP START] [src: GET A CHAR FROM THE NAME]
5F9A
CP 61H FE 61
Is it < 'a'? [LOOP] [src: LOWER]
5F9C
If < 'a', skip conversion [src: NP]
5F9E
CP 7BH FE 7B
Is it >= '{'?
5FA0
If >= '{', skip conversion [src: STILL NOT]
5FA2
XOR 20H EE 20
Convert lowercase to uppercase [src: UPPER]
5FA4FILLCC
LD (HL),A 77
Store char to buffer [src: STORE INTO FILNAME]
5FA5
INC HL 23
Next destination
5FA7
DEC E 1D
Decrement counter
5FA8
Continue until done [LOOP END] [src: COUNT ALL THE CHAR]
5FAA
LD (HL),E 73
Null-terminate (E=0)
5FAB
POP HL E1
Restore parser
5FAFH - Validate Filename with DOS
The filename parser converts lowercase (61H-7AH) to uppercase by XORing with 20H. Maximum filename is 23 characters (18H-1). Result stored at 6350H and validated through DOS call 441CH.
5FB1
LD HL,6350H LD HL,FILNAM21 50 63
HL = filename buffer
5FB4
INC DE 13
DE = FCB + 3
5FB5
INC DE 13
DE = FCB + 4
5FB6
DOS: Parse/validate filename [src: DO SYNTAX CHECK ON FILE NAME]
5FB9
If error (NZ), bad filename
5FBC
OR A B7
Check return code
5FBD
If non-zero, bad filename
5FC0
POP HL E1
Restore parser
5FC2
RET C9
Return to caller [SUCCESS]
5FC3H (OPEN) - OPEN Statement Handler *** CRITICAL ***
Main entry for OPEN statement. Syntax: OPEN "mode", #filenumber, "filename" [, recordlength]
*** CRITICAL ROUTINE *** Heart of the file system. All file operations start here.
5FC3OPEN
LD BC,2169H LD BC,CONOUT01 69 21
BC = return address [src: ZERO PTRFIL WHEN DONE]
5FC6
PUSH BC C5
Push return address
5FC7
Evaluate mode expression [src: READ THE FILE MODE]
5FCA
PUSH HL E5
Save parser [src: SAVE THE TEXT POINTER]
5FCB
Get string descriptor [src: FREE STRING TEMP & CHECK STRING]
5FCE
LD A,(HL) 7E
A = mode string length
5FCF
OR A B7
Check if empty
5FD0
If empty, bad file mode error [src: IF SO ,"BAD FILE MODE"]
5FD3
INC HL 23
Point to address
5FD4
LD C,(HL) 4E
C = address low [src: (BC) POINT AT MODE CHARACTER]
5FD5
INC HL 23
Point to address high
5FD6
LD B,(HL) 46
BC = mode string address
5FD7
LD A,(BC) 0A
Get first char of mode [src: (A)= MODE CHAR]
5FD8
AND DFH E6 DF
Convert to uppercase [src: MAP LOWER CASE TO UPPER]
5FDA
LD D,02H 16 02
D = 02H (output mode) [src: ASSUME ITS 'O']
5FDC
CP 4FH FE 4F
Is it 'O'? [src: IS IT?]
5FDE
If 'O', use mode 02H [src: (D) HAD COLLECT MODE]
5FE0
LD D,01H 16 01
D = 01H (input mode) [src: ASSUME SEQUENTIAL]
5FE2
CP 49H FE 49
Is it 'I'? [src: IS IT?]
5FE4
If 'I', use mode 01H [src: (D) HAS CORRECT MODE]
5FE6
LD D,04H 16 04
D = 04H (extend mode) [src: ASSUME SEQ, END OF FILE]
5FE8
CP 45H FE 45
Is it 'E'? [src: IS IT?]
5FEA
If 'E', use mode 04H [src: (D) IS CORRECT]
5FEC
LD D,03H 16 03
D = 03H (random mode) [src: MUST BE RANDOM]
5FEE
CP 52H FE 52
Is it 'R'?
5FF0
If not I/O/E/R, error [src: IF NOT,NO MATCH SO "BAD FILE MODE"]
5FF3H (HAVMOD) - Parse File Number and Filename
5FF3HAVMOD
POP HL E1
Restore parser [src: GET BACK THE TEXT POINTER]
5FF4
SYNCHR: Verify comma [src: SKIP A POSSIBLE ',']
5FF5
DEFB 2CH 2C
Expected: comma
5FF6
PUSH DE D5
Save mode in D [src: SAVE THE FILE MODE]
5FF7
CP 23H FE 23
Is next char '#'? [src: SKIP A POSSIBLE '#']
5FFC
Get file number in E [src: READ THE FILE NUMBER]
5FFF
SYNCHR: Verify comma [src: SKIP COMMA BEFORE NAME]
6000
DEFB 2CH 2C
Expected: comma
6001
LD A,E 7B
A = file number [src: (A)= FILE NUMBER]
6002
OR A B7
Check if zero [src: MAKE SURE FILE WASN'T ZERO]
6003
If zero, out of range error [src: IF SO," BAD FILE NUMBER]
6006
CP D5H FE D5
Compare with D5H (unused?) [src: SKIP NEXT BYTE WITH CPI]
6007H (PRGFIL) - Common Entry Point (used by LOAD/RUN/MERGE)
NOP placeholder - may be modified at runtime
6007PRGFIL
NOP 00
(Entry marker - may be modified) [src: SAVE THE MODE IN (DE)]
6008H - Get FCB and Parse Filename
6008
Get file# in A, FCB ptr in BC [src: (BC) POINT AT FILE DATA BLOCK]
600B
If file already open, error [src: IF NON ZERO MODE ,"FILE ALWAYS OPEN"]
600E
PUSH BC C5
Save FCB pointer [src: SAVE POINTER AT FILE DATA BLOCK]
600F
Parse filename to 6350H [src: READ THE NAME]
6012
LD B,00H 06 00
B = 0 (default record length) [src: AND DISK NUMBER INTO FILNAM AND LSTDSK]
6014
POP DE D1
DE = FCB pointer
6015
POP AF F1
A = file mode [src: GET FILE MODE]
6016
PUSH AF F5
Save mode again
6017
PUSH DE D5
Save FCB pointer
6018
CP 03H FE 03
Is mode random?
601A
If not random, skip rec len
601C
DEC HL 2B
Back up parser
601E
If end, use default [src: NO SPECIFICATION]
6021
DEFB 2CH 2C
Expected: comma
6022
Get record length in E
6025
LD B,E 43
B = record length
6026H (NORECL) - Save State and Call DOS
6026NORECL
LD (40DFH),HL LD (TEMP3),HL22 DF 40
Save parser position [src: SAVE THE TEXT POINTER FOR A WHILE]
6029
POP HL E1
HL = FCB pointer [src: (HL)=POINTER AT FILE DATA BLOCK]
602A
LD A,(442BH) LD A,(OVLFLG)3A 2B 44
A = DOS flags [src: CLEAR PROTECTED BIT]
602D
AND F9H E6 F9
Clear bits 1 and 2 [src: SO IT IS ALWAYS CORRECT]
602F
LD C,A 4F
C = modified flags [src: SAVE XMODE]
6030
LD A,(5200H) LD A,(DOPROT)3A 00 52
A = RUN/LOAD flag [src: TRY TO OPEN EXEC ONLY?]
6034
LD A,C 79
Restore flags
6035
If not RUN/LOAD, skip
6037
OR 04H F6 04
Set bit 2 (RUN/LOAD mode) [src: PRIVELEGE MODE - OPEN XEQ ONLY]
6039NOPRIV
LD (442BH),A LD (OVLFLG),A32 2B 44
Store modified DOS flags
603C
POP AF F1
A = file mode [src: GET BACK FILE MODE]
603D
PUSH AF F5
Save mode again [src: SAVE BACK]
603E
PUSH HL E5
Save FCB pointer [src: SAVE IT BACK]
603F
LD (63BEH),HL LD (PTRFIL),HL22 BE 63
Set current FCB pointer [src: SETUP AS CURRENT FILE]
6042
EX DE,HL EB
DE = FCB pointer [src: GET OS DCB POINTER IN (DE)]
6043
INC DE 13
DE = FCB + 1
6044
INC DE 13
DE = FCB + 2
6045
LD HL,0032H 21 32 00
HL = 50 (buffer offset)
6048
ADD HL,DE 19
HL = buffer start address
6049
LD C,A 4F
C = file mode [src: SAVE NODE IN (C)]
604A
LD A,B 78
A = record length [src: GET THE RECORD SIZE]
604C
If zero, use default [src: NOT VARIABLE SO NO CHECK]
604E
LD A,(426EH) LD A,(VARREC)3A 6E 42
A = verify flag [src: ARE VARIABLES ALLOWED?]
6051
OR A B7
Check if verify enabled
6052
If verify off with rec len, error
6055
INC H 24
Adjust buffer address (verify)
6056H (NVARCH) - Call DOS Open Based on Mode
OPEN determines file mode from first character: I=input(01H), O=output(02H), R=random(03H), E=extend(04H). Extend mode converts to output after positioning to end. Mode byte stored at FCB+0. Parser position saved at 40DFH. RUN/LOAD flag at 5200H modifies DOS behavior for program loading.
6056NVARCH
LD A,C 79
A = file mode
6057
CP 04H FE 04
Is it extend mode? [src: OUTPUT TO EOF?]
6059
If not extend, check others [src: NO, CONTINUE]
605B
Save state [src: OPEN THE FILE]
605E
If error, translate DOS error [src: ERROR, EXIT]
6061
POP HL E1
Clean stack [src: GET POINTER FOR A SEC]
6062
POP AF F1
Clean stack [src: GET MODE FOR A SEC]
6063
LD A,02H 3E 02
A = 02H (extend→output) [src: SET FOR OUTPUT]
6065
PUSH AF F5
Save mode [src: NEW MODE]
6066
PUSH HL E5
Save HL [src: POINTER BACK ON STACK]
6067
DOS: Open random access [src: POSITION TO END OF FILE]
606A
Continue to finalize [src: FINISH UP]
606CNOTEOF
CP 01H FE 01
Is it input mode? [src: INPUT MODE?]
606E
If input, open for read [src: USE OPEN CALL]
6070
CP 03H FE 03
Is it random mode? [src: RANDOM FILE?]
6072
If not random, must be output [src: NO, GO OPEN THE FILE]
6074
Save state [src: ATTEMPT TO OPEN THE FILE]
6077
If success, finalize [src: GOOD OPEN.]
6079NOTEO1
DOS: Open for output [src: CREATE THE FILE]
607C
Continue to finalize [src: FINISH UP]
607EINOPN
DOS: Open for input [src: OPEN THE FILE FOR READS]
6081
PUSH AF F5
Save result [src: SAVE ERROR CODE FLAGS]
6082
LD A,(5200H) LD A,(DOPROT)3A 00 52
A = RUN/LOAD flag [src: GET THE PROTECTION FLAGS]
6085
OR A B7
Check if RUN or LOAD [src: THIS FILE PROTECTED?]
6086
If not RUN/LOAD, skip [src: NO, CONTINUE]
6088
XOR A AF
A = 0 [src: YES, CLEAR THE FLAG]
6089
LD (5200H),A LD (DOPROT),A32 00 52
Clear RUN/LOAD flag
608C
LD A,(442BH) LD A,(OVLFLG)3A 2B 44
A = DOS flags [src: GET IT'S FLAGS]
6090
RRA 1F
Rotate right again
6091
SBC A,A 9F
A = FFH if carry, 00H otherwise
6092
LD (5201H),A LD (PROTFL),A32 01 52
Store flag at 5201H [src: AND SET THE INTERNAL PROTECTION FLAGS]
6095NOPRTC
POP AF F1
Restore DOS result
6096OPNDON
If DOS error (NZ), translate [src: NO ERRORS ALLOWED]
6099
POP HL E1
HL = FCB pointer [src: GET BACK THE FILE POINTER]
609A
POP AF F1
A = file mode [src: GET BACK THE MODE]
609B
LD (HL),A 77
Store mode at FCB+0 [src: SET UP THE MODE]
609C
INC HL 23
HL = FCB+1 [src: AND ZERO THE IMAGINARY]
609D
LD (HL),00H 36 00
Clear FCB+1 [src: PRINT POSITION]
609F
LD HL,(40DFH) LD HL,(TEMP3)2A DF 40
Restore parser position [src: GET BACK THE TEXT POINTER]
60A2
RET C9
Return to caller [SUCCESS]
60A3H (TSTPRT) - File Cleanup Routine
Cleans up after file operations. Clears buffers and resets flags.
60A3TSTPRT
PUSH AF F5
Save AF
60A5
LD (5200H),A LD (DOPROT),A32 00 52
Clear RUN/LOAD flag
60A8
LD A,(5201H) LD A,(PROTFL)3A 01 52
A = file buffer flag
60AC
If not set, skip cleanup
60AE
LD HL,(40A4H) LD HL,(TXTTAB)2A A4 40
HL = string space start
60B1
LD BC,044CH 01 4C 04
BC = 1100 (clear size)
60B4PLPZER
LD (HL),00H 36 00
Clear byte [CLEAR LOOP]
60B7
DEC BC 0B
Decrement counter
60B8
LD A,B 78
A = high byte
60B9
OR C B1
OR with low byte
60BA
Continue clearing [END LOOP]
60BC
LD (5201H),A LD (PROTFL),A32 01 52
Clear flag (A=0)
60C2
LD HL,54D2H LD HL,PROTMS21 D2 54
HL = address (table?)
60C8
Return to command level
60CBPOPSRT
POP AF F1
Restore AF
60CC
RET C9
Return to caller
60CDH (KILL) - KILL Statement Handler (continued)
Deletes a file from disk. Syntax: KILL "filename"
KILL statement uses DOS call 442CH to delete the file. The filename is parsed through 5F7FH and stored at 6350H. The three NOPs at 60D0H-60D2H may be placeholders for future modification.
60CDKILL
PUSH BC C5
Save BC [src: GET POINTER AT FILE ZERO]
60CE
PUSH DE D5
Save DE [src: SET UP (BC) AS POINTER AT DCB]
60D0
NOP 00
(Placeholder 1)
60D1
NOP 00
(Placeholder 2) [src: SCAN FILE NAME]
60D2
NOP 00
(Placeholder 3)
60D4
POP DE D1
Restore DE [src: SAVE TEXT POINTER]
60D5
POP BC C1
Restore BC [src: POINT AT FILE ZERO]
60D6
XOR A AF
A = 0 (file # 0 = get ptr)
60D7
Get file info (Z if closed)
60DA
Parse filename to 6350H
60DD
PUSH HL E5
Save parser [src: MUST FIND THE FILE FIRST]
60DE
LD HL,(63C0H) LD HL,(FILPTR)2A C0 63
HL = file pointer table base
60E1
EX DE,HL EB
DE = table base
60E2
INC DE 13
DE = table + 1
60E3
INC DE 13
DE = table + 2 [src: MIRROR THE DCB POINTER TO IX]
60E6
Save state [src: GET THE DRIVE NUMBER]
60E9
If error, translate DOS error [src: SAVE IT]
60EC
DOS: Delete file ($KILL) [src: GET THE LFN]
60EF
If error, translate DOS error [src: SAVE IT]
60F2
LD HL,(63C0H) LD HL,(FILPTR)2A C0 63
Get table base pointer [src: SAVE THE REGISTERS]
60F5
LD (HL),00H 36 00
Clear first byte [src: START AT FILE 1]
60F7KILL1
POP HL E1
Restore parser [src: GET MAX NUMBER OF FILES]
60F8
RET C9
Return to caller [SUCCESS]
60F9H-6110H - Error Code Jump Table (DATA)
Error entry points. Each loads specific error code and jumps to error handler at 19A2H.
Error Code Jump Table:
| 60F9H | LD E,6CH | Error 6CH - Bad File Mode |
| 60FBH | LD BC,681EH | Error 68H - unused? |
| 60FEH | LD BC,661EH | File Number Out of Range (error 66H) |
| 6101H | LD BC,7C1EH | Error 7CH |
| 6104H | LD BC,6E1EH | Error 6EH |
| 6107H | LD BC,801EH | Error 80H |
| 610AH | LD BC,7E1EH | Error 7EH |
| 610DH | LD BC,641EH | Error 64H |
| 6110H | JP 19A2H | Jump to error display routine |
6113H - DOS Error Translation *** CRITICAL ***
Translates DOS error codes to BASIC error numbers using table at 6126H.
*** CRITICAL ROUTINE *** All DOS errors pass through here for translation to user-friendly BASIC errors.
6113
LD B,00H 06 00
B = 0 (for 16-bit math)
6115
LD HL,6126H 21 26 61
HL = error translation table [src: GET THE FILE NUMBER BACK]
6118
CP 27H FE 27
Is DOS error >= 27H?
611A
If < 27H, use as index [src: AND DONE]
611CKILL2
LD A,01H 3E 01
A = 01H (default for unknown) [src: GET THE COUNTER BACK]
611EKNWERR
LD C,A 4F
BC = error index [src: AND CONTINUE]
611F
ADD HL,BC 09
HL = table + index
6120KILEXT
LD E,(HL) 5E
E = BASIC error code [src: RESTORE THE REGISTERS]
6121
LD (63BCH),A LD (DSKERR),A32 BC 63
Save DOS error code
6124
Jump to error display
6126H-614CH - DOS to BASIC Error Code Lookup Table (DATA)
39-byte table mapping DOS errors (00H-26H) to BASIC error numbers.
The error translation table converts DOS-specific error codes into user-friendly BASIC error messages. Error 72H is the most common (general I/O error). Error 66H indicates bad file number. Errors 1CH-1FH (EOF conditions) all map to error 66H.
Error Translation Table (6126H-614CH) - 39 bytes:
| Index | Bytes | BASIC Error |
| 00-06 | 72 72 72 72 72 72 72 | Error 72H (I/O error) - repeated |
| 07 | 80 | Error 80H (file error) |
| 08-0E | 72 72 72 72 72 72 | Error 72H - repeated |
| 0F | 88 | Error 88H (different I/O) |
| 10 | 66 | Error 66H (bad file number) |
| 11-12 | 72 72 | Error 72H |
| 13 | 80 | Error 80H |
| 14-18 | 72 72 72 72 6A | Error 72H, then 6AH |
| 19 | 8A | Error 8AH (write error) |
| 1A | 86 | Error 86H |
| 1B | 7A | Error 7AH |
| 1C-1F | 66 66 66 66 | Error 66H (repeated) |
| 20 | 80 | Error 80H |
| 21-24 | 66 66 66 66 | Error 66H (repeated) |
| 25 | 8A | Error 8AH |
| 26 | 66 | Error 66H |
| 27+ | xx | Defaults to Index 01 - Error 72H |
614DH (INIT) - PROGRAM ENTRY POINT *** CRITICAL ***
Main initialization when BASIC/CMD loads. Saves state, sets up file system, displays copyright.
*** PROGRAM ENTRY POINT *** This is where execution starts when BASIC/CMD is loaded. Critical initialization code.
614DINIT
LD (63EEH),HL LD (CPMLIN),HL22 EE 63
Save HL (entry parameter) [src: SAVE THE COMMAND LINE POINTER]
6150BUF
LD A,(HL) 7E
Get first byte. [src: GET COMMAND LINE CHAR]
6151
LD (63E4H),A LD (PTCMD),A32 E4 63
Save entry byte. [src: STORE FOR RESTART CHECK]
6154
LD HL,(40A4H) LD HL,(TXTTAB)2A A4 40
HL = string space base. [src: GET OLD PROGRAM START TOO]
6157
LD (63E5H),HL LD (SVTXTT),HL22 E5 63
Save string space pointer
615A
LD HL,(426DH) LD HL,(MAXFIL)2A 6D 42
HL = max file number
615D
LD (63E7H),HL LD (FILSVS),HL22 E7 63
Save max file number
6160
LD HL,(40A0H) LD HL,(STKTOP)2A A0 40
HL = memory top (MEMSIZ) [src: SAVE STACK TOP IN CASE OF RESTART]
6163
LD (63E9H),HL LD (OLSTTP),HL22 E9 63
Save memory top [src: READ FROM LOCKED/DELETED DATA RECORD]
6166
XOR A AF
A = 0 [src: PARITY ERROR DURING HEADER WRITE]
6167
LD (427AH),A LD (ABRTFL),A32 7A 42
Clear SYSTEM flag. [src: SET THE 'BASIC' FLAG]
616A
LD HL,022EH LD HL,BASBRK21 2E 02
HL = 022EH (offset?) [src: RESET THE CASSETTE/PRINTER 'BREAK']
616D
LD (4204H),HL LD (BREAK),HL22 04 42
Store at 4204H [src: ILLEGAL LOGICAL FILE NUMBER]
6170
LD DE,4080H 11 80 40
DE = 4080H (destination) [src: MOVE THE 'JP' TABLE TO LOW RAM]
6173
LD HL,18F7H 21 F7 18
HL = 18F7H (ROM source) [src: HIT READ ERROR]
6176
LD BC,0027H 01 27 00
BC = 39 bytes to copy [src: FILE ACCESS DENIED]
6179
LDIR ED B0
Copy ROM data to RAM [src: READ PAST END]
617B
LD HL,(63E7H) LD HL,(FILSVS)2A E7 63
Restore max file number [src: DIRECTORY FULL CANT EXTEND FILE]
617E
LD (426DH),HL LD (MAXFIL),HL22 6D 42
Store to 426DH [src: NO DEVICE SPACE AVAILABLE]
6181
LD HL,(4411H) LD HL,(MEMEND)2A 11 44
HL = DOS memory top [src: ATTEMPTED TO LOAD READ ONLY MEMORY]
6184
LD (40A0H),HL LD (STKTOP),HL22 A0 40
Set new memory top (MEMSIZ)
6187
LD SP,HL F9
Set stack pointer
6188H (REPMES) - Self-Modify Entry Point (First Run) **SELF-MODIFY**
6188REPMES
LD HL,614DH LD HL,INIT21 4D 61
HL = entry point address
618B
LD (HL),3AH 36 3A
Modify: LD A,(nnnn) **SELF-MODIFY**
618E
LD (HL),B 70
Store address low **SELF-MODIFY**
6190FILQ
LD (HL),2CH 36 2C
Store comma **SELF-MODIFY**
6193
LD (40A7H),HL LD (TEMPPT),HL22 A7 40
Save to input buffer ptr
6196
LD HL,63EBH LD HL,BUFEND21 EB 63
HL = 63EBH (flag location)
6199
LD (HL),00H 36 00
Clear initialization flag
619BH - Continue Initialization
619ENOCLS
Initialize interpreter
61A1
XOR A AF
A = 0. [src: CLEAR OUT THE 'CLS' CALL]
61A2
LD (619EH),A LD (NOCLS),A32 9E 61
Self-modify CALL **SELF-MODIFY**
61A5
LD (619FH),A 32 9F 61
Self-modify next byte **SELF-MODIFY**
61A8
LD (61A0H),A 32 A0 61
Self-modify third byte **SELF-MODIFY**
61AB
LD A,(441FH) LD A,(CURDOS)3A 1F 44
A = DOS version number
61AE
CP 13H FE 13
Is DOS >= 1.3?. [src: DOS VERSION 1.3 MODEL 3]
61B2H (REPMES) - DOS Version Too Old - Exit with Error
61B2REPMES
LD HL,6301H LD HL,BADMVS21 01 63
HL = "Use TRSDOS 1.3 or Later"
61B8
SCF 37
Set carry (error flag) [src: SET THE CARRY FOR 'ABORT']
61B9
Exit to SYSTEM (TRSDOS) [src: AND EXIT TO DOS]
61BCH (FILQ) - Check for Re-entry ('*' Parameter)
61BCFILQ
LD A,(63E4H) LD A,(PTCMD)3A E4 63
A = entry parameter byte
61BF
CP 2AH FE 2A
Is it '*' (re-entry)?. [src: RESTART WITH OLD PARAMETERS?]
61C1
If not '*', normal entry. [src: NO, TRUCK ON]
61C4
LD A,(426DH) LD A,(MAXFIL)3A 6D 42
A = current max file#. [src: SET UP FILPTR]
61C7
Allocate file buffers
61CA
LD BC,1A18H LD BC,STPRDY01 18 1A
BC = return address
61CD
LD HL,(63E9H) LD HL,(OLSTTP)2A E9 63
HL = saved memory top
61D0
LD (40A0H),HL LD (STKTOP),HL22 A0 40
Restore memory top
61D3
LD HL,(63E5H) LD HL,(SVTXTT)2A E5 63
HL = saved string space
61D6
LD (40A4H),HL LD (TXTTAB),HL22 A4 40
Restore string space
61D9
LD HL,(426FH) 2A 6F 42
HL = saved state. [src: RESET BASIC'S PROTECTION]
61DC
LD (5200H),HL LD (DOPROT),HL22 00 52
Restore state to 5200H
61E2H - Normal Entry Path
The entry point performs critical initialization. On first run (6188H-6199H), it self-modifies code at 614DH. The '*' parameter (2AH) triggers re-entry path at 61BCH which restores saved state. DOS version check at 61ABH requires TRSDOS 1.3 or later. The entry point copies 39 bytes from ROM (18F7H) to RAM (4080H) using LDIR.
61E2
PUSH AF F5
Save entry byte. [src: END OF COMMAND LINE?]
61E3
LD A,(5202H) 3A 02 52
A = display flag
61E7
If set, call display routine. [src: ASK ABOUT THE FILES]
61EA
POP AF F1
Restore entry byte
61EBFILQST
CP 20H FE 20
Is it space or higher? [src: END OF COMMAND LINE?]
61ED
If >= space, process command. [src: GET THE ANSWER]
61F0H (FILQS1) - Prompt "How Many Files"
Prompts user for number of files (0-15) and optional verify mode.
61F0FILQS1
LD HL,631AH LD HL,FILMES21 1A 63
HL = "How Many Files" [src: REASK ON BREAK]
61F6
Get input line [src: GET THE ANSWER]
61F9FILLOP
If error, re-prompt. [src: ANY FILES GIVEN?]
61FB
XOR A AF
A = 0 [src: ASSUME NOT VARIABLE LENGTH]
61FC
LD (426EH),A LD (VARREC),A32 6E 42
Clear verify flag. [src: NO, USE DEFAULT VALUE]
61FF
CHRGET: Get first char
6200NOTVRR
OR A B7
Check if zero (empty) [src: ANY FILES GIVEN?]
6201
LD A,03H 3E 03
A = 3 (default files) [src: THIS IS THE DEFAULT FILE VALUE]
6203
If empty, use default [src: NO, USE DEFAULT VALUE]
6205
LD A,(HL) 7E
Get character
6206
Parse integer to DE. [src: SAVE AS FLAG]
6209
CP 56H FE 56
Is it 'V'? [src: VARIABLE FILES?]
620D
LD (426EH),A LD (VARREC),A32 6E 42
Set verify flag (56H) [src: SAVE AS FLAG]
6211ORA
OR A B7
Check if end
6212MEMGET
If not end, syntax error. [src: DISPLAY IT]
6215
LD A,D 7A
A = high byte. [src: AND DO IT AGAIN]
6216
OR A B7
Check if > 255
6217
If > 255, re-prompt. [src: SHOULD NOT BE A HIGH ORDER]
6219
LD A,E 7B
A = file count
621A
CP 10H FE 10
Is it >= 16? [src: AND DO IT AGAIN]
621CORB
If >= 16, re-prompt [src: SHOULD NOT BE A HIGH ORDER]
621EH (DEFFIL) - Store File Count and Allocate
621EDEFFIL
LD (426DH),A LD (MAXFIL),A32 6D 42
Store max file number [src: REMEMBER HOW MANY FILES THERE ARE]
6221
PUSH AF F5
Save file count [src: SAVE THE NUMBER]
6223
PUSH DE D5
Save DE. [src: SAVE THE NUMBER]
6225
LD L,A 6F
L = file count
6226
LD H,00H 26 00
HL = file count
6228
Multiply by buffer size
622B
LD DE,0004H 11 04 00
DE = 4 [src: OFFSET TO 2ND LAST DIGIT]
622E
ADD HL,DE 19
HL = total + 4 [src: HL => 2ND LAST DIGIT]
622F
LD DE,63A2H LD DE,FILSAV11 A2 63
DE = 63A2H
6232TYPMEM
LD BC,0002H 01 02 00
BC = 2
6235
LDIR ED B0
Copy 2 bytes
623A
POP AF F1
Restore file count [src: GET AF BACK]
623BH (FLSET1) - Allocate File Buffer Array *** IMPORTANT ***
Creates file pointer table at 63C0H, allocates FCB+buffer space starting at 64DCH.
*** IMPORTANT ROUTINE *** Sets up the entire file buffer structure. Each file gets 360 bytes (168H).
623BFLSET1
INC A 3C
A = file count + 1. [src: GET AF BACK]
623C
LD HL,64DCH LD HL,ENDBAS21 DC 64
HL = buffer area base [src: THE PLACE TO START ALLOCATIING]
623F
LD DE,63C0H LD DE,FILPTR11 C0 63
DE = file pointer table [src: THE PLACE TO STORE THE POINTERS]
6242
LD (63E0H),HL LD (FILPT1),HL22 E0 63
Save buffer end pointer [src: SAVE A COPY OF THE POINTER AT FILE 0]
6245FILLOP
LD (HL),00H 36 00
Clear FCB status [ALLOC LOOP] [src: MAKE THE FILE LOOKING CLOSED]
6247TYPME1
EX DE,HL EB
HL = table, DE = buffer
6248
LD (HL),E 73
Store buffer ptr low
6249
INC HL 23
Next table byte
624A
LD (HL),D 72
Store buffer ptr high
624B
INC HL 23
Next table entry
624C
EX DE,HL EB
HL = buffer, DE = table
624D
LD BC,0168H 01 68 01
BC = 360 bytes per file
6250DIRTMP
ADD HL,BC 09
HL = next buffer location [src: ADD ON THE SIZE]
6251USEDEF
LD B,A 47
B = counter. [src: ADD ON THE SIZE]
6252
LD A,(426EH) LD A,(VARREC)3A 6E 42
A = verify flag
6255
OR A B7
Check if verify enabled
6258
INC H 24
Add 256 for verify buffer
6259RNOTVR
LD A,B 78
Restore counter
625A
DEC A 3D
Decrement counter [src: DECREMENT THE COUNT]
625B
Continue for all files [END LOOP]. [src: DECREMENT THE COUNT]
625D
LD A,(63E4H) LD A,(PTCMD)3A E4 63
A = entry parameter [src: IS IT RE-ENTER?]
6260
CP 2AH FE 2A
Is it '*' (re-entry)? [src: IF SO SETTING UP FILPTR WAS A]
6262
RET Z C8
If re-entry, return [src: SUBROUTINE AND OTS TIME TO RETURN]
6263
LD (HL),00H 36 00
Null-terminate table. [src: SUBROUTINE AND OTS TIME TO RETURN]
6265USEXXX
INC HL 23
HL = string space base
6266
LD (40A4H),HL LD (TXTTAB),HL22 A4 40
Set string space pointer
6269H (MEMGET) - Prompt for Memory Size
Prompts "Memory Size?" and allocates memory for BASIC.
6269MEMGET
LD HL,0105H 21 05 01
HL = 0105H (data offset?) [src: HL => 'MEMORY SIZE' MSG]
626C
Print "Memory Size?" [src: DISPLAY IT]
626F
Get input line [src: GET THE ANSWER]
6275
OR A B7
Check if empty
6276
If not empty, parse value
6278SSAVE
LD HL,(4411H) LD HL,(MEMEND)2A 11 44
HL = DOS memory top [src: GET END OF MEMORY]
627B
LD DE,FFFAH 11 FA FF
DE = -6. [src: GET END OF MEMORY]
627E
Compare/subtract [src: THIS IS A CLAIM THAT FFFA-D GET WIPED]
627F
If carry, use DE [src: OUT FROM TIME TO TIME]
6281
EX DE,HL EB
HL = DOS top - 6. [src: THIS IS A CLAIM THAT FFFA-D GET WIPED]
6282USEDE1
Set memory size [src: SET MEMORY]
6285
Continue [src: AND CONTINUE]
6287TYPMEM
Parse integer to DE. [src: SET MEMORY]
628A
OR A B7
Check if end. [src: AND CONTINUE]
628B
If not end, syntax error
628E
Validate and set size
6291H - Display Copyright and Return to BASIC
6291
Display copyright banner
6294
Return to command level
6297H (ZLUPE2) - Validate Memory Size
6297ZLUPE2
DEC DE 1B
DE = size - 1
6298TYPMX
LD HL,(4411H) LD HL,(MEMEND)2A 11 44
HL = DOS memory top. [src: DO IT AGAIN]
629B
Compare [src: AND EXIT TO COMMAND LEVEL]
629C
EX DE,HL EB
HL = requested size
629D
If too large, re-prompt. [src: DISPLAY THE MESSAGES]
629FH (USEDEF) - Set Memory Size and Allocate
629FUSEDEF
POP IX DD E1
IX = return address [src: GET THE CALLER INTO IX]
62A1
DEC HL 2B
HL = size - 1
62A2
EX DE,HL EB
DE = size [src: SEE OF SIZE IS REASONABLE]
62A3
LD HL,(40A4H) LD HL,(TXTTAB)2A A4 40
HL = string space base [src: THAT IS AT LEAST 300 BYTES BEYOND TXTTAB]
62A6
LD BC,012CH 01 2C 01
BC = 300 (minimum space)
62A9
ADD HL,BC 09
HL = base + 300
62AA
EX DE,HL EB
HL = size, DE = min
62AC
If < min, "Out of Memory"
62AF
LD DE,FFCEH 11 CE FF
DE = -50
62B2
LD (40B1H),HL LD (VARNAM),HL22 B1 40
Save actual top
62B5
ADD HL,DE 19
HL = top - 50
62B6
LD (40A0H),HL LD (STKTOP),HL22 A0 40
Set MEMSIZ (memory top)
62BC
LD HL,0000H LD HL,RST0021 00 00
HL = 0
62C5
PUSH HL E5
Save HL [src: CORRECT STACK FOR 8 BYTE DIFF]
62C6
LD DE,0005H 11 05 00
DE = 5
62C9
ADD HL,DE 19
HL = string + 5 [src: INTO THE STACK POINTER]
62CA
LD A,(HL) 7E
Get digit. [src: COME DOWN 50 BYTES]
62CB
SUB 06H D6 06
Subtract 6. [src: END OF STACK AREA]
62CD
CP 30H FE 30
Is it >= '0'? [src: STACK POINTER SAVED HERE]
62D1
DEC HL 2B
Back up. [src: SAVE THE STACK POINTER]
62D2
DEC (HL) 35
Decrement previous digit
62D3
INC HL 23
Forward [src: PLACE TO STORE IT]
62D6
LD (HL),A 77
Store digit [src: NUMBER OF ASCII CHARACTERS]
62D8
LD DE,638FH LD DE,MEMSAV11 8F 63
DE = display buffer
62DB
LD BC,0006H 01 06 00
BC = 6 bytes [src: CLEAR POINTERS AGAIN]
62DE
LDIR ED B0
Copy to buffer [src: RETURN TO CALLER]
62E0ZLUPE1
Process program [src: GET THE FLAG THAT SAYS WE'VE BEEN HERE]
62E3
JP (IX) DD E9
Return via IX [src: SAVE IT IN CASE OF TROUBLE LATER ON]
62E5H (ZLUPE1) - Display Copyright Banner **SELF-MODIFY**
Displays TRS-80 Model III Disk BASIC copyright. Self-modifies to run only once.
The copyright display routine uses self-modifying code. On first run, 62E6H contains 3EH (LD A,01H). After running once, it modifies itself to 3EH 00H (LD A,00H), so subsequent calls return immediately at 62EBH.
62E5ZLUPE1
LD A,01H 3E 01
A = 1 (first run flag) [src: PLACE TO STORE IT]
62E7
DEC A 3D
A = 0 **SELF-MODIFIED** [src: HL => TITLE MESSAGE]
62E8
LD (62E6H),A 32 E6 62
Modify LD A,01H → LD A,00H. [src: NUMBER OF ASCII CHARACTERS]
62EB
RET NZ C0
If not first run, return. [src: MOVE IT TO SCREEN MESSAGE]
62EC
LD HL,6329H LD HL,MESG21 29 63
HL = copyright string. [src: CLEAR POINTERS AGAIN]
62EF
Print copyright. [src: RETURN TO CALLER]
62F2
LD HL,63A6H LD HL,VARMSG21 A6 63
HL = "Memory" string. [src: GET THE FLAG THAT SAYS WE'VE BEEN HERE]
62F5
LD A,(426EH) LD A,(VARREC)3A 6E 42
A = verify flag. [src: SAVE IT IN CASE OF TROUBLE LATER ON]
62F8
OR A B7
Check if verify enabled. [src: EXIT IF WE'VE BEEN HERE BEFORE]
62F9ZLUPE2
If verify, skip. [src: HL => TITLE MESSAGE]
62FB
LD HL,63AFH LD HL,FLLMSG21 AF 63
HL = alt string
62FEZLUPE2
Print and return
6301H (BADMVS) - String Data and System Variables
Text strings, buffers, and system variables used by BASIC/CMD.
6301H (BADMVS) - Error Message: "Use TRSDOS 1.3 or Later"
6301BADMVS
DEFM "Use TRSDOS 1.3 or Later" 55 73 65...
Version error message
6318
DEFB 0DH 0D
CR (carriage return)
6319
DEFB 00H 00
Null terminator
631AH (FILMES) - Prompt: "How Many Files"
631AFILMES
DEFM "How Many Files" 48 6F 77...
File count prompt
6328
DEFB 00H 00
Null terminator
6329H (MESG) - Copyright Banner
6329MESG
DEFM "TRS-80 Model III Disk BASIC Rev 1.3" 54 52 53...
Product name and version
634C
DEFB 0DH 0D
CR (carriage return)
634D
DEFM "(c) (p) 1980 by Tandy Corp. All Rights Reserved." 28 63 29...
Copyright notice
637C
DEFB 0DH 0D
CR (carriage return)
637D
DEFM "Created 5-Jul-80" 43 72 65...
Creation date
638E
DEFB 0DH 0D
CR (carriage return)
638FH (MEMSAV) - Memory Size Display Buffer
The memory display buffer at 638FH is a template. Actual memory size digits are filled in at runtime at positions 638FH-6394H before display.
638FMEMSAV
DEFM "00,000 Free Bytes 00 " 30 30 2C...
Memory display template (15 bytes)
63A4
DEFB 00H 00
Null terminator
63A6H (VARMSG) - Verify Mode Message: "Variable Files"
Alternate message displayed when verify mode is disabled would be at a different location (not shown in verify path).
63A6VARMSG
DEFM "Variable Files" 56 61 72...
Verify mode enabled message
63B4
DEFB 0DH 0D
CR (carriage return)
63B5
DEFB 00H 00
Null terminator
63B6H (FLRL) - System Variables and Buffers
Runtime variables used by file system and initialization code.
63B6FLRL
DEFW 0000H 00 00
Record Length Storage (2 bytes)
63B8LINE1
DEFB 00H,00H,00H,00H 00 00 00 00
Reserved/padding (4 bytes)
63BCDSKERR
DEFB 00H 00
Last DOS error code. [src: ERROR NUMBER FROM OPERATING SYSTEM]
63BDMAXTRK
DEFB 00H 00
PUT/GET flag (FFH=write, 00H=read)
63BEPTRFIL
DEFW 0000H 00 00
Current File Control Block pointer. [src: ADDRESS OF FILE BEING USED]
63C0H (FILPTR) - File Pointer Table (32 bytes)
The file pointer table at 63C0H stores pointers to FCB+buffer structures for up to 16 files (0-15). Each entry is 2 bytes. File #0 is reserved. Actual number of entries used is determined by "How Many Files" prompt response.
63C0FILPTR
DEFW 0000H 00 00
File #0 buffer pointer. [src: TABLE OF FILE BLOCK POINTERS]
63C2
DEFW 0000H 00 00
File #1 buffer pointer
63C4
DEFW 0000H 00 00
File #2 buffer pointer
63C6
DEFW 0000H 00 00
File #3 buffer pointer
63C8
DEFW 0000H 00 00
File #4 buffer pointer
63CA
DEFW 0000H 00 00
File #5 buffer pointer
63CC
DEFW 0000H 00 00
File #6 buffer pointer
63CE
DEFW 0000H 00 00
File #7 buffer pointer
63D0
DEFW 0000H 00 00
File #8 buffer pointer
63D2
DEFW 0000H 00 00
File #9 buffer pointer
63D4
DEFW 0000H 00 00
File #10 buffer pointer
63D6
DEFW 0000H 00 00
File #11 buffer pointer
63D8
DEFW 0000H 00 00
File #12 buffer pointer
63DA
DEFW 0000H 00 00
File #13 buffer pointer
63DC
DEFW 0000H 00 00
File #14 buffer pointer
63DE
DEFW 0000H 00 00
File #15 buffer pointer
63E0H (FILPT1) - Last Allocated Buffer End
63E0FILPT1
DEFW 0000H 00 00
End address of last allocated buffer. [src: COPY OF POINTER AT FILE 0]
63E2LSTFRE
DEFB 00H,00H 00 00
Reserved/padding (2 bytes) [src: FLAG WHETHER TO RUN PROGRAM OR NOT]
63E4H (PTCMD) - Entry Parameter Byte
63E4PTCMD
DEFB 00H 00
Entry parameter (2AH='*' for re-entry)
63E5H (SVTXTT) - Saved String Space Pointer
63E5SVTXTT
DEFW 0000H 00 00
Saved string space base pointer
63E7H (FILSVS) - Saved Max File Number
63E7FILSVS
DEFW 0000H 00 00
Saved maximum file number (0-15)
63E9H (OLSTTP) - Saved Memory Top
63E9OLSTTP
DEFW 0000H 00 00
Saved memory top (MEMSIZ)
63EBH (BUFEND) - Initialization Flag
63EBBUFEND
DEFB 00H 00
Initialization complete flag
63ECH (FILFLG) - Command Line Flags
63ECFILFLG
DEFB 00H 00
File count specified flag (-F) [src: FLAG TO SHOW WE HAVE SET FILES]
63EDMEMFLG
DEFB 00H 00
Memory size specified flag (-M) [src: FLAG TO SHOW WE HAVE SET MEMORY SIZE]
63EEH (CPMLIN) - Saved Entry HL Register
63EECPMLIN
DEFW 0000H 00 00
Saved HL from entry point
63F0H (CPMNAM) - Temporary Filename Buffer (16 bytes)
63F0CPMNAM
DEFB 00H,00H,00H,00H 00 00 00 00
Temp buffer bytes 0-3
63F4
DEFB 00H,00H,00H,00H 00 00 00 00
Temp buffer bytes 4-7
63F8
DEFB 00H,00H,00H,00H 00 00 00 00
Temp buffer bytes 8-11
63FC
DEFB 00H,00H,00H,00H 00 00 00 00
Temp buffer bytes 12-15
The temporary buffer at 63F0H (16 bytes) is used during command line processing to build quoted filenames from command parameters before execution.
6400H - Reserved Area (9 bytes)
6400
DEFB 00H,00H,00H,00H 00 00 00 00
Reserved bytes 0-3
6404
DEFB 00H,00H,00H,00H 00 00 00 00
Reserved bytes 4-7
6408
DEFB 00H 00
Reserved byte 8
6409H (PARCMX) - Command Line Processing
Processes command line parameters passed to BASIC/CMD.
6409PARCMX
LD HL,64DCH LD HL,ENDBAS21 DC 64
HL = buffer base. [src: TEMP END OF BASIC]
640C
LD (40A4H),HL LD (TXTTAB),HL22 A4 40
Set string space
640F
LD HL,(63EEH) LD HL,(CPMLIN)2A EE 63
HL = entry parameter. [src: GET THE COMMAND LINE POINTER]
6412PARCMD
DEC HL 2B
Back up [PARSE LOOP]. [src: BACK UP ONE FOR GETCHR]
6413
CHRGET: Get char. [src: GET THE NEXT CHARACTER FROM LINE]
6414
CP 20H FE 20
Is it space? [src: END OF LINE?]
6416
If < space, end of params [src: YES. GO EXECUTE ANY COMMAND]
6419
CP 5BH FE 5B
Is it >= '['?. [src: END OF LINE?]
641B
If >= '[', end of params. [src: WE READING CORE TRASH?]
641E
CP 2DH FE 2D
Is it '-' (option)? [src: FILE OR MEMORY SPECIFIER?]
6420
If '-', process option. [src: FILE OR MEMORY SPECIFIER?]
6422
EX DE,HL EB
DE = source. [src: YES. PARSE IT]
6423
LD HL,63F0H LD HL,CPMNAM21 F0 63
HL = temp buffer [src: HL => TEMP FILE NAME AREA]
6426
LD (HL),22H 36 22
Store quote [src: SET A QUOTE]
6428
INC HL 23
Next byte [src: BUMP TO NEXT SLOT]
6429PARCM1
LD A,(DE) 1A
Get char [COPY LOOP] [src: GET A BYTE OF FILENAME]
642A
CP 21H FE 21
Is it < '!'? [src: END OF FILE NAME?]
642C
If < '!', end of filename [src: YES, EXIT LOOP]
642E
LD (HL),A 77
Copy char [src: NO, STORE THE CHARACTER]
642F
INC HL 23
Next dest [src: BUMP POINTERS]
6431
Continue copy [END LOOP]. [src: SET A QUOTE]
6433PARCM2
LD (HL),00H 36 00
Null-terminate. [src: GET A BYTE OF FILENAME]
6435
EX DE,HL EB
HL = source position [src: COMMAND LINE POINTER BACK TO HL]
6436
Continue parsing. [src: YES, EXIT LOOP]
6438H (PRSFIL) - Process Option Flags (-M or -F)
6438PRSFIL
CHRGET: Get option char. [src: NO, STORE THE CHARACTER]
6439
CP 4DH FE 4D
Is it 'M' (memory)?. [src: BUMP POINTERS]
643B
PUSH AF F5
Save flag. [src: LOOP TILL END FOUNC]
643C
If 'M', continue [src: YES]
643E
CP 46H FE 46
Is it 'F' (files)? [src: FILES?]
6440
If not M or F, syntax error. [src: AND CONTINUE PARSEING]
6443WASM
CHRGET: Skip option char [src: GET THE NEXT CHARACTER]
6444
SYNCHR: Verify '=' [src: MUST BE FOLLOWED BY COLON]
6445SYERR
DEFB 3DH 3D
Expected: '='. [src: MEMORY SIZE?]
6446
Get value??? [src: GET THE 'M' OR 'F' BACK]
6449
INC SP 33
Adjust stack [src: SET THE FILE FLAG]
644A
LD (63ECH),A LD (FILFLG),A32 EC 63
Store flag at 63ECH. [src: FILES?]
644E
LD (426EH),A LD (VARREC),A32 6E 42
Clear verify flag. [src: HL => SYNTAX ERROR MSG]
6450
LD A,(HL) 7E
Get next char
6451
Parse integer to DE. [src: DISPLAY IT]
6454
CP 56H FE 56
Is it 'V' (verify)?. [src: AND ABORT]
6456
If not 'V', skip [src: NO]
6458
LD (426EH),A LD (VARREC),A32 6E 42
Set verify flag (56H)
645B
INC HL 23
Skip 'V' [src: BUMP PAST THE 'V']
645CORA1
LD A,D 7A
A = high byte [src: SHOULD NOT BE A HIGH ORDER]
645D
OR A B7
Check if > 255. [src: GET THE 'M' OR 'F' BACK]
645E
If > 255, re-prompt. [src: IS MEMORY GO SET IT]
6461
LD A,E 7B
A = value [src: THE MOST ALLOWED IS 15 FILES]
6462
CP 10H FE 10
Is it >= 16?
6464
If >= 16, re-prompt [src: OVER LIMIT]
6467
PUSH AF F5
Save value [src: SAVE THE NUMBER OF FILES]
6468
LD A,2AH 3E 2A
A = '*' (re-entry marker) [src: GO GET THE NUMBER OF FILES INTO DE]
646A
LD (63E4H),A LD (PTCMD),A32 E4 63
Set re-entry flag
646D
POP AF F1
Restore value. [src: NO]
646E
PUSH HL E5
Save HL [src: SAVE THE COMMAND LINE POINTER]
646F
Allocate files [src: DO DEFINE THE FILES]
6472
LD (HL),00H 36 00
Null-terminate. [src: BUMP PAST THE 'V']
6475
LD (40A4H),HL LD (TXTTAB),HL22 A4 40
Set string space. [src: THERE WAS. EXIT]
6478
POP HL E1
Restore HL. [src: THE MOST ALLOWED IS 15 FILES]
6479
Continue parsing [src: AND CONTINUE WITH NEXT PARSE]
647CH (SMEM) - Process Memory Option (-M)
647CSMEM
LD (63EDH),A LD (MEMFLG),A32 ED 63
Store flag at 63EDH [src: SET THE MEMORY FLAG]
647F
Parse memory size to DE [src: GET THE MEMORY SIZE IN DE]
6482
OR A B7
Check if end [src: NO ANSWER?]
6483
If end, syntax error. [src: SAVE THE NUMBER OF FILES]
6487
POP IY FD E1
IY = saved HL
6489
LD HL,C9AFH 21 AF C9
HL = XOR A / RET
648C
LD (5CE9H),HL LD (CLSALL),HL22 E9 5C
Patch routine
6492
LD HL,C5D5H 21 D5 C5
HL = PUSH DE / PUSH BC
6495
LD (5CE9H),HL 22 E9 5C
Restore routine. [src: AND CONTINUE WITH NEXT PARSE]
6498
PUSH IY FD E5
Push IY. [src: SET THE MEMORY FLAG]
649A
POP HL E1
HL = IY [src: AND CONTINUE PARSING]
649B
Continue parsing. [src: GET THE MEMORY SIZE IN DE]
649EH (EXCMD) - Finalize Command Line Processing
649EEXCMD
LD A,(63ECH) LD A,(FILFLG)3A EC 63
A = file count flag. [src: NO ANSWER?]
64A2
If set, skip default [src: YES.]
64A4
LD A,2AH 3E 2A
A = '*' [src: SET THE 'RET']
64A6
LD (63E4H),A LD (PTCMD),A32 E4 63
Set re-entry flag
64A9
LD A,03H 3E 03
A = 3 (default files) [src: SET FOR 3 DEFAULT FILES]
64AE
LD (HL),00H 36 00
Null-terminate. [src: MOVE THE COMMAND LINE POINTER TO IY]
64B1
LD (40A4H),HL LD (TXTTAB),HL22 A4 40
Set string space
64B4EXCMD1
LD A,(63EDH) LD A,(MEMFLG)3A ED 63
A = memory flag [src: DID WE SET MEMORY SIZE?]
64B8
If set, skip default. [src: GET THE MEMORY SET UP]
64BA
LD HL,(4411H) LD HL,(MEMEND)2A 11 44
HL = DOS memory top [src: GET THE HIGH BYTES]
64BD
LD DE,FFFAH 11 FA FF
DE = -6
64C1
If carry, use DE. [src: GET THE COMMAND LINE POINTER BACK]
64C3
EX DE,HL EB
Use default
64C4EXCM11
Set memory size. [src: AND CONTINUE PARSING]
64C7EXCMD2
LD HL,63F0H LD HL,CPMNAM21 F0 63
HL = temp buffer [src: POINT TO POSSIBLE FILE]
64CA
LD A,(HL) 7E
Get first char [src: ANY FILE NAME GIVEN?]
64CB
OR A B7
Check if empty
64CC
If empty, finish [src: NO, EXIT]
64CF
Display copyright [src: DISPLAY THE SCREEN STUFF]
64D2
LD HL,1A19H LD HL,INTRPT21 19 1A
HL = return address. [src: YES.]
64D5
PUSH HL E5
Push return
64D6
LD HL,63F0H LD HL,CPMNAM21 F0 63
HL = filename buffer [src: GET THE FILE POINTER]
64D9
Execute RUN command. [src: SET FOR 3 DEFAULT FILES]
64DCH (ENDBAS) - File Buffer Area (END OF CODE)
Dynamic file buffer area. Each file allocated gets 360 bytes (168H).
File Buffer Structure:
Base Address: 64DCH
Size per file: 360 bytes (168H) in normal mode, 616 bytes (268H) in verify mode (adds 256-byte verify buffer)
Maximum allocation: 16 files × 360 bytes = 5,760 bytes. Actual allocation determined by "How Many Files" prompt (0-15)
Buffer Layout per file:
Offset 00H-31H: FCB (File Control Block) - 50 bytes
Offset 32H-131H: Record buffer - 256 bytes
Offset 132H-167H: Additional workspace - 54 bytes
File pointer table at 63C0H contains 2-byte pointers to each FCB.
Table is null-terminated when buffer list ends.