;---> Originally from the CPMUG volume 15 ; ;TSAVE V.4 - TARBELL SAVE ;BY WARD CHRISTENSEN ;WORKS FOR ANY CP/M FILE ;01/15/77 ORIGINALLY WRITTEN ;08/01/77 ADD CHECKSUM ;09/19/77 ADD DELAY BEFORE WRITING TO ; ALLOW TIME FOR MULTIPLE TLOADS ; VIA 'SUBMIT' COMMAND ; ;04/10/81 CORRECTED BUG IN EXIT ROUTINE THAT PREVENTED ;USE OF SUBMIT FILES - R.M.GLUECK ; ;WRITES 11 CHAR FILENAME, ; 1 BYTE # SECTORS, ; DATA, (TYPICALLY 4K BLOCKS) ; CHECKSUM ; ;IF 'TSAVE FN.FT ?' IS TYPED, CHECKS THE TAPE ; BY READING IT BACK NSEC EQU 32 ;NUMBER OF SECTORS/BLOCK SECDLY EQU 4 ;# SECONDS DELAY ;BEFORE EACH WRITE ORG 100H ;TO TPA CALL START ;SKIP ID ID DB 'Tarbell Save of 04/10/81 ',0DH,0AH,'$' START POP D ;GET ID MSG ADDR MVI C,PRINT CALL BDOS ;PRINT ID ;INIT PRIVATE STACK LXI H,0 DAD SP SHLD STACK LXI SP,STACK ;SAVE THE '?' FROM 'TSAVE FN.FT ?' LDA FCB+17 ;LOAD THE '?' STA CHECK ;SAVE ;OPEN FILE LXI D,FCB MVI C,OPEN CALL BDOS INR A ;OPEN OK? JZ OPNER ;WRITE 'AUDIO HEADER' ONTO THE TAPE LDA CHECK ;CHECKING? CPI '?' JZ READB ;SKIP HDR IF CHECKING MVI B,0 ;>1 SECONDS WORTH AUDIOH MVI A,11H ;GET DISTINCTIVE PATTERN CALL TOUT ;OUTPUT IT DCR B JNZ AUDIOH ; ;READ FILE, WRITE TARBELL ; IN NSEC SECTOR (4K) BLOCKS READB MVI E,'*' ;PRINT '*' EVERY BLOCK WRITTEN MVI C,WRCON ;PRINT '?' IF CHECKING, OTHERWISE '*' LDA CHECK CPI '?' ;CHECKING? JNZ PRAST ;NO, PRINT ASTERISK MOV E,A ;MOVE SO '?' PRINTS PRAST CALL BDOS ;PRINT '?' OR '*' RDLP LHLD BUFAD ;GET BUFFER ADDR XCHG ;MOVE TO D,E ;SET NEW BUFFER ADDR LXI H,128 ;GET BUFFER LENGTH DAD D ;POINT TO NEXT SHLD BUFAD MVI C,STDMA ;SET CALL BDOS ;..DMA ADDR LHLD BUFAD LXI D,FCB MVI C,READ CALL BDOS ORA A ;READ OK? JNZ RDER ;NO, CHECK EOF ;INCR BUFF COUNT, IF NSEC, WRITE LDA BUFFN INR A STA BUFFN CPI NSEC JC RDLP ;LOOP IF MORE TO DO ;HAVE READ NSEC SECTORS, WRITE THEM EOFWR LDA CHECK ;WAS TSAVE ? REQUESTED? CPI '?' JNZ NCK1 ;NO - INIT FOR OUTPUT ;INIT TARBELL FOR INPUT MVI A,10H ;GET INPUT RESET CHAR OUT 6EH ;RESET TARBELL JMP SENDF ;SKIP OUTPUT INIT ;CHECK NOT REQUESTED - INIT TARBELL OUTPUT NCK1 MVI A,3CH ;START BYTE CALL TOUT MVI A,0E6H ;GET TARBELL SYNCH CHAR CALL TOUT ;OUTPUT IT SENDF LXI H,FCB+1 ;SET UP AND MVI B,8+3 ;..OUTPUT FCBLP MOV A,M ;GET FCB CHAR CALL TOUT ;WRITE IT INX H ;POINT TO NEXT DCR B ;MORE? JNZ FCBLP ;WRITE THE SECTOR COUNT LDA BUFFN ;GET SECTOR COUNT CALL TOUT ;WRITE IT ;IF BUFFN IS 0, THEN THAT WAS EOF LDA BUFFN ORA A ;DONE? JZ DONE ;YES ;WRITE THE SECTORS LXI H,BUFF ;POINT TO START SHLD BUFAD ;INIT BUFF ADDR LDA BUFFN ;GET NUMBER OF BUFFERS MOV B,A ;SAVE IN B XRA A ;GET A ZERO STA CKSUM ;INIT CKSUM WRSEC MVI C,128 ;INIT C TO SECTOR LENGTH WRCHR MOV A,M ;GET CHAR CALL TOUT ;WRITE IT INX H ;POINT TO NEXT DCR C ;MORE IN SECTOR? JNZ WRCHR DCR B ;DECR # OF SECTORS JNZ WRSEC ;MORE SECTORS TO WRITE LDA CKSUM ;SEND CKSUM CALL TOUT XRA A ;GET A ZERO STA BUFFN ;INIT BUFF NUMBER ;SEND DELAY BYTES CALL DELAY ;IF EOF, SEND EOF REC (HDR, 0 DATA) LDA EOFLG ;GET FLAG ORA A ;EOF? JNZ EOFWR ;YES JMP READB ;GO READ MORE ;READ ERROR - CHECK FOR EOF RDER DCR A ;WAS IT 1? JNZ RDERR ;NO, GENUINE READ ERROR ;EOF REACHED INR A ;GET NON-ZERO VALUE STA EOFLG ;SET EOF FLAG JMP EOFWR ;GO WRITE LAST PART ;ALL DONE - WRITE 2 X DELAYS DONE CALL DELAY CALL DELAY JMP EXIT OPNER LXI D,MSG2 JMP ERXIT RDERR LXI D,MSG5 ;READ ERROR JMP ERXIT ERXIT MVI C,PRINT CALL BDOS ;PRINT MESSAGE EXIT LHLD STACK ;GET ORIGINAL STACK SPHL ;RESTORE IT JMP 0 ;(WAS RET - 4/10/81 RMG) ;TARBELL WRITE TOUT PUSH PSW ;CALC CKSUM PUSH H LXI H,CKSUM XRA M ;CALC CKSUM MOV M,A ;SAVE IT BACK POP H ;IF CHECKING, THEN READ AND MATCH LDA CHECK CPI '?' JZ RDCK ;READ, CHECK TWAIT IN 6EH ANI 20H JNZ TWAIT POP PSW OUT 6FH RET RDCK POP PSW ;GET CHAR PUSH B ;SAVE BC MOV B,A ;PUT CHAR IN B RDWT IN 6EH ;READ TARBELL STAT ANI 10H JNZ RDWT IN 6FH CMP B JZ CKOK ;CHAR MATCHED ;CHAR DIDN'T MATCH - LXI D,CKERR ;GET ERR MSG JMP ERXIT ;PRINT ERROR, EXIT CKOK POP B ;RESTORE BC RET ;TIME DELAY ROUTINE - WAITS 'SECDLY' SECONDS DELAY LDA CHECK ;DON'T DELAY CPI '?' ;..IF CHECKING RZ ;RET - CHECKING LXI B,187*SECDLY ;GET SECONDS DELAY2 MVI A,3CH ;TARBELL START CHAR CALL TOUT DCX B ;DONE? MOV A,B ORA C ;BC=0? JNZ DELAY2 RET DS 30 ;STACK AREA STACK DS 2 ;STACK POINTER MSG2 DB 'CANNOT OPEN$' MSG5 DB 'READ ERR$' CKERR DB 'COMPARE UNEQUAL$' BLKNO DB 0 ;BLOCKS READ, TO BE WRITTEN BUFFN DB 0 ;BUFFER NUMBER CHECK DS 1 ;IF TSAVE ? TYPED CKSUM DS 1 ;CHECKSUM EOFLG DB 0 ;EOF FLAG, 0=NO BUFAD DW BUFF ;CURRENT READ ADDR BUFF EQU $ ;BUFFER FROM HERE ON ; ; BDOS EQUATES (VERSION 2) ; RDCON EQU 1 WRCON EQU 2 PRINT EQU 9 OPEN EQU 15 ;0FFH=NOT FOUND CLOSE EQU 16 ; " " SRCHF EQU 17 ; " " SRCHN EQU 18 ; " " ERASE EQU 19 ;NO RET CODE READ EQU 20 ;0=OK, 1=EOF WRITE EQU 21 ;0=OK, 1=ERR, 2=?, 0FFH=NO DIR SPC MAKE EQU 22 ;0FFH=BAD REN EQU 23 ;0FFH=BAD STDMA EQU 26 BDOS EQU 5 REIPL EQU 0 FCB EQU 5CH ;SYSTEM FCB