M100 TS-DOS ROM RST 7 Handlers

From Bitchin100 DocGarden
Jump to navigationJump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

TS-DOS Model 100/102 ROM RST 7 Handlers

This is the code for the DOS-ON RST 7 Hooks, along with the TPDD1 Rename functionality.

; =========================================================================================
; Load default RST 7 vector table values
; =========================================================================================
3FFAH  LXI 7FF3H            ; Address of a RET opcode in ROM 
3FFDH  SHLD FAE6H           ; Save as hook for RST 7,0Ch??  We didn't modify this one
4000H  SHLD FB08H           ; Save as hook for RST 7,2Eh - DSKI$ function
4003H  SHLD FB0AH           ; Save as hook for RST 7,30h - OPEN/CLOSE/PRINT/LINE INPUT 
4006H  SHLD FAF0H           ; Save as hook for RST 7,16h - SAVE
4009H  SHLD FAF4H           ; Save as hook for RST 7,1Ah - RUN
400CH  LXI H,08DBH          ; Load address of "Generate FC Error" in Main ROM
400FH  SHLD FB2CH           ; Save as hook for RST 7,52h - LFILES
4012H  SHLD FB32H           ; Save as hook for RST 7,58h - KILL
4015H  SHLD FB34H           ; Save as hook for RST 7,5Ah - NAME
4018H  SHLD FB36H           ; Save as hook for RST 7,5Ch - SAVEM
401BH  SHLD FB38H           ; Save as hook for RST 7,5Eh - LOADM and RUNM
401EH  RET

; =========================================================================================
; Install our RST 7 hook for all RST 7 calls we are interested in.  This uses the "ON TIME"
;      time storage location to copy a 6-byte routine to switch to OptROM and call our 
;      RST 7 "switch" statement in our ROM.  This means ON TIME can't be used when using
;      the DOS-ON feature.
; =========================================================================================
401FH  CALL 3FFAH           ; Load default RST 7 vector table values
4022H  LXI H,4084H          ; Point to RST 7 RAM hook routine
4025H  LXI D,F93DH          ; Point Time for ON TIME interrupt to use as our hook routine
4028H  LXI B,0006H          ; Copy our RST 7 hood to the "ON TIME" time location
402BH  CALL 4A05H           ; Move BC bytes from HL to DE - copy our hook to RAM
402EH  LXI H,F93DH          ; Load address of "ON TIM" time where our hook was copied
4031H  SHLD FAF4H           ; Use our RAM RST 7 Hook for RST 7,1Ah - RUN
4034H  SHLD FAF0H           ; Use our RAM RST 7 Hook for RST 7,16h - SAVE
4037H  SHLD FB38H           ; Use our RAM RST 7 Hook for RST 7,5Eh - LOADM and RUNM
403AH  SHLD FB36H           ; Use our RAM RST 7 Hook for RST 7,5Ch - SAVEM
403DH  SHLD FB08H           ; Use our RAM RST 7 Hook for RST 7,2Eh - DSKI$
4040H  SHLD FB0AH           ; Use our RAM RST 7 Hook for RST 7,30h - OPEN/CLOSE/PRINT/INPUT
4043H  SHLD FB2CH           ; Use our RAM RST 7 Hook for RST 7,52h - LFILES
4046H  SHLD FB32H           ; Use our RAM RST 7 Hook for RST 7,58h - KILL
4049H  SHLD FB34H           ; Use our RAM RST 7 Hook for RST 7,5Ah - NAME
404CH  RET

; =========================================================================================
; Process jump to custom RST 7 Hook routine from Main ROM
; =========================================================================================
404DH  PUSH PSW             ; Preserve PSW
404EH  LDA FAC9H            ; Get address of last RST 38H call argument
4051H  CPI 1AH              ; RST 7,1Ah Hook - RUN statement 
4053H  JZ 4451H
4056H  CPI 16H              ; RST 7,16h Hook - SAVE statement
4058H  JZ 44E7H
405BH  CPI 5EH              ; RST 7,5Eh Hook - LOADM and RUNM statement 
405DH  JZ 43C1H
4060H  CPI 5CH              ; RST 7,5Ch Hook - SAVEM statement 
4062H  JZ 440DH
4065H  CPI 2EH              ; RST 7,2Eh Hook - DSKI$ function
4067H  JZ 4324H
406AH  CPI 30H              ; RST 7,30h Hook - OPEN/CLOSE/PRINT/LINE INPUT satement
406CH  JZ 451DH
406FH  CPI 52H              ; RST 7,52h Hook - LFILES 
4071H  JZ 4346H
4074H  CPI 58H              ; RST 7,58h Hook - KILL
4076H  JZ 4377H
4079H  CPI 5AH              ; RST 7,5Ah Hook - NAME statement 
407BH  JZ 4396H
407EH  POP PSW              ; Restore stack frame
407FH  MVI E,02H            ; Prepare to generate "SN" error
4081H  JMP 4C37H            ; Generate error in E

; =========================================================================================
; RST 7 Handler copied to RAM for DOS-ON
; =========================================================================================
4084H  CALL FAA4H           ; Call RAM hook to switch to OptROM
4087H  JMP 404DH            ; Jump to TS-DOS RST 7 handler in OptROM 

; =========================================================================================
; Open TPDD file for Read Mode.  File already stored in TX buffer.
; =========================================================================================
408AH  LXI H,0101H          ; Load "Open file" opcode
408DH  MVI A,03H            ; Load OPEN_READ mode into A
408FH  STA FCE8H            ; Save A in TX data storage (mode location)
4092H  JMP 409BH            ; Send Request in HL and await response - Open File

; =========================================================================================
; Send TPDD Write File opcode using RX buffer with length in A
; =========================================================================================
4095H  MOV H,A              ; Move length to H
4096H  MVI L,04H            ; Load TPDD_WRITE opcode to L
4098H  JMP 40A7H            ; Send TX packet using RX buffer

; =========================================================================================
; Send Request in HL and await response
; =========================================================================================
409BH  CALL 4822H           ; Send TPDD Command/Len in HL
409EH  CALL 49F0H           ; Wait for data to be ready
40A1H  CALL 47CCH           ; Copy Receive RX packet routine to RAM and execute it
40A4H  JMP 47F8H            ; Check RX packet for Normal Response & report errors

; =========================================================================================
; Use RX buffer to send a TX packet (used to send data).  Opcode/len in HL
; =========================================================================================
40A7H  SHLD FD02H           ; Save Opcode/len to RX buffer 
40AAH  LXI H,FD02H          ; Storage for RX packet
40ADH  CALL 4828H           ; Send TPDD pointed to by HL
40B0H  CALL 47CCH           ; Receive a packet
40B3H  JMP 47F8H            ; Check RX packet for Normal Response & report errors 

; =========================================================================================
; Send TPDD_READ data opcode and recieve response
; =========================================================================================
40B6H  LXI H,0003H          ; Load TPDD_READ opcode 
40B9H  CALL 4822H           ; Send TPDD Command/Len in HL
40BCH  CALL 47CCH           ; Receive a packet 
40BFH  LDA FD03H            ; Get length byte from RX buffer 
40C2H  LXI H,FD04H          ; Point to return data addres in RX buffer
40C5H  CPI 80H              ; Test for maximum read length  
40C7H  RET		  

; =========================================================================================
; Write HL bytes of data from (DE) to TPDD
; =========================================================================================
40C8H  PUSH D               ; Push address of write-data to stack  
40C9H  PUSH H               ; Push length of data to the stack  
40CAH  CALL 4101H           ; Test free Disk space and issue TPDD_OPEN request      
40CDH  POP H                ; Get address of data from stack 
40CEH  SHLD FCD5H           ; Save length as remaining length to write      
40D1H  POP H                ; Get address of data to write to TPDD from stack 
40D2H  LXI D,FD04H          ; Point to RX buffer to copy write data
40D5H  LXI B,0080H          ; Prepare to copy 128 bytes of data to the RX buffer  

; =========================================================================================
; Write BC bytes of data from (HL) to (DE) and write to TPDD, DE=RX buffer data pointer
; =========================================================================================
40D8H  CALL 4A05H           ; Move BC bytes from M to (DE) with increment       
40DBH  PUSH H               ; Push the updated address to the stack   
40DCH  LHLD FCD5H           ; Get the remaining lenth left to write       
40DFH  LXI B,0080H          ; Prepare to subtract 128 from the length   
40E2H  DSUB                 ; Subtract 128 bytes from remaining length to write 
40E3H  JC 40F4H             ; Jump out of loop if less than 128 bytes remaining     
40E6H  JZ 40F4H             ; Jump out of loop if exactly 128 bytes remaining     
40E9H  SHLD FCD5H           ; Save updated length left to write for next pass       
40ECH  MVI A,80H            ; Prepare to write 128 bytes to TPDD      
40EEH  CALL 4095H           ; Send TPDD Write File opcode using RX buffer with length in A       
40F1H  JMP 40D1H            ; Jump to send next packet of 128 bytes      

; =========================================================================================
; Write remaining bytes (128 or less from above) to TPDD
; =========================================================================================
40F4H  POP H                ; Clear stack of unneeded updated source address  
40F5H  LDA FCD5H            ; Load A with remainder of bytes to be sent
40F8H  CALL 4095H           ; Send TPDD Write File opcode using RX buffer with length in A 
40FBH  LXI H,0002H          ; Load TPDD_CLOSE opcode in HL
40FEH  JMP 409BH            ; Send Request in HL and await response

; =========================================================================================
; Test if enough space on disk for HL bytes and issue Open request, error if disk full
; =========================================================================================
4101H  LXI D,0500H          ; Load decimal 1280 to calculate sector number
4104H  XCHG                 ; Swap HL/DE to perform size/bytes_per_sector 
4105H  CALL 4C1BH           ; Signed integer divide (FAC1=DE/HL)       
4108H  LDA FD1FH            ; Get number of free sectors on disk      
410BH  SUB L                ; Compare required sectors with free space to see if enough room  
410CH  JC 4881H             ; Disk Full Error             
410FH  JZ 4881H             ; Disk Full Error     
4112H  LDA FCD6H            ; Load open mode (new, append, etc.)      
4115H  STA FCE8H            ; Save file open mode to TX buffer      
4118H  LXI H,0101H          ; Load TPDD_OPEN opcode
411BH  JMP 409BH            ; Send Request in HL and await response      

; =========================================================================================
; Insert BC spaces at address of RAM file being loaded/run
; =========================================================================================
411EH  LHLD FCE2H           ; Load address of file being processed
4121H  CALL 4C0BH           ; Insert BC spaces at M
4124H  JC 488AH             ; RAM full error

; =========================================================================================
; Open TPDD file and read data to file address being processed
; =========================================================================================
4127H  LHLD FCE2H           ; Get address of file being processed
412AH  PUSH H               ; Save address on stack  
412BH  CALL 408AH           ; Open TPDD file for Read Mode
412EH  CALL 40B6H           ; Send TPDD_READ data opcode and recieve response
4131H  MOV C,A              ; Move read length to C   
4132H  MVI B,00H            ; Clear MSB of copy length
4134H  POP D                ; Restore address to write data 

; =========================================================================================
; Write BC bytes from M to DE and subtract BC from total file size
; =========================================================================================
4135H  CALL 4A05H           ; Move BC bytes from M to (DE) with increment
4138H  PUSH D               ; Save updated address to stack  
4139H  LDA FD03H            ; Get length byte from RX buffer      
413CH  LHLD FCDDH           ; Get total file size from storage
413FH  MOV C,A              ; Load count of bytes transfered this block   
4140H  MVI B,00H            ; Clear MSB of count     
4142H  DSUB                 ; Subtract this block from total file length
4143H  SHLD FCDDH           ; Save remaining bytes to be read back to temp storage
4146H  JC 414EH             ; Branch if too many bytes read    
4149H  MOV A,L              ; Load LSB to A to test for zero   
414AH  ORA H                ; OR MSB to test for zero 
414BH  JNZ 412EH            ; Branch to read more data if not zero     
414EH  POP D                ; Pop address from stack - cleanup 
414FH  RET

; =========================================================================================
; Write data to FDC Emulation mode physical/logical sector
; =========================================================================================
4150H  LDA FCDDH            ; Get physical sector number        
4153H  CPI 01H              ; Test if physical sector is #1      
4155H  RZ                   ; Return if trying to write to sector 1 - reserved!!! 
4156H  CALL 4998H           ; Flush RX queue and discard         
4159H  MVI A,57H            ; Load FDC opcode for "W"rite sector                 
415BH  STA FCD3H            ; Save the FDC emulation mode opcode        
415EH  CALL 42CEH           ; Send FDC emulation mode opcode
4161H  CALL 4998H           ; Flush RX queue and discard
4164H  CALL 4176H           ; Increment to next logical/physical sector
4167H  LHLD FCE4H           ; FDC Emulation data pointer address 
416AH  CALL 48D9H           ; Send BC bytes to RS-232 from (HL) using XON/XOFF
416DH  SHLD FCE4H           ; LCD Buffer address of current file selection
4170H  CALL 42EEH           ; Read FDC Emulation mode response
4173H  JMP 4150H            ; Jump to write next sector ???        

; =========================================================================================
; Increment to next logical/physical sector
; =========================================================================================
4176H  LDA FD09H            ; Get byte 7 from the RX buffer (logical sector length)        
4179H  CALL 4191H           ; Get FDC Emulation RAM buffer sector length based on response         
417CH  CPI 35H              ; Test if RAM Buffer logical sector length is "500" (1280)      
417EH  JZ 4189H             ; Just update physical sector if RAM length = physical sector len       
4181H  LXI H,FCDEH          ; Load pointer to logical sector value
4184H  INR M                ; Increment to next logical sector    
4185H  MOV A,M              ; Get the next logical sector value      
4186H  CPI 14H              ; Test if logical sector = 20 (There are 20 64-byte logical sectors)      
4188H  RNZ                  ; Return if not paat end of physical sector  
4189H  LXI H,FCDDH          ; Point to physical sector storage          
418CH  INR M                ; Increment to next physical sector - we "rolled over"    
418DH  INX H                ; Point to logical sector    
418EH  MVI M,01H            ; Start with logical sector #1 in new physical sector        
4190H  RET

; =========================================================================================
; Get FDC Emulation RAM buffer sector length based on response code in A
; =========================================================================================
4191H  LXI B,0500H          ; Initialize to 1280 byte sector length
4194H  CPI 35H              ; Compare response to test for "500" 
4196H  RZ                   ; Return if match  
4197H  LXI B,0040H          ; Sector lenth not 1280, must be 64 bytes  
419AH  RET

; =========================================================================================
; Send TPDD opcode 0x08 - Go to FDC emulation mode
; =========================================================================================
419BH  LXI H,0008H          ; Prepare to send Opcode 0x08 (FDC Emulation Mode)
419EH  CALL 4822H           ; Send TPDD Command/Len in HL 
41A1H  CALL 49D3H           ; Send 0x0D to RS-232 and Delay 3ms 
41A4H  JMP 4998H            ; Flush RX queue and discard

; =========================================================================================
; Rename the TPDD file whose name is in "current BASIC program"
; =========================================================================================
41A7H  LXI H,FC93H          ; Filename of current BASIC program    
41AAH  LXI D,FCE8H          ; Point to data area in TX buffer
41ADH  LXI B,0006H          ; Move 6 bytes of filename data

; =========================================================================================
; Rename the TPDD file whose name is in (HL)
; =========================================================================================
41B0H  CALL 4A05H           ; Move BC bytes from M to (DE) with increment          
41B3H  LDA FCCBH            ; NADSBox / Desklink / TPDD2 flag         
41B6H  ANA A                ; Test for TPDD server     
41B7H  JNZ 4258H            ; Send TPDD_RENAME opcode and check response     

; =========================================================================================
; Rename on a TPDD.  I'm guessing the drive will allow changing a name to something
; that already exists, or there is no "rename", so TS-DOS is reading sector 1 and doing
; the rename opertaion manually, then writing sector 1 back to the disk.
; =========================================================================================
41BAH  CALL 4A72H           ; Send Dir Reference opcode         
41BDH  JNZ 487EH            ; File Exists Error        
41C0H  LXI D,0500H          ; Prepare to test for 1280 bytes of free ram (1 sector)          
41C3H  CALL 4308H           ; Test if at least DE bytes of RAM free         
41C6H  LXI H,0100H          ; Load HL with physical sector 1, logical sector 0          
41C9H  SHLD FCDDH           ; Save in FDC Emulation sector storage         
41CCH  CALL 419BH           ; Send opcode 0x08 - go to FDC emulation mode         
41CFH  CALL 427EH           ; Load Physical sector 1 to (HL) (HL=Unused memory pointer)         
41D2H  LHLD FBB6H           ; Get pointer to data - Unused memory pointer    
41D5H  PUSH H               ; Push data pointer to the stack       
41D6H  MVI B,28H            ; Prepare to test up to 40 filenames (max for TPDD)
41D8H  LXI D,FC9CH          ; Filename of last program loaded from tape    
41DBH  CALL 4269H           ; Compare "Last program loaded" filename with all files on TPDD    
41DEH  JC 487BH             ; Printer not ready / FF error         
41E1H  MOV A,B              ; Get index in TPDD Sector 1 of filename that matches the old filename        
41E2H  ANA A                ; Test if old filename exists      
41E3H  JZ 487BH             ; Jump to error if filename not found in sector 1 - FF error         
41E6H  PUSH H               ; Save address within Sector 1 of matching filename to stack       
41E7H  LXI D,FCE8H          ; Point to TX buffer data area (payload)            
41EAH  XCHG                 ; HL <--> DE  Prepare to copy new filename to Sector 1 data                 
41EBH  LXI B,0009H          ; Prepare to copy 9 bytes of filename            
41EEH  CALL 4A05H           ; Move BC bytes from M to (DE) with increment - copy new filename to sector 1           
41F1H  POP H                ; Restore pointer to filename address within sector 1      
41F2H  PUSH H               ; Save it to the stack again       
41F3H  LXI D,FD20H          ; Load address of data byte 28 in RX buffer            
41F6H  LXI B,001FH          ; Prepare to copy 31 bytes to RX buffer from Sector 1 data            
41F9H  CALL 4A05H           ; Move BC bytes from M to (DE) with increment - Save File data in RX buffer           

	; ==========================================================================================
	; Now we will "remove" the renamed file from sector 1 by copying over it with the remaining
	; files in the sector.  Filenames in sector 1 must be in alphabetical order, so we have to
	; remove it and reinsert it at the new location based on the new name.
	; ==========================================================================================

41FCH  POP D                ; Restore pointer to filename address within sector 1      
41FDH  PUSH D               ; Save it to the stack again       
41FEH  LXI H,001FH          ; Prepare to add 31 bytes to the sector 1 pointer (go to next file)            
4201H  DAD D                ; Point to next file after rename file within sector 1      
4202H  PUSH H               ; Save address of next file after rename file to stack       
4203H  LHLD FBB6H           ; Unused memory pointer    
4206H  LXI B,0500H          ; Load size of 1 TPDD sector (1280 bytes)            
4209H  DAD B                ; Point to end of sector 1 data in free memory region      
420AH  POP B                ; Restore address of next file after rename file from stack      
420BH  PUSH B               ; Save it back to the stack       
420CH  DSUB                 ; Calculate number of bytes from next file after rename to end of sector 1      
420DH  XTHL                 ; HL <--> (SP)  Prepare to move HL to BC, HL now has address of next file     
420EH  POP B                ; Get byte count to end of sector 1      
420FH  CALL 4A05H           ; Move BC bytes from M to (DE) with increment - shift bytes "left" in buffer           
4212H  LHLD FBB6H           ; Unused memory pointer - point to beginning of Sector 1 data    
4215H  MVI B,27H            ; Prepare to search throuh 39 files (we just deleted one)          
4217H  LXI D,FD20H          ; Load address of data byte 28 in RX buffer (our saved file)            
421AH  CALL 4269H           ; Search Sector-1 files at (HL) for filename at (DE)     
421DH  PUSH H               ; Save address of location where file should be inserted in Sector 1       
421EH  LHLD FBB6H           ; Unused memory pointer - point to beginning of Sector 1    
4221H  LXI B,04FFH          ; Prepare to move bytes "right" to end of sector (1280 bytes - 1)            
4224H  DAD B                ; Point to end of sector 1 data      
4225H  PUSH H               ; Save end of sector 1 address to stack       
4226H  LXI B,001FH          ; Prepare to subtract 1 file entry length from end of sector 1 address            
4229H  DSUB                 ; Shorten the copy operation by 1 file entry so we don't overflow memory     
422AH  POP D                ; Get end of sector 1 address from stack as our "copy to" address      
422BH  POP B                ; Get address where file needs to be inserted from the stack      
422CH  PUSH B               ; Save it back to the stack for later       
422DH  PUSH H               ; Save address of end of Sector 1 minus one file entry length to stack       
422EH  DSUB                 ; Calculate the copy lenght of data from insertion point to end of sector-1 file     
422FH  PUSH H               ; Save copy length to the stack to copy it to BC       
4230H  POP B                ; Get copy length into BC      
4231H  INX B                ; Increment length by 1 so the last byte is inclusive      
4232H  POP H                ; Get address of file insertion point from stack      
4233H  CALL 4C4EH           ; Move BC bytes from M to (DE) with decrement - shift files "right" in sector 1           
4236H  LXI H,FD20H          ; Get address of our saved file info in the RX buffer
4239H  POP D                ; Get address in Sector 1 of file insertion point      
423AH  LXI B,001FH          ; Prepare to copy 1 file entry size (31 bytes)            
423DH  CALL 4A05H           ; Move BC bytes from M to (DE) with increment           


	; ===============================================================================
	; Seems like the next two lines don't do anything. The value being loaded in HL 
	; *appears* to mean "Logical sector 20, physical sector 1", but only if the SHLD
	; target address is FCCDH.  Then 5 instructions further down, the value in
	; ED80h is overwritten with logical sector 0.
	; ===============================================================================
4240H  LXI H,1401H          ; Set L = logical sector 1, H=File type 0x14?            
4243H  SHLD FCDEH           ; Save logical sector & filetype           

4246H  POP H                ; POP stale address within Sector 1 of matching filename from stack      
4247H  POP H                ; Get address of unused memory (Sector 1 data storage) from stack      
4248H  SHLD FCE4H           ; Save in FDC Emulation data pointer address            
424BH  LXI H,0100H          ; Load HL= logical sector 1, physical sector 0            
424EH  SHLD FCDDH           ; Save in FDC Emulation physical/logical sector storage           
4251H  CALL 4150H           ; Write data to FDC Emulation mode physical/logical sector           
4254H  CALL 49CDH           ; Send "M1",0x0D to RS-232 and delay about 3ms - go to Standard mode           
4257H  RET

; =========================================================================================
; Send TPDD_RENAME opcode and check response for errors
; =========================================================================================
4258H  LXI H,190DH          ; Load TPDD_RENAME opcode
425BH  CALL 4822H           ; Send TPDD Command/Len in HL 
425EH  CALL 47CCH           ; Receive a packet 
4261H  LDA FD04H            ; Get response error code 
4264H  ANA A                ; Check for errors 
4265H  JNZ 487EH            ; Report File Exists Error if not zero
4268H  RET

; =========================================================================================
; Search Sector-1 files at (HL) for filename at (DE), maximum of "B" entries searched 
; =========================================================================================
4269H  MVI C,09H            ; Prepare to compare 9 bytes        
426BH  CALL 4A1CH           ; Compare (HL) with (DE), C bytes long (HL & DE preserved)         
426EH  RZ                   ; Return if they are the same 
426FH  RC                   ; Return if filename is less (files are sorted on TPDD) 
4270H  MOV A,M              ; Get 1st byte of filename to test for NULL      
4271H  ORA A                ; Test if A is 0    
4272H  RZ                   ; Return if string is NULL 
4273H  PUSH B               ; Save BC on stack     
4274H  LXI B,001FH          ; Prepare to add 31 to HL
4277H  DAD B                ; Add 31 to HL    
4278H  POP B                ; Restore original BC    
4279H  DCR B                ; Decrement loop counter    
427AH  RZ                   ; Return if no more items to compare 
427BH  JMP 4269H            ; Jump to compare next entry  

; =========================================================================================
; Read FDC sectors to New File Address (Free memory)
; =========================================================================================
427EH  LHLD FCE2H           ; Get pointer for TPDD read data
4281H  CALL 4298H           ; Read sector A into (HL)     
4284H  LDA FCDDH            ; Load current FDC Emulation physical sector number        
4287H  DCR A                ; Decrement to previous sector    
4288H  RZ                   ; Return if sector number is zero 
4289H  JMP 4281H            ; Jump to read another sector (what breaks the loop? - A not saved)        

; =========================================================================================
; Receive RX bytes to (HL) routine copied to RAM
; =========================================================================================
428CH  CALL 6D7EH           ; Get a character from RS232 receive queue
428FH  MOV M,A              ; Save next byte to (HL)
4290H  INX H                ; Increment pointer
4291H  DCX B                ; Decrement counter
4292H  MOV A,C              ; Prepare to test or zero
4293H  ORA B                ; OR in MSB of coutner
4294H  JNZ FD89H            ; Jump back to receive next character (RAM address)
4297H  RET

