M100 TS-DOS ROM TPDD Protocol
From Bitchin100 DocGarden
Jump to navigationJump to search
TS-DOS Model 100/102 ROM TPDD Protocol routines
; ========================================================================================= ; Flush the RX output buffer to the TPDD file ; ========================================================================================= 46DDH LHLD FCCEH ; Get address of FD control 46E0H LXI B,0007H ; Load offset of write buffer length 46E3H DAD B ; Calculate address of write buffer length within FD control 46E4H MOV A,M ; Load the write buffer length 46E5H PUSH H ; Save pointer to write buffer length in FD control on stack 46E6H INX H ; Skip the LSB of the write buffer pointer 46E7H INX H ; Skip the MSB of the write buffer pointer 46E8H INX H ; Point to the actual data in the file write buffer 46E9H LXI D,FD04H ; DE points to the data area in RX buffer 46ECH MOV C,A ; Load buffer length into BC 46EDH MVI B,00H ; Make MSB of BC zero 46EFH PUSH PSW ; Save write buffer length to stack 46F0H CALL 4A05H ; Move BC bytes from M to (DE) with increment 46F3H POP PSW ; Retrieve write buffer length from stack 46F4H ANA A ; Test if write buffer is empty 46F5H CNZ 4095H ; Send TPDD Write File opcode using RX buffer with length in A if not empty 46F8H POP H ; Retrieve pointer to write buffer length in FD control from stack 46F9H MVI M,00H ; Set length of write buffer to zero - it is flushed 46FBH INX H ; Increment to address in FD control of write buffer 46FCH MOV D,H ; Save HL to DE for storage of new buffer pointer address 46FDH MOV E,L ; Save MSB of HL to DE 46FEH INX H ; Increment to MSB of address in FD conrol of write buffer 46FFH INX H ; Increment to actual write buffer address 4700H SHLX ; Save new write buffer pointer to FD control 4701H RET ; ========================================================================================= ; Appears to be unused code ; ========================================================================================= 4702H POP PSW 4703H RET ; ========================================================================================= ; Display or print all disk files and free space ; ========================================================================================= 4704H LXI H,F685H ; Keyboard buffer 4707H SHLD FCDBH ; Initialize pointer to File Length table 470AH CALL 4735H ; Clear #files displayed, init TPDD and send 1st file dir referene opode 470DH JNZ 486AH ; Communication Error 4710H XRA A ; Prepare to initialize "skip page" count to zero 4711H STA FCDAH ; Load the "skip page" count 4714H STA FCD4H ; Current Page of files being displayed 4717H DCR A ; Set A to 0xFF 4718H STA FCD7H ; Save as Page size to print (print 255 files per page) 471BH MVI A,01H ; 471DH STA F63AH ; ??? 4720H CALL 4747H ; Get next page of files from server (NADSBox) with page size = 255 4723H JMP 4C23H ; Send CRLF to screen or printer ; ========================================================================================= ; Display Disk free space on LCD at current position ; NOT CALLED! ; Old function - reporting of Free space was merged into the printing of the function ; key display routine. ; ========================================================================================= 4726H CALL 4A10H ; Multiply TPDD free sectors len x 128 = free space 4729H CALL 4C3EH ; Print binary number in HL at current position 472CH LXI H,4AD1H ; Point to "0 Bytes free" text 472FH CALL 4A2CH ; Send buffer at M to screen 4732H JMP 4C23H ; Send CRLF to screen or printer ; ========================================================================================= ; Clear #files displayed, init TPDD and send 1st file dir referene opode ; ========================================================================================= 4735H XRA A ; Indicate zero files being displayed 4736H STA FCD6H ; Count of files on screen 4739H CALL 4943H ; Configure baud, test for NADSBox, get NADSBox dir 473CH LXI H,0146H ; Load code for "F" attribute and First File dir reference 473FH JMP 476FH ; Send Directory Reference opcode with HL=access mode ; ========================================================================================= ; Get next page of files from server (NADSBox / TPDD) ; ========================================================================================= 4742H MVI A,14H ; Maximum files that will fit on the display 4744H STA FCD7H ; Save for comparison of file count 4747H LDA FCCBH ; NADSBox / Desklink / TPDD2 flag 474AH ANA A ; Test if TPDD 474BH JNZ 4757H ; Skip 1st invocation of "Next file" if NADSBox or TPDD2?? 474EH LXI H,02F6H ; Load access mode code for "Next entry" dir reference 4751H CALL 476FH ; Send Directory Reference opcode with HL=access mode 4754H JNZ 47F8H ; Check RX packet for Noraml Response & report errors 4757H LDA FD04H ; 1st filename byte 475AH ANA A ; Test if 1st filename byte is zero 475BH RZ ; Return if last file retrieved 475CH LDA FCDAH ; Load the "skip page" count 475FH ANA A ; Test if this is a "skip page" 4760H CZ 4781H ; Call routine to display file if not a skip page 4763H LXI H,FCD6H ; Count of files on screen 4766H INR M ; Increment #files displayed on LCD 4767H LDA FCD7H ; Load count of max files that will fit on LCD 476AH CMP M ; Compare with current file count 476BH JNZ 474EH ; Jump back to get next file from TPDD if not full 476EH RET ; ========================================================================================= ; Send Directory Reference opcode with HL=access mode ; ========================================================================================= 476FH SHLD FD00H ; Save file attrib and reference mode to TX buffer 4772H LXI H,1A00H ; Load code and length for Directory Reference opcode 4775H CALL 4822H ; Send TPDD Command/Len in HL 4778H CALL 47CCH ; Receive a packet 477BH LDA FD02H ; Storage for RX packet - response byte 477EH CPI 11H ; Test if response was 0x11 (valid Dir Ref response) 4780H RET ; ========================================================================================= ; Print filename in RX buffer to LCD and save length info ; ========================================================================================= 4781H MVI C,09H ; Prepare to draw 9 bytes of filename to LCD 4783H LXI H,FD04H ; Location of filename in RX packet 4786H CALL 48E5H ; Redraw C characters from buffer at HL using current video mode 4789H MVI A,20H ; Prepare to draw a trailing space 478BH RST 4 ; Send char in A to LCD 478CH LHLD FD1DH ; Get file size parameter from RX buffer 478FH MOV E,H ; Save file size LSB in E 4790H MOV D,L ; Save file size MSB in D ; ========================================================================================= ; Store next file length to keyboard buffer ; ========================================================================================= 4791H LHLD FCDBH ; Next storage location for file size info 4794H XCHG ; HL <--> DE 4795H SHLX ; Store file length at address of next file save 4796H XCHG ; HL <--> DE 4797H INX H ; Increment storage address of next file length 4798H INX H ; Increment again (2 byte length) 4799H SHLD FCDBH ; Save new address for lenght storage for next file 479CH RET ; ========================================================================================= ; Receive an RX packet. This routine gets copied into RAM and executed from there while ; the Main ROM is selected. This allows the RX packet to be recieved without ; switching to and from the Main ROM to receive each individual byte. The jump ; addresses represent the RAM execution locations. ; ========================================================================================= 479DH LXI H,FD02H ; Storage for RX packet 47A0H PUSH H ; Save start of packet address on stack 47A1H CALL FDB2H ; Get next byte from RX into HL 47A4H CALL FDB2H ; Get next byte from RX into HL 47A7H MOV C,A ; Move length byte into C 47A8H CALL FDB2H ; Get next byte from RX into HL 47ABH MOV B,C ; Move length byte to B 47ACH MOV A,C ; Move length byte to A for zero test 47ADH ANA A ; Test if length is zero 47AEH JZ FDA4H ; Skip reading payload if zero length 47B1H CALL FDB2H ; Get next byte from RX into HL 47B4H DCR C ; Decrement length byte 47B5H JNZ FD9DH ; Keep looping until all data received 47B8H POP H ; Restore start of RX packet address 47B9H INR B ; Add opcode byte to length for checksum 47BAH INR B ; Add length byte to length for checksum 47BBH XRA A ; Clear A for checksum calculation 47BCH SIM ; ?Clear Interrupts 47BDH ADD M ; Add next byte to checksum 47BEH INX H ; Increment RX data pointer 47BFH DCR B ; Decrement length counter 47C0H JNZ FDA9H ; Keep looping until all bytes added 47C3H CMA ; Compliment the checksum 47C4H CMP M ; Compare with received checksum 47C5H RET ; Branch if no match - Communication Error ; ========================================================================================= ; Get next RX byte and store at HL, test for drive ready & print errors ; This routine (and the one above) get copied into RAM and then executed ; when the Main ROM is selected, so a direct call to the Main ROM address ; is allowed. ; ========================================================================================= 47C6H CALL 6D7EH ; Get a character from RS232 receive queue 47C9H MOV M,A ; Save byte at HL 47CAH INX H ; Increment HL 47CBH RET ; ========================================================================================= ; Copy the 2 Receive RX Packet routines above to RAM and execute ; ========================================================================================= 47CCH LXI H,479DH ; Point to Receive RX Packet routine 47CFH LXI D,FD89H ; Point to target destination in RAM 47D2H LXI B,002FH ; Length of the routine 47D5H CALL 4A05H ; Move BC bytes from M to (DE) with increment 47D8H CALL 4862H ; Test if DSR is set - drive ready, error otherwise 47DBH CALL 4BDBH ; Call Main ROM's Set interrupt to 1DH routine. 47DEH RST 1 ; Switch to Main ROM and execute "Receive RX Pakcet" routine 47DFH DW FD89H ; Address of our RX routine we just copied to RAM 47E1H JNZ 486AH ; Communication Error if no /DSR 47E4H RET ; ========================================================================================= ; Get next RX byte and store at HL, test for drive ready & print errors ; ========================================================================================= 47E5H CALL 47EBH ; Test drive and get byte from RX 47E8H MOV M,A ; Save byte at HL 47E9H INX H ; Increment HL 47EAH RET ; ========================================================================================= ; Test drive ready and get byte from RX, Report error if not ready ; ========================================================================================= 47EBH CALL 4862H ; Test if DSR is set - Drive Ready 47EEH CALL 4BE7H ; Get a character from RS232 receive queue 47F1H JC 488DH ; Empty Error Text 47F4H JNZ 486AH ; Communication Error 47F7H RET ; ========================================================================================= ; Check RX packet for Normal Response & report errors ; ========================================================================================= 47F8H LDA FD02H ; Storage for RX packet 47FBH CPI 12H ; Test for normal return code 47FDH JNZ 486AH ; Communication Error 4800H LDA FD04H ; Location of error code in RX packet 4803H ANA A ; Test if error code is zero 4804H RZ ; Return if no error 4805H CPI 10H 4807H JZ 487EH ; File Exists Error 480AH CPI 50H 480CH JZ 486DH ; Write Protect Error 480FH CPI 60H 4811H JZ 4881H ; Disk Full Error 4814H JC 486AH ; Communication Error 4817H JZ 4873H ; Disk not in drive error 481AH CPI 80H 481CH JC 4873H ; Disk not in drive error 481FH JMP 4870H ; Drive Trouble Error ; ========================================================================================= ; Send TPDD Command/Len in HL, H=len, L=Cmd. 0XED8A already has data ; ========================================================================================= 4822H SHLD FCE6H ; Store TDD CMD/Len passed in HL 4825H LXI H,FCE6H ; Point to Command/Len storage location 4828H PUSH H ; Save Cmd/Len storage address to stack 4829H LDA FCCAH ; TPDD Bank Numbere 482CH ANA A ; Test if reading from side zero 482DH JZ 4837H ; Skip ahead if reading from side zero 4830H ANI 01H ; Mask off all but LSB (only side 1 allowed) 4832H RAR ; Move the "1" to C 4833H RAR ; Move the "1" to bit 7 4834H RAR ; Move the "1" to bit 6 (could just do MVI 0x40 !!) 4835H ORA M ; OR the 0x40 with Cmd to access Disk Bank 1 4836H MOV M,A ; Save the updated cmd value back at (HL) 4837H MOV A,M ; Get the command value / modified value 4838H INX H ; Point to length parameter passed in 4839H ADD M ; Add the length parameter (checksum) 483AH MOV B,A ; Store checksum in B 483BH MOV A,M ; Get the Length parameter 483CH PUSH PSW ; Save length on stack 483DH INX H ; Point to data (already loaded before invocation) 483EH ANA A ; Test if length is zero 483FH JZ 484BH ; Skip data checksum if length zero 4842H MOV C,A ; Save current count 4843H MOV A,B ; Get running checksum value 4844H ADD M ; Add this byte to checksum 4845H INX H ; Point to next data byte 4846H DCR C ; Decrement count 4847H JNZ 4844H ; Keep looping until count is zero 484AH MOV B,A ; Save updated checksum in B 484BH MOV A,B ; Get Checksum from B 484CH CMA ; Compliment the checksum (protocol thing) 484DH MOV D,A ; Save complimented checksum in D 484EH LXI B,5A5AH ; Load "ZZ" header signature into BC 4851H CALL 49DBH ; Send BC to the serial port using XON/XOFF 4854H POP B ; Get the length from stack into BC 4855H MOV C,B ; Move the length into C 4856H MVI B,00H ; Clear upper MSB of count 4858H INX B ; Add Opcode byte to the TX length 4859H INX B ; Add length byte to the TX length 485AH POP H ; Get address of TX packet from stack 485BH CALL 48D9H ; Send BC bytes to RS-232 from (HL) using XON/XOFF 485EH MOV A,D ; Get checksum byte for TX ; ========================================================================================= ; Send A to RS-232 using XON/XOFF and check DSR when done ; ========================================================================================= 485FH CALL 4BE3H ; Call Main ROM's Send A to RS-232 using XON/XOFF routine ; ========================================================================================= ; Test if DSR is set - drive ready, error otherwise ; ========================================================================================= 4862H IN BBH ; Get I/O port with /DSR bit 4864H ANI 20H ; Mask all but the /DSR bit 4866H RZ ; Return if /DSR is asserted (low = asserted) ; ========================================================================================= ; Error jump table. Loads A with error number and prints ; ========================================================================================= 4867H (3EH) MVI A,01H DB 0x21 ; Filler - looks like "LXI H,XXXX" 486AH MVI A,02H ; Communication Error DB 0x21 486DH MVI A,03H ; Write Protect Error DB 0x21 4870H MVI A,04H ; Drive Trouble Error DB 0x21 4873H MVI A,05H ; Disk not in drive Error ; ========================================================================================= ; For any of the errors above, change the RAM/Disk mode back to RAM ; ========================================================================================= 4875H LXI H,FCD9H ; RAM / Disk mode (0=RAM, 1=DISK) 4878H MVI M,00H ; Go back to RAM mode DB 0x21 ; Filler - looks like "LXI H,XXXX" 487BH MVI A,06H ; Printer Not Ready Error DB 0x21 487EH MVI A,07H ; File Exists Error DB 0x21 4881H MVI A,08H ; Disk Full Error DB 0x21 4884H MVI A,09H ; File Empty Error DB 0x21 4887H MVI A,0AH ; Directory Full Error DB 0x21 488AH MVI A,0BH ; Ram Full Error DB 0x21 488DH MVI A,0CH ; ID Error (No text...runtime error only) DB 0x21 4890H MVI A,0DH ; Bad File Name Error ; ========================================================================================= ; Generate the error loaded in A above ; ========================================================================================= 4892H LXI H,4B02H ; Pointer to error string table 4895H MOV C,A ; Save error number for loop counting 4896H DCR C ; Decrement error counter to test if string found 4897H JZ 48A4H ; String found in table 489AH MOV A,M ; Get next byte of error string 489BH INX H ; Inrcrement pointer 489CH CPI 00H ; Test if end of string 489EH JNZ 489AH ; Loop until end of string found 48A1H JMP 4896H ; Branch back to decrement string counter ; ========================================================================================= ; Print error string at HL from error table ; ========================================================================================= 48A4H LDA FCD2H ; Get the "Print error messages" flag 48A7H ANA A ; Test if printing allowed 48A8H JZ 48D0H ; Jump to generate system error if not allowed to print 48ABH MVI A,07H ; Print BELL to cause a beep 48ADH RST 4 ; Send A to the LCD 48AEH INX H ; Skip the error code 48AFH CALL 48F4H ; Print string at HL to col 1 on the bottom line 48B2H CALL 48C7H ; Display "Press any key" and wait for key ; ========================================================================================= ; Perform Long jump ; ========================================================================================= 48B5H LHLD FCCEH ; Stack pointer upon entry 48B8H SPHL ; Restore stack frame 48B9H LHLD FCD0H ; Get return vector after error 48BCH PUSH H ; Prepare to return to return vector 48BDH RET ; ========================================================================================= ; Draw "Press any key" text with pre&post CR and wait for key press ; ========================================================================================= 48BEH CALL 4C23H ; Send CRLF to screen or printer 48C1H CALL 48C7H ; Display "Press any key" and wait for key 48C4H JMP 4C23H ; Send CRLF to screen or printer ; ========================================================================================= ; Draw "Press any key" text and wait for key press ; ========================================================================================= 48C7H LXI H,4BBBH ; Point to "Press any key" text 48CAH CALL 4A2CH ; Send buffer at M to screen 48CDH JMP 4BEBH ; Wait for key from keyboard ; ========================================================================================= ; Generate system error from code saved at (HL). This is called in liu of printing when ; the print/generate system error flag is set. The 1st byte of each error entry ; contains the system error number to generate. ; ========================================================================================= 48D0H MOV E,M ; Get the error code 48D1H LHLD FCCEH ; Stack pointer upon entry 48D4H MVI M,00H ; Indicate all arguments (none) processed 48D6H JMP 4C37H ; Generate error in E ; ========================================================================================= ; Send BC bytes to RS-232 from (HL) using XON/XOFF ; ========================================================================================= 48D9H MOV A,M ; Get next byte from (HL) 48DAH CALL 485FH ; Send A to RS-232 using XON/XOFF 48DDH INX H ; Increment poiner 48DEH DCX B ; Decrement byte count 48DFH MOV A,C ; Get C for zero comparison 48E0H ORA B ; Or in MSB of count 48E1H JNZ 48D9H ; Jump to send next byte if not zero 48E4H RET ; ========================================================================================= ; Draw C characters to LCD from buffer at HL using current video mode ; ========================================================================================= 48E5H MOV A,M ; Get next byte from LCD buffer 48E6H CPI 20H ; Test if it is a space 48E8H JNC 48EDH ; Test if it's less than space, jump if not to redraw 48EBH MVI A,20H ; Draw a space for "illegal" values 48EDH RST 4 ; Draw byte with current regular/inverse video mode 48EEH INX H ; Increment to next byte in LCD buffer 48EFH DCR C ; Decrement the loop counter 48F0H JNZ 48E5H ; Branch if not done to process next character 48F3H RET ; Done ; ========================================================================================= ; Print string at HL to col 1 on the bottom line ; ========================================================================================= 48F4H PUSH H ; Save pointer to error text on stack 48F5H LXI H,0108H ; Position cursor on col 1 of row 16 48F8H SHLD F639H ; Cursor row (1-8) 48FBH CALL 4C2BH ; Erase from cursor to end of line 48FEH POP H ; Restore pointer to error text from stack 48FFH JMP 4A2CH ; Send buffer at M to screen ; ========================================================================================= ; Copy filename at (HL) to current BASIC program ; ========================================================================================= 4902H PUSH H ; Save pointer to filename on stack 4903H MVI A,20H ; Load A with code for SPACE 4905H LXI H,FC93H ; Filename of current BASIC program 4908H MVI B,08H ; Prepare to fill current BASIC program with 8 spaces 490AH CALL 4A34H ; Fill (HL) with B bytes of A 490DH POP H ; Retrieve filename pointer from stack 490EH LXI D,FC93H ; Filename of current BASIC program 4911H MVI B,06H ; Prepare to copy 6 bytes of filename before ext 4913H MOV A,M ; Get next byte of filename from source 4914H CPI 41H ; Compare byte with 'A' to test validity 4916H JC 4890H ; Bad Filename Error if invalid char 4919H MOV A,M ; Get next byte again 491AH CPI 2EH ; Compare with '.' 491CH JZ 492BH ; Branch if '.' to fill remaining with ' ' 491FH ORA A ; Test for zero (NULL term) 4920H RZ ; Return if done copying filename (NULL term) 4921H STAX D ; Store next filename byte at (DE) 4922H INX H ; Increment source pointer 4923H INX D ; Increment dest pointer 4924H DCR B ; Decrement counter 4925H JNZ 4919H ; Keep looping until all bytes copied 4928H JMP 4933H ; Jump to copy 2 extension bytes ; ========================================================================================= ; Fill remainder of filename at (DE) with spaces, B has count ; ========================================================================================= 492BH MVI A,20H ; Load code for ' ' 492DH STAX D ; Save next byte as ' ' 492EH INX D ; Increment pointer 492FH DCR B ; Decrement count 4930H JNZ 492DH ; Keep looping until full ; ========================================================================================= ; Copy 2 extention bytes from (HL) to (DE) ; ========================================================================================= 4933H MVI B,02H ; Setup count = 2 4935H INX H ; Skip the '.' in the source name 4936H MOV A,M ; Load next extension byte from source 4937H ORA A ; Test for NULL termination 4938H RZ ; Return if NULL terminated 4939H STAX D ; Store in destination 493AH INX D ; Increment destination 493BH DCR B ; Decrement the counter 493CH JNZ 4935H ; Keep looping until done 493FH MVI A,00H ; Load NULL termination byte 4941H STAX D ; Add NULL termination to filename 4942H RET ; ========================================================================================= ; Configure baud, test for NADSBox, get NADSBox dir ; ========================================================================================= 4943H CALL 4A94H ; Configure baud (19200 for NADSBox/Desklink, 9600 otherwise) 4946H CALL 49A2H ; Send M1 and test for NADSBox/Desklink response 4949H CALL 47CCH ; Receive a packet 494CH CALL 47F8H ; Check RX packet for Normal Response & report errors 494FH LDA FCCBH ; NADSBo / Desklink / TPDD2 flag 4952H ANA A ; Test if server is NADSBox / Desklink 4953H RZ ; Return if not NADSBox / Desklink 4954H LXI H,0008H ; Load opcode 0x08 - FDC Emulation mode 4957H CALL 4822H ; Send TPDD Command/Len in HL 495AH CALL 47CCH ; Receive a packet - should be the current directory name 495DH LDA FD03H ; Load length byte from the RX payload area 4960H CPI 01H ; Test if length 1 4962H JZ 4977H ; Jump to send mystery opcodes if length = 1 4965H DCR A ; Subtract 1 from length (skip reserved 0x00 in filename) 4966H MOV C,A ; Save count in C 4967H MVI A,02H ; Prepare to indicate we have a NADSBox / Desklink directory name 4969H STA FCCBH ; NADSBox / Desklink flag = HAVE_NADS_DIR 496CH MVI B,00H ; Clear MSB of count 496EH LXI H,FD05H ; Point to filename in RX payload (skip 1st byte) 4971H LXI D,FCC0H ; Storage area for NADSBox directory 4974H JMP 4A05H ; Move BC bytes from M to (DE) with increment ; ========================================================================================= ; Send mystery opcodes ; ========================================================================================= 4977H LXI H,0023H ; Load mystery opcode 23 497AH CALL 4822H ; Send TPDD Command/Len in HL 497DH CALL 47CCH ; Receive a packet 4980H LXI H,4AE7H ; Point to mystery opcode 0x31 4983H CALL 498FH ; Send 9-byte protocol packet at HL 4986H LXI H,4AF0H ; Point to 2nd mystery opcode 0x31 4989H CALL 498FH ; Send 9-byte protocol packet at HL 498CH LXI H,4AF9H ; Point to 3rd mystery opcode 0x31 ; ========================================================================================= ; Send 9-byte protocol packet at HL ; ========================================================================================= 498FH LXI B,0009H ; Load byte counter to send 9 bytes 4992H CALL 48D9H ; Send BC bytes at (HL) to RS-232 using XON/XOFF 4995H JMP 47CCH ; Receive a packet ; ========================================================================================= ; Flush the RX queue & discard ; ========================================================================================= 4998H CALL 4BDFH ; Check RS232 queue for pending characters 499BH RZ ; Return if RS232 queue is empty 499CH CALL 47EBH ; Test drive ready and get byte from RX. 499FH JMP 4998H ; Branch to get next byte from RX ; ========================================================================================= ; Send M1 and test for NADSBox / Desklink response ; ========================================================================================= 49A2H CALL 4862H ; Test if DSR set - drive ready 49A5H CALL 49CDH ; Send "M1",0x0D to TX and delay about 3ms 49A8H CALL 4998H ; Flush the RX queue & discard 49ABH CALL 419BH ; Send Opcode 0x08 - FDC emulation mode 49AEH CALL 49D3H ; Send 0x0D to RS-232 and Delay 3ms 49B1H CALL 4BDFH ; Check RS232 queue for pending characters 49B4H MVI A,00H ; NADSBox / Desklink / TPDD2 flag 49B6H JNZ 49BAH ; Skip setting NADSBox / Desklink flag if no response 49B9H INR A ; Indicate response from "M1" command = NADSBox / Desklink 49BAH STA FCCBH ; Store NADSBox / Desklink / TPDD2 flag 49BDH CALL 4998H ; Flush the RX queue & discard 49C0H CALL 49CDH ; Send "M1" to TX and delay about 3ms 49C3H CALL 4998H ; Flush the RX queue & discard 49C6H LXI H,0007H ; Load opcode for Drive Status 49C9H CALL 4822H ; Send TPDD Command/Len in HL 49CCH RET ; ========================================================================================= ; Send "M1",0x0D to RS-232 and delay about 3ms ; ========================================================================================= 49CDH LXI B,4D31H ; Load code for "M1" 49D0H CALL 49DBH ; Send BC to RS-232 using XON/XOFF 49D3H MVI A,0DH ; Load code for CR (0x0D) 49D5H CALL 485FH ; Send A to RS-232 using XON/XOFF 49D8H JMP 49E3H ; Delay routine - about 3ms ; ========================================================================================= ; Send BC to RS-232 using XON/XOFF ; ========================================================================================= 49DBH MOV A,B ; Get first byte to send 49DCH CALL 485FH ; Send A to RS-232 using XON/XOFF 49DFH MOV A,C ; Get 2nd byte to send 49E0H JMP 485FH ; Send A to RS-232 using XON/XOFF ; ========================================================================================= ; Delay routine - about 72000 cycles = 28.9ms ; ========================================================================================= 49E3H MVI H,14H ; 7 Cycles 49E5H MVI L,FFH ; 7 Cycles 49E7H DCR L ; 4 Cycles 49E8H JNZ 49E7H ; 10 Cycles to Jump back. 14 * 255 = 3570 cycles inner loop 49EBH DCR H ; 4 Cycles. But we save 3 cycles from the final JNZ, so 1 cycle 49ECH JNZ 49E5H ; 10 Cycles to jump back. (3570+1+7)*20+7 = 71567 cycles 49EFH RET ; 71567 * 403.877ns = 28.904ms ; ========================================================================================= ; Wait for drive to be ready for 20480 counts of 28.9ms = 9.8 minutes???. ; Report error if no data received. ; ========================================================================================= 49F0H LXI B,FF50H ; Get count of delay times to wait 49F3H CALL 49E3H ; Delay 28.9ms 49F6H CALL 4BDFH ; Check RS232 queue for pending characters 49F9H RNZ ; Return if data available 49FAH DCR B ; Decrement inner loop count 49FBH JNZ 49F3H ; Branch to delay and test again 49FEH DCR C ; Decrement outer loop count 49FFH JNZ 49F3H ; Branch to delay and test again 4A02H JMP 4867H ; No data received - Drive Not Ready error ; ========================================================================================= ; Move BC bytes from M to (DE) with increment ; ========================================================================================= 4A05H MOV A,M ; Get next byte from (HL) 4A06H STAX D ; Store next byte at (DE) 4A07H INX H ; Increment source pointer 4A08H INX D ; Increment destination poiner 4A09H DCX B ; Decrement loop control 4A0AH MOV A,B ; Prepare to test for zero 4A0BH ORA C ; OR in LSB to test for zero 4A0CH JNZ 4A05H ; Keep looping until done 4A0FH RET ; ========================================================================================= ; Multiply TPDD free sectors len x 128 = free space. A '0' is added to LCD to convert this ; multiplication to x1280 (the TPDD sector size). ; ========================================================================================= 4A10H LDA FD1FH ; Get number of free sectors reported from server (TPDD) 4A13H MOV L,A ; Move #free sectors into HL for multiply 4A14H MVI H,00H ; Clear MSB of HL 4A16H LXI D,0080H ; Prepare to multiply #sectors x 128 4A19H JMP 4C1FH ; Signed integer muliply (FAC1=HL*DE) ; ========================================================================================= ; Compare (HL) with (DE), C bytes long ; ========================================================================================= 4A1CH PUSH D ; Save pointer to 1st buffer 4A1DH PUSH H ; Save pointer to 2nd buffer 4A1EH LDAX D ; Load next byte from 1st buffer 4A1FH SUB M ; Compare with nex byte from 2nd buffer 4A20H JNZ 4A29H ; Jump to exit if no match 4A23H INX H ; Increment 2nd buffer pointer 4A24H INX D ; Increment 1st buffer pointer 4A25H DCR C ; Decrement length 4A26H JNZ 4A1EH ; Jump to compare next byte if not at end 4A29H POP H ; Restore pointer to 2nd buffer 4A2AH POP D ; Restore pointer to 1st buffer 4A2BH RET ; ========================================================================================= ; Send buffer at M to screen ; ========================================================================================= 4A2CH (7EH) MOV A,M ; Get next byte to send to LCD 4A2DH (A7H) ANA A ; Test for end of string 4A2EH (C8H) RZ ; Return if end of string (NULL terminated) 4A2FH (E7H) RST 4 ; Send character in A to screen/printer 4A30H (23H) INX H ; Increment to next byte 4A31H (C3H) JMP 4A2CH ; Branch to test next byte for zero and print ; ========================================================================================= ; Fill (HL) with B bytes of A ; ========================================================================================= 4A34H MOV M,A ; Load next byte at (HL) with A 4A35H INX H ; Increment pointer 4A36H DCR B ; Decrement counter 4A37H JNZ 4A34H ; Keep looping until B bytes copied 4A3AH RET ; ========================================================================================= ; Initialize blank filename and attribute byte ; ========================================================================================= 4A3BH MVI A,20H ; Prepare to fill TX packet with spaces 4A3DH MVI B,18H ; Fill TX buffer with 24 spaces 4A3FH LXI H,FCE8H ; Address of TX packet data 4A42H CALL 4A34H ; Fill (HL) with B bytes of A 4A45H MVI A,46H ; Load "F" TPDD file attribute flag 4A47H STA FD00H ; Store in TX packet data location 4A4AH RET ; ========================================================================================= ; Get RAM directory address of selected file into HL ; ========================================================================================= 4A4BH LHLD FCE4H ; LCD Buffer address of current file selection 4A4EH CALL 4902H ; Copy filename at (HL) to current BASIC program ; ========================================================================================= ; Get RAM directory address of current BASIC program ; ========================================================================================= 4A51H CALL 4C0FH ; Update system pointers 4A54H JMP 4BFBH ; Find catalog entry address of current BASIC program ; ========================================================================================= ; Send Dir Reference for filename at (HL) ; ========================================================================================= 4A57H PUSH H ; Save filename address on stack 4A58H CALL 4A3BH ; Initialize blank filename and attribute byte 4A5BH POP H ; Restore filename address 4A5CH LXI D,FCE8H ; Address of TX packet data 4A5FH LXI B,0006H ; Prepare to copy 6 bytes of TX data 4A62H CALL 4A05H ; Move BC bytes from M to (DE) with increment 4A65H MVI A,2EH ; Load code for '.' 4A67H STAX D ; Add '.' between name and extension 4A68H INX D ; Increment TX pkt address pointer 4A69H LXI B,0002H ; Prepare to copy extension from filename 4A6CH CALL 4A05H ; Move BC bytes from M to (DE) with increment 4A6FH CALL 4943H ; Configure baud, test for NADSBox, get NADSBox dir ; ========================================================================================= ; Send Dir Reference opcode ; ========================================================================================= 4A72H MVI A,00H ; Set dir reference type to "reference" for open 4A74H STA FD01H ; Save in dir reference location in TX buffer 4A77H LXI H,1A00H ; Load opcode for directory reference 4A7AH CALL 4822H ; Send TPDD Command/Len in HL 4A7DH CALL 47CCH ; Receive a packet 4A80H LDA FD1CH ; Load attribute byte 4A83H ANA A ; Test attribute byte for zero 4A84H RET ; ========================================================================================= ; Save OS's baud rate string to storage area, A = "Print error messages" flag ; ========================================================================================= 4A85H STA FCD2H ; Store "Print error messages" flag 4A88H LXI D,F9A8H ; Storage area for previous baud setting 4A8BH LXI H,F65BH ; RS232 parameter setting table 4A8EH LXI B,0005H ; Copy 7 bytes of parameter data 4A91H JMP 4A05H ; Move BC bytes from M to (DE) with increment ; ========================================================================================= ; Configure baud, check for Desklink/NADSBox. Set to 9600 if not Desklink/NADSBox ; ========================================================================================= 4A94H CALL 4BD7H ; Wait for TX empty and Reset UART to accept mode bits 4A97H LXI H,4ADEH ; Baud rate string for "98N1D" 4A9AH LXI D,F65BH ; RS232 parameter setting table 4A9DH LXI B,0005H ; Prepare to copy 5 bytes to Baud Parameter table 4AA0H CALL 4A05H ; Move BC bytes from M to (DE) with increment 4AA3H LXI H,F65BH ; Point to RS232 parameter setting table 4AA6H STC ; Indicate Baud rate is part of string 4AA7H CALL 4BD3H ; Set RS232 parameters from string at M 4AAAH CALL 4998H ; Flush the RX queue & discard 4AADH CALL 49A2H ; Send M1 and test for NADSBox / Desklink response 4AB0H CALL 49E3H ; Delay routine - about 3ms 4AB3H CALL 4BDFH ; Check RS232 queue for pending characters 4AB6H JNZ 4998H ; Jump to flush RX and keep 19200 if NADSBox / Desklink found 4AB9H CALL 4BD7H ; Wait for TX empty and Reset UART to accept mode bits 4ABCH LXI H,F65BH ; Baud rate string for "98N1D" 4ABFH DCR M ; Set baud rate to '8' = 9600 baud 4AC0H STC ; Indicate Baud rate is part of string 4AC1H JMP 4BD3H ; Set RS232 parameters from string at M - change to 9600 Baud ; ========================================================================================= ; Restore original baud settings ; ========================================================================================= 4AC4H LXI H,F9A8H ; Storage for OS's baud settings 4AC7H MOV A,M ; Get 1st byte of setting 4AC8H SUI 3AH ; Test if 1st byte is numeric 4ACAH JC 4BD3H ; Set RS232 parameters from string at M 4ACDH INX H ; Skip setting baud if 1st byte is "M"odem 4ACEH JMP 4BD3H ; Set RS232 parameters from string at M ; ========================================================================================= ; Strings and table data ; ========================================================================================= 4AD1H DB "0 Bytes free",0x00 ; Old Text - NOT USED in ROM version, only RAM version 4ADEH DB "98N1DNN", 0x00 ; Parameters for setting baud rate 4ADFH DB "8N1D",0x00 4AE4H DB 0x02,0x03,0x01 ; RST 7,30h open mode to TPDD Open mode mapping 4AE9H DB "ZZ1",0x04,0x01,0x00,0x84,0xFF,"F" 4AF0H DB "ZZ1",0x04,0x01,0x00,0x96,0x0F,0x24 4AF9H DB "ZZ1",0x04,0x01,0x00,0x94,0x0F,0x26 4B02H DB 0x12,"Drive Not Ready",0x00 DB 0x12,"Communication Error",0x00 DB 0x12,"Write Protect",0x00 DB 0x12,"Drive Trouble",0x00 DB 0x12,"Disk not in drive",0x00 DB 0x34,"Printer not ready",0x00 DB 0x05,"File Exists",0x00 DB 0x39,"Disk Full",0x00 DB 0x1A,"File Empty",0x00 DB 0x39,"Directory Full",0x00 DB 0x07,"Ram Full",0x00 DB 0x36,0x00 DB 0x37,"Bad File Name",0x00 4BBBH DB " Press any key.",0x00 ; ========================================================================================= ; RST 1 Vectors to Main ROM. At places in the code where a call is needed to the Main ROM, ; a RST 1 followed by a 2-byte address is issued. The routines will jump to one of ; the handler functions below to perform that RST 1 operation. ; ========================================================================================= 4BCBH RST 1 ; Call main ROM at address in following 2 bytes 4BCCH DW 340AH 4BCEH RET ; ========================================================================================= ; Call Main ROM's Evaluate expressino at M-1 routine ; ========================================================================================= 4BCFH RST 1 ; Call main ROM at address in following 2 bytes 4BD0H DW 1113H 4BD2H RET ; ========================================================================================= ; Call Main ROM's Set RS232 parameters from string at M routine ; ========================================================================================= 4BD3H RST 1 ; Call main ROM at address in following 2 bytes 4BD4H DW 17E6H 4BD6H RET ; ========================================================================================= ; Call Main ROM's Wait for TX empty and Reset UART routine ; ========================================================================================= 4BD7H RST 1 ; Call main ROM at address in following 2 bytes 4BD8H DW 6ECBH 4BDAH RET ; ========================================================================================= ; Call Main ROM's Set interrupt to 1DH routine. ; Seems like it would be easy enough to just do it in this ROM! ; ========================================================================================= 4BDBH RST 1 ; Call main ROM at address in following 2 bytes 4BDCH DW 765CH 4BDEH RET ; ========================================================================================= ; Call Main ROM's Check RS232 queue for pending characters routine ; ========================================================================================= 4BDFH RST 1 ; Call main ROM at address in following 2 bytes 4BE0H DW 6D6DH 4BE2H RET ; ========================================================================================= ; Call Main ROM's Send A to RS-232 using XON/XOFF routine ; ========================================================================================= 4BE3H RST 1 ; Call main ROM at address in following 2 bytes 4BE4H DW 6E32H 4BE6H RET ; ========================================================================================= ; Call Main ROM's Get a character from RS232 receive queue routine ; ========================================================================================= 4BE7H RST 1 ; Call main ROM at address in following 2 bytes 4BE8H DW 6D7EH 4BEAH RET ; ========================================================================================= ; Call Main ROM's Wait for key from keyboard routine ; ========================================================================================= 4BEBH RST 1 ; Call main ROM at address in following 2 bytes 4BECH DW 12CBH 4BEEH RET ; ========================================================================================= ; Call Main ROM's Scan keyboard for character (CTRL-BREAK ==> CTRL-C) routine ; ========================================================================================= 4BEFH RST 1 ; Call main ROM at address in following 2 bytes 4BF0H DW 7242H 4BF2H RET ; ========================================================================================= ; Call Main ROM's Power Down routine ; ========================================================================================= 4BF3H RST 1 ; Call main ROM at address in following 2 bytes 4BF4H DW 13B5H 4BF6H RET ; ========================================================================================= ; Call Main ROM's Renew automatic power-off counter routine ; ========================================================================================= 4BF7H RST 1 ; Call main ROM at address in following 2 bytes 4BF8H DW 1BB1H 4BFAH RET ; ========================================================================================= ; Call Main ROM's Find Catalog Entry Address of current BASIC program routine ; ========================================================================================= 4BFBH RST 1 ; Call main ROM at address in following 2 bytes 4BFCH DW 20AFH 4BFEH RET ; ========================================================================================= ; Call Main ROM's Kill .DO file routine ; ========================================================================================= 4BFFH RST 1 ; Call main ROM at address in following 2 bytes 4C00H DW 1FBFH 4C02H RET ; ========================================================================================= ; Call Main ROM's Kill .BA file routine ; ========================================================================================= 4C03H RST 1 ; Call main ROM at address in following 2 bytes 4C04H DW 2017H 4C06H RET ; ========================================================================================= ; Call Main ROM's Kill .CO file routine ; ========================================================================================= 4C07H RST 1 ; Call main ROM at address in following 2 bytes 4C08H DW 1FD9H 4C0AH RET ; ========================================================================================= ; Call Main ROM's Insert BC spaces at M routine ; ========================================================================================= 4C0BH RST 1 ; Call main ROM at address in following 2 bytes 4C0CH DW 6B6DH 4C0EH RET ; ========================================================================================= ; Call Main ROM's Update system pointers routine ; ========================================================================================= 4C0FH RST 1 ; Call main ROM at address in following 2 bytes 4C10H DW 2146H 4C12H RET ; ========================================================================================= ; Call Main ROM's Find BASIC end of program routine ; ========================================================================================= 4C13H RST 1 ; Call main ROM at address in following 2 bytes 4C14H DW 05F4H 4C16H RET ; ========================================================================================= ; Call Main Rom's Write new entry to catalog routine ; ========================================================================================= 4C17H RST 1 ; Call main ROM at address in following 2 bytes 4C18H DW 2239H 4C1AH RET ; ========================================================================================= ; Call Main ROM's Signed integer divide (FAC1=DE/HL) routine ; ========================================================================================= 4C1BH RST 1 ; Call main ROM at address in following 2 bytes 4C1CH DW 377EH 4C1EH RET ; ========================================================================================= ; Call Main ROM's Signed integer muliply (FAC1=HL*DE) routine ; ========================================================================================= 4C1FH RST 1 ; Call main ROM at address in following 2 bytes 4C20H DW 3725H 4C22H RET ; ========================================================================================= ; Call Main ROM's Send CRLF to LCD routine ; ========================================================================================= 4C23H RST 1 ; Call main ROM at address in following 2 bytes 4C24H DW 4222H 4C26H RET ; ========================================================================================= ; Call Main ROM's CLS statement routine ; ========================================================================================= 4C27H RST 1 ; Call main ROM at address in following 2 bytes 4C28H DW 4231H 4C2AH RET ; ========================================================================================= ; Call Main ROM's Erase from cursor to end of line routine ; ========================================================================================= 4C2BH RST 1 ; Call main ROM at address in following 2 bytes 4C2CH DW 425DH 4C2EH RET ; ========================================================================================= ; Call Main ROM's Start inverse character mode routine ; ========================================================================================= 4C2FH RST 1 ; Call main ROM at address in following 2 bytes 4C30H DW 4269H 4C32H RET ; ========================================================================================= ; Call Main ROM's Cancel inverse video routine ; ========================================================================================= 4C33H RST 1 ; Call main ROM at address in following 2 bytes 4C34H DW 426EH 4C36H RET ; ========================================================================================= ; Call Main ROM's Generate error in E routine ; ========================================================================================= 4C37H LXI H,045DH ; Load address of Main ROM's Generate Error in E routine 4C3AH PUSH H ; Push routine to the stack 4C3BH JMP 00A6H ; Jump to Main ROM ; ========================================================================================= ; Call Main ROM's Print binary number in HL at current position routine ; ========================================================================================= 4C3EH RST 1 ; Call main ROM at address in following 2 bytes 4C3FH DW 39D4H 4C41H RET ; ========================================================================================= ; Call Main ROM's Print A to printer, expanding tabs if necessary routine ; ========================================================================================= 4C42H RST 1 ; Call main ROM at address in following 2 bytes 4C43H DW 4B55H 4C45H RET ; ========================================================================================= ; Call Main ROM's Input and display (no "?") line and store routine ; ========================================================================================= 4C46H RST 1 ; Call main ROM at address in following 2 bytes 4C47H DW 4644H 4C49H RET ; ========================================================================================= ; Call Main ROM's Check keyboard queue for pending characters routine ; ========================================================================================= 4C4AH RST 1 ; Call main ROM at address in following 2 bytes 4C4BH DW 13DBH 4C4DH RET ; ========================================================================================= ; Call Main ROM's Move BC bytes from M to (DE) with decrement routine ; ========================================================================================= 4C4EH RST 1 ; Call main ROM at address in following 2 bytes 4C4FH DW 6BE6H 4C51H RET ; ========================================================================================= ; Call Main ROM's LCOPY statement routine ; ========================================================================================= 4C52H RST 1 ; Call main ROM at address in following 2 bytes 4C53H DW 1E5EH 4C55H RET ; ========================================================================================= ; Call Main ROM's Stop automatic scrolling routine ; ========================================================================================= 4C56H RST 1 ; Call main ROM at address in following 2 bytes 4C57H DW 423FH 4C59H RET ; ========================================================================================= ; Call Main ROM's Resume Automatic Scrolling routine ; ========================================================================================= 4C5AH RST 1 ; Call main ROM at address in following 2 bytes 4C5BH DW 4244H 4C5DH RET ; ========================================================================================= ; Call Main ROM's Get char at M and convert to uppercase routine ; ========================================================================================= 4C5EH RST 1 ; Call main ROM at address in following 2 bytes 4C5FH DW 0FE8H 4C61H RET ; ========================================================================================= ; Call Main ROM's Get file descriptor for file in A routine ; NOT CALLED ; ========================================================================================= 4C62H RST 1 ; Call main ROM at address in following 2 bytes 4C63H DW 4C81H 4C65H RET ; ========================================================================================= ; Call Main ROM's Update line addresses for current BASIC program routine ; ========================================================================================= 4C66H RST 1 ; Call main ROM at address in following 2 bytes 4C67H DW 05F0H 4C69H RET ; ========================================================================================= ; Call Main ROM's Copy CO header bytes (6) from (HL) to "active" CO Header storage area routine ; ========================================================================================= 4C6AH RST 1 ; Call main ROM at address in following 2 bytes 4C6BH DW 253DH 4C6DH RET ; ========================================================================================= ; Call Main ROM's print CO address, length and invocation address to LCD routine ; ========================================================================================= 4C6EH RST 1 ; Call main ROM at address in following 2 bytes 4C6FH DW 25A4H 4C71H RET ; ========================================================================================= ; Call Main ROM's Process SAVEM arguments for address, length and entry point routine ; ========================================================================================= 4C72H RST 1 ; Call main ROM at address in following 2 bytes 4C73H DW 2346H 4C75H RET
Navigate to: