M100 TS-DOS ROM RST 7 Handlers

From Bitchin100 DocGarden
Jump to: navigation, search

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: