; Kermit.m68 - a telecommunications & error free file transfer program
; Version 2.0 - supports wildcarding, 3 byte CRC
; Author:       Robert P. Rubendunst, Soft Machines,
;               P.O. box 3701, Champaign, IL 61821

; Copyright 1984, 1991  Robert P. Rubendunst. All rights reserved. In
; addition, anthology copyrights prohibited without written permission from
; the author.

; N O T E  - requires 1.3D AMOS/L//1.0D AMOS/32 or later to assemble.
; To assemble, M68 KERMIT.m68 produces KERMIT.LIT

; Edit History:
;[024] 16 March 1994 13:45      Edited by Bob Rubendunst
;       Added test & message when re-entering user tries to
;       re-specify port name.
;[023] 31 January 1992 10:49    Edited by Bob Rubendunst
;       Corrected problems in RPAR which caused file transfers to fail.
;[022] 10 January 1992 09:37    Edited by Bob Rubendunst
;       Added logic to strip CONNECT to 7 bits if PARITY is not NONE.
;[021] 09 January 1992 09:37    Edited by Bob Rubendunst
;       Documentation changes in CONNECT message
;       Added TIMEOUT and ENDLINE parametes to SET parameters list in SHOW
;       Changed SHOCHR to always display 3 characters, show ^ as dim if ctl
;       fixed problem with outputting zero byte files
;       improved SPAR & RPAR logic to handle 7 bit cases better.
;[020] 31 December 1991 11:06   Edited by Bob Rubendunst
;       Added code to make CONNECT mode compatible with 8 bit terminals.
;       (Exit character must match all 8 bits if TDV presents TD$EXT)
;       Deleted BPT legerdemain and just used SUPVR instead in SETSTS!
;[019] 31 December 1991 10:41   Edited by Bob Rubendunst
;       AUTORECEIVE feature completed
;[018] 06 December 1991 13:08   Edited by Bob Rubendunst
;       Added random file bypass for batch SENDing.
;       Added code to eliminate possible bogus packet timeout at midnight.
;       Added command line help.
;       Added SET PARITY input checking
;[017] 02 December 1991 11:48   Edited by Bob Rubendunst
;       Added SET PACKETSTART option
;       Deleted code to save & restore jcb jobtyp word (not used)
;[016] 22 November 1991 13:27   Edited by Bob Rubendunst
;       Added AUTORECEIVE command
;       Changed SEND logic to send a Break packet if no files sent.
;       Corrected some help text with Karen Bojda's help.
;       Streamlined INUSE subroutine
;       Added code to revive job when attaching JCB & TCB
;       Completed graceful abort code for SENDing
;       Corrected tests for maximum retries - some were BNE instead of BLOS
;[015] 31 October 1991 16:49    Edited by Bob Rubendunst
;       Added wildcarding via CMDLIN.SYS. Kudos to Tom Niccum of KW fame.
;       Added totals statistics.
;       Added code to make SEND automatically send KERMIT and REC commands
;       to remote Kermit. Can be de-activated with SET AUTOSEND OFF.
;       Changed filenames to lower case for Unix compatibility.
;       Added 3 byte CRC check type. Should eliminate problems with
;       PC Kermits that do 2 byte CRCs wrong (Select either 1 or 3 byte option
;       in Procomm Plus - vers 2.0 STILL does 2 byte checksums wrong.)
;       Added SY$M40 symbol for possible AM4000 machine.
;       Added code to avoid T.SEM problems with smart I/O cards
;       Enhanced file size calcs to work under extended directories
;       Added file closes to make compatible with AMOS 2.x
;       Kermit only delays five seconds before SENDING in REMOTE mode instead
;       of fifteen.
;       Changed VMAJOR to 2.
;[014] 28 March 1991 12:38      Edited by Bob Rubendunst
;       Added routine to adjust sleep value for faster baud rates.
;       Note that this does improve performance at higher baud rates,
;       especially for file transfers. Due to limitations in TTYIN monitor
;       call, Kermit can still lose characters at higher baud rates.
;       Fixed bug in effective baud rate calculation when calculating
;       date rollover at midnight.
;[013] 28 March 1991 12:08      Edited by Bob Rubendunst
;       Corrected problems with received filenames being expanded to 6 & 3
;       even if they were shorter.
;       Fixed problem in edit 12 with max packetsize not being defaulted
;       at startup.
;[012] 06 February 1990 09:23   Edited by Bob Rubendunst
;       Corrected a few bugs in checking for previous or next packet
;       needing to be ACKed. Also fixed parameter display to display
;       active END-OF-LINE caharcter, rather than default end-of-line.
;[011] 02 Dec 1988
;       made compare for ESCAPE character 7 bits instead of 8 bits
;       added BLOCKSIZE to SET command
;[010] 11 Sept 1988
;       Changed handling of port busy bit so that REMOTE users do not monitor
;       or  change the terminal busy bit. Defines new SY$ symbols for 68020 &
;       68030 if not already defined.
;[009] 29 Jun 1988
;       Completed basic compatibility with AM3000 systems
;[008] May 1988
;       Started compatibility with AM3000 systems.
;[007] 24 Oct 1986
;       Changed CONNEC routine to properly set T.DAT bit and T.XLT bits so
;       nulls can be sent from keyboard.
;[006] 29 Jul 1986
;       Tidied up SHOW command, added dot for every packet of data sent or
;       rec'd, SET ? now shows SET list.
;[005] ??
;       Change Kermit to accept running under AMOS/32. rpr
;[004] 12 May 1986
;       straightened out 8-bit quoting problem in RPAR
;       updated INUSE bit to use new bit under 1.3B
;       transformed SET BINQUOTE feature into SET PARITY feature
;       (does not set parity, but info is used to determine 7 or 8 bit modes.)
;       corrected checkbyte size detection problem when used with unix c
;       where ACK to F contained new filename under c. Alpha-Kermit thought
;       this was an ACK to an I packet and used the wrong checkbyte type.
;       Fixed 255 to 255. in max retries entry code 6/27/85 rpr
;       Fix requires keeping track of the ACKing of the I packet via RIACK(A0)
;       Fixed QBIN not defined on short received SINIT packet 4/24/85 rpr
;       AMUS release (clean-up same TCB use) 12/3/84 rpr
;       Added 7 bit mode to allow use with ELS... 10/23/84 rpr
;       First non-alpha transfers 10/5/84 with ibm pc
;[000]  07 Sept 1984 project begun

