M100 TS-DOS ROM RST 7 Handlers: Difference between revisions

From Bitchin100 DocGarden
Jump to navigationJump to search
(use dynamic page list to generate nav)
(icuEhlHjnrzOdNG)
Line 1: Line 1:
== TS-DOS Model 100/102 ROM RST 7 Handlers ==
Great aritcle, thank you again for writing.
 
This is the code for the DOS-ON RST 7 Hooks, along with the TPDD1 Rename functionality.
 
<pre>
; =========================================================================================
; 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     
</pre>
 
Navigate to:
 
<DPL>
category=M100 TS-DOS ROM Disassembly
</DPL>
 
[[Category:M100 TS-DOS ROM Disassembly]]

Revision as of 16:02, 6 July 2011

Great aritcle, thank you again for writing.