; M4SEND/ASM ; ; SEND COMMAND ; SEND EQU $ CALL NEWLIN LD A,CMTXT ;PARSE A TEXT STRING LD DE,MFNBUF ;GIVE THE ADDRESS FOR THE STRING PUSH DE ;Save it CALL COMND ;GET THE INPUT JP KERMT2 ;GIVE UP ON BAD PARSE. POP HL ;Get the pointer LD (MFNPTR),HL ;Save it as the start LD A,1 ;Set the log names flag LD (LOGNAMES),A CALL BUILDF ;Build a list doing wildcarding LD A,(FILECNT) ;Get the number of files IFNZ SEND11 ;Jump if some files were found STROUT NOFILES ;Print the message JP KERMIT SEND11 LD (MFNPTR),HL ;Save the start of the found list CALL MFNAME ;Get the next from the list JR NC,SEND14 ;Jump if got a name CALL NEWLIN LD A,19 ;Issue system error, Illeagal filename CALL XERROR JP KERMIT ;GET A NEW COMMAND SEND14 CALL INIT ;Clear the line and initialize buffers XOR A LD (PKTNUM),A LD (NUMTRY),A ;SET THE NUMBER OF TRIES TO ZERO. LD HL,0 LD (NUMPKT),HL ;SET THE NUMBER OF PACKETS TO ZERO. LD (NUMRTR),HL ;SET THE NUMBER OF RETRIES TO ZERO. LD (KTRANS),HL LD A,'1' ;RESET TO USE SINGLE CHARACTER CHECKSUM LD (CURCHK),A ;FOR STARTUP NSTATE 'S' LD (DISFLG),A ;Put in something non zero CALL CONDCHR ;Display starting sendinit character 'S' CALL CLRPRT ;CLEAR OUT ANY STACKED NAKS STROUT HELPMSG CALL PROTO ;Do protocol states JP KERMIT ;Return to Kermit ; ; SEND ROUTINES ; SEND INITIATE ; SINIT CALL CHKTRYS ;Check retry threshold LD A,'1' ;RESET TO USE SINGLE CHARACTER CHECKSUM LD (CURCHK),A ;FOR STARTUP LD A,(CHKTYP) ;GET OUR DESIRED BLOCK CHECK TYPE LD (INICHK),A LD HL,DATA ;GET A POINTER TO OUR DATA BLOCK. CALL RPAR ;SET UP THE PARAMETER INFORMATION. LD (ARGBLK+1),A ;SAVE THE NUMBER OF ARGUMENTS. LD A,(NUMPKT) ;GET THE PACKET NUMBER. LD (ARGBLK),A SRPACK 'S' ;Do send init, and get response IFANOT 'Y',SINIT3 ;Was it an ACK? Jump if not CALL CHKBLK RET NZ ;IF NOT TRY AGAIN. CALL DOINC ;Increment and reset LD A,(ARGBLK+1) ;GET THE NUMBER OF PIECES OF DATA. LD HL,DATA ;POINTER TO THE DATA. CALL SPAR ;READ IN THE DATA. LD A,(INICHK) ;GET THE AGREED UPON BLOCK-CHECK-TYPE LD (CURCHK),A ;STORE AS TYPE TO USE FOR PACKETS NOW NSTATE 'F' ;Set the state CALL CONDCHR CALL GETFIL ;Open the file name given in FCB JP SNDABORT ;Something is wrong if come to here RET ;Next state in protocol ; ; Come here on bad answer to S packet ; SINIT3 CP 'N' ;NAK? JP NZ,BADERROR ;If not, then it is a fatal error CALL CONDCHR ;Output N character RET ;Back to protocol ; ; Terminate a transaction log because of an error ; ; ; SEND FILE HEADER ; SFILE CALL CHKTRYS ;Check retry threshold XOR A ;CLEAR A LD (CZSEEN),A LD DE,DATA ;GET A POINTER TO OUR DATA BLOCK. LD HL,MFREQ ;Get filename LD BC,255 ;B must be zero, C must be big for LDI SF1 LD A,(HL) IFA '/',SF2 IFA ':',SF4 IFALT ' ',SF4 LDI INC B JR SF1 SF2 LD (HL),'.' LDI INC B SF3 LD A,(HL) IFALT ' ',SF4 IFA ':',SF4 LDI INC B JR SF3 SF4 EQU $ LD (DATPTR),DE LD (FCBPTR),HL LD A,B ;NUMBER OF CHAR IN FILE NAME. LD (ARGBLK+1),A EX DE,HL LD (HL),EOS ;Put in the print terminator LD A,(PKTNUM) ;GET THE PACKET NUMBER. LD (ARGBLK),A SRPACK 'F' ;Send file header and get response IFANOT 'Y',SFILE2 ;Jump if not an ACK CALL CHKBLK ;Check packet number RET NZ ;Return if not the right one SFIL14 CALL DOINC ;Increment packet count SFIL15 CALL RSETPKT ;Reinitialize GETPKT() CALL GTCHR JP SFIL16 ;ERROR GO SEE IF ITS EOF. JR SFIL17 ;GOT THE CHARS, PROCEED. SFIL16 CP 0FFH ;IS IT EOF? JP NZ,SNDABORT ;IF NOT GIVE UP. NSTATE 'Z' ;Set EOF state CALL CONDCHR RET SFIL17 EQU $ NSTATE 'T' ;Set state to data send LD (DISFLG),A ;Make sure display is on RET SFILE2 CP 'N' ;NAK? JP NZ,BADERROR ;TRY IF ERROR PACKET. CALL CONDCHR ;Display the packet character CALL CHKBLKINC ;Check NAK for packet N+1 RET NZ ;If not, then try to resend JR SFIL14 ;As good as an ACK, join the ack code ; ; Send transition state from Send file to Send data ; SNDTRAN EQU $ STROUT KERSND ;Print SENDING message STROUT TFILNAM ;Print the file name LD A,(TRANLOG) ;Check if logging active IFZ SNDTRAN2 ;If not, then jump LD DE,TRFCB ;Get the log file FCB TRLOG KERSND,SNDTRAN1 ;Log the SENDING=> message TRLOG TFILNAM,SNDTRAN1 ;Log the file name TRLOG TIMEMES,SNDTRAN1;Log the time: message CALL PRTTIME ;Print the time JR SNDTRAN2 ;Join other code ; ; Close up on a logging error ; SNDTRAN1 EQU $ XOR A ;Reset the log open flag LD (TRANLOG),A LD DE,TRFCB ;Close the log file CALL XCLOSE SNDTRAN2 EQU $ NSTATE 'D' ;Set the state to SEND DATA RET ; ; SEND DATA ; SDATA CALL CHKTRYS ;Check the retry threshold LD DE,DATA ;Get the data area LD HL,FILBUF ;Get the file buffer LD A,(SIZE) ;Get the number of bytes encoded IFZ SDAT11 ;Jump if there are none LD C,A ;Put LSB into C LD B,0 ;Zero B LDIR ;Move the bytes SDAT11 LD A,(SIZE) ;Get the number of bytes back LD (ARGBLK+1),A ;Store it as the length LD A,(PKTNUM) ;Get the current packet number LD (ARGBLK),A ;Put it in the packet LD A,'D' ;Get the packet type CALL SPACK ;Send a data packet JP SNDABORT ;Abort if send fails LD A,(NUMPKT) ;See if time to log progress AND 3 ;Every 4 packets LD A,'.' ;Get the character CALL Z,CONDCHR ;Output if it is time RPACKET ;Get a packet IFANOT 'Y',SDATA2 ;Jump if not an ACK CALL CHKBLK ;See if proper packet number RET NZ ;Wait for more if not right number CALL DOINC ;Increment and reset LD A,(ARGBLK+1) ;Get the length of packet IFANOT 1,SDAT15 ;Jump if not 1 character LD A,(DATA) ;Get the character sent in ACK IFANOT 'Z',SDAT14 ;Is it end of file? Jump if not LD (CZSEEN),A ;Save it JR SDAT15 ;Continue SDAT14 IFANOT 'X',SDAT15 ;Was it EOT? Jump if not LD (CZSEEN),A ;Save it SDAT15 LD A,(CZSEEN) ;Get the character IFZ SDAT12 ;Jump if nothing there CALL CONDCHR ;Display the character NSTATE 'Z' ;Set the state to EOF RET ;Return to protocol ; SDAT12 CALL GTCHR ;Get more data from input file JP SDAT13 ;Jump if error occurs (might be EOF) RET ;Continue sending ; SDAT13 CP 0FFH ;Was the file error EOF? JP NZ,SNDABORT ;If not, then file error, so abort NSTATE 'Z' ;Set state to EOF CALL CONDCHR ;Output the state RET ;Return to protocol ; SDATA2 CP 'N' ;Is it a NAK? JP NZ,BADERROR ;Nope, check next type CALL CONDCHR ;Display packet type CALL CHKBLKINC ;NAK this packet plus one? JR Z,SDAT12 ;Just as good as an ACK, Join ACK code. CALL UPDRTR RET ; ; Send the EOF packet ; SEOF CALL CHKTRYS ;Check the retry threshold CALL INITBLK ;Initialize ARGBLK LD A,(CZSEEN) ;Check for ABORT IFZ SEOF14 ;If not aborted, then keep going LD A,(TRANLOG) ;Check if logging active IFZ SEOF10 ;Jump if no logging LD DE,TRFCB ;Get the log file FCB TRLOG TRANCANC,SEOF19 ;Log the canceled message SEOF10 LD A,(DISCARD) ;Should the file be deleted? IFZ SEOF11 ;Skip delete if user want to keep it LD A,'D' ;Tell other end to discard packet LD (DATA),A ;Store the delete character LD A,1 ;Length is one character SEOF11 LD (ARGBLK+1),A ;Store the length SEOF14 SRPACK 'Z' ;Send EOF, and get a response IFANOT 'Y',SEOF2 ;Jump if not an ACK CALL CHKBLK ;Check the packet number RET NZ ;Return if not correct one SEOF12 CALL DOINC ;Increment and reset CALL CHKFCB ;Check for file, don't close *SO CALL Z,XCLOSE ;Conditionally close it LD A,(CZSEEN) ;Did the user force us to stop? IFA 'Z',SEOF13 ;Jump if EOF was signaled by user CALL MFNAME ;Get a new file name JR C,SEOF13 ;Jump if no more CALL GETFIL ;AND OPEN IT JP SNDABORT ;SOMETHING IS WRONG, DIE. XOR A ;CLEAR A LD (CZSEEN),A NSTATE 'F' ;Set state to file send CALL CONDCHR LD IX,STRANS ;Update transmission information CALL UPDTRANS RET ;Continue protocol ; SEOF13 NSTATE 'B' ;Set state to EOT CALL CONDCHR LD IX,STRANS ;Update the transmission info CALL UPDTRANS RET ; SEOF2 CP 'N' ;NAK? JP NZ,BADERROR ;TRY AND SEE IF ITS AN ERROR PACKET. CALL CONDCHR CALL UPDRTR ;UPDATE THE NUMBER OF RETRIES. CALL CHKBLKINC RET NZ ;IF NOT GO TRY AGAIN. JR SEOF12 ;Just as good as an ACK ; SEOF19 XOR A ;Reset the log open flag LD (TRANLOG),A LD DE,TRFCB ;Close the file CALL XCLOSE JP SEOF10 ;Join other code ; ; Send EOT packet ; SEOT CALL CHKTRYS ;Check the retry threshold CALL INITBLK ;Initialize ARGBLK SRPACK 'B' ;Send END of BATCH and get response IFANOT 'Y',SEOT2 ;Jump if not ACK CALL CHKBLK ;Check the packet number RET NZ ;Return if not correct SEOT12 CALL DOINC ;Increment and reset NSTATE 'C' ;Set state to complete RET SEOT2 CP 'N' ;NAK? JP NZ,BADERROR ;IS IT ERROR. CALL CONDCHR CALL UPDRTR ;UPDATE THE NUMBER OF RETRIES. CALL CHKBLKINC JP Z,SEOT12 ;Good as an ACK, so continue OR A ;Is the other end starting over? JR Z,SEOT12 RET ; ; Check the retry threshold ; CHKTRYS EQU $ ;Check retry threshold LD A,(MAXTRY) ;Get the maximum LD B,A ;Save LD A,(NUMTRY) IFALT B,CHKTRYS1 ;Jump if not at limit POP DE ;Remove the callers return addr LD DE,ERMS14 ;Print the error message CALL ERROR3 JP SNDABORT ;CHANGE THE STATE TO ABORT. CHKTRYS1 EQU $ IFZ CHKTRYS2 ;Jump if first try PUSH AF ;Save the count LD A,'%' ;Print retrying message CALL CONDCHR POP AF ;Get the count back CHKTRYS2 EQU $ INC A ;Increment it LD (NUMTRY),A ;Save the new count RET ; ; Increment the packet count modulo 64, A already has the old one. ; INCPKT INC A AND 3FH LD (PKTNUM),A RET ; ; Move numtry to oldtry and zero numtry ; NUM2OLD EQU $ LD A,(NUMTRY) ;GET THE NUMBER OF TRIES. LD (OLDTRY),A ;SAVE IT. XOR A LD (NUMTRY),A ;RESET THE NUMBER OF TRIES. RET ; ; Increment display packet count ; INCDISPKT EQU $ LD HL,(NUMPKT) INC HL LD (NUMPKT),HL RET ; ; Do several things ; DOINC CALL INCPKT CALL INCDISPKT JP NUM2OLD ; ; Check the packet number 'received plus 1' verses that sent ; return their relation, eg <, >, =, <>. This is used as a ; method to determine that a NAK for packet N+1 is equivelent ; to an ACK for packet N. ; CHKBLKINC EQU $ LD A,(PKTNUM) ;Get the current packet number INC A ;Plus one LD B,A ;Save it LD A,(ARGBLK) ;Get the packet number returned CP B ;Are they equal? RET ;Return the flags setting ; ; Conditionally display the character in A based on the value ; of DISFLG. This is used to print the characters during transfers ; that show the status of the transfer. eg '.', 'Q', 'S', 'Z', etc ; CONDCHR EQU $ LD C,A ;Save the character LD A,(DISFLG) ;Check if should display the character OR A ;Set the flags RET Z ;Return if flag not set LD A,C ;Get the character back JP CONOUT ;Print the terminal on the console ; RSETPKT EQU $ XOR A ;GET A ZERO. LD (EOFLAG),A ;INDICATE NOT EOF. LD (SIZE),A ;Nothing in packet buffer LD (OSIZE),A ;No old length LD (LEFTOVER),A ;No leftovers from previous packet LD (RPTCNT),A ;No repeated characters yet LD (PREVCH),A ;Reset any previous character knowledge LD HL,-1 ;Set NO next character LD (NEXT),HL LD (CH),HL RET ; BADERROR EQU $ CP 'E' ;IS IT AN ERROR PACKET. JP NZ,SNDABORT CALL ERROR JP SNDABORT ; INITBLK EQU $ LD A,(PKTNUM) ;GET THE PACKET NUMBER. LD (ARGBLK),A XOR A LD (ARGBLK+1),A ;NO DATA. RET PRTTIME EQU $ PUSH AF ;Save the regs PUSH BC PUSH HL PUSH DE ;Save the FILE FCB LD HL,CLBUF ;Get the character buffer PUSH HL ;Save the address CALL XTIME ;Get the time LD (HL),CR ;Get a new line INC HL ;Point to next pos LD (HL),EOS ;Terminate the string POP HL ;Get the string to print back POP DE ;Get the log file FCB CALL OUTLOG CALL TIMCLOSE ;Close up if error occurs POP HL ;Restore the regs POP BC POP AF RET ; TIMCLOSE EQU $ XOR A ;Reset the file open flag LD (LOGTRAN),A LD DE,TRFCB ;Get the FCB JP XCLOSE ;Close the file and return. ; end of file