; Permission is granted to any individual or institution to copy or use this
; software and the routines described in it, except for explicitly commercial
; purposes. This software must not be sold to any person or institution.

;;;;;;;;;;;;;;;;;;;;;;;;;;;; D I S C L A I M E R ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; No warranty of the software or of the accuracy of the documentation     ;;
;; surrounding it is expressed or implied, and neither the authors,        ;;
;; Columbia University, Soft Machines, or AMUS acknowledge any liability   ;;
;; resulting from program or documentation errors.                         ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; usage format:
;       KERMIT <terminal-name> <escape character>
; then enter ? or HELP for use hints.

       SEARCH  SYS
       SEARCH  SYSSYM
       SEARCH  TRM
       COPY    CMDSYM

IF      NDF,SY$M20, SY$M20 = ^O20000    ; supply missing symbols [010]
IF      NDF,SY$M30, SY$M30 = ^O100000   ; supply missing symbols [010]
IF      NDF,SY$M40, SY$M40 = ^O2000000000 ; support possible 68040 [015]
IF      NDF,SY$EXT, SY$EXT = ^O10000000 ; support 8 bit terminals [021]
IF      NDF,TD$EXT, TD$EXT = ^O1000000000 ; support 8 bit terminals [021]
IF      NDF,T$EXT, T$EXT = ^O20000 ; support 8 bit terminals [021]

; supplementary symbols for finding file type & size
D.LEN=D.WRK
D.ACT=D.LEN+4
D.1ST=D.ACT+10

; symbols to define byte-word-lword relationships
; The Alpha Micro uses byte-swap logic to switch the sense of UDS & LDS
; in hardware, so that BYTE ACCESS of data is the opposite of normal 68000s.
; (This was done because the WD-16 processor used Intel style byte access,
; were the MSB of a word is stored at higher addresses. Motorola CPUs
; store words MSB at lower addresses.)
; (WORD & LWORD ACCESS is not affected, only BYTE ACCESS.)
; (change these definitions for non-AM style hardware!!)
       .B0W7   =       0       ; access LS byte of a 16 bit word
       .B8W15  =       1       ; access MS byte of a 16 bit word
       .B0L7   =       2       ; access bits 00-07 of a 32 bit word
       .B8L15  =       3       ; access bits 08-15 of a long word
       .B16L23 =       0       ; access bits 16-23 of a long word
       .B24L31 =       1       ; access bits 24-31 of a long word
       .W0L15  =       2       ; access LS word of long word
       .W16L31 =       0       ; access MS word of long word

; symbol definitions
TRUE    =       -1
FALSE   =       1


PAKSIZ  =       94.             ; max packet size
SOH     =       1.              ; default MARK character
CR      =       13.             ; ASCII carriage return
SPACE   =       32.             ; ASCII SP
DEL     =       127.            ; ASCII DEL
ESCCHR  =       '^              ; default escape character
A.BEL   =       7.              ; ASCII bell [24]

TRIES   =       10.             ; number of packet tries
MYQUOT  =       '#              ; control-quoting
MYPAD   =       0               ; number of pad chars
MYPCHR  =       0               ; the pad character I need
MYEOL   =       0               ; my end of line character
MYTIME  =       08.             ; seconds before timeout
MYBIN   =       'Y              ; binary qoute mode
MYCHK   =       '3              ; try to use 3 byte check bytes
MAXCHK  =       3               ; maximum check type supported
MAXTIM  =       60.             ; maximum timeout
MINTIM  =       2               ; minimum timeout period

; This macro is used to read a packet
DEFINE  RPACK   LEN,SEQ,PACKET,TYPE
       LEA     A3,PACKET
       CALL    RECPAK
       SSTS    D7
       MARG    MOVB,   D2,LEN
       MARG    MOVB,   D3,SEQ
       MARG    MOVB,   D4,TYPE
       LCC     D7
       ENDM

; This macro sends a packet to the REMOTE
DEFINE  SPACK   TYPE,SEQ,SIZE,PACKET
       LEA     A3,PACKET
       CCLR    SIZE,D2
       CCLR    SEQ,D3
       CCLR    TYPE,D4
       MARG    MOVB,   SIZE,D2
       MARG    MOVB,   SEQ,D3
       MARG    MOVB,   TYPE,D4
       CALL    SNDPAK
       ENDM

; This macro assembles argument linkage opcodes only where the default
; argument is not used. This provides more readable code without adding
; unnecessary instructions.
; For example, if D2 is the standard data link register, the macro
;       MARG    MOVW    D2,D2
; will not produce an assembly line, but
;       MARG    MOVW    D2,D3
; will assemble the line MOVW D2,D3
DEFINE  MARG    OPCODE, SRC, DST
       NTYPE   ...X,SRC
       NTYPE   ...Y,DST
       IF      NE,...X-...Y,OPCODE     SRC,DST
       ENDM
       ASECT


; This macro is used to pre-clear result variables before a packet call
; IF they are not registers.
DEFINE  CCLR    ARG,REG
       NTYPE   ...D,ARG
       NTYPE   ...E,REG
       IF      NE,...D-...E,CLR REG
       ENDM

       .=0
; define the impure area for KERMIT.
       NOSYM
; CONNECT command variables and general REMOTE/LOCAL channel variable
TNAME:  BLKW    2                       ; terminal name packed RAD50
SAVTDV: BLKL    1                       ; address of saved TDV
PSEUDO: BLKL    1                       ; address of PSEUDO driver
SAVSTS: BLKW    1                       ; saved TCB status
SAVJCB: BLKL    1                       ; saved attached JCB index
REMOTE: BLKL    1                       ; index to remote TCB
LOCAL:  BLKL    1                       ; index to local TCB
STIME:  BLKL    1                       ; start time of event
FSIZE:  BLKL    1                       ; size of file in bytes
KMETA:  BLKB    1                       ; escape character
DONE:   BLKB    1                       ; done with kermit flag
NOTALK: BLKB    1                       ; flag that remote TCB is job's.
ECHO:   BLKB    1                       ; duplex flag 0 for full, 377 for half
CCOUNT: BLKB    1                       ; control-c count
AUTOS:  BLKB    1                       ; autosend option for SEND
AUTOR:  BLKB    1                       ; AUTORECEIVE option for REC
COMSER: BLKB    1                       ; flag -1 if COMSER routines O.K.
EXTEND: BLKB    1                       ; extended device support flag
ABORTB: BLKB    1                       ; -1 if send batch to be aborted
ABORTF: BLKB    1                       ; -1 if send file to be aborted
WILDOK: BLKB    1                       ; -1 if wildcarding O.K.
CMASK:  BLKB    1                       ; bit mask for 7 or 8 bit characters
CFLAG:  BLKB    1                       ; flag we have breifed user on CONNECT
ATERM:  BLKB    7                       ; terminal name in ASCII & null
       EVEN
