home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / alphamicro / am68k.m68 < prev    next >
Text File  |  2020-01-01  |  108KB  |  3,548 lines

  1. ; Kermit.m68 - a telecommunications & error free file transfer program
  2. ; Version 2.0 - supports wildcarding, 3 byte CRC
  3. ; Author:    Robert P. Rubendunst, Soft Machines,
  4. ;        P.O. box 3701, Champaign, IL 61821
  5.  
  6. ; Copyright 1984, 1991  Robert P. Rubendunst. All rights reserved. In
  7. ; addition, anthology copyrights prohibited without written permission from
  8. ; the author.
  9.  
  10. ; N O T E  - requires 1.3D AMOS/L//1.0D AMOS/32 or later to assemble.
  11. ; To assemble, M68 KERMIT.m68 produces KERMIT.LIT
  12.  
  13. ; Edit History:
  14. ;[024] 16 March 1994 13:45    Edited by Bob Rubendunst
  15. ;    Added test & message when re-entering user tries to 
  16. ;    re-specify port name.
  17. ;[023] 31 January 1992 10:49    Edited by Bob Rubendunst
  18. ;    Corrected problems in RPAR which caused file transfers to fail.
  19. ;[022] 10 January 1992 09:37    Edited by Bob Rubendunst
  20. ;    Added logic to strip CONNECT to 7 bits if PARITY is not NONE.
  21. ;[021] 09 January 1992 09:37    Edited by Bob Rubendunst
  22. ;    Documentation changes in CONNECT message
  23. ;    Added TIMEOUT and ENDLINE parametes to SET parameters list in SHOW
  24. ;    Changed SHOCHR to always display 3 characters, show ^ as dim if ctl
  25. ;    fixed problem with outputting zero byte files
  26. ;    improved SPAR & RPAR logic to handle 7 bit cases better.
  27. ;[020] 31 December 1991 11:06    Edited by Bob Rubendunst
  28. ;    Added code to make CONNECT mode compatible with 8 bit terminals.
  29. ;    (Exit character must match all 8 bits if TDV presents TD$EXT)
  30. ;    Deleted BPT legerdemain and just used SUPVR instead in SETSTS!
  31. ;[019] 31 December 1991 10:41    Edited by Bob Rubendunst
  32. ;    AUTORECEIVE feature completed
  33. ;[018] 06 December 1991 13:08    Edited by Bob Rubendunst
  34. ;    Added random file bypass for batch SENDing.
  35. ;    Added code to eliminate possible bogus packet timeout at midnight.
  36. ;    Added command line help.
  37. ;    Added SET PARITY input checking
  38. ;[017] 02 December 1991 11:48    Edited by Bob Rubendunst
  39. ;    Added SET PACKETSTART option
  40. ;    Deleted code to save & restore jcb jobtyp word (not used)
  41. ;[016] 22 November 1991 13:27    Edited by Bob Rubendunst
  42. ;    Added AUTORECEIVE command
  43. ;    Changed SEND logic to send a Break packet if no files sent.
  44. ;    Corrected some help text with Karen Bojda's help.
  45. ;    Streamlined INUSE subroutine
  46. ;    Added code to revive job when attaching JCB & TCB
  47. ;    Completed graceful abort code for SENDing
  48. ;    Corrected tests for maximum retries - some were BNE instead of BLOS
  49. ;[015] 31 October 1991 16:49    Edited by Bob Rubendunst
  50. ;    Added wildcarding via CMDLIN.SYS. Kudos to Tom Niccum of KW fame.
  51. ;    Added totals statistics.
  52. ;    Added code to make SEND automatically send KERMIT and REC commands
  53. ;    to remote Kermit. Can be de-activated with SET AUTOSEND OFF.
  54. ;    Changed filenames to lower case for Unix compatibility.
  55. ;    Added 3 byte CRC check type. Should eliminate problems with
  56. ;    PC Kermits that do 2 byte CRCs wrong (Select either 1 or 3 byte option
  57. ;    in Procomm Plus - vers 2.0 STILL does 2 byte checksums wrong.)
  58. ;    Added SY$M40 symbol for possible AM4000 machine.
  59. ;    Added code to avoid T.SEM problems with smart I/O cards
  60. ;    Enhanced file size calcs to work under extended directories
  61. ;    Added file closes to make compatible with AMOS 2.x
  62. ;    Kermit only delays five seconds before SENDING in REMOTE mode instead
  63. ;    of fifteen.
  64. ;    Changed VMAJOR to 2.
  65. ;[014] 28 March 1991 12:38    Edited by Bob Rubendunst
  66. ;    Added routine to adjust sleep value for faster baud rates.
  67. ;    Note that this does improve performance at higher baud rates,
  68. ;    especially for file transfers. Due to limitations in TTYIN monitor
  69. ;    call, Kermit can still lose characters at higher baud rates.
  70. ;    Fixed bug in effective baud rate calculation when calculating
  71. ;    date rollover at midnight.
  72. ;[013] 28 March 1991 12:08    Edited by Bob Rubendunst
  73. ;    Corrected problems with received filenames being expanded to 6 & 3
  74. ;    even if they were shorter.
  75. ;    Fixed problem in edit 12 with max packetsize not being defaulted
  76. ;    at startup.
  77. ;[012] 06 February 1990 09:23    Edited by Bob Rubendunst
  78. ;    Corrected a few bugs in checking for previous or next packet
  79. ;    needing to be ACKed. Also fixed parameter display to display
  80. ;    active END-OF-LINE caharcter, rather than default end-of-line.
  81. ;[011] 02 Dec 1988
  82. ;    made compare for ESCAPE character 7 bits instead of 8 bits
  83. ;     added BLOCKSIZE to SET command
  84. ;[010] 11 Sept 1988
  85. ;    Changed handling of port busy bit so that REMOTE users do not monitor
  86. ;    or  change the terminal busy bit. Defines new SY$ symbols for 68020 & 
  87. ;    68030 if not already defined.
  88. ;[009] 29 Jun 1988
  89. ;    Completed basic compatibility with AM3000 systems
  90. ;[008] May 1988
  91. ;    Started compatibility with AM3000 systems.
  92. ;[007] 24 Oct 1986
  93. ;    Changed CONNEC routine to properly set T.DAT bit and T.XLT bits so 
  94. ;    nulls can be sent from keyboard.
  95. ;[006] 29 Jul 1986
  96. ;    Tidied up SHOW command, added dot for every packet of data sent or
  97. ;    rec'd, SET ? now shows SET list.
  98. ;[005] ??
  99. ;    Change Kermit to accept running under AMOS/32. rpr
  100. ;[004] 12 May 1986
  101. ;       straightened out 8-bit quoting problem in RPAR
  102. ;    updated INUSE bit to use new bit under 1.3B
  103. ;    transformed SET BINQUOTE feature into SET PARITY feature
  104. ;    (does not set parity, but info is used to determine 7 or 8 bit modes.)
  105. ;    corrected checkbyte size detection problem when used with unix c
  106. ;    where ACK to F contained new filename under c. Alpha-Kermit thought
  107. ;    this was an ACK to an I packet and used the wrong checkbyte type.
  108. ;    Fixed 255 to 255. in max retries entry code 6/27/85 rpr
  109. ;    Fix requires keeping track of the ACKing of the I packet via RIACK(A0)
  110. ;    Fixed QBIN not defined on short received SINIT packet 4/24/85 rpr
  111. ;    AMUS release (clean-up same TCB use) 12/3/84 rpr
  112. ;     Added 7 bit mode to allow use with ELS... 10/23/84 rpr
  113. ;    First non-alpha transfers 10/5/84 with ibm pc
  114. ;[000]    07 Sept 1984 project begun
  115.  
  116. ; Permission is granted to any individual or institution to copy or use this
  117. ; software and the routines described in it, except for explicitly commercial
  118. ; purposes. This software must not be sold to any person or institution.
  119.  
  120. ;;;;;;;;;;;;;;;;;;;;;;;;;;;; D I S C L A I M E R ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  121. ;; No warranty of the software or of the accuracy of the documentation     ;;
  122. ;; surrounding it is expressed or implied, and neither the authors,        ;;
  123. ;; Columbia University, Soft Machines, or AMUS acknowledge any liability   ;;
  124. ;; resulting from program or documentation errors.                         ;;
  125. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  126.  
  127. ; usage format:
  128. ;    KERMIT <terminal-name> <escape character>
  129. ; then enter ? or HELP for use hints.
  130.  
  131.     SEARCH    SYS
  132.     SEARCH    SYSSYM
  133.     SEARCH    TRM
  134.     COPY    CMDSYM
  135.  
  136. IF    NDF,SY$M20, SY$M20 = ^O20000    ; supply missing symbols [010]
  137. IF    NDF,SY$M30, SY$M30 = ^O100000    ; supply missing symbols [010]
  138. IF    NDF,SY$M40, SY$M40 = ^O2000000000 ; support possible 68040 [015]
  139. IF    NDF,SY$EXT, SY$EXT = ^O10000000 ; support 8 bit terminals [021]
  140. IF    NDF,TD$EXT, TD$EXT = ^O1000000000 ; support 8 bit terminals [021]
  141. IF    NDF,T$EXT, T$EXT = ^O20000 ; support 8 bit terminals [021]
  142.  
  143. ; supplementary symbols for finding file type & size
  144. D.LEN=D.WRK
  145. D.ACT=D.LEN+4
  146. D.1ST=D.ACT+10
  147.  
  148. ; symbols to define byte-word-lword relationships
  149. ; The Alpha Micro uses byte-swap logic to switch the sense of UDS & LDS
  150. ; in hardware, so that BYTE ACCESS of data is the opposite of normal 68000s.
  151. ; (This was done because the WD-16 processor used Intel style byte access,
  152. ; were the MSB of a word is stored at higher addresses. Motorola CPUs
  153. ; store words MSB at lower addresses.)
  154. ; (WORD & LWORD ACCESS is not affected, only BYTE ACCESS.)
  155. ; (change these definitions for non-AM style hardware!!)
  156.     .B0W7    =    0    ; access LS byte of a 16 bit word
  157.     .B8W15    =    1    ; access MS byte of a 16 bit word
  158.     .B0L7    =    2    ; access bits 00-07 of a 32 bit word    
  159.     .B8L15    =    3    ; access bits 08-15 of a long word
  160.     .B16L23    =    0    ; access bits 16-23 of a long word
  161.     .B24L31    =    1    ; access bits 24-31 of a long word
  162.     .W0L15    =    2    ; access LS word of long word
  163.     .W16L31    =    0    ; access MS word of long word
  164.  
  165. ; symbol definitions
  166. TRUE    =    -1
  167. FALSE    =    1
  168.  
  169.  
  170. PAKSIZ    =    94.        ; max packet size
  171. SOH    =    1.        ; default MARK character
  172. CR    =    13.        ; ASCII carriage return
  173. SPACE    =    32.        ; ASCII SP
  174. DEL    =    127.        ; ASCII DEL
  175. ESCCHR    =    '^        ; default escape character
  176. A.BEL    =    7.        ; ASCII bell [24]
  177.  
  178. TRIES    =    10.        ; number of packet tries
  179. MYQUOT    =    '#        ; control-quoting
  180. MYPAD    =    0        ; number of pad chars
  181. MYPCHR    =    0        ; the pad character I need
  182. MYEOL    =    0        ; my end of line character
  183. MYTIME    =    08.        ; seconds before timeout
  184. MYBIN    =    'Y        ; binary qoute mode
  185. MYCHK    =    '3        ; try to use 3 byte check bytes
  186. MAXCHK    =    3        ; maximum check type supported
  187. MAXTIM    =    60.        ; maximum timeout
  188. MINTIM    =    2        ; minimum timeout period
  189.  
  190. ; This macro is used to read a packet
  191. DEFINE    RPACK    LEN,SEQ,PACKET,TYPE
  192.     LEA    A3,PACKET
  193.     CALL    RECPAK
  194.     SSTS    D7
  195.     MARG    MOVB,    D2,LEN
  196.     MARG    MOVB,    D3,SEQ
  197.     MARG    MOVB,    D4,TYPE
  198.     LCC    D7
  199.     ENDM
  200.  
  201. ; This macro sends a packet to the REMOTE
  202. DEFINE    SPACK    TYPE,SEQ,SIZE,PACKET
  203.     LEA    A3,PACKET
  204.     CCLR    SIZE,D2
  205.     CCLR    SEQ,D3
  206.     CCLR    TYPE,D4
  207.     MARG    MOVB,    SIZE,D2
  208.     MARG    MOVB,    SEQ,D3
  209.     MARG    MOVB,    TYPE,D4
  210.     CALL    SNDPAK
  211.     ENDM
  212.  
  213. ; This macro assembles argument linkage opcodes only where the default
  214. ; argument is not used. This provides more readable code without adding
  215. ; unnecessary instructions.
  216. ; For example, if D2 is the standard data link register, the macro
  217. ;    MARG    MOVW    D2,D2
  218. ; will not produce an assembly line, but
  219. ;    MARG    MOVW    D2,D3
  220. ; will assemble the line MOVW D2,D3    
  221. DEFINE    MARG    OPCODE, SRC, DST
  222.     NTYPE    ...X,SRC
  223.     NTYPE    ...Y,DST
  224.     IF    NE,...X-...Y,OPCODE    SRC,DST
  225.     ENDM
  226.     ASECT
  227.  
  228.  
  229. ; This macro is used to pre-clear result variables before a packet call
  230. ; IF they are not registers.
  231. DEFINE    CCLR    ARG,REG
  232.     NTYPE    ...D,ARG
  233.     NTYPE    ...E,REG
  234.     IF    NE,...D-...E,CLR REG
  235.     ENDM
  236.  
  237.     .=0
  238. ; define the impure area for KERMIT.
  239.     NOSYM
  240. ; CONNECT command variables and general REMOTE/LOCAL channel variable
  241. TNAME:    BLKW    2            ; terminal name packed RAD50
  242. SAVTDV:    BLKL    1            ; address of saved TDV
  243. PSEUDO:    BLKL    1            ; address of PSEUDO driver
  244. SAVSTS:    BLKW    1            ; saved TCB status
  245. SAVJCB:    BLKL    1            ; saved attached JCB index
  246. REMOTE:    BLKL    1            ; index to remote TCB
  247. LOCAL:    BLKL    1            ; index to local TCB
  248. STIME:    BLKL    1            ; start time of event
  249. FSIZE:    BLKL    1            ; size of file in bytes
  250. KMETA:    BLKB    1            ; escape character
  251. DONE:    BLKB    1            ; done with kermit flag
  252. NOTALK:    BLKB    1            ; flag that remote TCB is job's.
  253. ECHO:    BLKB    1            ; duplex flag 0 for full, 377 for half
  254. CCOUNT:    BLKB    1            ; control-c count
  255. AUTOS:    BLKB    1            ; autosend option for SEND
  256. AUTOR:    BLKB    1            ; AUTORECEIVE option for REC
  257. COMSER:    BLKB    1            ; flag -1 if COMSER routines O.K.
  258. EXTEND:    BLKB    1            ; extended device support flag
  259. ABORTB:    BLKB    1            ; -1 if send batch to be aborted
  260. ABORTF:    BLKB    1            ; -1 if send file to be aborted
  261. WILDOK:    BLKB    1            ; -1 if wildcarding O.K.
  262. CMASK:    BLKB    1            ; bit mask for 7 or 8 bit characters
  263. CFLAG:    BLKB    1            ; flag we have breifed user on CONNECT
  264. ATERM:    BLKB    7            ; terminal name in ASCII & null
  265.     EVEN
  266. FIO:    BLKB    D.DDB            ; file I/O ddb area
  267. SIO:    BLKB    D.DDB            ; ddb just for file spec & cmdlin
  268. ; KERMIT packet receiver variables
  269. ASSUM:    BLKW    1        ; checksum storage
  270. FRMSUM:    BLKW    1        ; CRC storage
  271. RTOUT:    BLKL    1        ; time's up in seconds from midnight.
  272. FUDGE:    BLKL    1        ; fudge factor for midnight wrap-around
  273. TIMINT:    BLKL    1        ; # of seconds for timeout on sends
  274. DF.TIM:    BLKL    1        ; default timeout
  275. ; Global variables for file section
  276. LOGIC:    BLKB    1        ;  1=false, -1=true
  277. LDATA:    BLKB    1        ; size of present data
  278. SPSIZ:    BLKB    1        ; max send packet size
  279. PAD:    BLKB    1        ; # of padding chars to send
  280. PADCHR:    BLKB    1        ; pad character
  281. EOL:    BLKB    1        ; EOL character to send
  282. N:    BLKB    1        ; packet number
  283. MAXTRY:    BLKB    1        ; max # of tries
  284. NUMTRY:    BLKB    1        ; times this packet retried
  285. OLDTRY:    BLKB    1        ; times previous packet retried
  286. BUFCNT:    BLKB    1        ; # of data bytes for packet
  287. DEBUGO:    BLKB    1        ; level of debug output (0=none)
  288. DING:    BLKB    1        ; ding after each command flag (#0=yes)
  289. DF.EOL:    BLKB    1        ; default EOL character
  290. DF.CHK:    BLKB    1        ; default check type character
  291. PARITY:    BLKB    1        ; parity mode (None, Odd, Even, Space.)
  292. STATE:    BLKB    1        ; present state of file transfer automaton
  293. QUOTE:    BLKB    1        ; incoming quote char
  294. QBIN:    BLKB    1        ; storage & flag controlling 8 bit quoting:
  295.                 ; 0  indicates 8 bit path, no quoting
  296.                 ; -1 indicates 7 bit path, no quoting
  297.                 ; all other values 33.-62. 96.-126. are valid
  298.                 ; 8 bit quote characters (usually &)
  299. CHKT:    BLKB    1        ; checkbyte method as ascii character
  300. CHKNOW:    BLKB    1        ; checkbyte in use for this packet
  301. REPT:    BLKB    1        ; repeat byte (not implemented yet)
  302. FLLEN:    BLKB    1        ; filename length
  303. RMARK:    BLKB    1        ; the MARK character
  304. RIACK:    BLKB    1        ; flag we got an ACK to an I packet
  305. MXPKSZ:    BLKB    1        ; maximum packet size allowed
  306. STLCHR:    BLKB    1        ; stall character time in 100ths of a second
  307. RECPKT:    BLKB    PAKSIZ        ; buffer for receiving packets
  308. PACKET:    BLKB    PAKSIZ        ;  another one
  309. NFILNM:    BLKB    4        ; room for MARK,LEN,SEQ,TYPE
  310. FILNAM:    BLKB    60.        ; current filename
  311.     BLKB    20.
  312. COPY:    BLKB    60.        ;    ; copied filename
  313.     BLKB    PAKSIZ-80.
  314.     EVEN
  315. SLPVAL:    BLKL    1        ; sleep value in ticks for GETREM routine
  316. TFILES:    BLKL    1        ; total files sent or received
  317. TBYTES:    BLKL    1        ; total bytes in files sent or received
  318. TTIME:    BLKL    1        ; total elapsed times
  319. CLDDB:    BLKB    D.DDB        ; CMDLIN.SYS ddb area
  320. CMDERR:    BLKL    1        ; CMDLIN.SYS .CMINI error cod
  321. CMDPTR:    BLKL    1        ; ptr to CMDLIN.SYS module
  322. SAVSPC:    BLKL    1        ; ptr to user's command line
  323. CMNEXT:    BLKL    1        ; saved flags from CM.NXT in CMDLIN routines
  324. NXTCNT:    BLKB    1        ; count of times NXTSPC called w/o wildcard
  325. CMDFLG:    BLKB    1        ; flag we have CMDLIN.SYS
  326.     EVEN
  327. CMDIMP:    BLKB    IMP.SZ+100.    ; room for CMDLIN.SYS
  328.     EVEN
  329. KSIZE=.
  330.     .=0
  331. ; definition of KERMIT packet offsets
  332. MARK:    BLKB    1        ; the MARK character
  333. LEN:    BLKB    1        ; received LEN
  334. SEQ:    BLKB    1        ; received sequence
  335. TYPE:    BLKB    1        ; received type
  336. DATA:    BLKB    1        ; beginning of DATA
  337. ; 1, 2, or 3 byte check bytes follow the data and end the packet
  338.     .=0
  339.     SYM
  340.  
  341.  
  342. REMMOD = T$IMI!T$ECS!T$DAT    ; IMAGE, NOECHO mode bits
  343.  
  344.  
  345. ; The following macros define character tranlation functions needed to
  346. ; implement the KERMIT protocol.
  347. ; MACROs to perform CHAR, UNCHAR & CTL functions via register argument.
  348.  
  349.  
  350. ; C H A R  - change control character to printable character
  351. DEFINE    CHAR    DST
  352.     ADDB    #SPACE,DST
  353.     ENDM
  354.  
  355. ; U N C H A R  -change CHARed control character back into a control character
  356. DEFINE    UNCHAR    DST
  357.     SUBB    #SPACE,DST
  358.     ENDM
  359.  
  360. ; CTL - UNCONTROLIFY a CHARACTER. CTL(CTL(CHAR)) leaves CHAR unchanged.
  361. DEFINE    CTL    DST
  362.     XORB    #64.,DST
  363.     ENDM
  364.  
  365.  
  366.     PSECT
  367.  
  368.  
  369. ;  K E R M I T
  370. ; Main Kermit routine. The first time executed, KERMIT builds its impure area,
  371. ; KERMIT.IMP. Then the main routine accepts and performs user commands.
  372.     VMAJOR =2
  373.     VMINOR =0
  374.     VSUB = 0
  375.     VEDIT = 024.
  376.     VWHO =0
  377.  
  378.     RADIX    8.        ; default numbers in octal
  379.  
  380. KERMIT:    PHDR    -1,PV$RSM!PV$WSM!PV$RPD!PV$WPD,PH$REE!PH$REU
  381.     CMPB    @A2,#'/            ; flag?
  382.     BNE    2$
  383.     INC    A2
  384.     CMPB    @A2,#'?            ; help?
  385.     BEQ    1$
  386.     TTYI
  387.     ASCII    "undefined switch - assuming /? switch"
  388.     BYTE    CR,A.BEL,0
  389.     EVEN
  390. 1$:    TTYL    USAGE
  391.     EXIT
  392.  
  393. ; make sure we are running under an OS that supports TTYOUT.
  394. 2$:    CALL    KERTTL            ; show title and version
  395.     MOV    SYSTEM,D5        ; get system word
  396.     AND    #SY$M20!SY$M30!SY$M40,D5 ; mask to just AMOS/32
  397.     BNE    10$            ;  we are on AMOS/32, has TTYOUT
  398.     CMPB    PH.VER+.B8W15,#1.    ; MAJOR higher than 1?
  399.     BHI    10$            ;  yes-use new value
  400.     MOVB    PH.VER+.B16L23,D5    ;  no- get sub release
  401.     ANDB    #^O17,D5        ; strip out VWHO in top 4 bits
  402.     CMPB    D5,#2.            ; is this 1.2 or later?
  403.     BHIS    10$            ;  yes- we can execute
  404.                     ;  no- time to update the system!
  405.     TTYI
  406.     ASCII    "%This software requires AMOS/L 1.2 or later O/S."
  407.     BYTE    CR,0
  408.     EVEN
  409.     EXIT
  410.  
  411. 10$:    CALL    INIMEM            ; initial memory area
  412.      BNE    EXEUNT            ;  need more memory-abort
  413.      BMI    20$            ; TCB already assigned
  414. ; first time entry. Check for CONNECT terminal name
  415.     BYP                ; scan past blanks
  416.     CALL    FNDASN            ; find and assign user supplied terminal-name
  417.      BNE    EXEUNT            ;  no match
  418.     ORW    #FIL!LOK,-10(A0)    ; set file and locked in memo flags
  419. 20$:    JOBIDX                ; index A6 to JCB
  420.     ANDW    #^C<J.CCC>,@A6        ; clear control-c
  421.     CALL    CHOICE            ; get user's command choice
  422.     BNE    20$            ;  no such command!
  423.     CALL    PROCES            ; perform user's command
  424.     TSTB    DONE(A0)        ; done ?
  425.      BEQ    20$            ;  no, accept another command.
  426.  
  427. 40$:    CLRB    DONE(A0)
  428.  
  429. ; E X E U N T  - exit back to AMOS
  430. EXEUNT:    EXIT
  431.  
  432. ; I N I M E M 
  433. ; This routine builds, clears and initializes the user's impure area.
  434. INIMEM:    LEA    A6,IMPNAM        ; index impure module name
  435.     SRCH    @A6,A0,F.USR        ; search user area for kermit
  436.     BEQ    10$            ; already present-done
  437.     GETIMP    KSIZE,A0,100$        ; allocate impure area
  438.     CLEAR    @A0,KSIZE        ; clear it (redundant now, so what!)
  439.     LEA    A6,IMPNAM
  440.     MOV    (A6)+,-6(A0)        ; set module name to program name
  441.     MOVW    @A6,-2(A0)        ;  set module extension to .IMP
  442. ; do first time-only inits
  443.     CALL    INI2            ; get JCB & attached TCB addresses
  444.     CALL    INIXFR            ; init xfer section once.
  445.     CALL    OSVER            ; determine O/S version
  446.     CALL    TRMVER            ; determine terminal driver version
  447.     MOVB    #ESCCHR,KMETA(A0)    ; set CONNECT ESCAPE character
  448.     MOVB    #PAKSIZ,MXPKSZ(A0)    ; set maximum packet size allowed [13]
  449.     MOV    #100.,SLPVAL(A0)    ; set sleep ticks for GETREM [14]
  450.     MOVB    #-1,AUTOS(A0)        ; invoke auto-send [15]
  451.     MOVB    #-1,AUTOR(A0)        ; invoke auto-receive [16]
  452.     LCC    #PS.Z
  453.     RTN
  454.  
  455. ; finish re-entry inits
  456. 10$:    CALL    INI2            ; get JCB & attached TCB AGAIN
  457.     BYP                ; [024]
  458.     LIN                ; [024] port named?
  459.     BEQ    20$            ; [024]   no
  460.     TTYL    RENTER            ; [024]   yes, been there, done that!
  461. 20$:    LCC    #PS.N!PS.Z        ; set N and Z if impure already there
  462.     RTN
  463.  
  464. ; not enough memory, so depart
  465. 100$:    TYPECR    <?Insufficient memory for KERMIT.>
  466.     LCC    #0            ; flag no memory
  467.     RTN
  468.  
  469. ; OSVER plays twenty questions games to find out what resources are
  470. ; available in current operating system.
  471. OSVER:    MOV    SYSTEM,D7
  472.     AND    #SY$EXD,D7        ; system supports extended disks?
  473.     SETNE    EXTEND(A0)        ; set flag -1 if extended disk O.K.
  474.     CLRB    COMSER(A0)        ; assume we don't have new comm stuff
  475.     MOV    SYSTEM,D7        ; get system word
  476.     AND    #SY$M20!SY$M30!SY$M40,D7 ; mask to just AMOS/32
  477.     BNE    10$            ; all AMOS/32 has COMSER, CMDLIN
  478.     CMPB    PH.VER+.B8W15,#1.    ; MAJOR higher than 1?
  479.     BHI    10$            ;  yes-use new value
  480.     MOVB    PH.VER+.B16L23,D7    ;  no- get sub release
  481.     ANDB    #^O17,D7        ; strip out VWHO in top 4 bits
  482.     CMPB    D7,#3.            ; is this 1.3?
  483.     BLO    30$            ;  no-1.2 or older, no COMSER
  484.     BHI    10$            ;  no-1.4 or higher COMSER fur sure!
  485.     SETB    WILDOK(A0)        ; wildcarding started in 1.3
  486.     MOVB    PH.VER+.B8L15,D7    ;  exactly 1.3 - check for B
  487.     LSRB    D7,#4.            ; bring it to ground zero.
  488.     CMPB    D7,#'I-'@        ; is it B or higher?
  489.     BEQ    30$            ; 1.3I comes before 1.3B (go figure)
  490.     CMPB    D7,#'B-'@        ; is it B or higher?
  491.     BLO    30$            ;  yes-use new value
  492. 10$:    SETB    WILDOK(A0)        ; O.K. to user CMDLIN.SYS
  493. 20$:    SETB    COMSER(A0)        ; O/S has COMSER routines
  494. 30$:    RTN                ; O/S has got not a lot...
  495.  
  496. ; determine terminal driver resources (7 or 8 bit system & terminal driver)
  497. TRMVER:    MOVB    #^B01111111,CMASK(A0)    ; preset mask for 7 bit terminal
  498.     MOV    SYSTEM,D7        ; get system type
  499.     AND    #SY$EXT,D7        ; does system support 8 bit terms?
  500.     BEQ    10$            ;  no
  501.     MOV    LOCAL(A0),A5        ; A5 indexs local TCB
  502.     MOV    T.TDV(A5),A6        ; index terminal driver
  503.     MOVW    TD.TYP(A6),D7        ; get type word
  504.     ANDW    #TD$NEW,D7        ; is it a "new" TDV
  505.     BEQ    10$            ;  no, use 7 bit mask
  506.     MOV    TD.FLG(A6),D7        ;  yes, get tdv's flag bits
  507.     AND    #TD$EXT,D7        ;  mask
  508.     BEQ    10$            ; tdv is recent, but only 7 bit!
  509.     MOVB    #-1,CMASK(A0)        ;  TDV supports 8 bit terminals
  510. 10$:    RTN
  511.  
  512.  
  513. ; These values are inited every time KERMIT is executed.
  514. INI2:    JOBIDX    A6            ; index A6 to JCB
  515.     MOV    JOBTRM(A6),LOCAL(A0)    ; save address of local TCB
  516.     RTN
  517.  
  518. ; I N I X F R
  519. ; Initialize the the file transfer area
  520. INIXFR:    MOVB    #MYEOL,DF.EOL(A0)    ; set default EOL [17]
  521.     MOVB    #MYCHK,DF.CHK(A0)    ; set default check type
  522.     MOVB    #'N,PARITY(A0)        ; set parity to NONE.
  523.     MOVB    #PAKSIZ,SPSIZ(A0)    ; set max send size
  524. ;
  525.     MOVB    #SOH,RMARK(A0)        ; define start of packet byte
  526.     MOVB    #MYQUOT,QUOTE(A0)    ; set quote char
  527.     MOV    LOCAL(A0),A5        ; set index
  528.     MOVB    #MYPAD,PAD(A0)        ; pad count
  529.     MOVB    #MYPCHR,PADCHR(A0)    ; & character
  530.     MOVB    #TRIES,MAXTRY(A0)    ; set max tries
  531.     MOVB    #'1,CHKT(A0)        ; checkbyte type
  532.     MOV    #08.,TIMINT(A0)        ; set timeout period
  533.     MOV    #08.,DF.TIM(A0)        ; set default timeout period
  534.     RTN    
  535.  
  536. ;  F N D A S N
  537. ; FNDASN finds the user specified TCB, and marks it as busy if found.
  538. ; The "busy" bit in the TCB depends on the O/S version.
  539. ; If the O/S version is before 1.3B AMOS/L, the busy bit is bit 11. of T.STS
  540. ; If the O/S is AMOS/32, or AMOS/L 1.3B or later, the busy is bit 9. of T.STS
  541. FNDASN:    JOBIDX    A6            ; index A6 to JCB
  542.     MOV    JOBTRM(A6),A5        ; index our own TCB as default
  543.     LIN                ; user provide terminal name
  544.     BEQ    25$            ;  no-use our own terminal
  545.     LEA    A1,TNAME(A0)        ; index terminal name storage
  546.     PUSH    A1            ; save for unpack
  547.     PACK
  548.     PACK                ; pack the terminal name RAD50
  549.     POP    A1
  550.     LEA    A2,ATERM(A0)        ; then unpack it for later
  551.     UNPACK
  552.     UNPACK
  553.     CLRB    @A2            ; save ASCII version for SHOW.
  554.     MOV    TNAME(A0),D6        ; D6 gets whole RAD50 terminal name
  555.     LEA    A3,TRMDFC        ; index the head of the TCB chain
  556. 10$:    MOV    @A3,D7            ; get link to next entry
  557.     JEQ    100$            ;  no matching TCB name          [010]
  558.     MOV    D7,A3            ; A3 indexs next element
  559. 20$:    CMPL    D6,4(A3)        ; compare to this entry
  560.     BNE    10$            ;  try next one if no match
  561. ; TCB with matching name is found. Check for prior use
  562.     LEA    A6,10(A3)        ; index A6 to remote TCB         [010]
  563.     CMP    A5,A6            ; using specified own terminal?  [010]
  564.     BNE    22$            ;  no
  565.     CLRB    ATERM(A0)        ;  yes-clear name of terminal to [010]
  566.                     ;  to flag comm port & user's    [010]
  567.                     ;  port are the same.            [010]
  568. 22$:    MOV    A6,A5            ; index A5 to comm port          [010]
  569. 25$:    MOVW    @A5,SAVSTS(A0)        ; save the TCB status      
  570.     CALL    INUSE            ; get proper in-use bits
  571.     TSTB    ATERM(A0)        ; user & comm port the same?     [010]
  572.     BEQ    250$            ;  yes-leave busy bit as is      [010]
  573.     BSET    D6,1(A5)        ; set "assigned" bit
  574.     BNE    110$            ;  already set by prior use-.
  575. 250$:    MOV    A5,REMOTE(A0)        ; save pointer to remote TCB     [010]
  576.     MOV    T.TDV(A5),SAVTDV(A0)    ; save old TDV address
  577. ; find address of PSEUDO TCB in memory for data transfer use.
  578.     MOV    SAVTDV(A0),PSEUDO(A0)    ; preset any TDV in case PSEUDO is gone!
  579.     MOV    TRMTDC,A6        ; get base of tdv chain
  580.     MOV    #[PSE]_16.+[UDO],D7    ; D7 gets PSEUDO in RAD50 notation
  581. 30$:    CMP    D7,4(A6)        ; match ?
  582.     BEQ    40$            ;  yes
  583.     MOV    @A6,A6            ;  no-get next link
  584.     MOV    A6,D6            ; set flags
  585.     BNE    30$            ;  keep trying
  586.     BR    50$             ; give up
  587. 40$:    ADD    #^O10,A6        ; add offset size of link word and name
  588.     MOV    A6,PSEUDO(A0)        ; save address of PSEUDO driver
  589. 50$:    CMP    A5,LOCAL(A0)        ; TCB same as job's terminal's?
  590.     SETEQ    NOTALK(A0)        ;  yes-flag KERMIT owns the data TCB
  591.     BEQ    60$            ;   and bypass TDV swap.
  592. ; swap in PSEUDO terminal driver instead of normal TDV because some TDVs will
  593. ; use multi-byte capture sequences or other translate routines, which will
  594. ; mess up incoming or outgoing data.
  595. ; (There is a cleaner way to do this in newer O/Ss, but it isn't
  596. ; backwards compatible, so we won't bother - rpr 12/31/91)
  597.     MOV    PSEUDO(A0),T.TDV(A5)    ; substitute PSEUDO driver on remote
  598. ; unless TCB is owned by KERMIT job, detach all TCB <=> JCB links
  599. 60$:    MOV    T.JLK(A5),A6        ; get JCB link
  600.     MOV    A6,SAVJCB(A0)        ; save the JCB address for EXIT
  601.     BEQ    70$            ;  TCB already detached-done
  602.     TSTB    NOTALK(A0)        ; TCB owned by KERMIT job?
  603.     BNE    70$            ;  yes-leave it attached
  604.     CLR    JOBTRM(A6)        ;   else detach TCB from job
  605.     CLR    T.JLK(A5)        ;    and job from TCB
  606. 70$:    LCC    #PS.Z
  607.     RTN
  608.  
  609. 100$:    TTYL    NMTN
  610.     LCC    #0
  611.     RTN
  612. 110$:    TYPECR    <?terminal is being used by another job.>
  613.     LCC    #0
  614.     RTN
  615.  
  616. ; INUSE - routine to determine the proper INUSE bit values for this OS.
  617. ; The "busy" bit in the TCB depends on the O/S version.
  618. ; If the O/S version is before 1.3B AMOS/L, the busy bit is bit 11. of T.STS
  619. ; If the O/S is AMOS/32, or AMOS/L 1.3B or later, the busy is bit 9. of T.STS
  620. ; delivers status bit value for BTST to D6
  621. INUSE:
  622.     MOV    #1+8.,D6        ; D6 gets new INUSE bit value
  623.     TSTB    COMSER(A0)        ; do we have COMSER?
  624.     BNE    20$            ;  yes
  625.     MOV    #3.+8.,D6        ; set old INUSE bit
  626. 20$:    RTN
  627.  
  628.  
  629. ; R A W T R M  - set datacomm TCB to pass all data intact, character mode.
  630. RAWTRM:    MOV    REMOTE(A0),A5        ; get index to the TCB
  631.     MOVW    #REMMOD,D1        ; remote mode bits
  632.     CALL    SETSTS            ; set the status
  633.     RTN
  634.  
  635. ; L I N T R M  -  set datacomm TCB for normal AMOSL line mode.
  636. ; except echo is supressed if same TCB for comm & commands
  637. LINTRM:    TSTB    NOTALK(A0)        ; same TCB for comm and job?
  638.     BEQ    10$            ;  no-just return
  639. ; enable line input mode so user can enter commands
  640.     MOV    REMOTE(A0),A5        ;  yes-get index to the TCB
  641.     MOVW    #^C<REMMOD>,D1        ; clear remote mode bits
  642.     CALL    SETSTS            ; clear the status
  643. 10$:    RTN
  644.  
  645. ; P S E T D V  - assign PSEUDO driver if data TCB is owned by KERMIT job.
  646. PSETDV:    TSTB    NOTALK(A0)        ; TCB owned by KERMIT job?
  647.     BEQ    10$            ;  no-no need to swap
  648.     MOV    PSEUDO(A0),T.TDV(A5)    ; swap in PSEUDO driver
  649. 10$:    RTN
  650.  
  651. ; O R G T D V  - set normal terminal driver if data TCB is owned by KERMIT job.
  652. ORGTDV:    TSTB    NOTALK(A0)        ; TCB owned by KERMIT job?
  653.     BEQ    10$            ;  no-no need to swap
  654.     MOV    SAVTDV(A0),T.TDV(A5)    ; swap back real terminal driver
  655. 10$:    RTN
  656.  
  657. ; S E T S L P  - set SLEEP delay time based on serial baud rate
  658. ; added in edit [14]
  659. SETSLP:    MOV    #100.,D6        ; set default value
  660.     CLR    D7
  661.     MOVW    T.BAU(A5),D7        ; get baud rate code
  662.     CMPW    D7,#^O23        ; is it defined in our table?
  663.     BHI    10$            ;  no, use default
  664.     LSLW    D7            ; double index value
  665.     MOVW    SLPTBL[D7],D7        ; get table value in D7
  666.     BEQ    10$    
  667.     MOV    D7,D6
  668. 10$:    MOV    D6,SLPVAL(A0)    ; set sleep value
  669.     RTN
  670.  
  671. ; sleep time in ticks for one character at all defined alpha baud rates
  672. SLPTBL:    WORD    100000./50.
  673.     WORD    100000./75.
  674.     WORD    100000./110.
  675.     WORD    100000./134.
  676.     WORD    100000./150.
  677.     WORD    100000./200.
  678.     WORD    100000./300.
  679.     WORD    100000./600.
  680.     WORD    100000./1200.
  681.     WORD    100000./1800.
  682.     WORD    100000./2000.
  683.     WORD    100000./2400.
  684.     WORD    100000./3600.
  685.     WORD    100000./4800.
  686.     WORD    100000./7200.
  687.     WORD    100000./9600.
  688.     WORD    100000./19200.
  689.     WORD    100000./38400.
  690.     WORD    100000./57600.
  691.     WORD    100000./76800.
  692. ; end [14] additions for SETSLP
  693.  
  694. ; S N O O Z E - delay if data TCB owned by KERMIT job. This gives user
  695. ; time to escape back to the other KERMIT and enter REC.
  696. SNOOZE:    TSTB    NOTALK(A0)        ; data TCB same as KERMITs?
  697.     BEQ    10$            ;  no - do not wait.
  698.     SLEEP    #5.*10000.        ;  yes - wait 5 seconds
  699. 10$:    RTN
  700.  
  701. ;  E V L C H R
  702. ; EVLCHR evaluates the next non-blank character indexed by A2 and
  703. ; returns its value in D1.
  704. ; At exit, A2 is updated, and D1 contains the new character or 0.
  705. ; The Z flag is set if a character was encountered, else Z is clear.
  706. EVLCHR:    CLR    D1            ; pre-clear
  707.     BYP
  708.     LIN                ; end of line?
  709.     BEQ    100$            ;  yes-no characters to process
  710.     NUM                ;  else check for numeric
  711.     BNE    10$            ;   not numeric
  712.     GTDEC                ;   get the value
  713.     BR    40$            ;    and use it
  714.  
  715. ; process non-numeric
  716. 10$:    MOVB    (A2)+,D1
  717.     CMPB    D1,#'^            ; control character prefix ?
  718.     BNE    20$            ;  no-use straight ASCII.
  719.     LIN                ;  yes-check again for end of line
  720.     BEQ    40$            ;   treat as the ^ character [21]
  721.     MOVB    (A2)+,D1        ;   else get next character
  722.     AND     #^O37,D1        ;   mask to control character
  723.     BR    40$            ;   and exit
  724.  
  725. 20$:    CMPB    D1,#SPACE        ; compare to ASCII space
  726.     BLO    100$            ;  invalid argument
  727.     LIN
  728.     BNE    100$            ; bad input, too many chars
  729.     
  730. 40$:    LCC    #PS.Z            ;  arg ok, value in D1
  731.     RTN
  732.  
  733. 100$:    LCC    #0            ; arg is bad.
  734.     RTN
  735.  
  736. ; P R O M P T  displays the KERMIT command prompt.
  737. PROMPT:
  738.     MOV    #CR,D1
  739.     TTY
  740.     TSTB    ATERM(A0)        ; is this kermit the REMOTE?
  741.     BNE    10$            ;  no
  742.     TYPE    <REMOTE >        ;  yes-give user different prompts
  743. 10$:    TTYI                ;  for local & remote kermies.
  744.     ASCII    /Alpha-Kermit >/
  745.     BYTE    0
  746.     EVEN
  747.     RTN
  748.  
  749. ; C H O I C E - prompts the user for command & gets the command.
  750. CHOICE:    CALL    PROMPT            ; prompt the user
  751.     KBD    25$            ; get a command line in line mode
  752.     BYP                ; scan past blanks
  753.     LIN                ; end of line?
  754.     BEQ    CHOICE            ;  ignore blank lines
  755.     LEA    A1,KERCOM        ; index argument list
  756.     CALL    COMAND            ; match the command
  757.     BEQ    30$            ;  command matched
  758. ;  no match - show user bad news.
  759.     TYPE<? >            
  760. 10$:    LIN
  761.     BEQ    20$            ; end of line.
  762.     MOVB    (A2)+,D1        ;  else
  763.     TTY                ;  type the
  764.     BR    10$            ; character and loop
  765. 20$:    TYPECR    <? - undefined command.>; end error display
  766. 25$:    LCC    #0            ; flag no command
  767.     RTN                ; return
  768. 30$:    LCC    #PS.Z            ; flag valid command
  769.     RTN                ; return
  770.  
  771. ; C O M A N D - This subroutine compares the user's command string 
  772. ; to the command list indexed by A1 (e.g. KERCOM).
  773. ; If a match is found, A1 will index the command offset for a tabled call.
  774. ; At entry, A1 indexs the command/subcommand list. A2 indexs user's string.
  775. ; At exit, Z is set to indicate the command was valid.
  776. ; If Z is set, A1 indexs the command offset word.
  777. ;
  778. ; This routine will match the entire command, or to a valid and unique subset
  779. ; of the command name as defined in the table structure.
  780. ; e.g. The string CON will match the command name CONNECT.
  781.  
  782. COMAND:    SUB    #2,A1            ; adjustment for first entry
  783.     BYP                ; scan past seperators
  784.     PUSH    A2            ; save string address for compares
  785.       LIN                ; end of line?
  786.       BEQ    CHO.5            ;  no command-exit.
  787. ; calculate address of next entry and place in A1.
  788. CHO.1:      MOV    @SP,A2            ; restore string pointer
  789.       LEA    A3,2(A1)        ; A3 indexs next entry
  790.       TSTW    @A3            ;  end of table ?
  791.       BEQ    CHO.5            ;   yes-no match.
  792.       MOV    A3,A1            ;   no-get address of command size word
  793.       ADDW    (A3)+,A1        ;  and index to next command.
  794.       CLR    D5
  795.       MOVB    (A3)+,D5        ; D5 gets qualifier size in bytes
  796.  
  797. CHO.2:      TRM                ; check for end of word
  798.       BEQ    CHO.4            ;  yes-check match count
  799.       TSTB    @A3            ;  check for end of table entry
  800.       BEQ    CHO.1            ;  must be wrong if so.
  801. CHO.3:      MOVB    @A2,D1
  802.       UCS                ; convert to upper case
  803.       CMPB    D1,(A3)+        ; compare strings
  804.       BNE    CHO.4            ;  until no match
  805.       ADD    #1,A2            ; advance A2
  806.       TST    D5            ; check for minimum match length
  807.       BEQ    CHO.2            ;  made it-stop counting
  808.       SUB    #1,D5            ; decrement byte count
  809.       BR    CHO.2            ;  keep testing till line is terminated
  810.  
  811. CHO.4:      TST    D5            ; good match has zero count
  812.       BNE    CHO.1            ;  no good-try next
  813.       TRM                ; good match has no more data
  814.       BNE    CHO.1
  815.     POP                ; toss old A2
  816.     LCC    #PS.Z            ; flag command match found
  817.     RTN
  818.  
  819. ; undefined command - Clear Z flag
  820. CHO.5:    POP    A2            ; update A2 to index args
  821.     LCC    #0
  822.     RTN
  823.  
  824. ; P R O C E S
  825. ; Process performs the process defined by the user command.
  826. ; At Entry, A1 indexs the word offset (from A1) of the command address
  827. PROCES:    ADDW    @A1,A1            ; do a tabled called by adding
  828.     CALL    @A1            ; offset @A1 to A1 and executing at
  829.     RTN                ; that new address.
  830.  
  831. ; S E N D sends a file to the remote KERMIT using the KERMIT protocol.
  832. SEND:    TSTB    NOTALK(A0)
  833.     BNE    4$            ; AUTOsend doesn't make sense in REMOTE
  834.     TSTB    AUTOS(A0)        ; automatically sending KERMIT & RECEIVE?
  835.     BEQ    4$            ;  no
  836.     TYPECR    <Sending KERMIT and RECEIVE commands to remote Kermit>
  837.     LEA    A1,PRESND        ; index commands for remote kermit
  838.     CALL    SREMOT            ; send to remote
  839. 4$:    CALL    PREBAT            ; init wildcarding, if present
  840.     BYP
  841. 5$:    CALL    GETNXT            ; get next filename
  842. ; delay inspection of no files error until we are ready to send F packet,
  843. ; then, just send a B packet.
  844.     TSTB    FIO+D.ERR(A0)        ; file error?
  845.     BEQ    6$            ;  no
  846.     CALL    LFERR            ;  yes, display it
  847.     BR    5$            ;  and try for another spec
  848. 6$:    CALL    GTSIZE            ; save file size in bytes
  849.     CALL    STARTT            ; set start time
  850.     CALL    RAWTRM            ; put remote in data mode
  851.     CALL    SNOOZE            ; delay if TCB owned by KERMIT
  852.     CALL    PSETDV            ; swap in PSEUDO driver if needed
  853.     CALL    SETSLP            ; set sleep parameter
  854.     CALL    SENDSW            ; else send the file
  855.     CALL    LINTRM            ; put remote in line mode
  856.     CALL    ORGTDV            ; put back real TDV if PSEUDO used
  857.     TSTB    LOGIC(A0)        ; did it work?
  858.     BMI    10$            ;  yes
  859.     TYPECR    <?SEND failed>        ;  no
  860. 10$:    CALL    STATS
  861. 20$:    RTN
  862.     
  863. 100$:    CALL    LFERR
  864.     RTN
  865.  
  866. ; L F E R R
  867. ; LFERR displays local file errors on the user's CRT
  868. LFERR:    TSTB    NOTALK(A0)        ; do we have a user terminal?
  869.     BNE    10$            ;  no-do not print message.
  870.     TYPE    <Local file error, >
  871.     PFILE    FIO(A0)            ; show filename
  872.     ERRMSG    FIO+D.ERR(A0), OT$TRM!OT$LSP    ; and error message
  873.     CRLF
  874. 10$:    RTN
  875.  
  876. ; R E C E I V - receive a file from remote KERMIT using the KERMIT protocol.
  877. RECEIV:
  878.     MOV    A2,SAVSPC(A0)        ; save user's string ptr
  879.     MOVB    #1,NXTCNT(A0)        ; set count for output spec
  880.     CALL    SCNSTR            ; scan string for AUTO-receive
  881.     CLR    TFILES(A0)
  882.     CLR    TBYTES(A0)
  883.     CLR    TTIME(A0)        ; clear total stat amounts
  884.     MOV    #60.,TIMINT(A0)        ; 60 second timeout
  885.     CALL    SETSLP            ; set sleep parameter
  886.     CALL    PSETDV            ; swap in PSEUDO terminal driver
  887.     CALL    RAWTRM            ; remote TCB to character mode
  888.     CALL    RECSW            ; call receive state manager/switcher
  889.     CALL    LINTRM            ; remote TCB to line mode
  890.     CALL    ORGTDV            ; return to real TDV if PSEUDO used
  891.     TSTB    LOGIC(A0)        ;  test for sucess
  892.     BMI    10$            ;   it worked
  893.     TYPECR    <?RECEIVE failed.>    ;   it didn't work
  894. 10$:    CALL    STATS            ; show elapsed time & speed
  895.     RTN
  896.  
  897. ; scan user spec for = and spec following it. If found, send remote Kermit
  898. ; the commands KERMIT^M, and SEND followed by the user's filespec.
  899. SCNSTR:    
  900.     SAVE    A2
  901.     TSTB    NOTALK(A0)
  902.     BNE    100$            ; AUTOREC doesn't make sense in REMOTE
  903.     TSTB    AUTOR(A0)        ; automatically sending KERMIT & SEND?
  904.     BEQ    100$            ;  no
  905.     BYP
  906.     LIN                ; any parms?
  907.     BEQ    100$            ;  no
  908.     CMPB    @A2,#'=            ; do we have an equal sign?
  909.     BEQ    20$            ;  yes
  910.     FSPEC    FIO(A0),LST        ;  no, use FSPEC to skip past outspec
  911.     BYP
  912. 20$:    CMPB    (A2)+,#'=        ; do we have AUTO spec?
  913.     BNE    100$            ;  no
  914.                     ;  yes
  915.     TYPECR    <Sending KERMIT and SEND commands to remote Kermit>
  916.     LEA    A1,PREREC        ; index commands for remote kermit
  917.     CALL    SREMOT            ; send to remote
  918.     MOV    A2,A1
  919.     CALL    SREMOT            ; send user string ( even CR & LF)
  920. 100$:    REST    A2
  921.     RTN
  922.  
  923. ; G F I L N M
  924. ; This routine gets a filename and places it in FILNAM(A0)
  925. ; At entry, the filename has been loaded in ddb FIO(A0)
  926. ; On exit, FLLEN(A0) contains the length in bytes.
  927. ; Z is set if the filename was valid.
  928. GFILNM:
  929. ; now convert the name to KERMIT standard form which is NAME.EXT.        
  930. ; We must delete all spaces from the filespec.
  931.     LEA    A2,FILNAM(A0)        ; index the target area
  932.     PUSH    A2            ;  and save the index
  933.     LEA    A1,FIO+D.FIL(A0)    ; index the filname in the ddb
  934.     UNPACK
  935.     UNPACK                ; put the ASCII filename @A1
  936.     MOVB    #'.,(A2)+        ; add the comma
  937.     UNPACK
  938.     CLRB    @A2            ; terminate it
  939. ; clean up the filespec by deleting space & other illegal characters.
  940.     POP    A2            ; restore pointer to filnam
  941.     MOV    A2,A1            ; A1 will be write pointer
  942.     CLR    D0            ; D0 counts valid chars we found
  943. 10$:    MOVB    @A2,D1            ; get current char in D7
  944.     BEQ    20$            ;  end of line
  945.     LCS                ; convert to lower case [15]
  946.     CMPB    D1,#'.            ; current char a dot?
  947.     BEQ    20$            ;  yes -it is ok
  948.     ALF                ; is it alpha ?
  949.     BEQ    20$            ;  yes-use it.
  950.     NUM                ; or numeric ?
  951.     BNE    25$            ;  yes-use it
  952.  
  953. 20$:    MOVB    D1,(A1)+
  954.     BEQ    30$            ; end of string
  955.     ADD    #1,D0            ; count how many we found
  956. 25$:    ADD    #1,A2            ; bump pointer
  957.     BR    10$            ; continue scan
  958.  
  959. 30$:    CMP    D0,#3            ; got at least x.x?
  960.     BLO    100$            ; no-invalid filename
  961.     MOVB    D0,FLLEN(A0)        ; save the length
  962.     LCC    #PS.Z            ; valid filename received
  963.     RTN
  964.  
  965. 100$:    LCC    #0            ; bad filename given.
  966.     RTN
  967.     
  968. ; R F I L N M
  969. ; This routine gets the remote filename from NFILNM(A0) 
  970. ; and places it in the FIO(A0) DDB.
  971. ; It then opens the file for input and returns the OPEN condition codes
  972. ; to the caller. Z is set if the open was succesful.
  973. ; [13] revised to not extend filenames or extensions rpr
  974. RFILNM:
  975.     LEA    A2,FILNAM(A0)        ; index the filname
  976.     LEA    A1,COPY(A0)        ; index copy buffer
  977.     CLR    D2
  978.     MOVB    LDATA(A0),D2        ; d2 gets total length of filename
  979.                     ; from remote kermit
  980.     CMP    D2,#30.-1        ; compare to max allowed by definition
  981.     BLOS    10$
  982.     MOV    #30.-1,D2        ; set max
  983. ; terminate filename part to 6 characters
  984. 10$:    MOV    #6.,D0            ; set limit for filename
  985. 20$:    ALF
  986.     BEQ    30$            ; letters ok
  987.     NUM
  988.     BEQ    30$            ; numbers ok, too.
  989.     CMPB    @A2,#'.            ; period?
  990.     BEQ    60$            ;  yes-end of filename!
  991.     BNE    40$            ;  no-toss bad char & continue
  992.  
  993. 30$:    MOVB    @A2,(A1)+        ; save good character
  994. 40$:    ADD    #1,A2            ; advance pointer
  995.     SUB    #1,D2            ; count down total filename size
  996.     BEQ    100$            ;  end of filename (use .KMT extension)
  997.     SUB    #1,D0            ; adjust allowed filename chars
  998.     BNE    20$            ;  more allowed
  999.                     ;  else wait for a period.
  1000. ; truncate file names longer than 6 characters by waiting for a period
  1001. ; wait for a period
  1002. 50$:    CMPB    @A2,#'.            ; period
  1003.     BEQ    60$            ;  yes-ok.
  1004.     ADD    #1,A2            ;  no-advance ptr
  1005.     SUB    #1,D2            ; count down total filename size
  1006.     BNE    50$            ;  until period or end of file
  1007.     BR    100$            ;  no period found
  1008. ; we found the period (and truncated a long filename)
  1009. 60$:    ADD    #1,A2            ;  no-advance
  1010.     SUB    #1,D2            ; count down original filename size
  1011.     BEQ    100$            ;  no more filename, use default ext!
  1012.     MOVB    #'.,(A1)+        ; buffer a period
  1013.     MOV    #3.,D0            ; max size of extension.
  1014. 70$:    ALF
  1015.     BEQ    80$            ; ok
  1016.     NUM
  1017.     BNE    90$            ; not ok
  1018. 80$:    MOVB    @A2,(A1)+        ; buffer o.k. character
  1019. 90$:    ADD    #1,A2            ; advance pointer
  1020.     SUB    #1,D2            ; count down original filename size
  1021.     BEQ    100$            ; until a period
  1022.     SUB    #1,D0            ; count down
  1023.     BNE    70$            ;  yes
  1024. 100$:    CLRB    (A1)+            ;  no- end with a null
  1025. ; add code to override the name of first file received, if user gave a name
  1026.     TSTB    NXTCNT(A0)        ; been here before?
  1027.     BEQ    106$            ;  yes, not first time
  1028.     MOV    SAVSPC(A0),A2        ;  no, get user spec
  1029.     BYP
  1030.     LIN                ; do we have text?
  1031.     BEQ    106$            ;  no, user name from F packet
  1032.     CMPB    @A2,#'=            ;  yes, is text a filename?
  1033.     BNE    107$            ;   yes, override filename!
  1034.     INC    A2            ; else use name from F packet
  1035.     BYP
  1036. 106$:    CLRB    NXTCNT(A0)
  1037.     LEA    A2,COPY(A0)        ; index the new filename
  1038. 107$:    INIT    FIO(A0)            ; init the ddb
  1039.     FSPEC    FIO(A0),KMT        ; load the ddb with filespec
  1040.     LOOKUP    FIO(A0)            ; does file already exist?
  1041.     BNE    110$            ;  no
  1042.     DSKDEL    FIO(A0)            ;  yes-erase the old one
  1043. 110$:    OPENO    FIO(A0)            ; open it sequentially
  1044.     BNE    120$
  1045.     CALL    STARTT            ; start counting
  1046.     CLR    D7            ; clear Z flag
  1047. 120$:    RTN                ; Z is set if file found
  1048.  
  1049. ; C O N N E C
  1050. ; CONNEC is the local terminal <--> remote terminal conversational routine.
  1051. ; User keypresses are sent (except the ESCAPE or KMETA character) to the
  1052. ; remote computer & incoming characters form the remote are displayed on 
  1053. ; the user's CRT screen.
  1054. CONNEC:    TSTB    NOTALK(A0)        ; using same TCB for in & out?
  1055.     BEQ    4$            ;  no-ok.
  1056.     TTYL    NONONO            ;  tell user it is a no-no
  1057.     RTN
  1058.  
  1059. 4$:    TAS    CFLAG(A0)        ; have we been here before?
  1060.     BNE    5$            ;  yes
  1061.     TTYL    CUSAGE            ;  no, explain CONNECT to user
  1062. 5$:    CALL    RAWTRM            ; set remote in "raw" mode.
  1063.     CALL    SETSLP            ; set sleep parameter
  1064.     CALL    SHOESC            ; show the escape character in effect.
  1065.     MOV    LOCAL(A0),A5        ; A5 indexs local TCB
  1066.     MOVW    #REMMOD,D1        ; allow function key xlation
  1067.     TSTB    CMASK(A0)
  1068.     BPL    6$            ;  7 bit terminal
  1069.     ORW    #T$EXT,D1        ;  8 bit terminal
  1070. 6$:    CALL    SETSTS            ; set them via breakpoint
  1071.     MOV    A5,A4            ; A4 will be the local TCB pointer
  1072.     MOV    REMOTE(A0),A5        ; now A5 indexs REMOTE 
  1073. 10$:    CTRLC    15$            ;  user entered control-c?
  1074.     TST    T.ICC(A4)        ; LOCAL chars present ?
  1075.     BNE    20$            ;  something to do
  1076.     TST    T.ICC(A5)        ; REMOTE chars present ?
  1077.     BNE    20$            ;  something to do
  1078.     SLEEP    SLPVAL(A0)        ; take a one character nap. [14]
  1079.     BR    10$            ; see if the store needs minding now.
  1080.  
  1081. ; handle control-c's by trapping them, unflagging them and sending them out.
  1082. 15$:    JOBIDX                ; index A6 to JCB
  1083.     ANDW    #^C<J.CCC>,@A6        ; clear control-c flag
  1084.     MOV    #3,D1            ; get ASCII equivalent
  1085.     BR    37$            ; send it out
  1086.  
  1087. ; enter here when we have some communications data to move
  1088. 20$:    TST    T.ICC(A5)        ; have remote input ?
  1089.     BEQ    30$            ;  no
  1090.     TTYIN                ;  yes-grab a character
  1091.     CMPB    PARITY(A0),#'N
  1092.     BEQ    25$
  1093.     ANDB    #^B01111111,D1        ; strip to seven if PARITY is on [22]
  1094. 25$:    TTY                ; print it
  1095. 30$:    TCKI                ; have LOCAL input ?
  1096.     BNE    40$            ;  no local input
  1097.     KBD                ;  yes-get local input via KBD
  1098. 35$:    MOVB    D1,D7
  1099.     ANDB    CMASK(A0),D7        ; mask character to 7 or 8 bits
  1100.     CMPB    D7,KMETA(A0)        ; escape character ?
  1101.     BEQ    100$            ;  yes-leave
  1102. ; check for half duplex echoing
  1103.     TSTB    ECHO(A0)        ; got echoing?
  1104.     BEQ    37$            ;  no-full duplex
  1105.     CMPB    D7,#SPACE        ; printable?
  1106.     BHIS    36$            ; yes-echo it
  1107.     CMPB    D7,#CR            ; CR?
  1108.     BEQ    36$             ; yes-echo
  1109.     CMPB    D7,#08.            ; backspace?
  1110.     BEQ    36$             ; yes-echo
  1111.     CMPB    D7,#12            ; line feed ?
  1112.     BNE    37$            ;   ignore other ctl chars
  1113. 36$:    TTY                ;  yes-half duplex,
  1114.                     ;     so echo the character
  1115. ; transmit a character to the remote site.
  1116. 37$:    TTYOUT                ; send byte to REMOTE
  1117. 40$:    BR    10$            ; loop    
  1118.  
  1119. ; exit back to main routine, since user entered ESCAPE character.
  1120. 100$:    MOV    LOCAL(A0),A5        ; index user's TCB
  1121.     MOVW    #REMMOD,D1        ; get char mode bits
  1122.     TSTB    CMASK(A0)
  1123.     BPL    110$            ;  7 bit terminal
  1124.     ORW    #T$EXT,D1        ;  8 bit terminal
  1125. 110$:    COMW    D1            ; flip the bits to clear
  1126.     CALL    SETSTS            ; clear them via breakpoint
  1127. ;;    CALL    LINTRM            ; reset remote TCB to line mode.
  1128.     CRLF
  1129.     RTN
  1130.  
  1131. ; H E L P - inform user as to how KERMIT works.
  1132. HELP:    TTYL    HLP1
  1133.     LEA    A1,KERCOM        ; index argument list
  1134.     CALL    COMAND            ; see if we have an argument
  1135.     BNE    100$            ;  no-show the whole list.
  1136. ; show the selected help line by backing up to the start of it
  1137. 4$:    TSTB    -(A1)            ; backup to non-null
  1138.     BEQ    4$
  1139. 10$:    MOVB    -(A1),D1        ; look for null byte between command
  1140.     BNE    10$            ;  and help strings.
  1141.     CRLF
  1142.     TTYL    1(A1)            ; show the help message
  1143.     CRLF
  1144.     RTN
  1145.  
  1146. ; Show help lines for all commands
  1147. 100$:    LEA    A2,KERCOM        ; index table
  1148. 110$:    MOV    A2,A1
  1149.     CLR    D7
  1150.     MOVW    @A1,D7            ; get offset to end
  1151.     BEQ    140$            ; null is end of table
  1152.     MOV    A1,A2            
  1153.     ADDW    (A1)+,A2        ; A2 indexs the address field
  1154.     ADD    #2,A2            ; A2 now indexs the next entry
  1155.     ADD    #1,A1            ; ignore size byte
  1156.     CLR    D0
  1157.     CALL    PTRTYP            ; type command name
  1158.     TSTB    @A1
  1159.     BNE    120$
  1160.     ADD    #1,A1
  1161. 120$:    CMPB    D0,#09.            ; nine characters?
  1162.     BHI    130$            ;  yes, done spacing
  1163.     INC    D0            ;  no,
  1164.     TYPESP                ;   so space
  1165.     BR    120$            ;         out
  1166. 130$:    CALL    PTRTYP            ; type the help text
  1167.     CRLF
  1168.     BR    110$
  1169.  
  1170. 140$:    CRLF
  1171.     CRLF
  1172.     RTN
  1173.  
  1174. ; S H O W  - Show user the current optional settings & some packet info.
  1175. SHOW:    CALL    KERVER            ; show kermit version
  1176.     TTYL    SH1.0            ; type modem port:
  1177.     LEA    A1,ATERM(A0)        ; index TCB name    
  1178.     TSTB    @A1            ; do we have remote? [1]
  1179.     BNE    10$            ;  yes
  1180.     LEA    A1,SH.DAS        ;  else index dashes
  1181. 10$:    TTYL    @A1            ; show name or dashes
  1182. ; [016] display auto-receive
  1183.     TTYL    SH2.0
  1184.     LEA    A6,SH.ON        
  1185.     TSTB    AUTOR(A0)
  1186.     BNE    20$
  1187.     LEA    A6,SH.OFF
  1188. 20$:    TTYL
  1189. ; [015] display auto-send
  1190.     TTYL    SH2.1
  1191.     LEA    A6,SH.ON        
  1192.     TSTB    AUTOS(A0)
  1193.     BNE    30$
  1194.     LEA    A6,SH.OFF
  1195. 30$:    TTYL
  1196. ; display bell
  1197.     TTYL    SH2.2            ; do end of line 1 & BELL label
  1198.     LEA    A6,SH.OFF
  1199.     TSTB    DING(A0)
  1200.     BEQ    40$
  1201.     LEA    A6,SH.ON
  1202. 40$:    TTYL                ; show on or off
  1203. ; display blockcheck
  1204.     TTYL    SH2.3            ; blockcheck selected label
  1205.     MOVB    DF.CHK(A0),D1
  1206.     TTY
  1207. ; display debug
  1208.     TTYL    SH2.4            ; show DEBUG label
  1209.     LEA    A6,SH.OFF
  1210.     TSTB    DEBUGO(A0)
  1211.     BEQ    50$
  1212.     LEA    A6,SH.ON
  1213. 50$:    TTYL
  1214. ; show duplex
  1215.     TTYL    SH2.5            ; then type duplex label
  1216.     LEA    A6,SH.FUL        ; assume FULL
  1217.     TSTB    ECHO(A0)        ; check duplex 0=full, -1=half
  1218.     BEQ    60$
  1219.     LEA    A6,SH.HAL        ; o.k., then, HALF.
  1220. 60$:    TTYL                ; type string @A6
  1221. ; display user's endline
  1222.     TTYL    SH3.2            ; end of line 3, ENDLINE label
  1223. ;[012] display end-of-line character in use, rather than default
  1224.     MOVB    DF.EOL(A0),D1        ; set end of line char
  1225.     BNE    65$
  1226.     TTYL    SH.ZIP
  1227.     BR    67$            ; [015]
  1228. 65$:    TYPE    < >
  1229.     CALL    SHOCHR
  1230. 67$:
  1231. ; display ESCAPE
  1232.     TTYL    SH2.6            ; show ESCAPE label
  1233.     CLR    D1            ; preclear D1
  1234.     MOVB    KMETA(A0),D1
  1235.     CALL    SHOCHR            ; show escape character
  1236. ; display PACKETSIZE
  1237.     TTYL    SH2.7
  1238.     CLR    D1
  1239.     MOVB    MXPKSZ(A0),D1        ; set max value
  1240.     DCVT    4,OT$TRM!OT$ZER
  1241. ; display PACKETSTART
  1242.     TTYL    SH2.7A
  1243.     MOVB    RMARK(A0),D1
  1244.     CALL    SHOCHR
  1245. ; display PARITY
  1246.     TTYL    SH2.8            ; type parity label
  1247.     MOVB    PARITY(A0),D1
  1248.     CALL    SHOCHR
  1249. ; display default retries
  1250.     TTYL    SH2.8A
  1251.     MOVB    MAXTRY(A0),D1
  1252.     DCVT    4,OT$TRM!OT$ZER
  1253. ; display stall time in hundredths of seconds
  1254.     TTYL    SH2.9
  1255.     CLR    D1
  1256.     MOVB    STLCHR(A0),D1
  1257.     DCVT    4,OT$TRM!OT$ZER
  1258. ; display default TIMOUT
  1259.     TTYL    SH2.9A            ; show timeout label
  1260.     MOV    DF.TIM(A0),D1        ;  
  1261.     DCVT    4,OT$TRM!OT$ZER
  1262.     CRLF
  1263. ; display packet parameters
  1264. ; display blockchek
  1265.     TTYL    SH3.0
  1266.     MOVB    CHKT(A0),D1        ; get check type
  1267.     TTY
  1268. ; display eight bit quote
  1269.     TTYL    SH3.1
  1270.     MOVB    QBIN(A0),D1
  1271.     BMI    70$            ; 7 bit path
  1272.     BNE    80$            ; we have a real 8B quote, show it
  1273.     TTYL    SH.ZIP            ; we don't need 8B quote so far
  1274.     BR    90$
  1275. 70$:    MOVB    #'&,D1            ; show default 8 bit quote
  1276. 80$:    TYPE    < >
  1277.     CALL    SHOCHR
  1278. 90$:    
  1279. ; display endline
  1280.     TTYL    SH3.2            ; end of line 3, ENDLINE label
  1281. ;[012] display end-of-line character in use, rather than default
  1282.     MOVB    DF.EOL(A0),D1        ; set end of line char
  1283.     BNE    100$
  1284.     TTYL    SH.ZIP
  1285.     BR    110$            ; [015]
  1286. 100$:    TYPE    < >
  1287.     CALL    SHOCHR
  1288. ; display max packet size
  1289. 110$:    TTYL    SH3.3            ; do end of line 2, packet parms.
  1290.     CLR    D1
  1291.     MOVB    SPSIZ(A0),D1        ; get packet size
  1292.     DCVT    4,OT$TRM!OT$ZER
  1293. ; display packet end
  1294.     TTYL    SH3.4            ; show number of pads            
  1295.     MOVB    PAD(A0),D1        ; 
  1296.     DCVT    2,OT$TRM!OT$ZER
  1297.     TTYL    SH3.5            ; show pad character value
  1298.     MOVB    PADCHR(A0),D1        ; 
  1299.     CALL    SHOCHR
  1300.     TTYL    SH3.6            ; show timout label
  1301.     MOV    TIMINT(A0),D1        ;  
  1302.     DCVT    4,OT$TRM!OT$ZER
  1303.     TTYL    SH3.8
  1304.     RTN
  1305.  
  1306. ; S E T  - allow user to change some parameters.
  1307. ; SET command accepts a sub-command (or argument) to define the action.
  1308. ; If no sub-command is given, a short expansion of the subcommands is given.
  1309. SET:    BYP
  1310.     LIN                ; end of line?
  1311.     BEQ    100$            ;  yes-show user what can be set.
  1312.     CMPB    @A2,#'?            ; user wants some help?
  1313.     BEQ    100$            ;  yes-show user what he can set.
  1314.     LEA    A1,SETCOM        ; index set command list
  1315.     CALL    COMAND            ; see if we have an argument
  1316.     BNE    10$            ;  no-show user no can do.
  1317. ; perform the desired function. Each function does its own error-checking.
  1318.     CALL    PROCES            ; do the set
  1319.     RTN
  1320.  
  1321. 10$:    TYPE<? >            ;  no match - show user bad news.
  1322. 15$:    LIN                ; end of line?
  1323.     BEQ    20$            ;  yes-done typing user's entry
  1324.     MOVB    (A2)+,D1
  1325.     TTY                ; type a character
  1326.     BR    15$            ; until the end of line
  1327. 20$:    TYPECR    <? - undefined command.>
  1328. 25$:    RTN
  1329.  
  1330. ; Show explanation for all set commands
  1331. 100$:    TTYL    SET1
  1332.     LEA    A2,SETCOM        ; index table
  1333. 110$:    MOV    A2,A1
  1334.     CLR    D7
  1335.     MOVW    @A1,D7            ; get offset to end
  1336.     BEQ    140$            ; null is end of table
  1337.     MOV    A1,A2            
  1338.     ADDW    (A1)+,A2        ; A2 indexs the address field
  1339.     ADD    #2,A2            ; A2 now indexs the next entry
  1340.     ADD    #1,A1            ; ignore size byte
  1341.     CLR    D0            ; [015] count characters
  1342.     CALL    PTRTYP            ; type command name
  1343.     TSTB    @A1
  1344.     BNE    120$
  1345.     ADD    #1,A1
  1346. 120$:    CMPB    D0,#11.            ; eleven characters?
  1347.     BHI    130$            ;  yes, done spacing
  1348.     INC    D0            ;  no,
  1349.     TYPESP                ;   so space
  1350.     BR    120$            ;         out
  1351. 130$:    CALL    PTRTYP            ; type the help text
  1352.     CRLF
  1353.     BR    110$
  1354.  
  1355. 140$:    CRLF
  1356.     CRLF
  1357.     RTN
  1358.  
  1359. ;;        S E T   S U B C O M M A N D S
  1360.  
  1361. ; B E L L - set bell after each command completeion flag.
  1362. BELL:    LEA    A1,ONOFF        ; index option list
  1363.     CALL    GETOPT            ; process option
  1364.     BNE    10$            ;  no good
  1365.     MOVB    D1,DING(A0)        ; set bell option
  1366. 10$:    RTN
  1367.  
  1368. ; D U P L E X - set half or full duplex.
  1369. DUPLEX:    LEA    A1,EPLEX        ; index echoplex options
  1370.     CALL    GETOPT            ; process option
  1371.     BNE    10$            ;  no good
  1372.     MOVB    D1,ECHO(A0)        ; set duplex option
  1373. 10$:    RTN
  1374.  
  1375.  
  1376. ; B L O C K - set default check type. 1, 2 or 3 byte check types
  1377. BLOCK:    LEA    A1,ONE23        ; index check-type options
  1378.     CALL    GETOPT
  1379.     BNE    10$            ; no good
  1380.     MOVB    D1,DF.CHK(A0)        ; set default check type
  1381. 10$:    RTN
  1382.  
  1383. ; D E B U G - Set debug message print flag.
  1384. DEBUG:    LEA    A1,ONOFF        ; allow YES or NO.
  1385.     CALL    GETOPT
  1386.     BNE    10$
  1387.     MOVB    D1,DEBUGO(A0)        ; set debug option
  1388. 10$:    RTN
  1389.  
  1390. ; A U T S N D - Set AUTOSEND option flag.
  1391. AUTSND:    LEA    A1,ONOFF        ; allow YES or NO.
  1392.     CALL    GETOPT
  1393.     BNE    10$
  1394.     MOVB    D1,AUTOS(A0)        ; set autosend option
  1395. 10$:    RTN
  1396.  
  1397. ; A U T R E C - Set AUTORECEIVE option flag.
  1398. AUTREC:    LEA    A1,ONOFF        ; allow YES or NO.
  1399.     CALL    GETOPT
  1400.     BNE    10$
  1401.     MOVB    D1,AUTOR(A0)        ; set autosend option
  1402. 10$:    RTN
  1403.  
  1404. ; E N D L I N - set optional end of packet character. (normally CR.)
  1405. ENDLIN:    CALL    EVLCHR            ; get the character
  1406.     BNE    10$        
  1407.     MOVB    D1,DF.EOL(A0)        ; set default EOL
  1408. 10$:    RTN
  1409.  
  1410. ; P A K M R K - set optional start of packet character. (normally CR.)
  1411. PAKMRK:    CALL    EVLCHR            ; get the character
  1412.     BNE    10$        
  1413.     MOVB    D1,RMARK(A0)        ; set default MARK character
  1414. 10$:    RTN
  1415.  
  1416.  
  1417. ; E S C A P E - set the escape from CONNECT mode character.
  1418. ESCAPE:    CALL    EVLCHR
  1419.     BNE    10$            ; no good
  1420.     ANDB    CMASK(A0),D1        ; limit to valid character set range
  1421.     MOVB    D1,KMETA(A0)        ; set escape character
  1422. 10$:    RTN
  1423.  
  1424. ; T I M E R - set the timeout period used in packet transmission.
  1425. TIMER:    BYP
  1426.     GTDEC                ; get decimal number
  1427.     CMP    D1,#MINTIM        ; compare to minimum time
  1428.     BHIS    10$            ; allow 2 or more
  1429.     MOV    #MINTIM,D1        ;  force minimum
  1430.     TYPECR    <Setting timeout to 2 second minimum.>
  1431. 10$:    MOV    D1,DF.TIM(A0)        ; set default and
  1432.     MOV    D1,TIMINT(A0)        ; current timer value
  1433.     RTN
  1434.  
  1435. ; N E W T R Y   - sets the maximum # of tries for a packet.
  1436. NEWTRY:    BYP
  1437.     GTDEC
  1438.     TST    D1            ; test new value
  1439.     BEQ    20$            ; zero is too few!
  1440.     CMP    D1,#255.        ; this is max was ^O255
  1441.     BHI    20$            ;  too high-leave as is
  1442.     MOVB    D1,MAXTRY(A0)        ; set max value
  1443.     RTN
  1444. 20$:    TTYI
  1445.     ASCII    /?value out of range?/
  1446.     BYTE    A.BEL,CR,0
  1447.     EVEN
  1448.     RTN
  1449.  
  1450. ; P A K M A X - set maximum packet size supported
  1451. PAKMAX:    BYP
  1452.     GTDEC
  1453.     CMP    D1,#10.            ; compare to minimum
  1454.     BLO    20$            ;  too small [16]
  1455.     CMP    D1,#PAKSIZ        ; compare to max size allowed
  1456.     BHI    20$            ;  too high-leave as is
  1457.     MOVB    D1,MXPKSZ(A0)        ; set max value
  1458.     MOVB    D1,SPSIZ(A0)        ; set max send size, too!
  1459.     RTN
  1460.  
  1461. 20$:    TTYI
  1462.     ASCII    /?select a packet size from 10 to 94 bytes./
  1463.     BYTE    A.BEL,CR,0
  1464.     EVEN
  1465.     RTN
  1466.  
  1467. ; S E T P A R - set the parity type (already in use) by the remote
  1468. ; This allows Alpha-Kermit to know whether 8bit quoting is needed, or not.
  1469. SETPAR:    LEA    A1,PARLST        ; allow YES or NO.
  1470.     CALL    GETOPT
  1471.     BNE    10$
  1472.     MOVB    D1,PARITY(A0)        ; set parity
  1473.     CMPB    D1,#'N            ; no parity?
  1474.     SETNE    QBIN(A0)
  1475.     TTYL    NOSET            ; tell user limitations
  1476. 10$:    RTN
  1477.  
  1478. ; S T L V A L  - set # of 100ths of seconds to stall between output
  1479. ; characters for file transfers.
  1480. STLVAL:    BYP
  1481.     GTDEC
  1482.     TST    D1            ; test new value
  1483.     BEQ    20$            ; zero is too few!
  1484.     CMP    D1,#255.        ; this is max was ^O255
  1485.     BHI    20$            ;  too high-leave as is
  1486.     MOVB    D1,STLCHR(A0)        ; set max value
  1487.     RTN
  1488. 20$:    TTYI
  1489.     ASCII    /?STALL range is 0 to 255 hundredths of seconds./
  1490.     BYTE    A.BEL,CR,0
  1491.     EVEN
  1492.     RTN
  1493.  
  1494.  
  1495. ; G E T O P T  - compares the input option @A2 to the option list @A1.
  1496. ; If there is a match, the match number is returned in D1 and Z is set.
  1497. ; No match returns Z clear and displays the error message at  the end of the
  1498. ; option list.
  1499. GETOPT:    SUB    #2,A1            ; adjustment for first entry
  1500.     BYP                ; scan past seperators
  1501.     PUSH    A2            ; save string address for compares
  1502. ; calculate address of next entry and place in A1.
  1503. OPT.1:    MOV    @SP,A2            ; restore string pointer
  1504.     LEA    A3,2(A1)        ; A3 indexs next entry
  1505.     TSTW    @A3            ;  end of table ?
  1506.     BEQ    OPT.5            ;   yes-no match.
  1507.     MOV    A3,A1            ;   no-get address of command size word
  1508.     ADDW    (A3)+,A1        ;  and index to next command.
  1509.     CLR    D5
  1510.     MOVB    (A3)+,D5        ; D5 gets qualifier size in bytes
  1511.  
  1512. OPT.2:    TRM                ; check for end of word
  1513.     BEQ    OPT.4            ;  yes-check match count
  1514.     TSTB    @A3            ;  check for end of table entry
  1515.     BEQ    OPT.1            ;  must be wrong if so.
  1516. OPT.3:    MOVB    @A2,D1
  1517.     UCS                ; convert to upper case
  1518.     CMPB    D1,(A3)+        ; compare strings
  1519.     BNE    OPT.4            ;  until no match
  1520.     ADD    #1,A2            ; advance A2
  1521.     TST    D5            ; check for minimum match length
  1522.     BEQ    OPT.2            ;  made it-stop counting
  1523.     SUB    #1,D5            ; decrement byte count
  1524.     BR    OPT.2            ;  keep testing till line is terminated
  1525.  
  1526. OPT.4:    TST    D5            ; good match has zero count
  1527.     BNE    OPT.1            ;  no good-try next
  1528.     TRM                ; good match has no more data
  1529.     BNE    OPT.1
  1530.     POP                ; toss old A2
  1531.     CLR    D1
  1532.     MOVB    @A1,D1            ; D1 gets argument value
  1533.     LCC    #PS.Z            ; flag command match found
  1534.     RTN
  1535.  
  1536. ; undefined command - Clear Z flag
  1537. OPT.5:    POP    A2
  1538.     TTYL    2(A3)            ; display error message at end of list
  1539.     CRLF                ; [15]
  1540.     LCC    #0
  1541.     RTN                ; return with Z clear
  1542.  
  1543. ; P T R T Y P  - print the string indexed by A1 until a null is found.
  1544. PTRTYP:    MOVB    (A1)+,D1
  1545.     BEQ    10$
  1546.     INC    D0            ; count characters
  1547.     TTY
  1548.     BR    PTRTYP
  1549. 10$:    RTN
  1550.  
  1551. ; G O O D B Y  - exit from KERMIT to AMOS for good.
  1552. ; re-attach comm TCB to its former JCB, if any.
  1553. GOODBY:    ANDW    #^C<FIL!LOK>,-10(A0)    ; clear file and locked in mem flags
  1554.     MOV    REMOTE(A0),A5
  1555.     MOV    #^C<REMMOD>,D1        ; clear bits we set (except OIP)
  1556.     CALL    INUSE            ; get in-use bit
  1557.     TSTB    ATERM(A0)        ; user & comm port the same?     [010]
  1558.     BEQ    4$            ;  yes-leave busy bit as is      [010]
  1559.     BCLR    D6,D1            ; clear it for bit clear mask
  1560. 4$:    CALL    SETSTS            ; clear all those bits
  1561.     CLR    D1
  1562.     MOVW    SAVSTS(A0),D1        ; get saved status
  1563.     AND    #^CT$OIP,D1        ;  less OIP bit which hangs output!
  1564.     CALL    SETSTS            ; set the saved bits
  1565.     MOV    SAVJCB(A0),A6
  1566.     MOV    A6,T.JLK(A5)        ; restore any attached job
  1567.     BEQ    10$
  1568.     MOV    A5,JOBTRM(A6)        ; and JCB, if there was one
  1569. 10$:    MOV    SAVTDV(A0),T.TDV(A5)    ; restore TDV
  1570.     SAVE    A0            ; [16] JRUN the newly reattached job,
  1571.                     ; if it is waiting for OIP
  1572.     MOV    SAVJCB(A0),D7        ; get saved job
  1573.     BEQ    20$            ;  no saved job
  1574.     MOV    D7,A0
  1575.     MOVW    JOBSTS(A6),D7        ; get job status
  1576.     ANDW    #J.TOW,D7        ; was job waiting for output?
  1577.     BEQ    20$            ;  no
  1578.     JRUN    J.TOW            ;  yes
  1579. 20$:    REST    A0
  1580.     SETB    DONE(A0)        ; set the we are done flag
  1581.     RTN
  1582.  
  1583. ; A M O S - move to AMOS level temporarily.
  1584. AMOS:    SETB    DONE(A0)        ; set the we are done flag    
  1585.     RTN
  1586.  
  1587. ; S E T S T S
  1588. ; This routine sets or clears status bits in D1.
  1589. ; If D1 is minus, the bits are cleared. If they are +, the bits are set
  1590.  
  1591. ; This routine is used to set and reset TRMSER status word bits without
  1592. ; getting T$OIP fouled up and hanging the job's output.
  1593. SETSTS:    SUPVR
  1594. ; This routine runs in SUPVR mode
  1595. ; Used to change TRMSER status bits.
  1596. ; Made compatible with smart I/O cards by using new monitor calls if
  1597. ; O/S is new enough for it.
  1598.     SVLOK                ; prevent interrupts
  1599.     TSTB    COMSER(A0)        ; do we have COMSER? [015]
  1600.     BEQ    8$            ;  no, do it old way
  1601.     TSTW    D1            ; clear or set bits?
  1602.     BMI    4$            ; clear bits
  1603. ; new way to change T.STS word without violating T.SEM rules.
  1604.     PUSHW    D1
  1605.     TRMRST    D1,@A5            ; read status
  1606.     ORW    (SP)+,D1        ; stir in the new bits
  1607.     TRMWST    D1,@A5            ; write status
  1608.     BR    20$
  1609. 4$:    PUSHW    D1
  1610.     TRMRST    D1,@A5            ; read status
  1611.     ANDW    (SP)+,D1        ; pick out the icky bits
  1612.     TRMWST    D1,@A5            ; write status
  1613.     BR    20$
  1614.  
  1615. ; old way to change T.STS word
  1616. 8$:    TSTW    D1            ; set or clear bits?
  1617.     BMI    10$            ;  clear is negative
  1618.     ORW    D1,@A5            ; set bits if + or 0.
  1619.     BR    20$            ; done setting...
  1620. 10$:    ANDW    D1,@A5            ; clear those bits
  1621. 20$:    LSTS    #0            ; unlock CPU & return to user mode
  1622.     RTN
  1623. ;;;         F I L E   T R A N S F E R   R O U T I N E S
  1624.  
  1625. ; S E N D S W
  1626. ; SENDSW is the state table switch for file transfers. It loops either
  1627. ; until it finishes, or an error is encountered. The routines called
  1628. ; by SENDSW change the automaton state.
  1629. SENDSW:
  1630.     MOVB    #'S,STATE(A0)        ; start with SEND INIT
  1631.     CLRB    N(A0)            ; clear the seq number
  1632.     CLRB    NUMTRY(A0)        ;  and the retry count
  1633.     CLRB    LOGIC(A0)        ; CLEAR LOGIC
  1634.     CLRB    RIACK(A0)        ; clear the I is ACKed flag
  1635. 10$:    TSTB    LOGIC(A0)        ; test logic flag
  1636.     BNE    100$            ;  we are done
  1637.     CTRLC    ABORT            ; exit on control-C
  1638.     TSTB    DEBUGO(A0)        ; debug on ?
  1639.     BEQ    20$            ;   no
  1640.     TYPE    <SENDSW state >
  1641.     MOVB    STATE(A0),D1
  1642.     TTY
  1643.     CRLF
  1644.     CRLF
  1645. 20$:    LEA    A6,SWSTAT-4        ; index the state table
  1646.     MOVB    STATE(A0),D7        ; D7 gets the current state
  1647. 30$:    ADD    #4.,A6            ; pre-advance
  1648.     MOVB    @A6,D6
  1649.     BEQ    100$            ; undefined state - so exit
  1650.     CMPB    D6,D7            ;  matching state ?
  1651.     BNE    30$            ;   no
  1652.     ADD    #2.,A6            ; yes - advance to offset
  1653.     ADDW    @A6,A6            ; calc address of new routine
  1654.     CALL    @A6            ; execute it
  1655.     BR    10$            ; loop till we exit
  1656. 100$:    RTN
  1657.  
  1658. ABORT:    MOVB    #'A,STATE(A0)        ; flag it as bad.
  1659.     MOVB    #FALSE,LOGIC(A0)
  1660.     CALL    CLOSER
  1661.     RTN
  1662.  
  1663. COMPLT:    MOVB    #TRUE,LOGIC(A0)        ; flag complete o.k.
  1664.     RTN
  1665.  
  1666.  
  1667. ; S I N I T
  1668. ; Send (I) Initiate Packet & receive REMOTEs reply
  1669.  
  1670. SINIT:    ADDB    #1,NUMTRY(A0)        ; bump # of tries
  1671.     CMMB    NUMTRY(A0),MAXTRY(A0)    ; beyond the max?
  1672.     BLOS    20$
  1673.     MOVB    #'A,STATE(A0)
  1674. 10$:    RTN
  1675.  
  1676. 20$:    LEA    A3,PACKET(A0)        ; index the packet area
  1677.     CALL    SPAR            ; load default data for S packet
  1678.     CALL    FLUSH            ; flush pending input
  1679.     MOVB    DF.EOL(A0),EOL(A0)    ; use default EOL
  1680.     SPACK    #'S,N(A0),#PARSIZ,PACKET(A0)    ; send an S packet
  1681. ; just in case host requires an EOL character, send the default EOL value.
  1682.     MOVB    #CR,D1            ; send universal EOL value
  1683.     CALL    OUTBYT            ; output the EOL to get remote going
  1684. ;    RPACK    LEN,SEQ,PACKET,TYPE
  1685.     RPACK    D2,D3,RECPKT(A0),D4    ; receive a packet
  1686.     BNE    1000$            ; no packet received ; timeout
  1687.                     ;  or damaged packet
  1688.     CMPB    D4,#'N            ; NAK, try again
  1689.     JEQ    1000$            ;  just return, leave state as is.
  1690.     CMPB    D4,#'Y            ; ACK ?
  1691.     BNE    30$            ;  no ACK
  1692.     CMPB    D3,N(A0)        ;  yes-same # as I sent?
  1693.     BNE    1000$            ;   no-return, same state
  1694. ; get other side's init info.
  1695.     SETB    RIACK(A0)        ; flag we got ACK to I packet
  1696.     LEA    A3,RECPKT(A0)        ; index work area
  1697.     CALL    RPAR            ; load parameters from work area
  1698.     CMPB    QUOTE(A0),#SPACE    ; check for space or null
  1699.     BHI    32$
  1700.     MOVB    #MYQUOT,QUOTE(A0)    ; reset to #
  1701. 32$:    CLRB    NUMTRY(A0)        ; clear retries
  1702.     CALL    BUMPP            ; bump N mod 64.
  1703.     MOVB    #'F,STATE(A0)        ; move to state F
  1704.     JMP    1000$            ; done
  1705. 30$:    CMPB    D4,#'E            ; error packet received ?
  1706.     BNE    40$            ;  no
  1707.     CALL    PRTERR            ; show error
  1708. ; move to abort state on any undefined TYPEs
  1709. 40$:    MOVB    #'A,STATE(A0)        ; move to abort state.
  1710. 1000$:    RTN
  1711.  
  1712. ; S F I L E sends the file header.
  1713. SFILE:    TSTB    FIO+D.ERR(A0)        ; error on input file?
  1714.     BNE    2$            ;  yes, move to break state
  1715.     MOV    CMNEXT(A0),D7
  1716.     AND    #NX$END,D7        ; end of specs?
  1717.     BEQ    4$            ;  no
  1718. 2$:    MOVB    #'B,STATE(A0)        ;  yes, send a break
  1719.     RTN
  1720.  
  1721. 4$:    INCB    NUMTRY(A0)        ; bump the count
  1722.     CMMB    NUMTRY(A0),MAXTRY(A0)    ; beyond the max?
  1723.     BLOS    10$            ;  no
  1724.     MOVB    #'A,STATE(A0)        ; set state to abort
  1725.     RTN
  1726.  
  1727. 10$:    CLR    D2
  1728.     MOVB    FLLEN(A0),D2
  1729. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  1730.     SPACK    #'F,N(A0),D2,NFILNM(A0)    ; send the F packet
  1731.  
  1732. ;     RPACK    LEN,SEQ,PACKET,TYPE
  1733.     RPACK    D2,D3,RECPKT(A0),D4        ; wait for reply
  1734.     BNE    1000$                ; no reply
  1735. ; compare received sequence # to expected #
  1736.     CMPB    D4,#'N            ; NAK ?
  1737.     BNE    30$            ;  no NAK here
  1738. ; check to see if NAK is for next block, which we will
  1739. ; interpret as being an ACK for this block.
  1740.     CALL    NEXTN            ; D1 gets NEXT packet #
  1741.     CMPB    D1,D3            ; NAK for next block ?
  1742.     BNE    1000$            ;  no-return with state unchanged
  1743.     BR    35$            ;  yes-treat as ACK for this block
  1744.  
  1745. 30$:    CMPB    D4,#'Y            ; ACK ?
  1746.     BNE    40$            ;  no
  1747.     MOVB    N(A0),D1        ; D1 gets current SEQ #
  1748.     CMPB    D3,D1            ;  yes-is it expected SEQ?
  1749.     BNE    1000$            ;   no-return state unchanged
  1750. 35$:    CLRB    NUMTRY(A0)        ;   yes-clear retries count
  1751.     CALL    BUMPP
  1752.     LEA    A3,PACKET(A0)
  1753.     CALL    BUFFIL            ; fill a buffer @A3
  1754.     MOVB    #'D,STATE(A0)        ; goto Data state
  1755.     JMP    1000$
  1756.  
  1757. 40$:    CMPB    D4,#'E            ; Error packet received
  1758.     BNE    50$
  1759.     CALL    PRTERR            ; show the error
  1760. ; if any other case, move to abort case
  1761. 50$:    MOVB    #'A,STATE(A0)        ; move to abort state
  1762. 1000$:    RTN
  1763.  
  1764. ; S D A T A  - sends a portion of file contents
  1765. SDATA:    INCB    NUMTRY(A0)        ; bump try count
  1766.     CMMB    NUMTRY(A0),MAXTRY(A0)    ; maxxed out ?
  1767.     BLOS    10$            ;  no    
  1768.     MOVB    #'A,STATE(A0)        ;  yes-move to abort state
  1769.     RTN
  1770.  
  1771. 10$:    
  1772. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  1773.     SPACK    #'D,N(A0),BUFCNT(A0),PACKET(A0)    ; send data packet
  1774. ;    RPACK    LEN,SEQ,PACKET,TYPE
  1775.     RPACK    D2,D3,RECPKT(A0),D4    ; receive a packet
  1776.     JNE    1000$            ;  no data received
  1777.     CMPB    D4,#'N            ; NAK ?
  1778.     BNE    15$            ;  no
  1779.     CALL    NEXTN            ; D1 gets N
  1780.     CMPB    D1,D3            ; NAK for N+1?
  1781.     BEQ    40$            ;  yes-treat as lost ACK for N
  1782.     JMP    1000$            ; else exit state unchanged
  1783.  
  1784. 15$:    CMPB    D4,#'Y            ; ACK ?
  1785.     BNE    70$            ; no
  1786.     CMPB    D3,N(A0)        ; right SEQ of ACK?
  1787.     BNE    1000$            ;  no-state unchanged
  1788.     TSTB    LDATA(A0)        ; is data length zero?
  1789.     BEQ    30$            ;  yes
  1790. ;test for graceful abort request from RECeiving Kermit.
  1791.     MOVB    RECPKT+DATA(A0),D7    ;  no-get the byte
  1792.     ANDB    #^O177,D7        ; strip to ACSII
  1793.     CMPB    D7,#'Z            ; is it abort batch?
  1794.     BNE    20$            ;  no
  1795.     SETB    ABORTB(A0)        ;  yes, set abort batch flag
  1796.     BR    30$            ; 
  1797. 20$:    CMPB    D7,#'X            ; is it abort file?
  1798.     BNE    30$            ;  yes
  1799.     SETB    ABORTF(A0)
  1800. 30$:    CALL    SHODOT            ; tell user we moved some data
  1801. 40$:    CALL    BUMPP            ; bump packet count
  1802.     TSTB    ABORTF(A0)        ; abort file?
  1803.     BNE    50$            ;  yes
  1804.     CLRB    NUMTRY(A0)        ; clear the try count
  1805.     LEA    A3,PACKET(A0)        ; index the Packet
  1806.     CALL    BUFFIL            ; get a buffer
  1807.     TSTB    BUFCNT(A0)        ; any data to send ?
  1808.     BNE    60$    
  1809. 50$:    CALL    CLOSER            ; close file
  1810.     MOVB    #'Z,STATE(A0)        ; move to Z state (end of file)
  1811.     JMP    1000$
  1812. 60$:    MOVB    #'D,STATE(A0)        ; stay in D state
  1813.     JMP    1000$
  1814. 70$:    CMPB    D4,#'E            ; Error packet ?
  1815.     BNE    1000$
  1816.     CALL    PRTERR
  1817.     MOVB    #'A,STATE(A0)        ; move to A state.
  1818. 1000$:    RTN
  1819.     
  1820. ; S E O F  - send the end of file packet.
  1821. SEOF:    INCB    NUMTRY(A0)
  1822.     CMMB    NUMTRY(A0),MAXTRY(A0)
  1823.     BLOS    10$
  1824.     MOVB    #'A,STATE(A0)
  1825.     RTN
  1826.  
  1827. 10$:    CLR    D2            ; D2 is packet size
  1828.     TSTB    ABORTF(A0)        ; aborting this file ( or batch)?
  1829.     BEQ    20$            ;  no
  1830.     MOV    #1,D2            ;  yes, set size to 1 byte
  1831.     MOVB    #'D,PACKET+DATA(A0)    ; flag "DISCARD" to remote
  1832. 20$:
  1833. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  1834.     SPACK    #'Z,N(A0),D2,PACKET(A0)    ; send a Z packet
  1835. ;    RPACK    LEN,SEQ,PACKET,TYPE
  1836.     RPACK    D2,D3,RECPKT(A0),D4    ; get a reply
  1837.     BNE    1000$            ; 
  1838.     CMPB    D4,#'N            ; NAK ?
  1839.     BNE    30$
  1840.     CALL    NEXTN            ; D1 gets next N mod 64.
  1841.     CMPB    D1,D3            ; NAK for SEQ+1?
  1842.     BEQ    40$            ; yes-treat as ACK.
  1843.     JMP    1000$            ; return as is
  1844.  
  1845. 30$:    CMPB    D4,#'Y            ; ACK ?
  1846.     BNE    60$            ;  no
  1847.     CMPB    D3,N(A0)        ; matching SEQ #?
  1848.     BNE    1000$            ;  no-return as is
  1849. 40$:    CALL    BUMPP            ; bump the N value
  1850.     CALL    ENDTM            ; display speed stats
  1851.     CALL    DINGEM            ; [015]
  1852.     TSTB    ABORTB(A0)        ; abort batch? [015]
  1853.     BNE    50$            ;  yes [015]
  1854.     CALL    GETNXT            ; any more files?
  1855.     BVS    50$            ;  no
  1856.     TSTB    FIO+D.ERR(A0)        ;  file error?
  1857.     BNE    50$            ;  yes, end transfer
  1858.     CALL    GTSIZE            ; calc file size
  1859.     CALL    STARTT            ; set start time
  1860.     MOVB    #'F,STATE(A0)        ; reset state for more files
  1861. ;    CLRB    N(A0)            ; clear the seq number
  1862.     CLRB    NUMTRY(A0)        ;  and the retry count
  1863.     JMP    1000$
  1864.  
  1865. ; we found the "free time" for multiple files in 1991!
  1866. 50$:    MOVB    #'B,STATE(A0)        ; goto Break state
  1867.     JMP    1000$
  1868.  
  1869. 60$:    CMPB    D4,#'E            ; error packet ?
  1870.     BNE    70$            ;  no
  1871.     CALL    PRTERR            ;  yes-print erorrrr.
  1872.     JMP    1000$
  1873. 70$:    MOVB    #'A,STATE(A0)        ; abort on undefined types
  1874. 1000$:    RTN
  1875.  
  1876. ;  S B R E A K -  sends a break frame (no more files to send).
  1877. SBREAK:    INCB    NUMTRY(A0)        ; bump the try count
  1878.     CMMB    NUMTRY(A0),MAXTRY(A0)    ; maxxed out?
  1879.     BLOS    10$            ;  no
  1880.     MOVB    #'A,STATE(A0)        ;  yes-abort state
  1881.     RTN
  1882.  
  1883. 10$:    
  1884. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  1885.     SPACK    #'B,N(A0),#0,PACKET(A0)    ; send a B packet
  1886. ;    RPACK    LEN,SEQ,PACKET,TYPE
  1887.     RPACK    D2,D3,RECPKT(A0),D4    ; get a reply
  1888.     BNE    1000$            ; no reply
  1889.     CMPB    D4,#'N            ; NAK ?
  1890.     BNE    20$
  1891.     CALL    NEXTN            ; D1 gets next N mod 64.
  1892.     CMPB    D1,D3            ; NAK for SEQ+1?
  1893.     BEQ    30$            ; yes-treat as ACK.
  1894.     JMP    1000$            ; return as is
  1895.  
  1896. 20$:    CMPB    D4,#'Y            ; ACK ?
  1897.     BNE    40$            ;  no
  1898.     CMPB    D3,N(A0)        ; matching SEQ #?
  1899.     BNE    1000$            ;  no-return as is
  1900. 30$:    CALL    BUMPP            ; bump the N value
  1901.     MOVB    #'C,STATE(A0)        ; goto Complete state
  1902.     JMP    1000$
  1903.  
  1904. 40$:    CMPB    D4,#'E            ; error packet ?
  1905.     BNE    50$            ;  no
  1906.     CALL    PRTERR            ;  yes-print erorrrr.
  1907.     JMP    1000$
  1908.  
  1909. 50$:    MOVB    #'A,STATE(A0)        ; abort on undefined types
  1910. 1000$:    RTN
  1911.  
  1912. ; R E C S W  - is the state table switch for receiving files.
  1913. RECSW:    MOVB    #'R,STATE(A0)        ; start with RECV INIT state
  1914.     CLRB    N(A0)            ; clear the seq number
  1915.     CLRB    NUMTRY(A0)        ;  and the retry count
  1916.     CLRB    LOGIC(A0)        ; clear logic
  1917.     CLRB    RIACK(A0)        ; clear the I is ACKed flag
  1918. 10$:    TSTB    LOGIC(A0)        ; test logic flag
  1919.     BNE    100$            ;  we are done
  1920.     CTRLC    RABOR            ;  or user wants out
  1921.     TSTB    DEBUGO(A0)        ; debug on ?
  1922.     BEQ    20$            ;   no
  1923.     TYPE    <RECSW state >
  1924.     MOVB    STATE(A0),D1
  1925.     TTY
  1926.     CRLF
  1927. 20$:    LEA    A6,RCSTAT-4        ; index the state table
  1928.     MOVB    STATE(A0),D7        ; D7 gets the current state
  1929. 30$:    ADD    #4.,A6            ; pre-advance
  1930.     MOVB    @A6,D6
  1931.     BEQ    100$            ; undefined state - so exit
  1932.     CMPB    D6,D7            ;  matching state ?
  1933.     BNE    30$            ;   no
  1934.     ADD    #2.,A6            ; yes - advance to offset
  1935.     ADDW    @A6,A6            ; calc address of new routine
  1936.     CALL    @A6            ; execute it
  1937.     BR    10$            ; loop till we exit
  1938. 100$:    RTN
  1939.  
  1940. RABOR:    MOVB    #'A,STATE(A0)        ; flag transfer as bad
  1941.     MOVB    #FALSE,LOGIC(A0)
  1942.     RTN
  1943.  
  1944. RCOMP:    MOVB    #TRUE,LOGIC(A0)        ; flag complete o.k.
  1945.     RTN
  1946.  
  1947. ; R I N I T - is the receive init routine
  1948. ; Wait for the send-init packet from sending Kermit.
  1949. RINIT:    ADDB    #1,NUMTRY(A0)        ; count the tries
  1950.     CMMB    NUMTRY(A0),MAXTRY(A0)    ; beyond the max?
  1951.     BLOS    20$
  1952.     MOVB    #'A,STATE(A0)
  1953.     RTN
  1954.  
  1955. 20$:    
  1956. ;    RPACK    LEN,SEQ,PACKET,TYPE
  1957.     RPACK    D2,D3,PACKET(A0),D4    ; receive a packet
  1958.     BNE    50$            ;  no packet received ; timeout
  1959.     CMPB    D4,#'S            ;  got an S packet ?
  1960.     BNE    30$            ;   no S packet
  1961. ; get other side's init data
  1962.     LEA    A3,PACKET(A0)        ; index data packet address
  1963.     CALL    RPAR            ; get parameters
  1964.     LEA    A3,PACKET(A0)        ; index data packet address
  1965.     CALL    SPAR            ;  send our parameters
  1966. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  1967.     SPACK    #'Y,N(A0),#PARSIZ,PACKET(A0); send ACK with reply
  1968.     SETB    RIACK(A0)        ; flag ACK to I has been sent
  1969.     MOVB    NUMTRY(A0),OLDTRY(A0)    ; save try count
  1970.     CLRB    NUMTRY(A0)        ; clear count
  1971.     CALL    BUMPP            ; bump packet #
  1972.     MOVB    #'F,STATE(A0)        ; bump state
  1973.     JMP    1000$            ; end
  1974.  
  1975. 30$:    CMPB    D4,#'E            ; error received ?
  1976.     BNE    40$
  1977.     CALL    PRTERR            ; display the error.
  1978.     MOVB    #'A,STATE(A0)
  1979.     JMP    1000$            ; done
  1980. ; all others default to A state
  1981. 40$:    MOVB    #'A,STATE(A0)        ; received junk-abort
  1982.     JMP    1000$
  1983. ; no packet received - send a NAK
  1984. 50$:    SPACK    #'N,N(A0),#0,NFILNM(A0)    ; send a NAK packet
  1985.                     ; return without state change
  1986. 1000$:    RTN
  1987.  
  1988. ; R F I L E  - receive a file header frame with the filename.
  1989. RFILE:    ADDB    #1,NUMTRY(A0)        ; count the tries
  1990.     CMMB    NUMTRY(A0),MAXTRY(A0)    ; beyond the max?
  1991.     BLOS    20$
  1992.     MOVB    #'A,STATE(A0)
  1993.     RTN
  1994.  
  1995. 20$:    
  1996.  
  1997. ;    RPACK    LEN,SEQ,PACKET,TYPE
  1998.     RPACK    D2,D3,NFILNM(A0),D4    ; receive a packet (expecting filename)
  1999.     JNE    500$            ;  no packet received ; timeout
  2000.     CMPB    D4,#'S            ;  got an S packet ?
  2001.     BNE    50$            ;   no
  2002. ; SEND-INIT received, maybe ACK was lost.
  2003.     CALL    NEXTO            ; D1 gets next OLDTRY value
  2004.     CMPB    D1,MAXTRY(A0)        ;  time to give up?
  2005.     BLOS    30$            ;   no
  2006.     MOVB    #'A,STATE(A0)
  2007.     JMP    1000$            ; yes-goto abort state.
  2008.  
  2009. 30$:    MOVB    N(A0),D1        ; D1 gets current packet #
  2010.     CALL    PREVP            ; get previous packet #
  2011.     CMPB    D1,D3            ; previous packet ?
  2012.     BNE    40$            ;  no
  2013. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  2014.     SPACK    #'Y,D3,#PARSIZ,PACKET(A0)    ;   yes-ack again with SEND-INIT
  2015.     CLRB    NUMTRY(A0)        ; clear retry count
  2016.     JMP    1000$            ;  stay in state.
  2017.  
  2018. 40$:    MOVB    #'A,STATE(A0)        ; goto abort
  2019.     JMP    1000$            ;  done
  2020.  
  2021. 50$:    CMPB    D4,#'Z            ; end of file?
  2022.     BNE    80$            ;  no
  2023.     CALL    NEXTO            ; D1 gets next oldtry
  2024.     CMPB    D1,MAXTRY(A0)        ;  time to give up?
  2025.     BLOS    60$            ;   no
  2026.     MOVB    #'A,STATE(A0)        ;   yes-abort
  2027.     JMP    1000$            ; done
  2028.  
  2029. 60$:    MOVB    N(A0),D1        ; get N
  2030.     CALL    PREVP            ; calc previous packet # to D1
  2031.     CMPB    D1,D3            ;  same ?
  2032.     BNE    70$            ;  no
  2033. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  2034.     SPACK    #'Y,D3,#0,PACKET(A0)    ;   yes-ack Z from file before!
  2035.     CLRB    NUMTRY(A0)        ; reset tries
  2036.     JMP    1000$            ;  done
  2037.  
  2038. 70$:    MOVB    #'A,STATE(A0)        ; goto ABORT otherwise.
  2039.     JMP    1000$
  2040.  
  2041. 80$:    CMPB    D4,#'F            ; is it the blessed file header yet?
  2042.     JNE    200$            ;  no    
  2043.     CMPB    D3,N(A0)        ;  yes-is the packet # correct?
  2044.     BNE    70$            ;   no-move to abort state.
  2045.     CALL    RFILNM            ; process the filename & open.
  2046.     BEQ    90$            ; it opened ok
  2047.     CALL    LFERR            ; show local file error
  2048.     MOVB    #'A,STATE(A0)        ; move to abort state
  2049.     JMP    1000$            ; done
  2050. 90$:    TSTB    NOTALK(A0)        ; do we have a user terminal?
  2051.     BNE    120$            ;  no-bypass message
  2052.     CRLF
  2053.     TYPE    <Receiving >
  2054.     CLR    D0
  2055.     MOVB    LDATA(A0),D0
  2056.     LEA    A1,FILNAM(A0)
  2057.     BR    110$
  2058. 100$:    MOVB    (A1)+,D1
  2059.     TTY
  2060. 110$:    DBF    D0,100$
  2061.     TYPE    < as >
  2062.     PFILE    FIO(A0)
  2063.     CRLF
  2064. 120$:
  2065. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  2066.     SPACK    #'Y,N(A0),#0,PACKET(A0)    ;   send ACK for the F packet
  2067.     MOVB    NUMTRY(A0),OLDTRY(A0)    ; reset try counters
  2068.     CLRB    NUMTRY(A0)
  2069.     CALL    BUMPP            ; get next packet #
  2070.     MOVB    #'D,STATE(A0)        ; move to data state
  2071.     JMP    1000$
  2072.  
  2073. 200$:    CMPB    D4,#'B            ; break ?
  2074.     BNE    300$            ;  no
  2075.     CMPB    D3,N(A0)        ;  yes-is packet # correct?
  2076.     BNE    310$    
  2077. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  2078.     SPACK    #'Y,N(A0),#0,PACKET(A0)    ;   send ACK for the B packet
  2079.     MOVB    #'C,STATE(A0)        ; and move to Complete state
  2080.     JMP    1000$            ; end
  2081.  
  2082. 300$:    CMPB    D4,#'E            ; error frame ?
  2083.     BNE    400$            ;  no
  2084.     CALL    PRTERR            ;  show it
  2085. 310$:    MOVB    #'A,STATE(A0)        ; move to abort
  2086.     JMP    1000$
  2087. 400$:    MOVB    #'A,STATE(A0)        ; goto abort state
  2088.     JMP    1000$
  2089.  
  2090. ; didnt get a packet
  2091. 500$:
  2092. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  2093.     SPACK    #'N,N(A0),#0,PACKET(A0)    ;   send NAK 
  2094. 1000$:    RTN
  2095.  
  2096. ; R D A T A -  receives the data packets that make up the file.
  2097. RDATA:    ADDB    #1,NUMTRY(A0)        ; count the tries
  2098.     CMMB    NUMTRY(A0),MAXTRY(A0)    ; beyond the max?
  2099.     BLOS    20$
  2100.     MOVB    #'A,STATE(A0)
  2101.     RTN
  2102.  
  2103. 20$:    
  2104. ;    RPACK    LEN,SEQ,PACKET,TYPE
  2105.     RPACK    D2,D3,PACKET(A0),D4    ; receive a packet (expecting filename)
  2106.     JNE    500$            ;  no packet received ; timeout
  2107.     CMPB    D4,#'D            ; got a Data packet ?
  2108.     JNE    60$            ;  no
  2109.     CMPB    D3,N(A0)        ;  yes-is it right packet # ?
  2110.     BEQ    50$            ;   YES
  2111.     CALL    NEXTO            ;   NO-get next OLDTRY value in D1
  2112.     CMPB    D1,MAXTRY(A0)        ;  
  2113.     BLOS    25$
  2114.     MOVB    #'A,STATE(A0)        ; abort -retries exceeded
  2115.     JMP    1000$            ;  done
  2116.  
  2117. 25$:    MOVB    N(A0),D1        ; D1 gets current packet #
  2118.     CALL    PREVP            ; get previous packet #
  2119.     CMPB    D1,D3            ; previous packet ?
  2120.     BNE    40$            ;  no
  2121. ;    SPACK    TYPE,SEQ,SIZE,PACKET    
  2122.     SPACK    #'Y,D3,#6,PACKET(A0)    ;   yes-re-ack.
  2123.     CLRB    NUMTRY(A0)        ; clear retry count
  2124.     JMP    1000$            ;  stay in state.
  2125.  
  2126. 40$:    MOVB    #'A,STATE(A0)        ; goto abort
  2127.     JMP    1000$            ;  done
  2128.  
  2129. ; received valid data frame - output it
  2130. 50$:    CALL    BUFEMP            ; empty the buffer to disk
  2131. ;    SPACK    TYPE,SEQ,SIZE,PACKET    
  2132.     SPACK    #'Y,N(A0),#0,PACKET(A0)    ;   ack the data
  2133.     MOVB    NUMTRY(A0),OLDTRY(A0)    ; reset the try counters
  2134.     CLRB    NUMTRY(A0)        ; clear retry count
  2135.     CALL    BUMPP            ; bump the packet #
  2136.     MOVB    #'D,STATE(A0)        ; stick in D state.
  2137.     CALL    SHODOT            ; tell user we moved some data
  2138.     JMP    1000$            ;  stay in state.
  2139.  
  2140. 60$:    CMPB    D4,#'F            ; file header?
  2141.     BNE    80$            ;  no
  2142.     CALL    NEXTO            ; D1 gets next oldtry
  2143.     CMPB    D1,MAXTRY(A0)        ;  time to give up?
  2144.     BLOS    70$            ;   no
  2145. 65$:    MOVB    #'A,STATE(A0)        ;   yes-abort
  2146.     JMP    1000$            ; done
  2147. 70$:    MOVB    N(A0),D1        ; get N
  2148.     CALL    PREVP            ; calc previous packet # to D1
  2149.     CMPB    D1,D3            ;  same ?
  2150.     BNE    65$            ;  no
  2151. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  2152.     SPACK    #'Y,D3,#0,PACKET(A0)    ;   yes-ack again
  2153.     CLRB    NUMTRY(A0)        ; reset tries
  2154.     JMP    1000$            ;  done
  2155.  
  2156. 80$:    CMPB    D4,#'Z            ; end of file?
  2157.     BNE    200$            ;  no    
  2158.     CMPB    D3,N(A0)        ;  yes-is the packet # correct?
  2159.     BNE    65$            ;   no-move to abort state.
  2160. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  2161.     SPACK    #'Y,D3,#0,PACKET(A0)    ;   ack the Z
  2162.     CALL    CLOSER
  2163.     LOOKUP    FIO(A0)            ; do file lookup
  2164.     CALL    GTSIZE            ; to get file size
  2165.     CALL    ENDTM            ; show elapsed time & speed
  2166.     CALL    DINGEM            ; [015] alert user
  2167.     CALL    BUMPP            ; bumpthepacket#
  2168.     MOVB    #'F,STATE(A0)        ; return the F state
  2169.     BR    1000$
  2170.  
  2171. 200$:    CALL    CLOSER            ; close file if open
  2172.     CMPB    D4,#'E            ; error frame ?
  2173.     BNE    400$            ;  no
  2174.     CALL    PRTERR            ;  show it
  2175.     MOVB    #'A,STATE(A0)        ; move to abort
  2176.     JMP    1000$
  2177.  
  2178. 400$:    MOVB    #'A,STATE(A0)        ; goto abort state
  2179.     JMP    1000$
  2180. ; didnt get a packet
  2181. 500$:
  2182. ;    SPACK    TYPE,SEQ,SIZE,PACKET
  2183.     SPACK    #'N,N(A0),#0,PACKET(A0)    ;   send NAK 
  2184. 1000$:    RTN
  2185.  
  2186. ;;;               P A C K E T   U T I L I T I E S
  2187.  
  2188. ; B U M P P - bumps the current packet mod 64. The new N is returned in D1,
  2189. ; and is also updated in N(A0).
  2190. BUMPP:    BCALL    NEXTN
  2191.     MOVB    D1,N(A0)
  2192.     RTN
  2193.  
  2194. ; N E X T N - returns the next N(A0) value in D1. It does NOT update N(A0).
  2195. NEXTN:    CLR    D1
  2196.     MOVB    N(A0),D1
  2197.     ADD    #1,D1
  2198.     ANDB    #63.,D1
  2199.     RTN
  2200.  
  2201. ; N E X T O - returns the next OLDTRY(A0) value in D1. 
  2202. ; It does not update OLDTRY(A0).
  2203. NEXTO:    CLR    D1
  2204.     MOVB    OLDTRY(A0),D1
  2205.     ADD    #1,D1
  2206.     ANDB    #63.,D1
  2207.     RTN
  2208.  
  2209. ; P R E V P - returns the prior packet to D1 in D1. ( D1-1 mod 64. )
  2210. PREVP:    SUB    #1,D1
  2211.     AND    #63.,D1
  2212.     RTN
  2213.  
  2214. ; P R T E R R - prints the error message contained in the Error packet
  2215. PRTERR:    CLR    D0            ; 
  2216.     MOVB    LDATA(A0),D0        ; get length of data field
  2217.     LEA    A1,DATA(A3)
  2218.     TTYL    ABTTTL
  2219.     BR    30$
  2220. 20$:    MOVB    (A1)+,D1
  2221.     TTY
  2222. 30$:    DBF    D0,20$
  2223.     CRLF
  2224.     RTN
  2225.  
  2226. ; R P A R  -  get the REMOTE's send-init parameters.
  2227. ; At entry, A3 indexs the packet area
  2228. ; revised [21]
  2229. RPAR:    MOVB    #'1,CHKT(A0)        ; default to 1 char checksum
  2230.     MOVB    #SPACE,REPT(A0)        ; and no repeat
  2231.     CLRB    QBIN(A0)        ; default to no quoting, 7 bit path
  2232. 10$:    LEA    A1,DATA(A3)        ; index the payload area
  2233.     CLR    D1
  2234.     MOVB    (A1)+,D1        ; get MAXL byte
  2235.     AND    #177,D1            ; strip to ASCII in case of parity
  2236.     UNCHAR    D1
  2237.     CMPB    D1,#PAKSIZ        ; bigger than protocol max?
  2238.     BHI    19$            ;  yes, use default
  2239. 15$:    CMPB    D1,MXPKSZ(A0)        ; compare to user's max
  2240.     BLO    18$            ;  but no higher
  2241.     MOVB    MXPKSZ(A0),D1        ; use our local max
  2242. 18$:    CMPB    D1,#10.            ; MAXL should be at least 10.
  2243.     BHIS    30$
  2244. 19$:    MOV    #80.,D1            ; yes, use default MAXL of 80.
  2245. 30$:    MOVB    D1,SPSIZ(A0)        ; set send packet size
  2246.     MOVB    (A1)+,D1         ; get TIME byte
  2247.     UNCHAR    D1
  2248.     MOV    D1,TIMINT(A0)        ; set when I should time out
  2249.     MOVB    (A1)+,D1        ; get NPAD byte
  2250.     UNCHAR    D1
  2251.     MOVB    D1,PAD(A0)        ; set pad count.
  2252.     MOVB    (A1)+,D1        ; get PADC byte
  2253.     CTL    D1
  2254.     MOVB    D1,PADCHR(A0)        ; set pad character
  2255.     MOVB    (A1)+,D1        ; get EOL byte
  2256.     UNCHAR    D1
  2257.     MOVB    D1,EOL(A0)        ; set end of line char
  2258.     MOVB    (A1)+,D1        ; get QCTL byte
  2259.     CMPB    D1,#SPACE
  2260.     BHI    40$
  2261.     MOV    #MYQUOT,D1        ; default it
  2262. 40$:    MOVB    D1,QUOTE(A0)        ; set control-quote.
  2263.     CLR    D2
  2264.     MOVB    LDATA(A0),D2        ; get size of data area
  2265.     SUB    #6,D2            ; have more than basic 6 bytes?
  2266.     JLOS    140$            ; no more data
  2267. ; get QBIN
  2268.     MOVB    (A1)+,D1        ; get QBIN byte
  2269.     AND    #177,D1            ; strip to ASCII
  2270.     CMPB    D1,#'Y            ; will quote if we request?
  2271.     BNE    50$            ;  no
  2272.     MOV    #1,D0            ;  yes
  2273.     BR    80$
  2274. ; allowable ranges are decimal 33-62 & 96-126. Reject all others.
  2275. 50$:    CMPB    D1,#SPACE        ; was it a space through null?
  2276.     BLOS    70$            ;  not legal 8b quote value
  2277.     CMPB    D1,#62.            ; ASCII 33-62?
  2278.     BLOS    60$            ;  yes-use it
  2279.     CMPB    D1,#127.        ; check high boundary of 2nd range
  2280.     BHIS    70$            ;  not legal 8b quote value
  2281.     CMPB    D1,#96.            ; check lower bound of 2nd range
  2282.     BHIS    60$            ;  legal
  2283.     BR    70$            ;  not legal
  2284. 60$:    MOV    #2,D0            ; set case 2 - we have valid 8b q
  2285.     BR    80$
  2286. 70$:    MOV    #0,D0            ; case 0 - we have no 8b q info
  2287. ; D0 is 0, 1 or 2
  2288. 80$:    DEC    D0            ; was it 0?
  2289.     BCC    90$            ;  no
  2290.     CMPB    PARITY(A0),#'N        ; do we have NO parity?
  2291.     SETNE    QBIN(A0)        ;  P=None, allow full 8 bits
  2292.                     ;  P=other, mask to 7 bits
  2293.     BR    110$
  2294. 90$:    DEC    D0            ; was it 1? (quote if needed only)
  2295.     BCC    100$            ;  no
  2296.     CMPB    PARITY(A0),#'N        ; do we have NO parity?
  2297.     BEQ    95$            ;  yes-flag 8 bits, no quoting
  2298.     MOVB    #'&,QBIN(A0)        ; else 7 bits, default quote
  2299.     BR    110$
  2300. 95$:    CLRB    QBIN(A0)        
  2301.     BR    110$
  2302. 100$:    MOVB    D1,QBIN(A0)        ; got QBIN - 7 bits w/quoting
  2303. 110$:    SUB    #1,D2
  2304.     BEQ    140$            ; no more
  2305. ; get CHKT
  2306.     MOVB    (A1)+,D1        ; get CHKT byte
  2307. ;;[023]    CMPB    D1,#'2            ; higher than 2?
  2308.     CMPB    D1,DF.CHK(A0)        ; higher than max user value? [023]
  2309.     BHI    120$            ;  yes-force to one
  2310.     BEQ    130$            ;  no-allow it
  2311.     CMPB    D1,#1            ; do not allow zero
  2312.     BEQ    130$
  2313. 120$:    MOV    #'1,D1            ; force to 1 if BOTH SIDES don't agree
  2314. 130$:    MOVB    D1,CHKT(A0)        ; set checksum method
  2315.     SUB    #1,D2
  2316.     BEQ    140$
  2317. ; get REPT
  2318.     MOVB    (A1)+,D1        ; get REPT byte
  2319.     UNCHAR    D1
  2320.     MOVB    D1,REPT(A0)        ; set repeat prefix
  2321. 140$:    CMPB    QUOTE(A0),#SPACE    ; quote undefined ?
  2322.     BNE    150$            ;  no-defined
  2323.     MOVB    #'#,QUOTE(A0)        ;  yes-use default
  2324. 150$:    RTN
  2325.  
  2326.  
  2327. ; S P A R  - fill data area with send-init parameters
  2328. SPAR:    LEA    A1,DATA(A3)    ; index payload area
  2329.     CLR    D1
  2330.     MOVB    MXPKSZ(A0),D1        ; get max packet size
  2331.     CHAR    D1
  2332.     MOVB    D1,(A1)+        ; 1 max packet size
  2333.     MOV     DF.TIM(A0),D1        ; get our default value
  2334.     CHAR    D1
  2335.     MOVB    D1,(A1)+        ; 2 # of seconds to my timeout
  2336.     MOV    #MYPAD,D1
  2337.     CHAR    D1
  2338.     MOVB    D1,(A1)+        ; 3 # of padding characters
  2339.     MOV    #MYPCHR,D1
  2340.     CTL    D1            ; the pad character translated
  2341.     MOVB    D1,(A1)+        ; 4
  2342.     MOV    #0,D1            ; we do not need an EOL this end.
  2343.     CHAR    D1
  2344.     MOVB    D1,(A1)+        ; 5 end of line character
  2345.     MOV    #MYQUOT,D1
  2346.     MOVB    D1,(A1)+        ; 6 control quoting character
  2347. ; handle QBIN
  2348.     MOVB    QBIN(A0),D1        ; get QBIN
  2349.     BEQ    40$            ;  only quote on request
  2350.     CMPB    D1,#^O377        ; is QBIN already defined?
  2351.     BNE    60$            ;  yes, else
  2352. 40$:    MOVB    #'Y,D1            ; default to quoting on request
  2353. 60$:    MOVB    D1,(A1)+        ; 7 the optional binary quoter
  2354.     MOVB    DF.CHK(A0),(A1)+    ; 8 the optional checkbyte type
  2355.     PARSIZ    =8.
  2356.     RTN
  2357.  
  2358.  
  2359. ; FLUSH deletes all pending input from the input buffer
  2360. FLUSH:    MOV    REMOTE(A0),A5
  2361. 10$:    TST    T.ICC(A5)        ; more data?
  2362.     BEQ    20$            ;  no, done
  2363.     TTYIN                ; dump a byte
  2364.     BR    10$
  2365. 20$:    RTN
  2366.  
  2367. ; B U F F I L  -  fills a packet @A3 with data.
  2368. ; we will limit data size to 3 less than actual size to allow the last
  2369. ; character to be control and 8bit quoted, without look-ahead schemes.
  2370. ; the worst cases are '# = &## and '& = &#&.
  2371. ; data count goes to BUFCNT(A0).
  2372. ; At entry,     A3 must index the data packet area to be filled,
  2373. ;        CHKNOW(A0) must contain the binary checkbyte size
  2374. BUFFIL:    CLR    D0
  2375.     MOVB    SPSIZ(A0),D0        ; D0 gets max msg size to remote
  2376.     SUBB    CHKNOW(A0),D0        ; less size of checkbyte
  2377.     SUB    #<3.>,D0        ;  less overhead bytes    
  2378.     LEA    A1,DATA(A3)        ; index the data area
  2379. 10$:    CALL    INBYTE            ; get a data byte
  2380.     TST    FIO+D.SIZ(A0)        ; end of file ?
  2381.     BEQ    100$            ;  yes
  2382. ; test for high bit
  2383.     BTST    #7.,D1            ;  no-test for eighth bit set.
  2384.     BEQ    30$            ;   bit 7 is clear
  2385. ; handle high bit prefixing, if any
  2386.     MOVB    QBIN(A0),D7        ; get 8bit quote character.
  2387.     BMI    20$            ;  no high bit can be used
  2388.     BEQ    30$            ;  no 8 bit quoting needed!
  2389.     MOVB    D7,(A1)+        ; buffer the 8bit quote
  2390.     SUB    #1,D0            ; decrement the count
  2391. 20$:    AND    #^O177,D1        ; strip to ascii
  2392. 30$:    MOVB    D1,D2        
  2393.     ANDB    #^O177,D2        ; D2 gets stripped version
  2394.     CMPB    D2,#DEL            ; is it a DEL
  2395.     BEQ    35$            ;   this is non-printable.
  2396. ; also prefix the prefix, and the high bit prefix with the prefix!
  2397.     CMPB    D2,QUOTE(A0)        ; is this character the prefix?
  2398.     BNE    32$            ;   no
  2399.     MOVB    D2,(A1)+        ;   yes-prefix it with itself
  2400.     SUB    #1,D0
  2401. 32$:    TSTB    QBIN(A0)        ; check 8 bit quoting
  2402.     BLE    34$            ;  none
  2403.     CMPB    D2,QBIN(A0)        ; matching?
  2404.     BNE    34$            ;  no-      [10/23/84 rpr]
  2405.     MOVB    QUOTE(A0),(A1)+        ;  yes-quote it first
  2406.     SUB    #1,D0            ; less one for quote
  2407. 34$:    CMPB    D2,#SPACE        ; is it control ?
  2408.     BHIS    50$            ;  no-prinatble
  2409. ; unctrol-ify the character, while preserving possible bit7.
  2410. 35$:    CTL    D1            ; uncontrol-ify
  2411. 40$:    MOVB    QUOTE(A0),(A1)+
  2412.     SUB    #1,D0
  2413. 50$:    MOVB    D1,(A1)+
  2414.     SUB    #1,D0
  2415.     BGT    10$            ; loop till filled up
  2416. 100$:    LEA    A6,DATA(A3)        ; ptr to start of data
  2417.     MOV    A1,D1            ; get ending ptr
  2418.     SUB    A6,D1            ; D1 gets outgoing data size
  2419.     MOVB    D1,BUFCNT(A0)        ; set data count
  2420.     RTN
  2421.  
  2422. ; INBYTE gets a byte from a disk file. 
  2423. INBYTE:    TST    FIO+D.SIZ(A0)        ; EOF already?
  2424.     BEQ    10$            ;  yes, done
  2425.     FILINB    FIO(A0)            ; get a byte from file
  2426. 10$:    RTN
  2427.  
  2428. ; close file if it is open.
  2429. CLOSER:    TSTB    FIO+D.OPN(A0)        ; is file open?
  2430.     BEQ    10$            ;  no
  2431.     CLOSE    FIO(A0)            ;   yes-close the file
  2432.     CLRB    FIO+D.OPN(A0)        ; and clear open code!
  2433. 10$:    RTN
  2434.  
  2435.  
  2436. ; B U F E M P  -  empties the incoming data contents of the packet @A3 to
  2437. ; the FIO(A0) file.
  2438. BUFEMP:    LEA    A1,DATA(A3)        ; index the data area
  2439.     CLR    D0
  2440.     MOVB    LDATA(A0),D0        ; D0 gets the count
  2441.     BR    600$            ; check for 0 bytes in packet [21]
  2442. 10$:    CALL    GETBYT            ; get an input byte [10/23/84]
  2443. ; doing 8bit quoting?
  2444.     MOVB    QBIN(A0),D2        ; get 8bit quote character
  2445.     BLE    100$            ;  no binary quoting
  2446.     CMPB    D2,D1            ; is it binary quote ?
  2447.     BNE    100$            ;  no
  2448. ; 8bit quote received. Evaluate following characters.
  2449.     MOV    #^O200,D3        ; set high bit flag
  2450.     CALL    GETBYT            ; get next byte
  2451.     CALL    EVALQ            ; evaluate this & next chars
  2452.     ORB    D3,D1            ; combine evaluated char & top bit
  2453.     BR    500$
  2454.  
  2455. 100$:    CLR    D3            ; clear high bit flag
  2456.     CALL    EVALQ            ; evaluate
  2457. 500$:    FILOTB    FIO(A0)            ; output the data byte
  2458. 600$:    TST    D0
  2459.     BGT    10$            ; output all bytes
  2460.     RTN
  2461.  
  2462. ; E V A L Q  - evaluates the byte in D1. Expands quoted control characters,
  2463. ; quoted quotes, and eighth bit quotes and quoted eighth bit quotes.
  2464. EVALQ:    CMPB    D1,QUOTE(A0)        ; is it a quote ?
  2465.     BNE    100$            ;  no-just return with value
  2466.     CALL    GETBYT            ;  yes - get next byte
  2467.     MOVB    D1,D7
  2468.     AND    #^O177,D7        ; get stripped version of character
  2469.     CMPB    D7,QUOTE(A0)        ; is it double qoute ?
  2470.     BEQ    100$            ; yes-pass it literally
  2471.     TSTB    QBIN(A0)        ; test for 8 bit quote active
  2472.     BLE    10$            ;  no-sending binaries
  2473.     CMPB    D1,QBIN(A0)        ; 8bit quote prefixed by ctl quote?
  2474.     BEQ    100$            ;  yes-use literally.
  2475. 10$:    CTL    D1            ; turn it to control
  2476. 100$:    RTN        
  2477.  
  2478. ; G E T B Y T - gets the next data byte for BUFEMP.
  2479. GETBYT:    MOVB    (A1)+,D1        ; get a byte    
  2480.     TSTB    QBIN(A0)        ; allowing binaries?
  2481.     BEQ    10$            ;  yes
  2482.     AND    #^O177,D1        ;  no-strip to seven    
  2483. 10$:    SUB    #1,D0            ;  adjust count
  2484.     RTN
  2485.  
  2486. ; R E C P A K  -  receives a data packet from the remote computer.
  2487. ; This routine simply inputs a single packet, without performing
  2488. ; packet checking or other details.
  2489. ; On Entry,    A3 indexs the packet destination
  2490.  
  2491. ; On exit,    D0 is the received checkbyte
  2492. ;        D1 is the calculated checkbyte
  2493. ;        D2 is the LEN
  2494. ;        D3 is the SEQ
  2495. ;        D4 is the TYPE
  2496. ;        Z is set if a packet is received
  2497. ;         CHKNOW(A0) contains binary 1,2, or 3 for checkbyte size
  2498. RECPAK:    
  2499. ; initialize packet receiver
  2500.     CALL    SETEND            ; set timer ending time
  2501.     MOV    REMOTE(A0),A5        ; index the remote TCB
  2502. 10$:    CALL    GETREM            ; get remote character
  2503.     JNE    100$            ;  timeout, no data
  2504. ; syncronize the packet to the mark byte (usually ^A)
  2505.     AND    #^O177,D1        ; strip parity here, always
  2506.     CMPB    D1,RMARK(A0)        ; start of packet ?
  2507.     BNE    10$            ;  no-keep looking
  2508. 20$:    MOV    A3,A1            ; use A1 as work register.
  2509.     MOVB    D1,(A1)+        ;  yes-store it
  2510. ; get the length from the next byte
  2511.     CALL    GETREM            ;   get LEN
  2512.     JNE    100$            ; timeout, no data
  2513.     CMPB    D1,RMARK(A0)        ; start of packet ?
  2514.     BEQ    20$            ;  yes-resync.
  2515.     MOVB    D1,(A1)+        ;  else save the LEN
  2516.     CALL    CLRSUM            ; clear checkbytes
  2517.     CALL    ACCUM
  2518.     UNCHAR    D1            ; convert to binary
  2519.     MOV    D1,D2            ; save the LEN
  2520. ; receive the SEQ byte
  2521. 30$:    CALL    GETREM            ;   get SEQ
  2522.     JNE    100$            ; timeout, no data
  2523.     CMPB    D1,RMARK(A0)        ; start of packet ?
  2524.     BEQ    20$            ;  yes-resync.
  2525.     MOVB    D1,(A1)+        ;  else save the SEQ
  2526.     CALL    ACCUM
  2527.     MOV    D1,D3
  2528.     UNCHAR    D3            ; D3 is sequence #
  2529. ; receive the TYPE byte
  2530.     CALL    GETREM            ;   get TYPE
  2531.     JNE    100$            ; timeout, no data
  2532.     CMPB    D1,RMARK(A0)        ; start of packet ?
  2533.     BEQ    20$            ;  yes-resync.
  2534.     MOVB    D1,(A1)+        ;  else save the TYPE
  2535.     CALL    ACCUM            ; update checkbyte
  2536.     MOV    D1,D4            ; D4 gets the type
  2537. ; calc the data area size.
  2538.     MOV    D2,D1            ; D1 gets the binary length
  2539.     CALL    CALCHK            ; calculate checkbyte size
  2540.     CLR    D0
  2541.     MOVB    CHKNOW(A0),D0        ; get checkbyte size
  2542.     ADD    #2.,D0            ; D0 gets size of SEQ,TYPE
  2543.     SUB    D0,D1            ;  D1 gets size of data area
  2544.     MOVB    D1,LDATA(A0)        ; save length of data
  2545.     MOV    D1,D0            ; D0 gets length
  2546.     CMPB    D0,#95.-3.        ; is it legal ?
  2547.     JHI    10$            ;   no-toss it & try again
  2548.     BR    45$            ; use DBF to control buffering of
  2549.                     ; 0 or more characters.
  2550. ; buffer the data bytes
  2551. 40$:    CALL    GETREM            ; get a byte
  2552.     JNE    100$            ;  timeout
  2553.     CMPB    D1,RMARK(A0)        ; start of packet ?
  2554.     BEQ    20$            ;  yes-resync.
  2555.     MOVB    D1,(A1)+        ; store data
  2556.     CALL    ACCUM            ; update checkbyte
  2557. 45$:    DBF    D0,40$            ;  gather packet.
  2558. ; now get the checkbyte(s)
  2559.     CALL    GETREM            ;   get CHECK
  2560.     JNE    100$            ; timeout, no data
  2561.     CMPB    D1,RMARK(A0)        ; start of packet ?
  2562.     JEQ    20$            ;  yes-resync.
  2563.     UNCHAR    D1            ; convert CHECK
  2564.     CLR    D0
  2565.     MOVB    D1,D0            ; D0 gets checkbyte byte #1
  2566.     CMPB    CHKNOW(A0),#3.        ; three character checkbyte?
  2567.     BNE    50$            ;  no-leave CHECK type as normal
  2568. ; handle 3 byte 16 bit CCITT reverse CRC here
  2569.     ANDB    #^B1111,D0        ;  yes, mask 1st byte to 4 bits
  2570.     RORW    D0,#4.            ; move 1st byte bits to B15-B12
  2571.     CALL    GETREM            ;  and get second byte
  2572.     JNE    100$            ;  receive data fault
  2573.     UNCHAR    D1            ; convert it
  2574.     LSLW    D1,#6.            ; shift 2nd byte to bits 11-6
  2575.     ORW    D1,D0            ; D0 gets bits 11-0
  2576.     CALL    GETREM            ;  yes- get 3rd byte
  2577.     JNE    100$            ;  receive data fault
  2578.     UNCHAR    D1            ; convert it
  2579.     ORW    D1,D0            ; D0 gets complete checkbytes
  2580.     MOVW    FRMSUM(A0),D1        ; D1 gets calculated CRC-ITT
  2581.     BR    90$
  2582. ; handle 2 byte 12 bit checksum here
  2583. 50$:    CMPB    CHKNOW(A0),#2.        ; two character checkbytes?
  2584.     BNE    60$            ;  no-leave CHECK type as normal
  2585.     CALL    GETREM            ;  yes- get second byte
  2586.     JNE    100$            ;  receive data fault
  2587.     UNCHAR    D1            ; convert it
  2588.     LSL    D0,#6.            ; shift 1st byte to bits 11-6
  2589.     ORW    D1,D0            ; D0 gets bits 11-0
  2590.     MOVW    ASSUM(A0),D1        ; D1 gets calculated ASSUM
  2591.     ANDW    #^B0000111111111111,D1    ; mask it to 12 bits only
  2592.     BR    90$
  2593. ; handle one byte 6 bit checksum here
  2594. 60$:    CLR    D1
  2595.     MOVB    ASSUM+.B0W7(A0),D1    ; {ok} get calculated sum
  2596.     MOV    D1,D7            ;  twice
  2597.     LSRW    D7,#6.            ; move bits 7-6 to 1-0
  2598.     ANDW    #3,D7            ; toss all other bits
  2599.     ADDW    D7,D1            ; add to sum
  2600.     ANDW    #^O77,D1        ; strip to 6 bits.
  2601. 90$:    TSTB    DEBUGO(A0)        ; debug mode ?
  2602.     JEQ    95$            ;  no
  2603.     PUSH    D1
  2604.     CLR    D1
  2605.     TYPE    <==Received Packet # >
  2606.     MOV    D3,D1                
  2607.     DCVT    2,OT$TRM!OT$TSP        ; output as 2 characters
  2608.     TYPE    <, Type >    
  2609.     MOV    D4,D1
  2610.     TTY
  2611.     TYPE    < Length: >
  2612.     MOV    D2,D1
  2613.     DCVT    2,OT$TRM
  2614.     CRLF
  2615.     TYPE    <Checkbytes >    
  2616.     MOV    @SP,D1            ; get calced sum
  2617.     CMPW    D0,D1            ; do they match ?
  2618.     BNE    93$            ;  no
  2619.     TYPE    <match (>
  2620.     DCVT    0,OT$TRM
  2621.     TYPE    <)>
  2622.     BR    94$
  2623.  
  2624. 93$:    TYPE    <calculated = >
  2625.     DCVT    0,OT$TRM
  2626.     TYPE    <, received = >
  2627.     MOV    D0,D1
  2628.     DCVT    0,OT$TRM
  2629. 94$:    CRLF
  2630.     CRLF
  2631.     POP    D1
  2632. 95$:    TSTB    NOTALK(A0)        ; are we showing crc errors?
  2633.     BNE    98$            ;  no
  2634.     CMPW    D0,D1            ; compare checkbytes
  2635.     BEQ    96$            ;  no error
  2636.     TYPE    c
  2637.     BR    98$
  2638. ; come here if packet is O.K. Check for NAK. If NAK, put n on screen
  2639. 96$:    CMPB    D4,#'N            ; was it a NAK?
  2640.     BNE    98$
  2641.     TYPE    n
  2642. 98$:    CMPW    D0,D1            ; compare checkbytes
  2643.     RTN
  2644.  
  2645. ; come here on timeout while waiting for packets.
  2646. ; show timeouts as t's if there is a user watching.
  2647. 100$:    TSTB    NOTALK(A0)        ; TCB owned by KERMIT job?
  2648.     BNE    110$            ;  yes - do not type anything
  2649.     TYPE    <t>            ;  no-go ahead & show user kermit
  2650. 110$:    LCC    #0            ; flag timeout
  2651.     RTN                ;  
  2652.  
  2653.  
  2654.  
  2655. ; S N D P A K  -  sends a packet.
  2656. ; On Entry,    A3 indexs the packet destination
  2657. ;        D2 is the LEN
  2658. ;        D3 is the SEQ
  2659. ;        D4 is the TYPE
  2660. ; At exit,    CHKNOW(A0) contains the checkbyte size used.
  2661. SNDPAK:    TSTB    DEBUGO(A0)
  2662.     BEQ    30$
  2663.     TYPE    <Sending ">
  2664.     MOVB    D4,D1
  2665.     TTY
  2666.     TYPE    <" packet # >
  2667.     CLR    D1    
  2668.     MOVB    D3,D1
  2669.     DCVT    0,OT$TRM
  2670.     TYPE    < of length >
  2671.     MOVB    D2,D1
  2672.     DCVT    0,OT$TRM
  2673.     CRLF
  2674.     TYPE    <Data =">
  2675.     SAVE    A2,D0
  2676.     LEA    A2,DATA(A3)
  2677.     MOV    D2,D0
  2678.     SUB    #1,D0
  2679.     BMI    20$
  2680. 10$:    MOVB    (A2)+,D1
  2681.     TTY
  2682.     DBF    D0,10$
  2683. 20$:    REST    A2,D0
  2684.     TYPECR    <">
  2685.     CRLF
  2686. ; send a packet to the remote KERMIT
  2687. 30$:    MOV    REMOTE(A0),A5        ; index remote TCB
  2688.     CLR    D0
  2689.     MOVB    PAD(A0),D0        ; get pad count
  2690.     MOVB    PADCHR(A0),D1        ; and pad character
  2691.     BR    50$
  2692. 40$:    TTYOUT                ; send the pad character
  2693.     CALL    STALL            ; stall, if needed
  2694. 50$:    DBF    D0,40$            ; output pad chars while D0#0
  2695.     MOV    A3,A1            ; A1 is work pointer
  2696.     MOVB    RMARK(A0),(A1)+        ; buffer MARK character
  2697.     MOV    D2,D1            ; D1 gets LEN
  2698.     CALL    CALCHK            ; calculate checkbyte size
  2699.     ADDB    CHKNOW(A0),D1        ; add size of checkbyte
  2700.     ADD    #2.,D1            ; plus SEQ & TYPE
  2701.     CHAR    D1            ; make it printable
  2702.     MOVB    D1,(A1)+        ; store LEN    
  2703.     CALL    CLRSUM
  2704.     CALL    ACCUM            ; update checkbyte & CRC
  2705.     MOV    D3,D1
  2706.     CHAR    D1
  2707.     MOVB    D1,(A1)+        ; store SEQ
  2708.     CALL    ACCUM            ; update checkbyte & CRC
  2709.     MOVB    D4,(A1)+        ; store TYPE    
  2710.     MOVB    D4,D1
  2711.     CALL    ACCUM            ; update checkbyte & CRC
  2712. ; data (if any) is already in buffer. Add it to checkbyte
  2713.     CLR    D1
  2714.     BR    70$            
  2715. 60$:    MOVB    (A1)+,D1        ; get a byte
  2716.     CALL    ACCUM
  2717. 70$:    DBF    D2,60$            ; loop till all data checked
  2718. ; handle checkbyte(s) translation
  2719. ; [015] add code for three character CRC
  2720. 75$:    CMPB    CHKNOW(A0),#3.        ; three character checkbyte ?
  2721.     BNE    80$            ;  no - try for two!
  2722. ; three character checkbyte
  2723.     CLR    D1
  2724.     MOVW    FRMSUM(A0),D1        ; get all bits
  2725.     CLR    D7
  2726.     MOVW    D1,D7            ;  in two regs
  2727.     ROLW    D7,#4.            ; position bits D15-D12
  2728.     ANDW    #^B1111,D7        ; strip to 4 bits
  2729.     CHAR    D7            ; make it printable
  2730.     MOVB    D7,(A1)+        ; store D15-D12
  2731.     MOVW    D1,D7            ;  in two regs
  2732.     LSRW    D7,#6.            ; get bits D11-D6 in low 6
  2733.     ANDW    #^B111111,D7        ; strip to 6 bits
  2734.     CHAR    D7            ; make it printable
  2735.     MOVB    D7,(A1)+        ; store D11-D6
  2736.     ANDW    #^B111111,D1        ; strip to 6 bits
  2737.     CHAR    D1            ; make it printable
  2738.     MOVB    D1,(A1)+        ; store checkbyte bits D5-D0
  2739.     BR    100$
  2740.  
  2741. 80$:    CMPB    CHKNOW(A0),#2.        ; two character checkbyte ?
  2742.     BNE    90$            ;  no - must be one character
  2743. ; two character checkbyte
  2744.     MOVW    ASSUM(A0),D1        ; get all bits
  2745.     MOV    D1,D7            ;  in two regs
  2746.     LSR    D7,#6.            ; position bits D11-D6
  2747.     AND    #^O77,D7        ; strip to 6 bits
  2748.     CHAR    D7            ; make it printable
  2749.     MOVB    D7,(A1)+        ; store D11-D6
  2750.     AND    #^O77,D1        ; strip to 6 bits
  2751.     CHAR    D1            ; make it printable
  2752.     MOVB    D1,(A1)+        ; store checkbyte bits D5-D0
  2753.     BR    100$
  2754.  
  2755. 90$:    MOVB    ASSUM+.B0W7(A0),D1    ; {ok} D1 gets low eight of sum
  2756.     MOV    D1,D7            ; D7 gets same
  2757.     AND    #^O300,D7        ; take just bits 7-6.
  2758.     LSR    D7,#6.            ; shift to bits 1-0
  2759.     ADD    D7,D1            ; D1 gets sum
  2760.     AND    #63.,D1            ; make it six bits again.
  2761.     CHAR    D1            ; make it prinatble
  2762.     MOVB    D1,(A1)+        ; store checkbyte
  2763. ; check for EOL character
  2764. 100$:    MOVB    EOL(A0),D7        ; remote need any EOL ?
  2765.     BEQ    110$            ;  no
  2766.     MOVB    D7,(A1)+        ;  yes-store it
  2767. ; calculate size of buffered packet from pointer displacement
  2768. 110$:    MOV    A1,D0            ; current position
  2769.     SUB    A3,D0            ;  less start is length
  2770.     SUB    #1,D0
  2771. 120$:    MOVB    (A3)+,D1        ; get a byte
  2772.     TTYOUT                ; output it to REMOTE
  2773.     CALL    STALL            ; stall ,if needed
  2774.     DBF    D0,120$            ;  till packet is sent
  2775.     RTN
  2776.  
  2777. ; O U T B Y T   - This routine outputs the byte in D1 to the remote.
  2778. OUTBYT:    MOV    REMOTE(A0),A5        ; get TCB pointer for remote
  2779.     TTYOUT                ; send the byte out
  2780.     RTN
  2781.  
  2782. ; S T A L L - stalls a certain amount of time after output in progress
  2783. ; is lowered. At entry, A5 must index the output TCB.
  2784. STALL:    TSTB    STLCHR(A0)        ; do we need to stall?
  2785.     BEQ    20$            ;  no
  2786. 10$:    CTRLC    20$            ; abort - CTS must be low
  2787.     TSTB    @A5
  2788.     BMI    10$            ; wait for OIP to drop
  2789.     CLR    D7
  2790.     MOVB    STLCHR(A0),D7
  2791.     MUL    D7,#10000./100.        ; transform to ticks
  2792.     SLEEP    D7
  2793. 20$:    RTN
  2794.  
  2795. ; SREMOT - send the A1 string to the remote
  2796. SREMOT:    MOV    REMOTE(A0),A5        ;  index to remote TCB
  2797. 10$:    MOVB    (A1)+,D1
  2798.     BEQ    100$
  2799.     CMPB    D1,#-1            ; is it wait byte?
  2800.     BNE    20$            ;  no
  2801.     SLEEP    #10000./2.        ; yes, wait .5 seconds
  2802.     BR    10$        
  2803. 20$:    TTYOUT
  2804.     BR    10$
  2805. 100$:    RTN
  2806.  
  2807. ; C A L C H K  -  determines the current checkbyte size.
  2808. ; This routine unifies the logic needed to force 1 byte checkbytes on SEND-INIT
  2809. ; fields and their ACKS.
  2810. ; At entry,
  2811. ;    D2 contains the LEN in binary
  2812. ;    D4 contains the packet type
  2813. ; At exit, CHKNOW(A0) contains the binary value of the current checkbyte size.
  2814. CALCHK:    CLR    D7
  2815.     MOVB    CHKT(A0),D7        ; get checkbyte type
  2816.     SUBB    #'0,D7            ;  less ASCII bias
  2817. ; if NAK, we can deduce packet size from LEN
  2818. ; this is useful if the 1st packet after changing checkbyte types is damaged.
  2819. ; The other side will NAK, and we can recover the right length from the LEN
  2820. ; of the NAK packet. (ACK packets may have filenames or discard info appended
  2821. ; their size is not predictable.)
  2822.     CMPB    D4,#'N            ; is it a NAK?
  2823.     BNE    10$            ;  no- use selected type
  2824.     MOVB    D2,D6            ;  yes-get LEN
  2825.     SUBB    #2.,D6            ; less 2 gives checkbyte size
  2826.     CMPB    D6,#MAXCHK        ; compare to largest supported type    
  2827.     BHI    30$            ;  out of range - ignore bad advice    
  2828.     MOVB    D6,D7            ; well
  2829.     ADDB    #'0,D6            ; D6 gets character
  2830.     MOVB    D6,CHKT(A0)        ; force proper check type
  2831.     BR    30$            ; and set binary type as well
  2832. ; handle all but NAKs here
  2833. 10$:    TSTB    RIACK(A0)        ; have we recv'd "S" packet? 
  2834.     BNE    30$            ;  yes, use 
  2835.     MOV    #1,D7            ;   no-force checkbyte type 1
  2836. 30$:    MOVB    D7,CHKNOW(A0)        ; save current checkbyte choice
  2837.     RTN
  2838.  
  2839. ; G E T R E M  -  gets a single character from the remote computer. 
  2840. ; At entry, A5 must index the REMOTE TCB
  2841. ; At exit, D1 will contain the character, or a -1 for no character.
  2842. ; Z will be set if a character was available for input.
  2843. GETREM:    MOV    #-1,D1            ; preset for no data
  2844.     BR    20$
  2845. 10$:    SLEEP    SLPVAL(A0)        ; wait for more data [14]
  2846. ; wait 1 character time for more date for higher throughput [14]
  2847.     CTRLC    100$
  2848.     GTIMEI    D7
  2849.     SUB    FUDGE(A0),D7        ; less the fudge factor for wraparound
  2850.     CMP    D7,RTOUT(A0)        ; EXPIRED?
  2851.     BGT    200$            ;  YES
  2852. 20$:    TST    T.ICC(A5)        ; any data to input ?
  2853.     BEQ    10$            ;  no input
  2854.     CLR    D1            ; pre-clear D1
  2855.     TTYIN                ; get a character
  2856.     TSTB    QBIN(A0)        ; are we allowing 8 data bits?
  2857.     BEQ    30$            ;  yes
  2858.     AND    #^O177,D1        ;  no-strip parity bit
  2859. 30$:    CMPB    D1,#3.            ; control-c?
  2860.     BNE    40$            ; no
  2861.     COMB    CCOUNT(A0)        ; yes-toggle /2 counter
  2862.     BNE    50$            ; only one detected
  2863.     JOBIDX
  2864.     ORW    #J.CCC,@A6        ; two detected - set control-c flag
  2865. 40$:    CLRB    CCOUNT(A0)        ; clear control-c count
  2866. 50$:    LCC    #PS.Z
  2867.     RTN
  2868. 100$:    LCC    #0
  2869.     RTN
  2870. 200$:    LCC    #PS.V            ; flag overflow for timeout
  2871.     RTN
  2872.  
  2873. ; S E T E N D  -  calculates and stores the value of the timeout point 
  2874. ; in internal format.
  2875. SETEND:    CLR    FUDGE(A0)        ; clear wrap-around value
  2876.     GTIMEI    D7            ; D6 gets internal format time.
  2877.     ADD    TIMINT(A0),D7
  2878.     MOV    #24.*60.*60.,D6        ; D6 gets highest internal time+1
  2879.     CMP    D7,D6
  2880.     BLO    10$             ; o.k. - no wraparound
  2881.     SUB    D6,D7            ; handle wrap-around
  2882.     MOV    D6,FUDGE(A0)        ; set fudge factor to indicate
  2883.                     ; time wraparound
  2884. 10$:    MOV    D7,RTOUT(A0)        ; SET TIME-OUT TIME
  2885.     RTN
  2886.  
  2887.  
  2888. ; G T S I Z E  -  gets file size in bytes. Destroys D6,D7. Assumes file 
  2889. ; has been looked up on FIO(A0). FSIZE(A0) contains the size on exit.
  2890. GTSIZE:    MOV    FIO+D.SIZ(A0),D7    ; D7 gets record size
  2891.     MOV    FIO+D.LEN(A0),D6    ; D6 gets # of blocks
  2892.     TSTW    FIO+D.ACT+.W0L15(A0)    ; random file ?
  2893.     BMI    10$            ;  yep-straight multiply
  2894.     SUB    #2.,D7            ;  no-subtract pointer bytes.
  2895.     TSTB    EXTEND(A0)        ;  O/S support extended disks?
  2896.     BEQ    8$            ;   no
  2897.     SUBW    FIO+D.FMT(A0),D7    ;   yes, get extra link bytes (if any)
  2898. 8$:    SUB    #1,D6            ;  and less last block
  2899. 10$:    MUL    D7,D6            ; block payload size * blocks
  2900.     TSTW    FIO+D.ACT+.W0l15(A0)    ; random file ?
  2901.     BMI    20$            ;  yep.
  2902.     ADD    FIO+D.ACT(A0),D7    ;  sequential-add last block's count
  2903.     SUB    #2.,D7            ; less link word in last block
  2904.     TSTB    EXTEND(A0)        ;  O/S support extended disks?
  2905.     BEQ    20$            ;  no
  2906.     SUBW    FIO+D.FMT(A0),D7    ;  yes, get extra link bytes (if any)
  2907. 20$:    MOV    D7,FSIZE(A0)        ; size of the file
  2908.     RTN
  2909.  
  2910. ; send the user terminal a BELL if SET ALARM ON.
  2911. DINGEM:    TSTB    DING(A0)        ; wake the user up?
  2912.     BEQ    20$            ;  no
  2913.     TTYI                ;  yes
  2914.     BYTE    A.BEL,0
  2915.     EVEN
  2916. 20$:    RTN
  2917.  
  2918.  
  2919. ; S T A R T T  - gets the current time and saves it in STIME(A0).
  2920. ; Used to determine the elapsed time in file transfers.
  2921. STARTT:    GTIMEI    STIME(A0)        ; save the start time
  2922.     RTN
  2923.  
  2924. ; E N D T M  - calculate and display the elapsed time & effective baud rate
  2925. ; for a file transfer.
  2926. ; At entry, FSIZE must contain the file size in bytes.
  2927. ENDTM:    TSTB    NOTALK(A0)        ; do we have a user terminal?
  2928.     BNE    30$
  2929.     TSTB    ABORTF(A0)        ; file aborted?
  2930.     BNE    40$
  2931.     GTIMEI    D2            ; get current time
  2932.     SUB    STIME(A0),D2        ; less start time
  2933.     BCC    10$            ;  no midnight wraparound
  2934.     ADD    #24.*60.*60.,D2        ;  else add 24 hours of seconds [14]
  2935. 10$:    ADD    D2,TTIME(A0)        ; add to total time
  2936.     MOV    FSIZE(A0),D7
  2937.     ADD    D7,TBYTES(A0)        ; accum total bytes
  2938.     INC    TFILES(A0)        ; accum total files
  2939.     MOV    D2,D4            ; save for effective baud rate
  2940.     MOV    FSIZE(A0),D3        ; get characters
  2941.     CRLF
  2942.     CALL    ELAPSE
  2943. 30$:    RTN
  2944. 40$:    CRLF
  2945.     TYPECR    <File transfer interrupted.>
  2946.     RTN
  2947.  
  2948. STATS:    TSTB    NOTALK(A0)
  2949.     BNE    100$            ; no user to talk to
  2950.     TYPE    <A total of>
  2951.     MOV    TBYTES(A0),D1
  2952.     DCVT    0,OT$TRM!OT$TSP!OT$LSP
  2953.     TYPE    <byte>
  2954.     CALL    PLURAL
  2955.     TYPE    < in>
  2956.     MOV    TFILES(A0),D1
  2957.     DCVT    0,OT$TRM!OT$TSP!OT$LSP
  2958.     TYPE    <file>
  2959.     CALL    PLURAL
  2960. 20$:    TYPECR    < transferred.>
  2961.     CMP    D1,#1
  2962.     BLOS    100$            ; show cumulative effect for <1 file
  2963.     MOV    TBYTES(A0),D3        ; get characters
  2964.     MOV    TTIME(A0),D2        ; get seconds
  2965.     TYPE    <Total >
  2966.     CALL    ELAPSE
  2967. 100$:    RTN
  2968.  
  2969. ; PLURAL - print an "s" if D1 is not 1.
  2970. PLURAL:    CMP    D1,#1    ; is it singular?
  2971.     BEQ    20$    ;  yes
  2972.     TYPE    <s>    ; no, plural
  2973. 20$:    RTN
  2974.  
  2975.     
  2976. ; ELAPSE displays the elapsed time & baud rate
  2977. ; At entry, D2 contains the time, and D3 contains the number of bytes xferred
  2978. ; trashes D4,D1,D6,D7,A6
  2979. ELAPSE:    TYPE    <elapsed time was >
  2980.     CLR    D1
  2981.     MOV    D2,D4
  2982.     DIV    D4,#60.*60.        ; convert to hours
  2983.     MOVW    D4,D1
  2984.     DCVT    2,OT$TRM!OT$ZER        ; display hours
  2985.     TYPE    :
  2986.     CLRW    D4
  2987.     SWAP    D4            ; remainder to lower 16 bits
  2988.     DIV    D4,#60.            ; make it minutes
  2989.     MOVW    D4,D1
  2990.     DCVT    2,OT$TRM        ; display minutes
  2991.     TYPE    :
  2992.     CLRW    D4
  2993.     SWAP    D4            ; seconds remiander to low 16
  2994.     MOV    D4,D1
  2995.     DCVT    2,OT$TRM        ; display seconds
  2996.     TST    D2            ; were seconds 0?
  2997.     BEQ    20$            ;  baud rate is infinite!
  2998.     TYPE    <, effective baud rate was >
  2999.     MOV    D3,D1
  3000. ; multiply by 10 by adding 2*D1 and 8*D1
  3001.     MOV    D1,D7            ; duplicate
  3002.     ADD    D1,D1            ;  double
  3003.     LSL    D7,#3.            ;   shift to make 8* old D1
  3004.     ADD    D7,D1            ;    add to make 10 * old D1
  3005.     DIV    D1,D2            ;  divided by seconds
  3006.     AND    #^O177777,D1        ; strip off remainder
  3007.     DCVT    0,OT$TRM        ; display it
  3008. 20$:    TYPECR    <.>            ; new line
  3009. 30$:    RTN
  3010.  
  3011.  
  3012. ; S H O E S C  displays the current escape from connect mode character.
  3013. SHOESC:    TYPE    <Escape character is >
  3014.     MOVB    KMETA(A0),D1
  3015.     CALL    SHOCHR
  3016.     CRLF
  3017.     RTN
  3018.  
  3019. ; S H O C H R  -  displays in printable form the character in D1.
  3020. SHOCHR:    PUSH    D1
  3021.     TSTB    CMASK(A0)        ; 7 or 8 bit terminal?
  3022.     BMI    10$            ;  terminal is 8 bits!
  3023.     BTST    #7.,D1
  3024.     BEQ    10$
  3025.     TYPE    <%>
  3026.     BR    15$
  3027. 10$:    TYPE    < >
  3028. 15$:    ANDB    CMASK(A0),D1
  3029.     CMPB    D1,#DEL
  3030.     BNE    18$
  3031.     TYPE    DEL
  3032.     BR    50$
  3033. 18$:    CMPB    D1,#SPACE
  3034.     BHIS    20$
  3035.     PUSH    D1
  3036.     MOVW    #177400!11.,D1
  3037.     TCRT
  3038.     TYPE    ^
  3039.     MOVW    #177400!12.,D1
  3040.     TCRT
  3041.     POP    D1
  3042.     CTL    D1            ; un-controlify it
  3043.     BR    30$
  3044. 20$:    TYPE    < >
  3045. 30$:    TTY    
  3046. 50$:    POP    D1
  3047.     RTN
  3048.  
  3049. ; show the notice & title & version
  3050. KERTTL:    TTYL    TITLE        ; show the title
  3051. ; show the program name & version
  3052. KERVER:    TTYL    TITL2
  3053.     VCVT    KERMIT+PH.VER,OT$TRM    ; show the version #
  3054.     CRLF
  3055.     RTN
  3056.  
  3057. ; S H O D O T  - print a dot on user's terminal whenever a packet has been
  3058. ; sent or recvd. (But don't do it when using user's terminal for I/O.)
  3059. SHODOT:    TSTB    NOTALK(A0)        ; TCB owned by KERMIT job?
  3060.     BNE    10$            ;  yes - do not type dot!
  3061.     TYPE    <.>            ;  no-go ahead & show user kermit
  3062. 10$:    RTN                ;  is working
  3063.  
  3064. ; initialize wildcarder
  3065. PREBAT:
  3066.     ORB    #D$BYP!D$ERC,FIO+D.FLG(A0) ; bypass error messages
  3067.     CLRB    ABORTB(A0)        ; clear batch abort flag
  3068.     CLR    TFILES(A0)
  3069.     CLR    TBYTES(A0)
  3070.     CLR    TTIME(A0)        ; clear total stat amounts
  3071.     MOV    A2,SAVSPC(A0)        ; save user's file spec
  3072.     CLR    CMDPTR(A0)        ; clear ptr to CMDLIN.SYS
  3073.     CLR    CMDERR(A0)        ; clear CMDLIN error value
  3074.     CLRB    NXTCNT(A0)        ; pre-clear # of times GETNXT called
  3075.     TSTB    WILDOK(A0)        ; O.K. to use wildcarding?
  3076.     JEQ    100$            ;  no, don't even try!
  3077.     LEA    A2,CMDLNS
  3078.     FSPEC    CLDDB(A0)        ; load the DDB
  3079. ; fetch or find CMDLIN.SYS module - often in system memory
  3080.     FETCH    CLDDB(A0),A6        ; find or fetch it
  3081.     BNE    100$            ;  not found
  3082.     MOV    A6,CMDPTR(A0)
  3083.     SAVE    A0,A5
  3084.      LEA    A5,CMDIMP(A0)
  3085.      MOV    CMDPTR(A0),A6    
  3086.      MOV    A6,D7
  3087.      ADD    #PH.SIZ,A6
  3088. ; set up CMDLIN's internal ptrs in our impure area
  3089.      MOV    (A6)+,CMINI$(A5)    ; CMINI offset
  3090.      MOV    (A6)+,CMNXT$(A5)    ; CMNXT offset
  3091.      MOV    (A6)+,CMQRY$(A5)    ; CMQRY offset
  3092.      MOV    (A6)+,CMCMP$(A5)    ; CMCMP offset
  3093.      MOV    (A6)+,CMSKP$(A5)    ; CMSKP offset
  3094.      MOV    (A6)+,CMFSP$(A5)    ; CMFSP offset
  3095.      ADD    D7,CMINI$(A5)        ; CMINI address
  3096.      ADD    D7,CMNXT$(A5)        ; CMNXT address
  3097.      ADD    D7,CMQRY$(A5)        ; CMQRY address
  3098.      ADD    D7,CMCMP$(A5)        ; CMCMP address
  3099.      ADD    D7,CMSKP$(A5)        ; CMSKP address
  3100.      ADD    D7,CMFSP$(A5)        ; CMFSP address
  3101. ; now init CMDLIN    
  3102.      MOV    SAVSPC(A0),A2        ; user's spec
  3103.      LEA    A0,DFAULT        ; default spec
  3104.      CLR    D7            ; operation flags
  3105.      .CMINI
  3106.     REST    A0,A5            ; restore regs CMDLIN uses
  3107.     MOV    D6,CMDERR(A0)        ; save CMDLIN error, if any
  3108.     SETB    CMDFLG(A0)        ; flag we have CMDLIN.SYS
  3109. 100$:    MOV    SAVSPC(A0),A2
  3110.     RTN
  3111.  
  3112.  
  3113. ; wildcard next spec routine
  3114. ; handles a single spec if CMDLIN.SYS is not available.
  3115. ;     V set if end of spec 
  3116. GETNXT:
  3117.     PUSHB    FIO+D.FLG(A0)        ; save flags
  3118.      PUSH    FIO+D.BUF(A0)        ; save buffer address (if any)
  3119.       CLEAR    FIO(A0),D.DDB        ; clean the ddb for re-use
  3120.      POP    FIO+D.BUF(A0)        ; 
  3121.     POPB    FIO+D.FLG(A0)        ; restore buffer address & flags
  3122.     CLRB    ABORTF(A0)        ; clear abort file flag
  3123.     TSTB    CMDFLG(A0)        ; do we have CMDLIN?
  3124.     BNE    10$            ;  yes
  3125.     TSTB    NXTCNT(A0)        ;  no, bump count
  3126.     JNE    60$            ;  done    
  3127.     INCB    NXTCNT(A0)
  3128.     MOV    SAVSPC(A0),A2
  3129.     ORB    #D$BYP!D$ERC,SIO+D.FLG(A0) ; bypass error messages
  3130.     FSPEC    SIO(A0),LST
  3131.     BR    20$            ; transfer
  3132.  
  3133. ; handle file request via system wildcarder.
  3134. 10$:    MOV    SAVSPC(A0),A2        ; index the spec
  3135.     PUSH    A5
  3136.      LEA    A5,CMDIMP(A0)        ; index CMDLIN impure ptr
  3137.     .CMNXT    SIO(A0)            
  3138.      MOV    D7,CMNEXT(A0)
  3139.     POP    A5
  3140.     MOV    A2,SAVSPC(A0)        ; save the spec
  3141.     MOV    CMNEXT(A0),D7        ; get the flags
  3142.     AND    #NX$END,D7        ; end of specs?
  3143.     JNE    60$            ;  yes-end
  3144. ; handle /Q logic if not invoking send remotely
  3145.     TSTB    NOTALK(A0)        ; invoked remotely?
  3146.     BNE    20$            ;  yes, no user to query
  3147.     PFILE    SIO(A0)
  3148.     SAVE    A5
  3149.      LEA    A5,CMDIMP(A0)        ; index CMDLIN impure ptr
  3150.     .CMQRY                ; ask user
  3151.     REST    A5
  3152.     BEQ    10$            ;  user didn't want to send that file
  3153. 20$:
  3154. ; copy filespec to working ddb
  3155.     MOVW    SIO+D.DEV(A0),FIO+D.DEV(A0)
  3156.     MOVW    SIO+D.DRV(A0),FIO+D.DRV(A0)
  3157.     MOV    SIO+D.FIL(A0),FIO+D.FIL(A0)
  3158.     MOVW    SIO+D.EXT(A0),FIO+D.EXT(A0)
  3159.     MOVW    SIO+D.PPN(A0),FIO+D.PPN(A0)
  3160.     MOV    SIO+D.CPU(A0),FIO+D.CPU(A0)
  3161.     CALL    GFILNM            ; process the filename
  3162.     INIT    FIO(A0)
  3163.     LOOKUP    FIO(A0)            ; does the file exist?    
  3164.     BEQ    30$            ;  yes-ok, proceed
  3165.     NEGB    FIO+D.ERR(A0)        ; normalize error code
  3166.     BR    50$            ; and exit
  3167. 30$:    TSTW    FIO+D.ACT+.W0L15(A0)    ; random file ?
  3168.     BPL    40$            ;  no
  3169.     TSTB    NOTALK(A0)        ;   yes-we dont do these!
  3170.     BNE    34$            ;    no user to show!
  3171.     TYPE    <%Bypassing random file >
  3172.     PFILE    FIO(A0)
  3173.     CRLF
  3174. 34$:    JMP    10$            ; skip the random file
  3175.  
  3176. 40$:    OPENI    FIO(A0)            ; open for input
  3177. 50$:    MOV    #1,D7            ; cheap LCC #0
  3178.     BR    70$
  3179. 60$:    LCC    #PS.V            ; end of spec
  3180. 70$:    RTN
  3181.  
  3182. ; clear the checkbytes
  3183. CLRSUM:    CLRW    ASSUM(A0)        ; clear checksum
  3184.     CLRW    FRMSUM(A0)        ; and clear CRC
  3185.     RTN
  3186.  
  3187. ; accumulate the checksum & CRC
  3188. ACCUM:    PUSH    D1
  3189.     AND    #^H0FF,D1
  3190.     ADDW    D1,ASSUM(A0)        ; handle 1 & 2 byte sums
  3191.     CALL    CCITT            ; handle 3 byte CRC
  3192.     POP    D1
  3193.     RTN
  3194.  
  3195. ;    x^16+x^12+x^5+1 REVERSE!!!!!
  3196. ; Routine to calculate CCITT CRC for byte in D1.
  3197. ; this routine breaks down the task into two nibble operations.
  3198. ; based on C routine by andy lowry of columbia university. 
  3199. ; See page 257 of Da Cruz book.
  3200. CCITT:    SAVE    D2,D4,D7
  3201.     MOVW    FRMSUM(A0),D4        ; get remainder bits
  3202.     ANDW    #^H0FF,D1        ; mask to 8 bits
  3203.     XORB    D4,D1            ; combine
  3204.     MOVW    D1,D2            ; copy
  3205.     RORW    D2,#4.            ; move bits 7-4 to 3-0
  3206.     ANDW    #^B1111,D2        ; strip to a nibble
  3207.     ANDW    #^B1111,D1        ; strip to a nibble
  3208.     LSLW    D2,#1
  3209.     LSLW    D1,#1            ; make them word offsets
  3210. ; NOTE THAT [~Dx] IS OK SINCE D1 & D2 ARE STRIPPED TO A NIBBLE!
  3211. ; (got to watch sign extend on word ops!)
  3212.     MOVW    CRCTB2[~D1],D1
  3213.     MOVW    CRCTAB[~D2],D7
  3214.     XORW    D7,D1
  3215.     RORW    D4,#8.            ; get old B15-B8 in lo 8
  3216.     ANDW    #^O377,D4
  3217.     XORW    D1,D4            ; xor in new bits
  3218.     MOVW    D4,FRMSUM(A0)        ; store CRC
  3219.     REST    D2,D4,D7
  3220.     RTN
  3221.  
  3222. ; Data tables for CRC-CCITT generation
  3223. CRCTAB:    word    0
  3224.     word    10201
  3225.     word    20402
  3226.     word    30603
  3227.     word    41004
  3228.     word    51205
  3229.     word    61406
  3230.     word    71607
  3231.     word    102010
  3232.     word    112211
  3233.     word    122412
  3234.     word    132613
  3235.     word    143014
  3236.     word    153215
  3237.     word    163416
  3238.     word    173617
  3239.  
  3240. CRCTB2:    word    0
  3241.     word    10611
  3242.     word    21422
  3243.     word    31233
  3244.     word    43044
  3245.     word    53655
  3246.     word    62466
  3247.     word    72277
  3248.     word    106110
  3249.     word    116701
  3250.     word    127532
  3251.     word    137323
  3252.     word    145154
  3253.     word    155745
  3254.     word    164576
  3255.     word    174367
  3256.  
  3257.  
  3258.  
  3259.  
  3260. IMPNAM:    RAD50    /KERMITIMP/        ; name of user's variables module.
  3261.  
  3262. ; This table defines the KERMIT commands and the subroutine address
  3263. DEFINE    KCOM    NAME, KSIZE, ADDR, HELP
  3264.     WORD    10$$-.
  3265.     BYTE    KSIZE
  3266.     ASCII    /NAME/
  3267.     BYTE    0
  3268.     EVEN
  3269.     ASCII    /HELP/
  3270.     BYTE    0
  3271.     EVEN
  3272. 10$$:    WORD    ADDR-.
  3273.     ENDM
  3274.  
  3275. ; K E R C O M   is the main commands table for KERMIT.
  3276. KERCOM:    
  3277. KCOM    AMOS,1,AMOS,<Execute an AMOS command.>
  3278. KCOM    CONNECT,1,CONNEC,<Connects your terminal to the remote KERMIT site.>
  3279. KCOM    EXIT,1,GOODBY,<Exit from KERMIT to AMOS.>
  3280. KCOM    HELP,1,HELP,<Types a summary of KERMIT commands and what they do.>
  3281. KCOM    RECEIVE,1,RECEIV,<RECEIVE {filespec} receives one or more files from the remote KERMIT.>
  3282. KCOM    SEND,1,SEND,<SEND {filespec} sends one or more files to remote KERMIT.>
  3283. KCOM    SET,3,SET,<Set controls options: enter SET ? for more help.>
  3284. KCOM    SHOW,2,SHOW,<Show displays the current SET options.>
  3285. KCOM    ?,1,HELP,<The shorthand version of HELP.>
  3286.     WORD    0
  3287.  
  3288. ; S E T C O M  is the SET subcommands table for SET.
  3289. SETCOM:    
  3290. KCOM    AUTORECEIVE,5,AUTREC,<RECEIVE command automatically sends KERMIT & SEND to remote Kermit.>
  3291. KCOM    AUTOSEND,5,AUTSND,<SEND command automatically sends KERMIT & RECEIVE to remote Kermit.>
  3292. KCOM    BELL,2,BELL,<Beep after each file transfer.>
  3293. KCOM    BLOCKCHECK,2,BLOCK,<Block-check type: 1, 2, or 3 check bytes.>    
  3294. KCOM    DEBUG,2,DEBUG,<Debug option ON or OFF.>
  3295. KCOM    DUPLEX,2,DUPLEX,<Set FULL or HALF duplex.>
  3296. KCOM    ENDLINE,2, ENDLIN,<Packet terminator character.>
  3297. KCOM    ESCAPE,2,ESCAPE,<Escape character for CONNECT.>
  3298. KCOM    PACKETSIZE,8.,PAKMAX,<Maximum packet size.>
  3299. KCOM    PACKETSTART,8.,PAKMRK,<Packet starting character.>
  3300. KCOM    PARITY,2,SETPAR,<Denote parity type for NON-alpha remotes.>
  3301. KCOM    RETRIES,1,NEWTRY,<Number of failed packet attempts that cause abort.>
  3302. KCOM    STALL,1,STLVAL,<Number of hundreths of seconds to pause between characters.>
  3303. KCOM    TIMEOUT,1,TIMER,<Packet time-out value in seconds.>
  3304.     WORD    0
  3305.  
  3306. ; This table defines the GETOPT list for options arguments.
  3307. DEFINE    OPT    NAME, KSIZE, VALUE
  3308.     WORD    10$$-.    ; offset to next entry
  3309.     BYTE    KSIZE    ; # of unique bytes in entry
  3310.     ASCII    /NAME/    ; entry text
  3311.     BYTE    0    ; terminator
  3312.     EVEN        ; word oriented table
  3313. 10$$:    WORD    VALUE    ; associated value
  3314.     ENDM
  3315.  
  3316. ; This defines the format of the end of the options list.
  3317. DEFINE    OMSG    STRING
  3318.     WORD    0
  3319.     ASCII    /STRING/
  3320.     BYTE    0
  3321.     ENDM
  3322.  
  3323. ; options list for logical options (YES, NO, 1,0, TRUE, FALSE are valid)
  3324. ONOFF:
  3325. YESNO:    OPT    YES,1,377
  3326.     OPT    NO,1,0
  3327.     OPT    ON,2,377
  3328.     OPT    OFF,2,0
  3329.     OPT    TRUE,1,377
  3330.     OPT    FALSE,1,0
  3331.     OPT    1,1,377
  3332.     OPT    0,1,0
  3333.     OMSG    <%Use YES or NO, ON or OFF, TRUE or FALSE, 1 or 0.>
  3334.     EVEN    
  3335.  
  3336. ; options list for block check size
  3337. ONE23:    OPT    1,1,'1
  3338.     OPT    2,1,'2
  3339.     OPT    3,1,'3
  3340.     OPT    ONE,1,'1
  3341.     OPT    TWO,2,'2
  3342.     OPT    THREE,2,'3
  3343.     OPT    III,3,'3
  3344.     OPT    II,2,'2
  3345.     OPT    I,1,'1
  3346.     OMSG    <%Use 1, 2, 3, ONE ,TWO, THREE, I, II, III to set check value size.>
  3347.     EVEN
  3348.  
  3349. ; list of valid parity settings, so you can't set parity George, but you
  3350. ; can set parity Mark.
  3351. PARLST:    OPT    NONE,1,'N
  3352.     OPT    EVEN,1,'E
  3353.     OPT    ODD,1,'O
  3354.     OPT    MARK,1,'M
  3355.     OPT    SPACE,1,'S
  3356.     OPT    YES,1,'Y
  3357.     OMSG    <%Use None, Even, Odd, Mark, or Space.>
  3358.     EVEN
  3359.  
  3360. ; options for echoplex (see DUPLEX:)
  3361. EPLEX:    OPT    FULL,1,0
  3362.     OPT    HALF,1,377
  3363.     OMSG    <%Use FULL or HALF to set duplex options.>
  3364.     EVEN
  3365.  
  3366.  
  3367. ; S W C A S E - macro to define the switcher state table
  3368. DEFINE    SWCASE    STATE, ROUTE
  3369.     BYTE    STATE
  3370.     EVEN
  3371.     OFFSET    ROUTE
  3372.     ENDM
  3373.  
  3374. ; S W S T A T  is the table of valid SEND FILE states for KERMIT,
  3375. ; and the offsets to the corresponding next routines.
  3376. SWSTAT:    SWCASE    'S,SINIT
  3377.     SWCASE    'F,SFILE
  3378.     SWCASE    'D,SDATA
  3379.     SWCASE    'Z,SEOF
  3380.     SWCASE    'B,SBREAK
  3381.     SWCASE    'C,COMPLT
  3382.     SWCASE    'A,ABORT
  3383.     BYTE    0
  3384.  
  3385.     EVEN
  3386.  
  3387. ; R C S T A T  is the table of valid RECEIVE FILE states for KERMIT,
  3388. ; and the offsets to the corresponding next routines.
  3389. RCSTAT:    SWCASE    'R,RINIT            ; receive init
  3390.     SWCASE    'F,RFILE            ; receive file
  3391.     SWCASE    'D,RDATA            ; receive data
  3392.     SWCASE    'C,RCOMP            ; receive complete
  3393.     SWCASE    'A,RABOR            ; receieve abort
  3394.     BYTE    0
  3395.  
  3396.  
  3397.  
  3398. HLP1:    ASCII    /          ========== Alpha-Kermit help ==========/
  3399.     BYTE    CR,CR,0    
  3400.  
  3401. ABTTTL:    ASCII    /KERMIT aborting with the following error from REMOTE host:/
  3402.     BYTE    CR,0
  3403.  
  3404. ; tables for GETOPT subroutine
  3405.  
  3406. DEFINE    OPT    CHAR,CODE = BYTE    CHAR,CODE
  3407.  
  3408.  
  3409. SET1:    ASCII    / SET allows you to change the following parameters./
  3410.     BYTE    CR,CR,0
  3411.  
  3412. NONONO:    ASCII    /%You cannot CONNECT to your own terminal!/
  3413.     BYTE    CR
  3414.     ASCII    /You must specify the communications port name when KERMIT is invoked:/
  3415.     BYTE    CR
  3416.     ASCII    /     e.g.  KERMIT MODEM uses the MODEM communications port./
  3417.     BYTE    CR,0
  3418.  
  3419. TITLE:
  3420.     ASCII    'Copyright 1984, 1994 Robert P. Rubendunst.'
  3421.     BYTE    CR    
  3422.     ASCII    'Alpha-Kermit by Soft Machines.'
  3423.     BYTE    CR
  3424.     ASCII    'Permission is granted to use this software at no charge'
  3425.     BYTE    CR
  3426.     ASCII    'provided that this message is not changed or deleted from'
  3427.     BYTE    CR
  3428.     ASCII    'any copy of this software.'
  3429.     BYTE    CR,0
  3430.  
  3431.  
  3432.     DEFINE    TEXT    ARG
  3433.     ASCII    ~ARG~
  3434.     BYTE    CR
  3435.     ENDM
  3436. USAGE:
  3437.     BYTE    CR,CR
  3438.     TEXT    <Usage: KERMIT  {communications-port}>
  3439.     BYTE    CR
  3440.     TEXT    <   NOTE: KERMIT has two modes of operation - Local and Remote!>
  3441.     BYTE    CR
  3442.     TEXT    <   LOCAL mode supports serial communications and file transfers through>
  3443.     TEXT    <   a separate communications port, e.g. MODEM1.>
  3444.     TEXT    <   For LOCAL mode, enter KERMIT and the name of the communications port,>
  3445.     TEXT    <   and then a carriage return, e.g. KERMIT MODEM1.>
  3446.     BYTE    CR
  3447.     TEXT    <   REMOTE mode is used to support only file transfers for REMOTE users,>
  3448.     TEXT    <   e.g. PC users signed on to the Alpha Micro.>
  3449.     TEXT    <   REMOTE mode uses the same port for commands and file transfers.>
  3450.     TEXT    <   For REMOTE mode, just enter KERMIT and return.>
  3451.     BYTE    CR,CR
  3452.     TEXT    <KERMIT will display the prompt Alpha-Kermit> if you have selected LOCAL mode,>
  3453.     TEXT    <or REMOTE Alpha-Kermit if you have selected REMOTE mode.>
  3454.     BYTE    0
  3455.  
  3456. CUSAGE:
  3457.     BYTE    CR
  3458.     TEXT    <You are now communicating with whatever device is connected>
  3459.     TEXT    <to the serial port (e.g. your modem, or another system.)>
  3460.     TEXT    <Data received by the serial port will be displayed on this screen.>
  3461.     TEXT    <Until you press the special escape character, all of your keypresses>
  3462.     TEXT    <will be sent out of the serial port.>
  3463.     TEXT    <Pressing the escape character returns you to Alpha-Kermit's command mode.>
  3464.     BYTE    CR
  3465.     TEXT    <If you are using a modem, your terminal is now "connected">
  3466.     TEXT    <to the modem. Consult your modem manual for instructions on>
  3467.     TEXT    <dialing, hanging up, changing modem settings, etc.>
  3468.     BYTE    CR
  3469.     TEXT    <Special tips for most modem users:>
  3470.     TEXT    <  Before dialing, enter the characters ATE1Q0 and a return,>
  3471.     TEXT    <  even though your keypresses may not be echoed on the screen.>
  3472.     TEXT    <  Before exiting CONNECT, enter ATE0Q1 and a return!>
  3473.     BYTE    CR
  3474.     TEXT    <Have fun!>
  3475.     BYTE    CR,CR,0
  3476.  
  3477. ; string that SEND command sends to remote Kermit to automatically get it
  3478. ; ready to receive data.
  3479. PRESND:    ASCII    "KERMIT"
  3480.     BYTE    CR,-1
  3481.     ASCII    "RECEIVE"
  3482.     BYTE    CR,0
  3483. ; string that RECEIVE command sends to remote Kermit to automatically get it
  3484. ; ready to send data.
  3485. PREREC:    ASCII    "KERMIT"
  3486.     BYTE    CR,-1
  3487.     ASCII    "SEND "    ; note no CR - RECEIVE will send the filespec later!
  3488.     BYTE    0
  3489. ; show command strings
  3490. SH1.0:    ASCIZ    "Modem Port: "
  3491. SH2.0:    BYTE    CR
  3492.     TEXT    <             SET Options>
  3493.     ASCIZ    " Autoreceive:  "
  3494. SH2.1:    ASCIZ    "      Autosend:  "
  3495. SH2.2:    BYTE    CR
  3496.     ASCIZ    "        Bell:  "
  3497. SH2.3:    ASCIZ    "    Blockcheck:    "
  3498. SH2.4:    BYTE    CR
  3499.     ASCIZ    "       Debug:  "
  3500. SH2.5:    ASCIZ    "        Duplex: "
  3501. SH2.6:    ASCIZ    "        Escape:  "
  3502. SH2.7:    BYTE    CR
  3503.     ASCIZ    " Packet Size: "
  3504. SH2.7A:
  3505.     ASCIZ    "  Packet Start:  "
  3506. SH2.8:    BYTE    CR
  3507.     ASCIZ    "      Parity:  "
  3508. SH2.8A:    ASCIZ    "       Retries: "
  3509. SH2.9:    BYTE    CR
  3510.     ASCIZ    "       Stall: "
  3511. SH2.9A:    ASCIZ    "/100   Timeout: "
  3512. SH3.0:    BYTE    CR
  3513.     TEXT    <Received or Default Packet Parameters>
  3514.     ASCIZ    "  Blockcheck:    "
  3515. SH3.1:    ASCIZ    "    8Bit Quote: "
  3516. SH3.2:    BYTE    CR
  3517.     ASCIZ    "     Endline: "
  3518. SH3.3:    ASCIZ    "  Maximum Size: "
  3519. SH3.4:    BYTE    CR
  3520.     ASCIZ    "   Pad Count:   "
  3521. SH3.5:    ASCIZ    "     Pad Value:  "
  3522. SH3.6:    BYTE    CR
  3523.     ASCIZ    "     Timeout: "
  3524. SH3.8:    BYTE    CR,CR,0
  3525.     
  3526. SH.DAS:    ASCIZ    "------"
  3527. SH.OFF:    ASCIZ    "OFF"
  3528. SH.ON:    ASCIZ    " ON"
  3529. SH.FUL:    ASCIZ    "FULL"
  3530. SH.HAL:    ASCIZ    "HALF"
  3531. SH.ZIP:    ASCIZ    "NONE"
  3532. NOSET:    BYTE    CR
  3533.     ASCII    /%Kermit cannot change the communications port parity, but setting is noted./
  3534.     BYTE    CR,0
  3535. TITL2:    BYTE    CR
  3536.     ASCII    'Alpha-Kermit version '
  3537.     BYTE    0
  3538. CMDLNS:    ASCIZ    "DSK0:CMDLIN.SYS[1,4]"
  3539. DFAULT:    ASCIZ    "*.*"
  3540. NMTN:    ASCII    "?No matching terminal name"
  3541.     BYTE    CR,0
  3542. RENTER:    ASCII    "Note: Kermit session already in progress - new port name ignored."
  3543.     BYTE    CR,A.BEL,0
  3544.     EVEN
  3545.  
  3546.     END END END
  3547.