; =========================================================================================
; Read FDC sector A to (HL), BC has length
; =========================================================================================
4298H  PUSH H               ; Save target address for RX data stack
4299H  MVI A,52H            ; Load FDC Emulation opcode for "R"ead
429BH  STA FCD3H            ; Save as FDC Emulation opcode to send
429EH  CALL 42CEH           ; Send FDC emulation mode opcode
42A1H  CALL 4176H           ; Increment to next logical/physical sector
42A4H  CALL 4862H           ; Test if DSR is set - drive ready, error otherwise
42A7H  PUSH B               ; Save length of RX to the stack
42A8H  LXI H,428CH          ; Load address of RX routine to copy to RAM
42ABH  LXI B,000CH          ; Size of the RX routine to be copied to RAM
42AEH  LXI D,FD89H          ; Target address of RX routine (in ALTLCD buffer)
42B1H  CALL 4A05H           ; Move BC bytes from M to (DE) with increment
42B4H  MVI A,0DH            ; Prepare to send CR to RS-232
42B6H  CALL 485FH           ; Send A to RS-232 using XON/XOFF          
42B9H  CALL 4BDBH           ; Call Main ROM's Set interrupt to 1DH routine.
42BCH  POP B                ; Restore count of bytes to receive
42BDH  POP H                ; Restore target address for RX data
42BEH  RST 1                ; Call main ROM at address in following 2 bytes
42BFH  DW FD89H             ; Switch to Main ROM and call our RAM based RX routine
42C1H  RET