FIO:    BLKB    D.DDB                   ; file I/O ddb area
SIO:    BLKB    D.DDB                   ; ddb just for file spec & cmdlin
; KERMIT packet receiver variables
ASSUM:  BLKW    1               ; checksum storage
FRMSUM: BLKW    1               ; CRC storage
RTOUT:  BLKL    1               ; time's up in seconds from midnight.
FUDGE:  BLKL    1               ; fudge factor for midnight wrap-around
TIMINT: BLKL    1               ; # of seconds for timeout on sends
DF.TIM: BLKL    1               ; default timeout
; Global variables for file section
LOGIC:  BLKB    1               ;  1=false, -1=true
LDATA:  BLKB    1               ; size of present data
SPSIZ:  BLKB    1               ; max send packet size
PAD:    BLKB    1               ; # of padding chars to send
PADCHR: BLKB    1               ; pad character
EOL:    BLKB    1               ; EOL character to send
N:      BLKB    1               ; packet number
MAXTRY: BLKB    1               ; max # of tries
NUMTRY: BLKB    1               ; times this packet retried
OLDTRY: BLKB    1               ; times previous packet retried
BUFCNT: BLKB    1               ; # of data bytes for packet
DEBUGO: BLKB    1               ; level of debug output (0=none)
DING:   BLKB    1               ; ding after each command flag (#0=yes)
DF.EOL: BLKB    1               ; default EOL character
DF.CHK: BLKB    1               ; default check type character
PARITY: BLKB    1               ; parity mode (None, Odd, Even, Space.)
STATE:  BLKB    1               ; present state of file transfer automaton
QUOTE:  BLKB    1               ; incoming quote char
QBIN:   BLKB    1               ; storage & flag controlling 8 bit quoting:
                               ; 0  indicates 8 bit path, no quoting
                               ; -1 indicates 7 bit path, no quoting
                               ; all other values 33.-62. 96.-126. are valid
                               ; 8 bit quote characters (usually &)
CHKT:   BLKB    1               ; checkbyte method as ascii character
CHKNOW: BLKB    1               ; checkbyte in use for this packet
REPT:   BLKB    1               ; repeat byte (not implemented yet)
FLLEN:  BLKB    1               ; filename length
RMARK:  BLKB    1               ; the MARK character
RIACK:  BLKB    1               ; flag we got an ACK to an I packet
MXPKSZ: BLKB    1               ; maximum packet size allowed
STLCHR: BLKB    1               ; stall character time in 100ths of a second
RECPKT: BLKB    PAKSIZ          ; buffer for receiving packets
PACKET: BLKB    PAKSIZ          ;  another one
NFILNM: BLKB    4               ; room for MARK,LEN,SEQ,TYPE
FILNAM: BLKB    60.             ; current filename
       BLKB    20.
COPY:   BLKB    60.             ;       ; copied filename
       BLKB    PAKSIZ-80.
       EVEN
SLPVAL: BLKL    1               ; sleep value in ticks for GETREM routine
TFILES: BLKL    1               ; total files sent or received
TBYTES: BLKL    1               ; total bytes in files sent or received
TTIME:  BLKL    1               ; total elapsed times
CLDDB:  BLKB    D.DDB           ; CMDLIN.SYS ddb area
CMDERR: BLKL    1               ; CMDLIN.SYS .CMINI error cod
CMDPTR: BLKL    1               ; ptr to CMDLIN.SYS module
SAVSPC: BLKL    1               ; ptr to user's command line
CMNEXT: BLKL    1               ; saved flags from CM.NXT in CMDLIN routines
NXTCNT: BLKB    1               ; count of times NXTSPC called w/o wildcard
CMDFLG: BLKB    1               ; flag we have CMDLIN.SYS
       EVEN
CMDIMP: BLKB    IMP.SZ+100.     ; room for CMDLIN.SYS
       EVEN
KSIZE=.
       .=0
; definition of KERMIT packet offsets
MARK:   BLKB    1               ; the MARK character
LEN:    BLKB    1               ; received LEN
SEQ:    BLKB    1               ; received sequence
TYPE:   BLKB    1               ; received type
DATA:   BLKB    1               ; beginning of DATA
; 1, 2, or 3 byte check bytes follow the data and end the packet
       .=0
       SYM


REMMOD = T$IMI!T$ECS!T$DAT      ; IMAGE, NOECHO mode bits


; The following macros define character tranlation functions needed to
; implement the KERMIT protocol.
; MACROs to perform CHAR, UNCHAR & CTL functions via register argument.


; C H A R  - change control character to printable character
DEFINE  CHAR    DST
       ADDB    #SPACE,DST
       ENDM

; U N C H A R  -change CHARed control character back into a control character
DEFINE  UNCHAR  DST
       SUBB    #SPACE,DST
       ENDM

; CTL - UNCONTROLIFY a CHARACTER. CTL(CTL(CHAR)) leaves CHAR unchanged.
DEFINE  CTL     DST
       XORB    #64.,DST
       ENDM


       PSECT


;  K E R M I T
; Main Kermit routine. The first time executed, KERMIT builds its impure area,
; KERMIT.IMP. Then the main routine accepts and performs user commands.
;
       VMAJOR =2
       VMINOR =0
       VSUB = 0
       VEDIT = 024.
       VWHO =0

       RADIX   8.              ; default numbers in octal

KERMIT: PHDR    -1,PV$RSM!PV$WSM!PV$RPD!PV$WPD,PH$REE!PH$REU
       CMPB    @A2,#'/                 ; flag?
       BNE     2$
       INC     A2
       CMPB    @A2,#'?                 ; help?
       BEQ     1$
       TTYI
       ASCII   "undefined switch - assuming /? switch"
       BYTE    CR,A.BEL,0
       EVEN
1$:     TTYL    USAGE
       EXIT

; make sure we are running under an OS that supports TTYOUT.
2$:     CALL    KERTTL                  ; show title and version
       MOV     SYSTEM,D5               ; get system word
       AND     #SY$M20!SY$M30!SY$M40,D5 ; mask to just AMOS/32
       BNE     10$                     ;  we are on AMOS/32, has TTYOUT
       CMPB    PH.VER+.B8W15,#1.       ; MAJOR higher than 1?
       BHI     10$                     ;  yes-use new value
       MOVB    PH.VER+.B16L23,D5       ;  no- get sub release
       ANDB    #^O17,D5                ; strip out VWHO in top 4 bits
       CMPB    D5,#2.                  ; is this 1.2 or later?
       BHIS    10$                     ;  yes- we can execute
                                       ;  no- time to update the system!
       TTYI
       ASCII   "%This software requires AMOS/L 1.2 or later O/S."
       BYTE    CR,0
       EVEN
       EXIT

10$:    CALL    INIMEM                  ; initial memory area
        BNE    EXEUNT                  ;  need more memory-abort
        BMI    20$                     ; TCB already assigned
; first time entry. Check for CONNECT terminal name
       BYP                             ; scan past blanks
       CALL    FNDASN                  ; find and assign user supplied terminal-name
        BNE    EXEUNT                  ;  no match
       ORW     #FIL!LOK,-10(A0)        ; set file and locked in memo flags
20$:    JOBIDX                          ; index A6 to JCB
       ANDW    #^C<J.CCC>,@A6          ; clear control-c
       CALL    CHOICE                  ; get user's command choice
       BNE     20$                     ;  no such command!
       CALL    PROCES                  ; perform user's command
       TSTB    DONE(A0)                ; done ?
        BEQ    20$                     ;  no, accept another command