! ! NAME: MTRANS ! ! FUNCTION: This is the transmit module for the MacTerminal protocol ! support on the AlphaMicro. MRECV provides the receive support. ! This protocol is similar to and uses the same as XMODEM protocol. ! First, the sender sends an escape sequence to tell the receiver to go ! into receive mode. Then it sends the file information block in standard ! XMODEM format, then an EOT. Then XMODEM protocol is used twice, all ! the way from the beginning NAK from the receiver to the ending ! EOT from the sender and ACK from receiver; the first time the data ! fork is sent; then the resource fork. ! ! AUTHOR: Tom Dahlquist ! ! EDIT HISTORY: ! When Who What ! 11/10/84 TAD Written (from XTRANS). ! 01/16/84 TAD Several changes. 1) Use FILEIN for input from file, thus ! allowing us to use RUN instead of XRUN. 2) Use TIMEIN ! for input from terminal, allowing timeouts. 3) Ignore ! CTL-C unless three of them hit in a row. 4) Fix little ! bug in TRY'AGAIN. ! 01/24/85 TAD Accept either three DEL's or CTL-C's to kill us. ! 05/09/85 TAD Use CMPCRC to compute CRC. ! ! This map is for the entire contents of one XMODEM transmission. ! First is the SOH, then the block #, then the inverted block #, ! then 128 data bytes, and finally the checksum. ! MAP1 WHOLE'BLOCK,X MAP2 SOH,X,1,CHR$(1) MAP2 BLOCK'NUMBER,B,1,1 MAP2 NOT'BLOCK'NUMBER,B,1 MAP2 IO'BLOCK,X,128 MAP2 CHECK'SUM'BYTE,X,1 ! ! This is the map of the file information block sent by MacTerminal. ! The filler byte sent after the SOH, block #, inverted block # has ! been kept as the first byte of the block for simplicity, since the ! AlphaMicro doesn't really care about alignment. ! MAP1 FILE'INFO,@IO'BLOCK MAP2 FILL1,X,1 ! first filler byte MAP2 FNAME,X,64 ! MacIntosh file name MAP2 FTYPE,S,4 ! file type MAP2 FCREATE,S,4 ! file creator MAP2 FFLAGS,B,2 ! file flags MAP2 FLOC,B,4 ! location in folder MAP2 FFOLDER,B,2 ! file folder MAP2 LOCKED,B,2 ! locked flags MAP2 DSIZE,X,4 ! size of data fork MAP2 RSIZE,X,4 ! size of resource fork MAP2 FLCRDAT,B,4 ! creation date MAP2 FLMDDAT,B,4 ! modification date MAP2 FILL2,X,29 ! filler MAP1 BLOCK'LENGTH,F,,128 MAP1 IN'CHR,X,1 MAP1 TEST'CHR,X,1 MAP1 OUT'CHR,X,1 MAP1 DISK'FSPEC,S,12 MAP1 OUT'UNIT,F,,0 MAP1 CHECK'SUM,F MAP1 CTRLC,X,1,CHR$(3) MAP1 DEL,X,1,CHR$(255) MAP1 EOT,X,1,CHR$(4) MAP1 ACK,X,1,CHR$(6) MAP1 BELL,X,1,CHR$(7) MAP1 NAK,X,1,CHR$(21) MAP1 ESCAPE,X,1,CHR$(27) MAP1 I,F MAP1 NUM'BLOCKS,F MAP1 COUNT'BLOCKS,F MAP1 GOT'NAK,F MAP1 DEBUG,F MAP1 TRUE,F,,-1 MAP1 FALSE,F,,0 MAP1 TIMER,F MAP1 TEMP1,X,4 MAP1 TEMP1X(4),X,1,@TEMP1 MAP1 TEMP2,X,4 MAP1 TEMP2X(4),X,1,@TEMP2 MAP1 TEMP'SIZE,B,4,@TEMP2 MAP1 SIZED,F MAP1 SIZER,F MAP1 SIZE,F MAP1 CHOICE,F MAP1 AREA,X,616 ! for FILEIN MAP1 DRAIN'BUF,X,20 MAP1 LENGTH,F ! from FILEIN and TIMEIN MAP1 TIMEOUT,F MAP1 NAK'COUNT,F MAP1 TIMEOUT'CNT,F MAP1 START'TIME,F GET'FILENAME: DISK'FSPEC="" INPUT LINE "Name of file to be transmitted: ",DISK'FSPEC IF DISK'FSPEC="" GOTO GET'FILENAME IF UCS(DISK'FSPEC[-2,-1])="/D" THEN & DISK'FSPEC=DISK'FSPEC[1,-3] : & OPEN #99,"MTRANS.LST",OUTPUT : & DEBUG=TRUE DISK'FSPEC=UCS(DISK'FSPEC) I=INSTR(1,DISK'FSPEC,".") IF I=0 THEN DISK'FSPEC=DISK'FSPEC+".MAC" LOOKUP DISK'FSPEC,I IF I=0 THEN & CALL TRY'AGAIN : & GOTO GET'FILENAME XCALL IMG XCALL FILEIN,1,AREA,DISK'FSPEC ! OPEN #OUT'UNIT, "TRM:", OUTPUT ! ! Transfer starts with sender (us) sending "ESC a" sequence to the ! receiver, then wait for an ACK. Then the first block is sent ! in standard XMODEM block format. Then we wait for an ACK. Then ! we send an EOT and wait for an ACK. NOTE: since for some ! unfathomable reason the current version of MacTerminal (1.1) will ! not retransmit the file information block if a NAK is received, ! we will duplicate that behavior here. ! OUT'CHR=ESCAPE CALL SEND'ONE OUT'CHR="a" CALL SEND'ONE CALL WAIT'ACK IF GOT'NAK GOTO CLOSE'UP IF NOT TIMEOUT GOTO NT1 IF DEBUG THEN & ?#99,"Timed out waiting for ACK after header" GOTO TIMEOUT NT1: XCALL FILEIN,2,AREA,IO'BLOCK,LENGTH IF LENGTH#BLOCK'LENGTH GOTO BAD'FILE TIMER=TIME+2 WAIT: IF TIME ACK GOTO WAIT'ACK RETURN SEND'EOT: OUT'CHR=EOT CALL SEND'ONE CALL WAIT'ACK IF GOT'NAK GOTO SEND'EOT IF NOT TIMEOUT RETURN IF DEBUG THEN & ?#99,"Timed out waiting for ACK after EOT" GOTO TIMEOUT MASSAGE: FOR I=1 TO 4 TEMP2X(5-I)=TEMP1X(I) NEXT RETURN GET'ONE: START'TIME=TIME TIMEOUT=FALSE XCALL TIMEIN,60,IN'CHR,LENGTH IF DEBUG AND LENGTH#0 THEN & ?#99,"-";STR(ASC(IN'CHR)) IF LENGTH=0 THEN & TIMEOUT=TRUE : & IF DEBUG THEN ?#99,"Time=";STR(TIME-START'TIME) RETURN SEND'ONE: ?#OUT'UNIT,OUT'CHR; IF DEBUG THEN & ?#99,STR(ASC(OUT'CHR)) RETURN DEL'ABORT: TEST'CHR=DEL GOTO TEST'ABORT CTRLC'ABORT: TEST'CHR=CTRLC TEST'ABORT: FOR I=1 TO 2 XCALL TIMEIN,2,IN'CHR,LENGTH IF LENGTH=0 OR IN'CHR#TEST'CHR RETURN NEXT ?"Ending due to operator interrupt!" GOTO CLOSE'UP TIMEOUT: ?"Sorry, your Mac isn't talking to me--ending." GOTO CLOSE'UP BAD'FILE: GOTO CLOSE'UP CLOSE'UP: IF DEBUG THEN CLOSE #99 END !=================================================================== TRY'AGAIN: ? "That file --- "DISK'FSPEC " --- could not be found. " ? ? "Would you like to: " ? " 1 -- Try Again! " ? " 2 -- Return to the Menu." INPUT " (enter the number of your choice --- > ", CHOICE IF CHOICE=1 RETURN IF CHOICE#2 GOTO TRY'AGAIN END