; =========================================================================================
; Convert decimal value in A to base 10 ASCII value in BC
; =========================================================================================
42C2H  MVI B,2FH            ; Start with '0' - 1
42C4H  SUI 0AH              ; Subtract 10 from A 
42C6H  INR B                ; Increment B (10's position) 
42C7H  JNC 42C4H            ; Keep looping until A negative
42CAH  ADI 3AH              ; Convert negative remainder to positive ASCII '0'-'9' 
42CCH  MOV C,A              ; Store LSB ASCII value in C  
42CDH  RET		

; =========================================================================================
; Send FDC emulation mode opcode
; =========================================================================================
42CEH  LDA FCDDH            ; Get physical sector number         
42D1H  CALL 42C2H           ; Convert A to 10-based ASCII          
42D4H  LDA FCD3H            ; Load the FDC emulation mode opcode to send         
42D7H  CALL 485FH           ; Send A to RS-232 using XON/XOFF          
42DAH  CALL 49DBH           ; Send BC to RS-232 using XON/XOFF - send physical sector #          
42DDH  LDA FCDEH            ; Get logical sector number         
42E0H  CALL 42C2H           ; Convert A to 10-based ASCII          
42E3H  MVI A,2CH            ; Load code for ','         
42E5H  CALL 485FH           ; Send A to RS-232 using XON/XOFF          
42E8H  CALL 49DBH           ; Send BC to RS-232 using XON/XOFF - send logical sector #          
42EBH  CALL 49D3H           ; Send 0x0D to RS-232 and Delay 3ms          

; =========================================================================================
; Read FDC Emulation mode response
; =========================================================================================
42EEH  LXI H,FD04H          ; Point to RX buffer data area          
42F1H  PUSH H               ; Save RX buffer address on stack     
42F2H  MVI C,08H            ; Prepare to read 8 bytes from RX - standard FDC response length        
42F4H  CALL 47E5H           ; Get next byte from RX into HL         
42F7H  DCR C                ; Decrement loop counter    
42F8H  JNZ 42F4H            ; Keep looping until 8 bytes read        
42FBH  POP H                ; Get start of RX buffer address from stack    
42FCH  MOV A,M              ; Get first response byte      
42FDH  CPI 30H              ; Test if response error code is '0' - no error      
42FFH  RZ                   ; Return if no error 
4300H  CPI 42H              ; Test for FDC Emulation mode "write protect" error code      
4302H  JZ 486DH             ; Write Protect Error       
4305H  JMP 4867H            ; Drive Not Ready Error        

; =========================================================================================
; Test if at least DE bytes of RAM left
; =========================================================================================
4308H  LHLD FBB6H           ; Unused memory pointer  
430BH  PUSH H               ; Push unused memory location on stack    
430CH  SHLD FCE2H           ; Save unused memory location locally        
430FH  LXI H,FFC0H          ; Prepare to subtract 64 from stack pointer 
4312H  DAD SP               ; Add SP to HL (-64) (need some call space to run program)    
4313H  POP B                ; Restore unused memory location in BC            
4314H  DSUB                 ; Subtract stack from unused memory pointer  
4315H  RST 3                ; Compare DE and HL - check if enough free RAM 
4316H  JC 488AH             ; RAM full error      
4319H  RET

; =========================================================================================
; Issue TPDD Delete file Opcode
; =========================================================================================
431AH  XRA A                ; Prepare to indicate we can't use Next Dir feature
431BH  STA FD01H            ; Save in dir reference location in TX buffer
431EH  LXI H,0005H          ; Load Delete File opcode into HL
4321H  JMP 409BH            ; Send Request in HL and await response

; =========================================================================================
; RST 7,2Eh Hook - DSKI$ function
; =========================================================================================
4324H  POP PSW              ; Pop return address - we will return manually to Main ROM
4325H  CPI 30H              ; Test A against '0' to check for bounds (only allow '0' and '1')       
4327H  JC 00A6H             ; Return to Main ROM if less than '0' - not our's        
432AH  CPI 32H              ; Test A against '2' to check for bounds       
432CH  JNC 00A6H            ; Return to Main ROM if >= '2'         
432FH  SUI 30H              ; Convert ASCII bank number to binary       
4331H  STA FCCAH            ; Save the target bank number in TPDD2 Bank number space         
4334H  INX H                ; Point to next byte to ensure it is ':'     
4335H  DCR E                ; ? Maybe length     
4336H  MOV A,M              ; Get next byte of filename       
4337H  CPI 3AH              ; Test if it is ':'       
4339H  JNZ 00A6H            ; Return if not ':'         
433CH  INX H                ; Increment to filename portion     
433DH  DCR E                ; ? Maybe length     
433EH  XTHL                 ; Put pointer to filename on stack so we don't lose it when we pop             
433FH  POP H                ; Pop so we return to our caller's return address     
4340H  MVI A,09H            ; Load A with a value we will test for later to see if it's our file         
4342H  ORA A                ; Set return flags     
4343H  JMP 00A6H            ; Return to Main ROM

; =========================================================================================
; RST 7,52h Hook - LFILES function
; =========================================================================================
4346H  POP PSW              ; POP return address from stack...we will return manually
4347H  PUSH D               ; Preserve DE on STACK     
4348H  PUSH H               ; Preserve HL on STACK     
4349H  PUSH PSW             ; Preserve A on STACK       
434AH  XRA A                ; Flag to generate system errors vs. printing    
434BH  CALL 4A85H           ; Save OS's baud rate string to storage area         
434EH  LDES 02H             ; DE = SP + 2       
4350H  LHLX                 ; Get value of HL pushed to stack above - LFILES argument pointer   
4351H  MOV A,M              ; Get 1st byte of argument      
4352H  ANA A                ; Test if arguement is zero             
4353H  JZ 436AH             ; Jump to display files from current TPDD bank number if zero       
4356H  CPI 3AH              ; Test if 1st byte is ':'      
4358H  JZ 436AH             ; Jump to display files from current TPDD bank number if ':"       
435BH  CALL 4BCFH           ; Evaluate expression at M-1 - Convert "0:" or "1:" to decimal         
435EH  MOV A,E              ; Get result of evaluation      
435FH  CPI 02H              ; Compare result for bounds      
4361H  JNC 4370H            ; Jump to exit routine if not 0 or 1        
4364H  STA FCCAH            ; Save as TPDD2 Bank number        
4367H  LDES 02H             ; DE = SP + 2       
4369H  SHLX                 ; Save updated expression pointer to stack location prior to RST 7   
436AH  CALL 4704H           ; Display / print all files and free space         
436DH  CALL 4AC4H           ; Restore original baud settings         

; =========================================================================================
; RST 7 Hook exit routine
; =========================================================================================
4370H  POP PSW              ; Get preserved A from stack    
4371H  POP H                ; Get preserved HL from stack  
4372H  POP D                ; Get preserved DE from stack  
4373H  POP B                ; B isn't PUSHed in the Hook routines, POP the return address  
4374H  JMP 00A6             ; Return to the Main ROM

; =========================================================================================
; RST 7,58h Hook - KILL statement
; =========================================================================================
4377H  POP PSW              ; POP the return address - we will return manually
4378H  CPI 09H              ; Test if we found "0:" or "1:" in the DSKI$ function    
437AH  JNZ 4516H            ; Generate FC error      
437DH  PUSH D               ; Preserve DE on the stack   
437EH  PUSH H               ; Preserve HL on the stack   
437FH  PUSH PSW             ; Preserve A on the stack     
4380H  XRA A                ; Flag to generate system errors vs. printing  
4381H  CALL 4A85H           ; Save OS's baud rate string to storage area       
4384H  LXI H,FC93H          ; Filename of current BASIC program            
4387H  CALL 4A57H           ; Send Dir Reference for filename at (HL)       
438AH  JZ 487BH             ; "FF" error if attribute byte is zero     
438DH  CALL 431AH           ; Issue TPDD Delete file Opcode       
4390H  CALL 4AC4H           ; Restore original baud settings       
4393H  JMP 4370H            ; RST 7 Hook exit routine      

; =========================================================================================
; RST 7,5Ah Hook - NAME statement
; =========================================================================================
4396H  POP PSW              ; POP the return address - we will return manually
4397H  CPI 09H              ; Test if we found "0:" or "1:" in the DSKI$ function    
4399H  JNZ 4516H            ; Generate FC error      
439CH  PUSH D               ; Preserve DE on the stack   
439DH  PUSH H               ; Preserve HL on the stack   
439EH  PUSH PSW             ; Preserve A on the stack     
439FH  XRA A                ; Flag to generate system errors vs. printing          
43A0H  CALL 4A85H           ; Save OS's baud rate string to storage area       
43A3H  LXI H,FC9CH          ; Filename of last program loaded from tape            
43A6H  CALL 4A57H           ; Send Dir Reference for filename at (HL)       
43A9H  JZ 487BH             ; "FF" error if attribut byte is zero     
43ACH  LXI H,FCE8H          ; Point to TX buffer data area (payload)        
43AFH  LXI D,FC9CH          ; Filename of last program loaded from tape            
43B2H  LXI B,0009H          ; Prepare to copy 9 bytes of filename        
43B5H  CALL 4A05H           ; Move BC bytes from M to (DE) with increment       
43B8H  CALL 41A7H           ; Rename the TPDD file whose name is in "current BASIC program"       
43BBH  CALL 4AC4H           ; Restore original baud settings       
43BEH  JMP 4370H            ; RST 7 Hook exit routine      

; =========================================================================================
; RST 7,5Eh Hook - LOADM and RUNM statement
; =========================================================================================
43C1H  POP PSW        
43C2H  CPI 09H              ; Test if we found "0:" or "1:" in the DSKI$ function    
43C4H  JNZ 00A6H            ; Return if not a TPDD file      
43C7H  POP B                ; Pop return address from stack - we will jump manually to exit  
43C8H  PUSH H               ; Preserve HL on the stack   
43C9H  LXI B,4F43H          ; Load code for "CO" filename extension        
43CCH  CALL 44BAH           ; Compare extension in current BASIC program filename with value in BC    
43CFH  JZ 487BH             ; "FF" Printer not ready error     
43D2H  CALL 408AH           ; Open TPDD file for Read Mode       
43D5H  LHLD FD1DH           ; Get file size parameter from RX buffer       
43D8H  MOV A,L              ; Swap endianness of file size    
43D9H  MOV L,H              ; Move MSB to LSB    
43DAH  MOV H,A              ; Move LSB to MSB    
43DBH  SHLD FCDDH           ; Save endian modified length back to storage       
43DEH  CALL 40B6H           ; Send TPDD_READ data opcode and recieve response, HL=RX buf upon return       
43E1H  CALL 4C6AH           ; Copy CO header bytes (6) from (HL) to "active" CO Header storage area       
43E4H  PUSH H               ; Push updated (+6) RX data pointer to stack   
43E5H  CALL 4C6EH           ; Go print CO address, length and invocation address to LCD       
43E8H  LHLD FACEH           ; Address of CO Header - get CO load address       
43EBH  PUSH H               ; Push CO load address to stack   
43ECH  PUSH H               ; Push another copy to the stack to preserve value during XTHL/POP   
43EDH  LHLD F5F4H           ; RST 5.5 RAM Vector   
43F0H  XTHL                 ; HL <--> (SP)  Load RST 5.5 RAM vector as return address 
43F1H  POP B                ; BC now has RST 5.5 RAM Vector, HL= CO load address  
43F2H  DSUB                 ; Test if CO load address is less that RST 5.5 RAM address 
43F3H  JC 488AH             ; Trying to clober RST5.5 RAM vectors - generate RAM full error     
43F6H  POP D                ; Get CO load address saved on stack   
43F7H  POP H                ; Get Updated (+6) RX data pointer from stack   
43F8H  LDA FD03H            ; Load RX Length byte from RX data buffer       
43FBH  SUI 06H              ; Subtract CO header length from packet data length     
43FDH  MOV C,A              ; Save packet data length in BC     
43FEH  MVI B,00H            ; Make MSB of BC zero       
4400H  CALL 4135H           ; Write BC bytes from M to DE and subtract BC from total file size        
4403H  CALL 4AC4H           ; Restore original baud settings        
4406H  LXI H,251AH          ; Load new return address in Main ROM
4409H  PUSH H               ; Push new return address to stack
440AH  JMP 00A6H            ; Jump to Main ROM

; =========================================================================================
; RST 7,5Ch Hook - SAVEM statement
; =========================================================================================
440DH  POP PSW              ; POP the return address - we will return elsewhere
440EH  CPI 09H              ; Test if we found "0:" or "1:" in the DSKI$ function    
4410H  JNZ 00A6H            ; Return if not a TPDD file      
4413H  CALL 4C72H           ; Process SAVEM arguments for address, length and entry point       
4416H  LXI B,4F43H          ; Load code for "CO" file extension        
4419H  CALL 44BAH           ; Compare ext. in current BASIC program with BC, send dir ref. if match            
441CH  JNZ 487EH            ; Jump to generate File Exists Error if found      
441FH  MVI A,01H            ; Set open mode for new file      
4421H  STA FCD6H            ; Save open mode to input variable      
4424H  LHLD FAD0H           ; Length of last program loaded/saved to tape            
4427H  LXI B,0006H          ; Prepare to add CO header size (6 bytes) to required length        
442AH  PUSH B               ; Push CO header length to stack   
442BH  DAD B                ; Add CO header size to required length  
442CH  PUSH H               ; Push updated file length to stack   
442DH  CALL 4101H           ; Test free Disk space and issue TPDD_OPEN request       
4430H  POP H                ; Get updated file length from stack  
4431H  SHLD FCD5H           ; Save as lenght of file being saved / loaded       
4434H  POP B                ; Get CO header length from stack          
4435H  LXI H,FACEH          ; Load address of "active" CO header block        
4438H  LXI D,FD04H          ; DE points to the data area in RX buffer        
443BH  CALL 4A05H           ; Move BC bytes from M to (DE) with increment       
443EH  LHLD FD04H           ; DE points to the data area in RX buffer       
4441H  LXI B,007AH          ; Prepare to write 122 bytes of data to next location in RX buffer        
4444H  CALL 40D8H           ; Write 122 bytes from (HL) and send TPDD_WRITE to TPDD       
4447H  CALL 4AC4H           ; Restore original baud settings       
444AH  LXI H,0501H          ; Load return address in Main ROM - vector to BASIC ready
444DH  PUSH H               ; Push return address to stack
444EH  JMP 00A6H            ; Return to Main ROM

; =========================================================================================
; RST 7,1Ah Hook - RUN statement
; =========================================================================================
4451H  POP PSW       
4452H  CPI 09H              ; Test if we found "0:" or "1:" in the DSKI$ function   
4454H  JNZ 00A6H            ; Return if not TPDD file     
4457H  POP B                ; Get return address from stack  
4458H  POP PSW              ; Get 1st byte of RUN statement argument   
4459H  PUSH PSW             ; Put back the data we stole    
445AH  PUSH B               ; Put back the return address  
445BH  JZ 00A6H             ; Return if there were no arguments to the RUN statement    
445EH  SBB A                ; Clear zero flag (C is set and A=0xFF) 
445FH  STA FC92H            ; Save in flag to execute BASIC program (non-zero = execute)     
4462H  LXI B,4142H          ; Load code for "BA" BASIC file extension       
4465H  CALL 44BAH           ; Compare ext. in current BASIC program with BC, send dir ref. if match           
4468H  JZ 487BH             ; Jump to error if not "BA" or "  " - generate "FF" error    
446BH  LHLD FD1DH           ; Get file size parameter from RX buffer      
446EH  MOV C,H              ; Swap endianness of file size   
446FH  MOV B,L              ; Swap LSB to MSB   
4470H  MOV H,B              ; Copy file size parameter back to HL   
4471H  MOV L,C              ; Copy LSB of file size to HL   
4472H  SHLD FCDDH           ; Store length of file       
4475H  CALL 44ABH           ; Call NEW statement, upon return HL=address of last variable assigned      
4478H  INX H                ; Increment to free memory space 
4479H  SHLD FCE2H           ; Save as address of file being loaded/saved/etc.      
447CH  LHLD FCDDH           ; Get disk file length      
447FH  PUSH H               ; Save file length on stack  
4480H  PUSH H               ; Push file length to stack to copy to BC  
4481H  POP B                ; Pop file length to BC 
4482H  CALL 411EH           ; Insert BC spaces at address of RAM file being loaded/run      
4485H  POP D                ; Get length of disk file from stack 
4486H  LHLD FBAEH           ; Load Start of DO files pointer    
4489H  DAD D                ; Increment Start of DO files pointer by disk file length    
448AH  SHLD FBAEH           ; Save updated Start of DO files pointer    
448DH  LHLD FAD8H           ; Load pointer to address used for RAM Input processing         
4490H  DAD D                ; Increment pointer by disk file length    
4491H  SHLD FAD8H           ; Save updated RAM Input processing pointer         
4494H  CALL 4AC4H           ; Restore original baud settings         
4497H  XRA A                ; Clear zero flag and A    
4498H  LXI H,23F5           ; Load address in Main ROM to configure and execute current BASIC programH         
449BH  PUSH H               ; Push return address to stack
449CH  JMP 00A6H            ; Return to Main ROM

; =========================================================================================
; Call "BASIC NEW" helper routine.  This get's copied to RAM below.
; =========================================================================================
449FH  XRA A                ; Prepare to switch to Main ROM
44A0H  OUT E0H              ; Switch to Main ROM
44A2H  CALL 20FFH           ; Call BASIC NEW statement
44A5H  CALL FAA4H           ; Switch back to OptROM
44A8H  JMP 4478H            ; Jump back into RST 7,1Ch Hook - RUN statement

; =========================================================================================
; Copy "BASIC NEW" helper routine to RAM and Jump to it --- Call Main ROM's NEW statement
; =========================================================================================
44ABH  LXI H,449FH          ; Point to helper function to copy to RAM
44AEH  LXI D,FD89H          ; RAM destination
44B1H  LXI B,000CH          ; Length of helper funciton
44B4H  CALL 4A05H           ; Copy helper to RAM
44B7H  JMP FD89H            ; Branch to helper function

; =========================================================================================
; Compare current BASIC program file extension with value in BC or "  "
; =========================================================================================
44BAH  PUSH PSW             ; Preserve A on Stack     
44BBH  PUSH H               ; Preserve HL on Stack   
44BCH  PUSH D               ; Preserve DE on Stack   
44BDH  PUSH B               ; Preserve comparison file extension on Stack   
44BEH  LHLD FC99H           ; Load 2 extension field bytes of current BASIC program name       
44C1H  LXI D,2020H          ; Load 2 spaces (0x20) into DE
44C4H  RST 3                ; Test if filename extension in current BASIC program is "  "            
44C5H  JZ 44D6H             ; Jump if current BASIC program filename extension is "  "     
44C8H  POP D                ; Get comparison file extension from stack into DE  
44C9H  PUSH D               ; Push file extension back to stack for storage   
44CAH  RST 3                ; Test if current BASIC program filename extension matches BC                    
44CBH  JZ 44D6H             ; Jump if current BASIC program filename extension matches BC     
44CEH  POP B                ; Get BC back off stack  
44CFH  POP D                ; Recover DE from stack  
44D0H  POP H                ; Recover HL from stack  
44D1H  POP PSW              ; Recover A & flags from stack    
44D2H  POP B                ; Pop return address - File extension doesn't match so don't run  
44D3H  JMP 00A6H            ; Return to Main ROM

; =========================================================================================
; Store expected extension (on stack) to current BASIC program and send dir reference for 
;    the disk file
; =========================================================================================
44D6H  POP H                ; Get expected file extension "BA" or "CO" from stack  
44D7H  SHLD FC99H           ; Save to 2 extension field bytes of current BASIC program name       
44DAH  POP D                ; Restore DE from stack  
44DBH  POP H                ; Restore HL from stack  
44DCH  POP PSW              ; Restore A from stack    
44DDH  XRA A                ; Flag to generate system errors vs. printing  
44DEH  CALL 4A85H           ; Save OS's baud rate string to storage area       
44E1H  LXI H,FC93H          ; Filename of current BASIC program            
44E4H  JMP 4A57H            ; Send Dir Reference for filename at (HL)      

; =========================================================================================
; RST 7,16h Hook - SAVE statement
; =========================================================================================
44E7H  POP PSW              ; POP return address, we will return manually
44E8H  CPI 09H              ; Test if we found "0:" or "1:" in the DSKI$ function    
44EAH  JNZ 00A6H            ; Return if not a TPDD file      
44EDH  LXI B,4142H          ; Load code for "BA" basic extension        
44F0H  CALL 44BAH           ; Compare extension in current BASIC program filename with value in BC            
44F3H  JNZ 487EH            ; File Exists Error      
44F6H  CALL 4C66H           ; Update line addresses for current BASIC program       
44F9H  LHLD F67CH           ; Start of BASIC program pointer            
44FCH  XCHG                 ; HL <--> DE  DE=BASIC program strt, HL=BASIC program end 
44FDH  RST 3                ; Compare DE and HL    
44FEH  JZ 450FH             ; Vector to BASIC ready - print Ok if BASIC start=BASIC end     
4501H  PUSH D               ; Save start of BASIC program to stack   
4502H  POP B                ; POP start of BASIC program from stack  
4503H  DSUB                 ; Subtract BASIC start address from BASIC end address 
4504H  MVI A,01H            ; Set file open mode for new file      
4506H  STA FCD6H            ; Save open mode to pass to function      
4509H  CALL 40C8H           ; Write HL bytes of data from (DE) to TPDD       
450CH  CALL 4AC4H           ; Restore original baud settings       
450FH  LXI H,0502H          ; Load address in Main ROM of Vector to BASIC ready - print Ok        
4512H  PUSH H               ; Push new return address to stack
4513H  JMP 00A6H            ; Return to Main ROM

; =========================================================================================
; Return to Main ROM's Generate FC Error routine
; =========================================================================================
4516H  LXI H,08DBH          ; Load address of Generate FC error routine
4519H  PUSH H               ; Push return address to the stack
451AH  JMP 00A6H            ; Return to Main ROM

; =========================================================================================
; RST 7,30h Hook - OPEN/CLOSE/READ/WRITE/LINE INPUT statement
; =========================================================================================
451DH  XRA A                ; Clear A to set print error flag                  
451EH  STA FCD2H            ; Set flag to generate system errors vs. print
4521H  POP PSW              ; POP return address ... returning manually
4522H  SHLD FCCEH           ; Save HL in Stack pointer upon entry location     
4525H  PUSH D               ; Preserve DE on stack     
4526H  PUSH H               ; Preserve HL on stack       
4527H  PUSH PSW             ; Preserve A on stack          
4528H  LXI D,0004H          ; Offset of the file descriptor address MSB    
452BH  DAD D                ; Point to the file descriptor address MSB      
452CH  MOV A,M              ; Get MSB address of FD      
452DH  CPI 09H              ; Test if we found "0:" or "1:" in the DSKI$ function       
452FH  JZ 4538H             ; Jump to process the sub-operation code if it's a TPDD file
				  
; =========================================================================================
; RST 7,30h Hook exit routine
; =========================================================================================
4532H  POP PSW              ; Restore A from stack          
4533H  POP H                ; Restore HL from stack        
4534H  POP D                ; Restore DE from stack        
4535H  JMP 00A6H            ; Return to Main ROM 

; =========================================================================================
; Test the RST 7,30h sub-operation code and vector to the proper handler function
; =========================================================================================
4538H  POP PSW              ; Retrieve A from the stack - contains sub-operation code   
4539H  PUSH PSW             ; Restore to stack    
453AH  CPI 00H              ; Test for OPEN sub-operation   
453CH  JZ 455CH       
453FH  CPI 02H              ; Test for CLOSE sub-operation   
4541H  JZ 45E8H       
4544H  CPI 04H              ; Test for PRINT # sub-operation   
4546H  JZ 46B0H       
4549H  CPI 06H              ; Test for EOF sub-operation   
454BH  JZ 4607H       
454EH  CPI 08H              ; Test for LINE INPUT sub-operation   
4550H  JNZ 4532H       
4553H  LDES 06H             ; Get stack location upon entry (we pushed 3 times = 6 bytes) in DE    
4555H  LXI H,161BH          ; Not an operation we care about, load address for "Special RAM IO" routine
4558H  SHLX                 ; Replace our return address so we return to "Special RAM IO" routine instead
4559H  JMP 4532H            ; Jump to RST 7,32h exit routine     

; =========================================================================================
; RST 7,30h OPEN sub-operation
; =========================================================================================
455CH  XRA A                ; Generate system errors vs. printing 
455DH  CALL 4A85H           ; Save OS's baud rate string to storage area      
4560H  LXI H,FC99H          ; Load address of 1st extension byte of current BASIC program filename       
4563H  MOV A,M              ; Get 1st byte of file extension from current BASIC program   
4564H  CPI 20H              ; Test if opening a file with no extension   
4566H  JZ 456EH             ; Branch to proivde "DO" default extension if non provided    
4569H  CPI 44H              ; Test if A is 'D' - opening a "DO" file   
456BH  JNZ 488DH            ; Generate system error 0x0C - ID Error     
456EH  MVI M,44H            ; Change 1st extension byte to 'D'     
4570H  INX H                ; Increment to 2nd extension byte 
4571H  MVI M,4FH            ; Change 2nd extension byte to 'O'     
4573H  LXI H,FC93H          ; Filename of current BASIC program       
4576H  CALL 4A57H           ; Send Dir Reference for filename at (HL)      
4579H  MOV C,A              ; Move attribute byte to C   
457AH  CALL 465BH           ; Calculate offset of BASIC instruction file # EOF marker      
457DH  MVI M,00H            ; Set EOF marker to zero - not EOF     
457FH  POP H                ; POP PSW and discard 
4580H  POP H                ; Restore address of FD control 
4581H  POP D                ; Restore DE 
4582H  PUSH D               ; Save DE back to stack  
4583H  PUSH H               ; Save FD control address back to stack  
4584H  MOV D,C              ; Save TPDD file attribute byte to D               
4585H  MOV A,E              ; Move open mode to A (8=Append,1=Read,2=Write)   
4586H  ANI 07H              ; Mask all but lower 3 bits so we get 0, 1, or 2   
4588H  LXI H,4AE4H          ; Get address of RST 7,32h open mode to TPDD Open mode mapping       
458BH  MOV C,A              ; Save mapping mode table offset to C   
458CH  MVI B,00H            ; Clear MSB of offset for 16-bit add     
458EH  DAD B                ; Calculate index address into mapping table        
458FH  MOV A,M              ; Load TPDD open mode from mapping   
4590H  DCR A                ; Test if TPDD open mode is Write     
4591H  JZ 45CDH             ; Jump if opening for write mode        
4594H  DCR A                ; Test if TPDD open mode is Append     
4595H  JNZ 45E0H            ; Jump to open TPDD for Read mode if not zero         
4598H  LDA FD1CH            ; Load attribute byte from RX buffer         
459BH  ANA A                ; Opening for Append, test if file already exists     
459CH  JNZ 45A1H            ; Jump to perform open for append if file already exists         
459FH  INX H                ; Opening for append but file doesn't exist, increment mapping to Write     
45A0H  INX H                ; Increment again to skip "read" mapping in table     

; =========================================================================================
; Open TPDD file with open mode as specified by RST 7,32h mapping table
; =========================================================================================
45A1H  MOV A,M              ; Reload the TPDD open mode from the mapping table     
45A2H  STA FCE8H            ; Point to TX buffer data area (payload)       
45A5H  LXI H,0101H          ; Load TPDD_OPEN opcode in HL         
45A8H  CALL 409BH           ; Send Request in HL and await response        
45ABH  LHLD FCCEH           ; Get address of FD control        
45AEH  LXI D,0007H          ; Load offset of write buffer length within FD control         
45B1H  DAD D                ; Point to write buffer length within FD control   
45B2H  XRA A                ; Clear A   
45B3H  MOV M,A              ; Set the write buffer length to zero - just opened the file     
45B4H  INX H                ; Increment to write buffer output pointer address   
45B5H  MOV D,H              ; Save HL to DE to update write buffer output pointer     
45B6H  MOV E,L              ; Save LSB of HL to DE     
45B7H  INX H                ; Increment to MSB of write buffer output pointer   
45B8H  INX H                ; Increment to write buffer location   
45B9H  SHLX                 ; Reset write buffer output poiner to beginning of buffer  
45BAH  POP H                ; Restore address of FD control   
45BBH  POP D                ; Restore DE from stack   
45BCH  MOV A,E              ; Load RST 7,32h open mode into A     
45BDH  CPI 08H              ; Test if open mode is Append     
45BFH  JNZ 45C4H            ; Jump to retain open mode if not append       
45C2H  MVI E,02H            ; Change Append open mode value to "Write"       
45C4H  MOV M,E              ; Save open status to FD control     
45C5H  XTHL                 ; HL <--> (SP)  Prepare to change our return address, saving HL  
45C6H  LXI H,14DEH          ; Load new return address in ROM "LCD and PRT file open" routine         
45C9H  XTHL                 ; Put return address back to stack, restoring HL           
45CAH  JMP 00A6H            ; Return to the new address in LCD and PRT file open routine in Main ROM

; =========================================================================================
; RST 7,30h open file for write mode.  The Attribute byte from the Dir Ref opcode is in D
; =========================================================================================
45CDH  MOV A,D              ; Get the File attribute byte from the Dir Reference operation    
45CEH  ORA A                ; Test if the file exists (will be 'F' if the file exists)  
45CFH  JZ 45A1H             ; Jump to create the file if it doesn't already exist     
45D2H  PUSH H               ; Save HL to the stack for restoration   
45D3H  CALL 431AH           ; Issue TPDD Delete file Opcode - Overwriting existing file       
45D6H  LXI H,FC93H          ; Filename of current BASIC program    
45D9H  CALL 4A57H           ; Send Dir Reference for filename at (HL) - Need new Dir Ref       
45DCH  POP H                ; Restore HL from stack  
45DDH  JMP 45A1H            ; Open TPDD file with open mode as specified by RST 7,32h mapping table      

; =========================================================================================
; RST 7,30h open file for read mode.  Ensure the file exists via the attribute byte in D
; =========================================================================================
45E0H  MOV A,D              ; Load the file attribute byte from the Dir Ref opcode  
45E1H  ORA A                ; Test if attribute byte is zero
45E2H  JZ 487BH             ; Generate "FF" error if file doesn't exist 
45E5H  JMP 45A1H            ; Jump to open the file

; =========================================================================================
; RST 7,30h Sub command - CLOSE FILE
; =========================================================================================
45E8H  POP PSW              ; Retrieve A PUSHed by RST 7,32a entry    
45E9H  POP H                ; Retrieve HL  
45EAH  POP D                ; Retrieve DE  
45EBH  PUSH H               ; Save FD control pointer to stack   
45ECH  MOV A,M              ; Get FD control status byte    
45EDH  MVI M,00H            ; Change FD control status to "closed"      
45EFH  CPI 02H              ; Test if status     
45F1H  CZ 46DDH             ; Call flush output buffer routine if opened for write mode     
45F4H  LXI H,0002H          ; Load TPDD_CLOSE opcode into HL        
45F7H  CALL 409BH           ; Send Request in HL and await response       
45FAH  CALL 4AC4H           ; Restore original baud settings       
45FDH  POP H                ; Restore FD control pointer  
45FEH  XTHL                 ; HL <--> (SP) so we can preserve HL through POP         
45FFH  POP H                ; Pop return address (actually FD control address) from stack  
4600H  LXI H,4D59H          ; Load new reuturn address - LCD, CRT, and LPT file close routine        
4603H  PUSH H               ; Push new return address to stack - not returning to caller   
4604H  JMP 00A6H            ; Return to Main ROM

; =========================================================================================
; RST 7,30h Sub command - EOF
; =========================================================================================
4607H  CALL 465BH           ; Calculate offset of BASIC instruction file # EOF marker        
460AH  MOV A,M              ; Get the current EOF marker     
460BH  MVI M,00H            ; Set the EOF marker to zero to reset it       
460DH  ANA A                ; Test if at EOF for this file   
460EH  JNZ 4627H            ; Jump if EOF marker for this file not zero       
4611H  LHLD FCCEH           ; Get address of FD control        
4614H  LXI B,0007H          ; Offset of write buffer length within FD control         
4617H  DAD B                ; Point to write buffer length   
4618H  MOV A,M              ; Get current write buffer length     
4619H  INX H                ; Point to LSB of read/write buffer output pointer within FD control   
461AH  PUSH H               ; Save address of read/write buffer output pointer to stack    
461BH  ANA A                ; Test if data left in the buffer   
461CH  CZ 4663H             ; Call to read more data from TPDD if buffer empty      
461FH  POP D                ; Restore address of read/write output buffer within FD control   
4620H  LHLX                 ; Get current read/write pointer location from FD control  
4621H  MOV A,M              ; Read the next byte from the buffer     
4622H  INX H                ; Increment buffer pointer to the next byte   
4623H  SHLX                 ; Save read/write buffer pointer back to FD control  
4624H  DCX D                ; Decrement back to read/write buffer length within FD control   
4625H  XCHG                 ; HL <--> DE  Prepare to update buffer length  
4626H  DCR M	            ; Decrement length since we just read a byte
      
; =========================================================================================
; Test if EOF for BASIC file #
; =========================================================================================
4627H  CPI 1AH              ; Test if byte is EOF marker      
4629H  STC                  ; Ensure the Carry flag is set  
462AH  CMC                  ; And now clear it to indicate not EOF  
462BH  JNZ 4633H            ; Jump if not at end of file        
462EH  CALL 465BH           ; Calculate offset of BASIC instruction file # EOF marker         
4631H  MOV M,A              ; Save EOF marker for this file #      
4632H  STC                  ; Set Carry to indicate EOF  

; =========================================================================================
; Save EOF status
; =========================================================================================
4633H  PUSH PSW             ; Save EOF indication in Carry flag and marker value to stack      
4634H  LDES 10H             ; Load offset to our return address (we PUSHed a bunch to the stack)      
4636H  LHLX                 ; Load HL with our return address from the stack  
4637H  LXI B,189AH          ; Load address of return within EOF function         
463AH  DSUB                 ; Test if we were called from the EOF function  
463BH  JNZ 464FH            ; Jump if not called from ROM EOF function - don't to EOF logical testing       
463EH  CALL 465BH           ; Calculate offset of BASIC instruction file # EOF marker        
4641H  POP PSW              ; Retreive EOF and marker value from stack     
4642H  MOV M,A              ; Save the marker value to the file # marker storage location     
4643H  MOV C,A              ; Save marker value in C     
4644H  SBB A                ; Subtract with borrow (C was set if EOF)   
4645H  CALL 4BCBH           ; Call into SGN function to set FAC1 with sign of A (EOF test)        
4648H  LDES 12H             ; Prepare to "POP" 6 register pairs from the stack all at once      
464AH  XCHG                 ; HL <--> DE  HL now has new stack value  
464BH  SPHL                 ; HL <--> SP  "POP" 6 values from the stack           
464CH  JMP 00A6H            ; Return to Main ROM

; =========================================================================================
; Non-EOF function call return
; =========================================================================================
464FH  POP PSW              ; Restore PSW with EOF indication (C flag)   
4650H  POP H                ; Pop old PSW - we don't want it 
4651H  POP H                ; Resore HL from stack 
4652H  POP D                ; Restore DE from stack 
4653H  XTHL                 ; Push HL to stack to set new return address       
4654H  LXI H,4E8AH          ; Load address of a "Stack frame retrun" routine
4657H  XTHL                 ; Stack gets new return address, restore HL
4658H  JMP 00A6H            ; Return to the new address (not returning to parent)     

; =========================================================================================
; Calculate offset of BASIC instruction file # EOF marker
; =========================================================================================
465BH  LHLD FAA2H           ; Get file # of active BASIC instruction (EOF, LINE INPUT, etc.) 
465EH  LXI D,FA91H          ; Load base address of file status array 
4661H  DAD D                ; Add offset to base of file status byte array
4662H  RET

; =========================================================================================
; RST 7,30A Read data from server (TPDD) into FD file buffer
; =========================================================================================
4663H  LXI H,0003H          ; Load TPDD_READ opcode in HL         
4666H  CALL 4822H           ; Send TPDD Command/Len in HL        
4669H  CALL 47CCH           ; Receive a packet        
466CH  LDA FD02H            ; Get response byte from storage for RX packet       
466FH  CPI 10H              ; Test for valid read file response     
4671H  JNZ 469EH            ; Branch if not valid read from file response       
4674H  LDA FD03H            ; Get length of read from RX buffer       
4677H  LHLD FCCEH           ; Get pointer to FD control        
467AH  LXI D,0008H          ; Offset of address of read/write buffer relative to FD control         
467DH  DAD D                ; Point to address of read/write buffer within FD control            
467EH  PUSH H               ; Save address of read/write buffer to stack    
467FH  MOV D,H              ; Move address of read/write buffer to DE for update     
4680H  MOV E,L              ; Move LSB     
4681H  INX H                ; Increment to MSB of read/write buffer address in FD control   
4682H  INX H                ; Increment to read/write buffer   
4683H  SHLX                 ; Reset pointer to read/write buffer - we just read more data  
4684H  LXI D,FD04H          ; DE points to the RX data in the buffer         
4687H  XCHG                 ; HL <--> DE  Prepare to move data from RX buffer to FD buffer  
4688H  MOV C,A              ; Move the RX data length to C     
4689H  MVI B,00H            ; Clear MSB of BC count       
468BH  CALL 4A05H           ; Move BC bytes from M to (DE) with increment - copy to FD buffer        
468EH  LDA FD03H            ; Get length of RX read data again       
4691H  CPI 80H              ; Test for maximum read length     
4693H  JZ 469AH             ; If maximum read, skip writing EOF marker to read/write buffer      
4696H  XCHG                 ; HL = destination address in FD buffer  
4697H  MVI M,1AH            ; Terminate .DO file in FD read/write buffer with EOF marker       
4699H  INR A                ; Increment length to reflect EOF marker 
  
; =========================================================================================
; RST 7,32A Read - not max read size
; =========================================================================================
469AH  POP H                ; Get address of read/write buffer in FD control from stack       
469BH  DCX H                ; Decrement to FD control read/write buffer length location       
469CH  MOV M,A              ; Save length of data in read/write buffer to FD control                  
469DH  RET         

; =========================================================================================
; RST 7,32A Read - unsuccessful TPDD read
; =========================================================================================
469EH  LHLD FCCEH           ; Get address of FD control      
46A1H  LXI D,0007H          ; Load offset of output buffer count in FD control       
46A4H  DAD D                ; Point to output buffer length in FD control 
46A5H  MVI M,01H            ; Set read/write buffer length to 1 to indicate EOF marker     
46A7H  INX H                ; Increment to LSB of read/write buffer output address in FD control 
46A8H  MOV D,H              ; Save HL in DE for update of read/write buffer output in FD control   
46A9H  MOV E,L              ; Save LSB of HL to DE   
46AAH  INX H                ; Increment to MSB of read/write buffer in FD control 
46ABH  INX H                ; Increment to the FD read/write buffer 
46ACH  SHLX                 ; Reset the FD control read/write buffer pointer to begining of buffer
46ADH  MVI M,1AH            ; Write an EOF marker to the buffer
46AFH  RET

; =========================================================================================
; RST 7,32h PRINT # sub-operation
; =========================================================================================
46B0H  LHLD FCCEH           ; Pointer to FD control       
46B3H  LXI D,0007H          ; ?Offset to output byte count        
46B6H  DAD D                ; Get pointer to file's output byte count  
46B7H  MOV A,M              ; Load byte count of pending bytes to write    
46B8H  CPI 80H              ; Test if 128 bytes to write    
46BAH  CZ 46DDH             ; Call routine to flush output buffer to file     
46BDH  POP PSW              ; Restore A from stack (from RST 7,32h entry)    
46BEH  POP H                ; Restore HL from stack  
46BFH  POP D                ; Restore DE from stack  
46C0H  POP H                ; Pop the return address - we will return via JMP  
46C1H  POP PSW              ; Get the caller's A so we know what byte is being written    
46C2H  PUSH PSW             ; Put it back on the stack...it isn't ours     
46C3H  CPI 1AH              ; Test if writing an EOF marker to the file    
46C5H  JZ 46D6H             ; Jump if writing EOF marder to the file - don't actually write it     
46C8H  LHLD FCCEH           ; Get address of FD control       
46CBH  LXI D,0007H          ; Get offset of output buffer length within FD control        
46CEH  DAD D                ; Point to output buffer length address  
46CFH  INR M                ; Increment the output buffer length - writing 1 byte  
46D0H  INX H                ; Point to current file location pointer in FD control  
46D1H  XCHG                 ; HL <--> DE  Move address of file location pointer to DE 
46D2H  LHLX                 ; Load current file location address to HL 
46D3H  MOV M,A              ; Save the byte in the buffer (RX buffer for subsequent write)    
46D4H  INX H                ; Increment the curent file location pointer (we will flush later)  
46D5H  SHLX                 ; Save the update current file location pointer to FD control         
46D6H  LXI H,14EAH          ; Load address to update automatic timer and POP regs from the stack        
46D9H  PUSH H               ; Push new return address.  We will return to the parent's caller   
46DAH  JMP 00A6H            ; Return to Main ROM      

Navigate to: