home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / ccpm86 / cn8pro.a86 < prev    next >
Text File  |  2020-01-01  |  43KB  |  1,437 lines

  1. ; * * * * * * * * * * * * * * *  version 2.9  * * * * * * * * * * * * * * *
  2. ; [34c]    Add sorted wildcard SENDs with initial filename
  3. ; * * * * * * * * * * * * * * *  version 2.7  * * * * * * * * * * * * * * *
  4. ; [31]    Fix display on file renaming.
  5. ;    RonB, 05/05/84
  6. ; [30c] Isolate ANSI escape sequences for machine independence.
  7. ; [29g]  Add 8th bit quoting.
  8. ; [29d]  Enlarge receive buffer and check for packet overruns.
  9. ; [29b]  Add TAKE processing (close command file when aborting).
  10. ; [29a]  Send error packet when aborting.
  11. ;    RonB, 04/08/84
  12. ; * * * * * * * * * * * * * * *  version 2.6  * * * * * * * * * * * * * * *
  13. ; [28b]  Make file-not-found error more informative (include filename).
  14. ; [28a]  Clear attribute bits from filename before sending
  15. ;    RonB, 03/27/84
  16. ; [25] - make KERCMD more modular by eliminating some use of text
  17. ;    strings by other modules (KERPRO, KERSYS), and moving some
  18. ;    parsing into KERCMD (ESCAPE and EOLSET logic in KERSYS)
  19. ; * * * * * * * * * * * * * * *  version 2.4  * * * * * * * * * * * * * * *
  20. ;  [21a] Add timeout enable/disable
  21. ;    RonB,03/05/84
  22. ;  [20a] Fix version & send/receive header
  23. ;  [20e] Clean up environment better before rebooting in KABORT
  24. ;    RonB,03/02/84
  25. ;  [19f] Add ^X/^Z file interruption - adapted from PC Kermit V1.20
  26. ;     Put in Help line for above.
  27. ;  [19g] Put in timeouts.
  28. ;    R. Garland 2/84
  29. ; * * * * * * * * * * * * * * *  version 2.1  * * * * * * * * * * * * * * *
  30. ;  [14]    Fix nout to print decimal.
  31. ;    RonB,12/28/83
  32. ;  [13]    Use control-Z's for filler in partial sectors instead of nulls.
  33. ;    RonB,12/27/83
  34. ;  [12]    Allow user abort from the keyboard in the send and receive routines.
  35. ;    RonB,12/27/83
  36. ;  [9]    Fix filename parsing, and add wildcard ability.
  37. ;    RonB,12/26/83
  38. ; * * * * * * * * * * * * * * *  version 2.0  * * * * * * * * * * * * * * *
  39. ; This module contains the routines that actually implement the Kermit
  40. ; protocol.
  41.  
  42. ; Packet definitions.
  43.  
  44. maxpkt    equ    '~'-' '+2O    ;Maximum size of a packet.
  45. maxtry    equ    05O        ;Default number of retries on a packet.
  46. imxtry    equ    20O        ;Default number of retries send initiate.
  47. drpsiz    equ    5EH        ;Default receive packet size.
  48. dspsiz    equ    20H        ;Default send packet size.
  49. dstime    equ    0AH        ;Default send time out interval.
  50. drtime    equ    05H        ;Default receive time out interval.
  51. dspad    equ    00H        ;Default send padding.
  52. drpad    equ    00H        ;Default receive padding.
  53. dspadc    equ    00H        ;Default send padding char.
  54. drpadc    equ    00H        ;Default receive padding char.
  55. dseol    equ    cr        ;Default send EOL char.
  56. dreol    equ    cr        ;Default receive EOL char.
  57. dsquot    equ    '#'        ;Default send quote char.
  58. drquot    equ    '#'        ;Default receive quote char.
  59. dqbin    equ    '&'        ;Default 8th-bit quote char.    ;[29g]
  60.  
  61. bufsiz    equ    80H        ;Size of DMA.
  62.  
  63. ; A few control characters
  64.  
  65. ctlc    equ    03H        ;[19f]
  66. ctlx    equ    18H        ;[19f]
  67. ctlz    equ    1AH        ;[19f]
  68.  
  69.     DSEG $
  70.  
  71. ; Program storage.
  72.  
  73. belflg    db    1        ;Use bell.
  74. incmod    db    0        ;Insert Character mode.
  75. hierr    db    0        ;Non-ascii char (non-zero if yes).
  76. parflg    db    defpar        ;Parity flag (default none.)
  77. flwflg    db    0        ;File warning flag (default off).
  78. ibmflg    db    0        ;IBM flag (default off).
  79. incnt    dw    0        ;Number of chars read in from port.
  80. pktptr    dw    0        ;Position in receive packet.
  81. spsiz    db    dspsiz        ;Send packet size.
  82. rpsiz    db    drpsiz        ;Receive packet size.
  83. stime    db    dstime        ;Send time out.
  84. rtime    db    drtime        ;Receive time out.
  85. spad    db    dspad        ;Send padding.
  86. rpad    db    drpad        ;Receive padding.
  87. spadch    db    dspadc        ;Send padding char.
  88. rpadch    db    drpadc        ;Receive padding char.
  89. seol    db    dseol        ;Send EOL char.
  90. reol    db    dreol        ;Receive EOL char.
  91. squote    db    dsquot        ;Send quote char.
  92. rquote    db    drquot        ;Receive quote char.
  93. ebquot    db    'Y'        ;Send 8th-bit quote char.        ;[29g]
  94. pktnum    dw    0        ;Packet number.
  95. numpkt    dw    0        ;Total number of packets sent.
  96. numrtr    dw    0        ;Total number of retries.
  97. numtry    db    0        ;Number of tries on this packet.
  98. oldtry    db    0        ;Number of tries on previous packet.
  99. cxzflg    db    0        ;[19f] flag for ^X/^Z file interruption
  100. state    db    0        ;Present state of the automaton.
  101. packet    rb    4        ;Packet (data is part of it).
  102. data    rb    60H        ;Data and checksum field of packet.    ;[29d]
  103. recpkt    rb    100H        ;Receive packet storage.        ;[29d]
  104. temp    dw    0
  105. argblk    dw    0        ;For subroutine arguments.
  106. argbk1    dw    0
  107. argbk2    dw    0
  108. argbk3    dw    0
  109. tickst    dw    10*(7470/clckrt);[19g] "magic" formula for loops/tick
  110.                 ;[19g] CLCKRT is the system clock rate ...
  111.                 ;[19g] ... defined in KERIO
  112. ticklp    dw    0        ;[19g] Dynamic loop count for tick
  113. tickct    db    dstime        ;[19g] # ticks for timeout to occur
  114. tmodon    db    0        ;[19g] flag for time-out message
  115.  
  116.     CSEG $
  117.  
  118. ; Check for a user abort or interrupt during the send or receive ;[12] begin
  119. ;            modified by Rg.
  120. kabort:    
  121.     call    dbinst        ;Check if a char has been typed.
  122.      jmp    r        ;[19f]  Merrily return.
  123.     call    dbin        ;Get the character.
  124.     cmp    al, ctlc    ;Abort if control-C [19f]
  125.     je    kabrt2
  126.     cmp    al, ctlx    ;[19f] Is it control-x ?
  127.     je    kabrta        ;[19f] yes
  128.     cmp    al, ctlz    ;[19f] control-z ?
  129.     jne    kabrtb        ;[19f] no
  130. kabrta:    add    al, 100O    ;[19f] make into 'X' or 'Z'
  131.     mov    cxzflg, al    ;[19f] set the flag
  132.     call    intmsg        ;[19f] reassure the user
  133.     ret            ;[19f] return
  134. kabrtb:    cmp    al, cr        ;if <cr> do a timeout        ;[29a] begin
  135.     jne    kabrtc
  136.     pop    bx        ;return of kabort
  137.     pop    bx        ;receive packet pointer
  138.                 ;... next is return of inpkt
  139.     ret            ;return to timeout routine    ;[29a] end
  140. kabrtc:    cmp    al, escchr    ;or the escape character followed by 'C'.
  141.     jne    kabrt9
  142.     mov    cx, 1000    ;Only wait just so long for the next char.
  143. kabrt1:    push    cx
  144.     call    dbin
  145.     pop    cx
  146.     cmp    al, 0
  147.     loope    kabrt1
  148.     cmp    al, ctlc    ;Control-C also works here. [19f]
  149.     je    kabrt2
  150.     and    al, 137O    ;Capitalize it.
  151.     cmp    al, 'C'        ;If not a 'C' then continue.
  152.     jne    kabrt9
  153. kabrt2:    cmp    tkflg, 0    ;Close any command file in use    ;[29b] begin
  154.     je    kabrt3
  155.     call    tkcls                        ;[29b] end
  156. kabrt3:    call    binst        ;Clear out extraneous input    ;[29a] begin
  157.         jmp    kabrt4    ;If none, go abort this transmission.
  158.     call    bin
  159.     jmps    kabrt2
  160. kabrt4:    pop    bx        ;return from kabort
  161.     pop    bx        ;receive packet pointer
  162.     pop    bx        ;return from inpkt
  163.     pop    bx        ;return from rpack
  164.                 ;... next is return from r??? to read
  165.     mov    dx, offset erms21 ;Print '* aborted *' message.
  166.     jmp    fatal                        ;[29a] end
  167. kabrt9:    mov    dl, bell    ;beep                [19f]
  168.     call    dbout        ;                [19f]
  169.     ret            ;return no error        [19f]
  170.  
  171.  
  172. ; Send the generic finish command to the remote Kermit.
  173.  
  174. finsen:    mov    ah, 'F'        ;Ask for the finish command.
  175.     call    gensen
  176.     ret
  177.  
  178.  
  179. ; Send the generic logout command to the remote Kermit.
  180.  
  181. byesen:    mov    ah, 'L'        ;Ask for the logout command.
  182.     call    gensen
  183.     ret
  184.  
  185.  
  186. ; This procedure processes all the generic single packet sends.
  187.  
  188. gensen:    mov    temp, ax    ;Save the specific generic command.
  189.     mov    numtry, 0    ;Initialize count.
  190.     call    cfibf        ;Clear out input buffer of extra NAKs.
  191. fins1:    mov    ah, numtry
  192.     cmp    ah, maxtry    ;Too many times?
  193.     js    fins3        ;Nope, try it.
  194. fins2:    mov    dx, offset erms18
  195.     call    tcrmsg
  196.     ret
  197.  
  198. fins3:    inc    numtry        ;Increment number of tries.
  199.     mov    argblk, 0    ;Packet number zero.
  200.     mov    argbk1, 1    ;One piece of data.
  201.     mov    bx, offset data
  202.     mov    ax, temp    ;Get the generic command.
  203.     mov    [bx], ah    ;Finish running Kermit.
  204.     mov    ah, 'G'        ;Generic command packet.
  205.     call    spack
  206.         jmp fins2    ;Tell user and die.
  207.     call    rpack        ;Get ACK.
  208.      jmp    fins1        ;Go try again.
  209.     cmp    ah, 'Y'        ;Got an ACK?
  210.     jnz    fins4
  211.     ret            ;Yes, then we're done.
  212. fins4:    cmp    ah, 'E'        ;Error packet?
  213.     jnz    fins1        ;Try sending it again.
  214.     call    error1
  215.     ret
  216.  
  217. ;    Packet routines
  218.  
  219. ; Send_Packet
  220. ; This routine assembles a packet from the arguments given and sends it
  221. ; to the host.
  222. ;
  223. ; Expects the following:
  224. ;    AH     - Type of packet (D,Y,N,S,R,E,F,Z,T)
  225. ;    ARGBLK - Packet sequence number
  226. ;    ARGBK1 - Number of data characters
  227. ;
  228. ; Returns: +1 always
  229.  
  230. spack:    push    ax        ;Save the packet type.
  231.     mov    bx, offset packet ;Get address of the send packet.
  232.     mov    ah, soh        ;Get the start of header char.
  233.     mov    [bx], ah    ;Put in the packet.
  234.     inc    bx        ;Point to next char.
  235.     mov    ax, argbk1    ;Get the number of data chars.
  236.     xchg    ah, al
  237.     add    ah, ' '+3    ;Real packet character count made printable.
  238.     mov    [bx], ah    ;Put in the packet.
  239.     inc    bx        ;Point to next char.
  240.     mov    cl, ah        ;Start the checksum.
  241.     mov    ax, argblk    ;Get the packet number.
  242.     xchg    ah, al
  243.     add    ah, ' '        ;Add a space so the number is printable.
  244.     mov    [bx], ah    ;Put in the packet.
  245.     inc    bx        ;Point to next char.
  246.     add    cl, ah        ;Add the packet number to the checksum.
  247.     pop    ax        ;Get the packet type.
  248.     mov    [bx], ah    ;Put in the packet.
  249.     inc    bx        ;Point to next char.
  250.     add    cl, ah        ;Add the type to the checksum.
  251.     mov    dx, argbk1    ;Get the packet size.
  252. spack2:    cmp    dx, 0        ;Are there any chars of data?
  253.      jz    spack3        ; No, finish up.
  254.     dec    dx        ;Decrement the char count.
  255.     mov    ah, [bx]    ;Get the next char.
  256.     inc    bx        ;Point to next char.
  257.     add    cl, ah        ;Add the char to the checksum.
  258.     jmp    spack2        ;Go try again.
  259. spack3:
  260. sp3x:    mov    ah, cl        ;Get the character total.
  261.     mov    ch, cl        ;Save here too (need 'cl' for shift).
  262.     and    ah, 0C0H    ;Turn off all but the two high order bits.
  263.     mov    cl, 6
  264.     shr    ah, cl        ;Shift them into the low order position.
  265.     mov    cl, ch
  266.     add    ah, cl        ;Add it to the old bits.
  267.     and    ah, 3FH        ;Turn off the two high order bits.  (MOD 64)
  268.     add    ah, ' '        ;Add a space so the number is printable.
  269.     mov    [bx], ah    ;Put in the packet.
  270.     inc    bx        ;Point to next char.
  271.     mov    ah, seol    ;Get the EOL the other host wants.
  272.     mov    [bx], ah    ;Put in the packet.
  273.     inc    bx        ;Point to next char.
  274.     mov    ah, 0        ;Get a null.
  275.     mov    [bx], ah    ;Put in the packet.
  276.     cmp    debug, 0    ;debug mode.
  277.     je    spack4
  278.     inc    bx
  279.     mov    ah, '$'
  280.     mov    [bx], ah
  281.     mov    dx, offset scrsp ;Print string to move cursor.
  282.     call    poscur                        ;[30c] begin
  283.     call    clreol        ;Clear current line
  284.     mov    dl, lf        ;  and next one
  285.     call    bout
  286.     call    clreol
  287.     mov    dx, offset scrsp ;Print string to move cursor.
  288.     call    poscur                        ;[30c] end
  289.     mov    dx, offset spmes
  290.     call    tmsg
  291.     mov    dx, offset packet
  292.     call    tmsg        ;Debug end.
  293. spack4:    call    outpkt        ;Call the system dependent routine.
  294.     jmp    rskp
  295.  
  296.  
  297. ;    Write out a packet.
  298.  
  299. outpkt:    mov    dh, spad    ;Get the number of padding chars.
  300. outpk2:    dec    dh
  301.     cmp    dh, 0
  302.     jl    outpk3        ;If none left proceed.
  303.     mov    al, spadch    ;Get the padding char.
  304.     call    prtout        ;Output it.
  305.     jmp    outpk2
  306. outpk3:    mov    bx, offset packet ;Point to the packet.
  307. outlup:    mov    al, [bx]    ;Get the next character.
  308.     cmp    al, 0        ;Is it a null?
  309.     jnz    outlp2
  310.     ret
  311. outlp2:    call    prtout        ;Output the character.
  312.     inc    bx        ;Increment the char pointer.
  313.     jmp    outlup
  314.  
  315.  
  316. ; Receive_Packet
  317. ; This routine waits for a packet arrive from the host.
  318.  
  319. rpack:    call    inpkt        ;Read up to a carriage return.
  320.      jmp    rptimo        ; User timed us out.
  321. rpack0:    call    getchr        ;Get a character.
  322.      jmp    rpack        ; Hit the carriage return, go try again.
  323.     cmp    ah, soh        ;Is the char the start of header char?
  324.      jne    rpack0        ; No, go until it is.
  325. rpack1:    call    getchr        ;Get a character.
  326.      jmp    r        ; Hit the carriage return, return bad.
  327.     cmp    ah, soh        ;Is the char the start of header char?
  328.      jz    rpack1        ; Yes, then go start over.
  329.     mov    cl, ah        ;Start the checksum.
  330.     sub    ah, ' '+3    ;Get the real data count.
  331.     mov    dh, ah        ;Save it for later.
  332.     mov    al, ah        ;Swap halves.
  333.     mov    ah, 0
  334.     mov    argbk1, ax    ;Save the data count.
  335.     call    getchr        ;Get a character.
  336.      jmp    r        ; Hit the carriage return, return bad.
  337.     cmp    ah, soh        ;Is the char the start of header char?
  338.      jz    rpack1        ; Yes, then go start over.
  339.     add    cl, ah        ;Add it to the checksum.
  340.     sub    ah, ' '        ;Get the real packet number.
  341.     mov    al, ah        ;Swap halves.
  342.     mov    ah, 0
  343.     mov    argblk, ax    ;Save the packet number.
  344.     call    getchr        ;Get a character.
  345.      jmp    r        ; Hit the carriage return, return bad.
  346.     cmp    ah, soh        ;Is the char the start of header char?
  347.      jz    rpack1        ; Yes, then go start over.
  348.     mov    temp, ax    ;Save the message type.
  349.     add    cl, ah        ;Add it to the checksum.
  350.     mov    bx, offset data    ;Point to the data buffer.
  351. rpack2:    dec    dh        ;Any data characters?
  352.      js    rpack3        ; If not go get the checksum.
  353.     call    getchr        ;Get a character.
  354.      jmp    r        ; Hit the carriage return, return bad.
  355.     cmp    ah, soh        ;Is the char the start of header char?
  356.      jz    rpack1        ; Yes, then go start over.
  357.     mov    [bx], ah    ;Put the char into the packet.
  358.     inc    bx        ;Point to the next character.
  359.     add    cl, ah        ;Add it to the checksum.
  360.     jmp    rpack2        ;Go get another.
  361. rpack3:    call    getchr        ;Get a character.
  362.      jmp    r        ; Hit the carriage return, return bad.
  363.     cmp    ah, soh        ;Is the char the start of header char?
  364.      jz    rpack1        ; Yes, then go start over.
  365.     sub    ah, ' '        ;Turn the char back into a number.
  366.     mov    dh, cl        ;Get the character total.
  367.     and    dh, 0C0H    ;Turn off all but the two high order bits.
  368.     mov    ch, cl
  369.     mov    cl, 6
  370.     shr    dh, cl        ;Shift them into the low order position.
  371.     mov    cl, ch
  372.     add    dh, cl        ;Add it to the old bits.
  373.     and    dh, 3FH        ;Turn off the two high order bits.  (MOD 64)
  374.     cmp    dh, ah        ;Are they equal?
  375.      jz    rpack4        ; If so finish up.
  376.     call    cfibf        ;Clear out any other characters on the line.
  377.     ret            ;And return failure.
  378.  
  379. rpack4:    mov    ah, 0
  380.     mov    [bx], ah    ;Put a null at the end of the data.
  381.     mov    ax, temp    ;Get the type.
  382.     call    cfibf        ;Clear out any other characters on the line.
  383.     jmp    rskp
  384.  
  385. rptimo:    call    cfibf        ;On a time out clear out any remaining chars.
  386.     ret
  387.  
  388. inpkt:    mov    bx, offset recpkt ;Point to the beginning of the packet.
  389.     mov    incnt, 0
  390. inpkt2:    mov    al, stime    ;[19g] set up timeout loop.
  391.     mov    tickct, al    ;[19g]
  392.     mov    ax, tickst    ;[19g] "magic" number loops/tick
  393.     mov    ticklp, ax    ;[19g]
  394. inpkta:    cmp    tmrflg, 0    ;Is timeout disabled?            ;[21a]
  395.     je    inpktb        ;  If so, skip tick routine        ;[21a]
  396.     dec    ticklp        ;[19g]
  397.     cmp    ticklp, 0    ;[19g] done this tick?
  398.     jne    inpktb        ;[19g] not yet
  399.     mov    ax, tickst    ;[19g] reload loop count
  400.     mov    ticklp, ax    ;[19g]
  401. ;    call    ticmsg        ;[19g] beep for debugging
  402.     dec    tickct        ;[19g]
  403.     cmp    tickct, 0    ;[19g] timed-out?
  404.     jne    inpktb        ;[19g] not yet
  405.     call    tmomsg        ;[19g] alert user
  406.     jmp    inpkt9        ;[19g] go time-out
  407. inpktb:    push    bx        ;[19g][12] bx gets trashed by kb status check.
  408.     call    kabort        ;[19g] Doesn't return if user aborted.
  409.     pop    bx        ;[19g]
  410.     call    instat        ;Any char there?
  411.      jmp    inpkta        ; Go until there is one.
  412.     call    inchr        ;Get the character.
  413.     mov    [bx], al    ;Put the char in the packet.
  414.     inc    bx
  415.     inc    incnt
  416.     cmp    incnt, length recpkt ;Have we overrun the input buffer? ;[29d]
  417.     jb    inpktc
  418.     jmp    inpkt        ;If so, just clear and restart
  419. inpktc:    cmp    al, reol    ;Is it the EOL char?        ;[29d] end
  420.     jne    inpkt2        ;If not loop for another.
  421.     cmp    incnt, 1    ;Ignore bare CR.
  422.     jne    inpkt6
  423.     jmp    inpkt
  424. inpkt6:    cmp    ibmflg, 0    ;Is this the (dumb) IBM mainframe?
  425.     jz    inpkt4        ;If not then proceed.
  426. inpkt5:    cmp    state, 'S'    ;Check if this is the Send-Init packet.
  427.     jz    inpkt4        ;If so don't wait for the XON.
  428. inpkt3:    call    instat        ;Wait for the turn around char.
  429.      jmp    inpkt3
  430.     call    inchr
  431.     cmp    al, xon        ;Is it the IBM turn around character?
  432.     jne    inpkt3        ;If not, go until it is.
  433. inpkt4:    cmp    debug, 0
  434.     jz    inpkt7        ;If not debugging don't print the packet.
  435.     mov    al, '$'        ;Get a dollar sign.
  436.     mov    [bx], al    ;Put in the packet.
  437.     inc    bx        ;Point to next char.
  438.     mov    dx, offset scrrp ;Print the packet.
  439.     call    poscur                        ;[30c] begin
  440.     call    clreol        ;Clear current line
  441.     mov    dl, lf        ;  and next one
  442.     call    bout
  443.     call    clreol
  444.     mov    dx, offset scrrp ;Print string to move cursor.
  445.     call    poscur                        ;[30c] end
  446.     mov    dx, offset rpmes
  447.     call    tmsg
  448.     mov    dx, offset recpkt
  449.     call    tmsg
  450.  
  451. inpkt7:    mov    bx, offset recpkt
  452.     mov    pktptr, bx    ;Save the packet pointer.
  453.     call    tmoclr        ;[19g] Clear timeout message
  454.     jmp    rskp        ;If so we are done.
  455.  
  456. inpkt9:    ret            ;return failure on time out.
  457.  
  458.  
  459. getchr:    push    bx
  460.     mov    bx, pktptr    ;Get the packet pointer.
  461.     mov    ah, [bx]    ;Get the char.
  462.     inc    bx
  463.     mov    pktptr, bx
  464.     pop    bx        ;Restore BX.
  465.     cmp    ah, reol    ;Is it the EOL char?
  466.     jne    getcr2        ;If not return retskp.
  467.     ret            ;If so return failure.
  468. getcr2:    jmp    rskp
  469.  
  470.  
  471. ;This is where we go if we get an error packet.  A call to ERROR
  472. ; positions the cursor and prints the message.  A call to ERROR1
  473. ; just prints a CRLF and then the message.
  474.  
  475. error:    mov    state, 'A'    ;Set the state to abort.
  476.     mov    dx, offset screrr
  477.     call    poscur                        ;[30c]
  478.     jmp    error2
  479. error1:    call    tcrlf
  480. error2:    mov    bx, offset data    ;Get to the string.
  481.     add    bx, argbk1    ;Add the length of the data.
  482.     mov    ah, '$'        ;Put a dollar sign at the end.
  483.     mov    [bx], ah
  484.     mov    dx, offset data    ;Print the error message.
  485.     call    tmsg
  486.     ret
  487.  
  488. ; Jump here if we die during a transfer.  Print the error message in
  489. ; DX and abort.
  490.  
  491. fatal:    push    dx        ;Save the error message.
  492.     mov    dx, offset screrr
  493.     call    poscur                        ;[30c]
  494.     pop    dx
  495.     call    tmsg
  496.     jmp    abort        ;Change the state to abort.
  497.  
  498. ; Print the status message in DX, ring the bell and position of the prompt.
  499.  
  500. fnstat:    push    dx
  501.     mov    dx, offset scrst ;Print string to move cursor.
  502.     call    poscur                        ;[30c]
  503.     pop    dx
  504.     call    tmsg
  505.     mov    dx, offset ender ;Ring them bells.
  506.     call    tmsg
  507.     mov    dx, offset scrhlp ;[19f] Cursor position
  508.     call    poscur                        ;[30c]
  509.     call    clreol        ;[19f] Clear help line        ;[30c]
  510.     mov    dx, offset scrrpr ;Put cursor back
  511.     call    poscur                        ;[30c]
  512.     ret
  513.  
  514.  
  515. ;    This routine sets up the data for init packet (either the
  516. ;    Send_init or ACK packet).
  517.  
  518. rpar:    mov    ah, rpsiz    ;Get the receive packet size.
  519.     add    ah, ' '        ;Add a space to make it printable.
  520.     mov    [bx], ah    ;Put it in the packet.
  521.     mov    ah, rtime    ;Get the receive packet time out.
  522.     add    ah, ' '        ;Add a space.
  523.     mov    1[bx], ah    ;Put it in the packet.
  524.     mov    ah, rpad    ;Get the number of padding chars.
  525.     add    ah, ' '
  526.     mov    2[bx], ah    ;Put it in the packet.
  527.     mov    ah, rpadch    ;Get the padding char.
  528.     add    ah, 100O    ;Uncontrol it.
  529.     and    ah, 7FH
  530.     mov    3[bx], ah    ;Put it in the packet.
  531.     mov    ah, reol    ;Get the EOL char.
  532.     add    ah, ' '
  533.     mov    4[bx], ah    ;Put it in the packet.
  534.     mov    ah, rquote    ;Get the quote char.
  535.     mov    5[bx], ah    ;Put it in the packet.
  536.     mov    ah, ebquot    ;Get 8th-bit quote char    ;[29g] begin
  537.     mov    6[bx], ah    ;Put it in the packet.
  538.     mov    ah, '1'        ;Set single character check type
  539.     mov    7[bx], ah    ;Put it in the packet.
  540.     mov    ah, ' '        ;Set no repeat prefix
  541.     mov    8[bx], ah    ;Put it in the packet.
  542.     mov    ah, 0        ;Initialize capability byte
  543.     cmp    tmrflg, 0    ;Are we able to time out?
  544.     je    rpar1        ;  No, leave bit set to zero
  545.     or    ah, 20h        ;  Otherwise set timeout capability flag
  546. rpar1:    add    ah, ' '        ;Add space to make it printable
  547.     mov    9[bx], ah    ;Put it in the packet.
  548.     mov    ah, 10        ;Ten pieces of data.        ;[29g] end
  549.     ret
  550.  
  551. ;    This routine reads in all the send_init packet information.
  552.  
  553. spar:    push    cx        ;Save CX.
  554.     mov    cx, ax        ;Save the number of arguments.
  555.     mov    ah, [bx]    ;Get the max packet size.
  556.     sub    ah, ' '        ;Subtract a space.
  557.     mov    spsiz, ah    ;Save it.
  558.     mov    ax, cx        ;[19g]
  559.     cmp    al, 2        ;[19g] Fewer than two pieces?
  560.     jge    spar1        ;[19g]                ;[29g]
  561.     jmp    sparx1                        ;[29g]
  562. spar1:    mov    ah, 1[bx]    ;[19g] Get the timeout value
  563.     sub    ah, ' '        ;[19g]
  564.     mov    stime, ah    ;[19g] save it.
  565.     mov    ax, cx
  566.     cmp    al, 3        ;Fewer than three pieces?
  567.     jge    spar2                        ;[29g]
  568.     jmp    sparx2                        ;[29g]
  569. spar2:    mov    ah, 2[bx]    ;Get the number of padding chars.
  570.     sub    ah, ' '
  571.     mov    spad, ah
  572.     mov    ax, cx
  573.     cmp    al, 4        ;Fewer than four pieces?
  574.     jge    spar3                        ;[29g]
  575.     jmp    sparx3                        ;[29g]
  576. spar3:    mov    ah, 3[bx]    ;Get the padding char.
  577.     add    ah, 100O    ;Re-controlify it.
  578.     and    ah, 7FH
  579.     mov    spadch, ah
  580.     mov    ax, cx
  581.     cmp    al, 5        ;Fewer than five pieces?
  582.     jge    spar4                        ;[29g]
  583.     jmp    sparx4                        ;[29g]
  584. spar4:    mov    ah, 4[bx]    ;Get the EOL char.
  585.     sub    ah, ' '
  586.     mov    seol, ah
  587.     mov    ax, cx
  588.     cmp    al, 6        ;Fewer than six pieces?
  589.     jge    spar5                        ;[29g]
  590.     jmp    sparx5                        ;[29g]
  591. spar5:    mov    ah, 5[bx]    ;Get the quote char.
  592.     mov    squote, ah
  593.     mov    ax, cx                        ;[29g] begin
  594.     cmp    al, 7        ;Fewer than seven pieces?
  595.     jge    spar6
  596.     jmp    sparx6
  597. spar6:    mov    ah, 6[bx]    ;Get the 8th-bit quote char.
  598.     call    doquo        ;Set the quote character.
  599.     jmp    sparxx
  600. sparx1:    mov    stime, dstime    ;Default timeout interval
  601. sparx2:    mov    spad, dspad    ;Default number of padding chars
  602. sparx3:    mov    spadch, dspadc    ;Default pad character
  603. sparx4:    mov    seol, dseol    ;Default eol character
  604. sparx5:    mov    squote, dsquot    ;Default send quote character.
  605. sparx6:    mov    ebquot, 'N'    ;No 8th bit quoting.
  606. sparxx:    pop    cx                        ;[29g] end
  607.     ret            ;If so we are done.
  608.  
  609. ; Set 8-bit quote character based on my capabilities        ;[29g] begin
  610. ; and the other Kermit's request.
  611.  
  612. doquo:    cmp    ebquot,'N'    ;Can I do 8-bit quoting at all?
  613.     je    dq2        ;No - so forget it.
  614.     cmp    ebquot,'Y'    ;Can I do it if requested?
  615.     jne    dq0        ;No - it's a must that I do it.
  616.     mov    ebquot,ah    ;Do whatever he wants.
  617.     jmp    dq2
  618. dq0:    cmp    ah,'Y'        ;I need quoting - can he do it?
  619.     je    dq2        ;Yes - then all is settled.
  620.     cmp    ah,'N'        ;No - then don't quote.
  621.     je    dq1
  622.     cmp    ah,ebquot    ;Both need quoting - chars must match.
  623.     je    dq2
  624.     mov    ah,'N'
  625. dq1:    mov    ebquot,ah
  626. dq2:    mov    ah,ebquot
  627.     cmp    ah,rquote    ;Same prefix?
  628.     je    dq3        ;Not allowed, so don't do quoting. 
  629.     cmp    ah,squote    ;Same prefix here?
  630.     je    dq3        ;This is illegal too.
  631.     ret
  632. dq3:    mov    ebquot,'N'    ;Quoting will not be done.
  633.     ret                            ;[29g] end
  634.  
  635. ; These are some utility routines.
  636.  
  637. ; Increment the packet number.
  638.  
  639. incpkt:    inc    ax        ;Increment it.
  640.     and    ax, 3FH        ;Turn off the two high order bits.
  641.     mov    pktnum, ax    ;Save modulo 64 of the number.
  642.     inc    numpkt        ;Increment the number of packets.
  643.     ret
  644.  
  645. ; Check if the packet number is the present packet.
  646.  
  647. chkpeq:    mov    ax, argblk    ;Get the packet number.
  648.     cmp    ax, pktnum    ;Is it the right packet number?
  649.     je    chkpe2
  650.     ret            ;No.
  651. chkpe2:    jmp    rskp        ;Yes.
  652.  
  653. ; Is the packet number one more than present.
  654.  
  655. chkpom:    mov    ax, pktnum    ;Get the present packet number.
  656.     inc    ax        ;Increment.
  657.     and    ax, 03FH    ;Account for wraparound.
  658.     cmp    ax, argblk    ;Is the packet's number one more than now?
  659.     jz    chkpm2        ;Yes, success.
  660.     ret
  661. chkpm2:    jmp    rskp
  662.  
  663. ; Check if the packet number is the previous packet.
  664.  
  665. chkpol:    inc    oldtry        ;Save the updated number of tries.
  666.     mov    ax, pktnum    ;Get the present packet number.
  667.     cmp    ax, 0        ;Had we wrapped around?
  668.     jne    chkpl2
  669.     mov    ax, 64
  670. chkpl2:    dec    ax        ;Decrement.
  671.     cmp    ax, argblk    ;Is the packet's number one less than now?
  672.     je    chkpl3    
  673.     jmp    rskp
  674. chkpl3:    ret
  675.  
  676. ;    Abort
  677.  
  678. abort:    mov    argblk, 0    ;packet number 0        ;[29a] begin
  679.     mov    argbk1, 0    ;no data
  680.     mov    ah, 'E'        ;error type
  681.     call    spack
  682.      jmp    $                            ;[29a] end
  683.     mov    state, 'A'    ;Otherwise abort.
  684.     ret
  685.  
  686. ; ACK the packet.
  687.  
  688. uupack:    call    updat        ;[19f] entry which doesn't zero argbk1
  689.     jmp    ack1        ;[19f]
  690. upack:    call    updat        ;Update the number of tries.
  691. ack:    mov    argbk1, 0    ;No data.  (Packet number already in argblk).
  692. ack1:    mov    ah, 'Y'        ;Acknowledge packet.
  693.     call    spack        ;Send the packet.
  694.      jmp    r
  695.     jmp    rskp
  696.  
  697. updat:    mov    ah, numtry    ;Get the number of tries.
  698.     mov    oldtry, ah    ;Save it.
  699.     mov    numtry, 0    ;Reset the number of tries.
  700.     ret
  701.  
  702. ; Re-ACK the previous packet.
  703.  
  704. reack:    call    nretry        ;Increment and print the number of retries.
  705.     mov    numtry, 0    ;Reset the number of tries.
  706.     mov    ah, 'Y'        ;Acknowledge packet.
  707.     call    spack        ;Send the packet.
  708.      jmp    r
  709.     jmp    rskp
  710.  
  711. ; NAK that packet.
  712.  
  713. nak:    mov    ax, pktnum    ;Get the packet number we're waiting for.
  714.     mov    argblk, ax
  715.     mov    argbk1, 0
  716.     mov    ah, 'N'        ;NAK that packet.
  717.     call    spack
  718.      jmp    abort
  719.     call    nretry        ;Increment and print the number of retries.
  720.     ret            ;Go around again.
  721.  
  722. ; Print the number of retries.
  723.  
  724. nretry:    inc    numrtr        ;Increment the number of retries.
  725. pretry:    mov    dx, offset scrnrt
  726.     call    poscur                        ;[30c]
  727.     mov    ax, numrtr
  728.     call    nout        ;Write the number of retries.
  729.     ret
  730.  
  731. ; Print the number of packets.
  732.  
  733. pnmpkt:    mov    dx, offset scrnp ;Print string to move cursor.
  734.     call    poscur                        ;[30c]
  735.     mov    ax, numpkt
  736.     call    nout        ;Write the number of packets.
  737.     ret
  738.  
  739. ; This routine prints the number in AX on the screen.
  740.  
  741. nout:    push    ax        ;save all registers        ;[14] begin
  742.     push    bx
  743.     push    cx
  744.     push    dx
  745.     mov    cx, 0        ;number of digits to print
  746.     mov    bx, 10        ;radix to use for dividing
  747. nout1:    mov    dx, 0        ;clear high word of dividend
  748.     div    bx        ;divide dx:ax by 10
  749.     push    dx        ;push this remainder
  750.     inc    cx        ;count it
  751.     cmp    ax, 0        ;anything left in the quotient?
  752.     jne    nout1        ;   if so, keep dividing
  753. nout2:    pop    dx        ;get a digit
  754.     add    dl, '0'        ;make it ascii
  755.     push    cx        ;save our count
  756.     call    bout        ;print the digit
  757.     pop    cx        ;repeat until all digits printed
  758.     loop    nout2
  759.     pop    dx        ;restore all registers
  760.     pop    cx
  761.     pop    bx
  762.     pop    ax
  763.     ret
  764.  
  765. ;    Initialize file buffers and paint screen.
  766.  
  767. init:
  768.     call    dspver        ;Clear screen and display version header
  769.     mov    dx, offset scrnp ;Position to packet location
  770.     call    poscur
  771.     mov    dx, offset pktlin                        ;[20a]
  772.     call    tmsg
  773.     mov    dx, offset scrhlp ;[19f] Cursor position
  774.     call    poscur        ;[19f] for help line            ;[30c]
  775.     call    revon        ;Bottom line reverse            ;[30c]
  776.     mov    dx, offset infm10 ;[19f] Help for file transfer
  777.     call    tmsg        ;[19f]
  778.     call    revoff                            ;[30c]
  779.  
  780. init1:    mov    chrcnt, bufsiz    ;Number of chars left.
  781.     mov    bufpnt, offset dma ;Addr for beginning.
  782.     ret
  783.  
  784.  
  785. ;  Clear out the old filename on the screen.
  786.  
  787. clrfln:    mov    dx, offset scrfr ;Move cursor to file rename.    ;[31] begin
  788.     call    poscur
  789.     call    clreol        ;Clear to EOL.            ;[31] end
  790.     mov    dx, offset scrfln ;Move cursor to file name position.
  791.     call    poscur                        ;[30c]
  792.     call    clreol        ;Clear to EOL.            ;[30c]
  793.     ret
  794.  
  795. ; acknowledge ^X/^Z with a message        [19f] start
  796. intmsg:    mov    dx, offset scrint ;position info
  797.     call    poscur        ;output it            ;[30c]
  798.     mov    dx, offset infms8 ;File message
  799.     cmp    cxzflg, 'X'    ;but first check
  800.     je    intm01        ;yes it was X
  801.     mov    dx, offset infms9 ;no it was 'Z' - file group.
  802.     cmp    cxzflg, 'Z'    ;or was it?
  803.     je    intm01        ;yes - go output
  804.     call    clreol        ;anything else - clear line    ;[30c]
  805.     jmps    intm02                        ;[30c]
  806. intm01:    call    tmsg        ;output it
  807. intm02:    ret            ;goodbye    [19f] end
  808.  
  809. ;    let the time-out clock "tick"    ;[19g] start
  810. ticmsg:    mov    dl, bell    ;output a ...
  811.     call    dbout        ;... beep!
  812.     ret
  813.  
  814. ;    notify of time-out
  815. tmomsg:    mov    dx, offset scrst ;cursor position
  816.     call    poscur                        ;[30c]
  817.     mov    dx, offset timoms ;timeout message
  818.     call    tmsg
  819.     mov    tmodon, 1    ;flag for message
  820.     ret
  821.  
  822. ;    clear time-out    message
  823. tmoclr:    cmp    tmodon, 0    ;message on screen?
  824.     jne    tmocl1        ;yes - go get it
  825.     ret            ;nothing to clear - return
  826. tmocl1:    mov    dx, offset scrst ;cursor position
  827.     call    poscur                        ;[30c]
  828.     call    clreol        ;clear line            ;[30c]
  829.     mov    tmodon, 0    ;indicate line is clear
  830.     ret            ;[19g] end
  831.  
  832. ;    RECEIVE command
  833.  
  834. read:    call    init        ;Paint the screen and initialize file buffers.
  835.     call    cfibf        ;Clear out any stacked NAKs.
  836. read1:    mov    numpkt, 0    ;Set the number of packets to zero.
  837.     mov    numrtr, 0    ;Set the number of retries to zero.
  838.     mov    pktnum, 0    ;Set the packet number to zero.
  839.     mov    numtry, 0    ;Set the number of tries to zero.
  840.     mov    cxzflg, 0    ;[19f] reset ^X/^Z flag
  841.     call    pretry
  842.     mov    state, 'R'    ;Set the state to receive initiate.
  843. read2:    call    pnmpkt
  844.     mov    ah, state    ;Get the state.
  845.     cmp    ah, 'D'        ;Are we in the data send state?
  846.     jne    read3
  847.     call    rdata
  848.     jmp    read2
  849. read3:    cmp    ah, 'F'        ;Are we in the file receive state?
  850.     jne    read4
  851.     call    rfile        ;Call receive file.
  852.     jmp    read2
  853. read4:    cmp    ah, 'R'        ;Are we in the receive initiate state?
  854.     jne    read5
  855.     call    rinit
  856.     jmp    read2
  857. read5:    cmp    ah, 'C'        ;Are we in the receive complete state?
  858.     jne    read6
  859.     mov    dx, offset infms3 ;Plus a little cuteness.
  860.     cmp    cxzflg,0    ;[19f] an interruption?
  861.     je    read59        ;[19f] no - do normal thing
  862.     mov    dx, offset infms7 ;[19f] substitute 'interrupted' message.
  863. read59:    call    fnstat
  864.     ret
  865. read6:    mov    dx, offset infms4 ;Plus a little cuteness.
  866.     call    fnstat
  867.     ret
  868.  
  869.  
  870. ;    Receive routines
  871.  
  872. ;    Receive init
  873.  
  874. rinit:    mov    ah, numtry    ;Get the number of tries.
  875.     cmp    ah, imxtry    ;Have we reached the maximum number of tries?
  876.     jl    rinit2
  877.     mov    dx, offset ermes7 ;Print this error and die.
  878.     jmp    fatal
  879.  
  880. rinit2:    inc    ah        ;Increment it.
  881.     mov    numtry, ah    ;Save the updated number of tries.
  882.     call    rpack        ;Get a packet.
  883.      jmp    nak        ; Trashed packet: nak, retry.
  884.     cmp    ah, 'S'        ;Is it a send initiate packet?
  885.     jne    rinit3        ;If not see if its an error.
  886.     mov    ebquot, 'Y'    ;Initialize my 8th-bit quote flag    ;[29g]
  887.     mov    ah, numtry    ;Get the number of tries.
  888.     mov    oldtry, ah    ;Save it.
  889.     mov    numtry, 0    ;Reset the number of tries.
  890.     mov    ax, argblk    ;Returned packet number.  (Synchronize them.)
  891.     call    incpkt        ;Increment the packet number.
  892.     mov    ax, argbk1    ;Get the number of arguments received.
  893.     mov    bx, offset data    ;Get a pointer to the data.
  894.     call    spar        ;Get the data into the proper variables.
  895.     mov    bx, offset data    ;Get a pointer to our data block.
  896.     call    rpar        ;Set up the receive parameters.
  897.     xchg    ah, al
  898.     mov    ah, 0
  899.     mov    argbk1, ax    ;Store the returned number of arguments.
  900.     call    ack1        ;ACK the packet.
  901.         jmp    abort
  902.     mov    ah, 'F'        ;Set the state to file send.
  903.     mov    state, ah
  904.     ret
  905. rinit3:    cmp    ah, 'E'        ;Is it an error packet?
  906.     jne    rinit4
  907.     call    error
  908. rinit4:    jmp    abort
  909.  
  910.  
  911. ;    Receive file
  912.  
  913. rfile:    cmp    numtry, maxtry    ;Have we reached the maximum number of tries?
  914.     jl    rfile1
  915.     mov    dx, offset ermes8 ;Print this error and die.
  916.     jmp    fatal
  917.  
  918. rfile1:    inc    numtry        ;Save the updated number of tries.
  919.     call    rpack        ;Get a packet.
  920.      jmp    nak        ; Trashed packet: nak, retry.
  921.  
  922.     cmp    ah, 'S'        ;Is it a send initiate packet?
  923.     jne    rfile2        ; No, try next type.
  924.     cmp    oldtry, imxtry    ;Have we reached the maximum number of tries?
  925.     jl    rfil12        ;If not proceed.
  926.     mov    dx, offset ermes7 ;Print this error and die.
  927.     jmp    fatal
  928. rfil12:    call    chkpol        ;Check the packet number, is it right?
  929.      jmp    nak        ;No, NAK and try again.
  930.     mov    bx, offset data    ;Get a pointer to our data block.
  931.     call    rpar        ;Set up the parameter information.
  932.     xchg    ah, al
  933.     mov    ah, 0
  934.     mov    argbk1, ax    ;Save the number of arguments.
  935.     call    reack        ;Re-ACK the old packet.
  936.      jmp    abort
  937.     ret
  938.  
  939. rfile2:    cmp    ah, 'Z'        ;Is it an EOF packet?
  940.     jne    rfile3        ; No, try next type.
  941.     cmp    oldtry, maxtry    ;Have we reached the maximum number of tries?
  942.     jl    rfil21        ;If not proceed.
  943.     mov    dx, offset ermes9 ;Print this error and die.
  944.     jmp    fatal
  945. rfil21:    call    chkpol        ;Check the packet number, is it right?
  946.      jmp    nak        ;No, NAK and try again.
  947.     mov    argbk1, 0    ;No data.
  948.     call    reack        ;Re-ACK the previous packet
  949.      jmp    abort
  950.     ret
  951.  
  952. rfile3:    cmp    ah, 'F'        ;Start of file?
  953.     jne    rfile4
  954.     call    chkpeq        ;Packet numbers equal?
  955.      jmp    nak        ; No, NAK it and try again.
  956.     call    incpkt        ;Increment the number of packets.
  957.     call    gofil        ;Get a file to write to.
  958.      jmp    abort
  959.     call    init1        ;Initialize all the file buffers.
  960.     call    upack        ;Update counters and ACK the packet.
  961.      jmp    abort
  962.     mov    state, 'D'    ;Set the state to data receive.
  963.     ret
  964.  
  965. rfile4:    cmp    ah, 'B'        ;End of transmission?
  966.     jne    rfile5
  967.     call    chkpeq        ;Packet numbers equal?
  968.      jmp    nak        ; No, NAK it and try again.
  969.     call    ack        ;ACK the packet.
  970.      jmp    abort
  971.     mov    state, 'C'    ;Set the state to complete.
  972.     ret
  973.  
  974. rfile5:    cmp    ah, 'E'        ;Is it an error packet?
  975.     jne    rfile6
  976.     call    error
  977. rfile6:    jmp    abort
  978.  
  979.  
  980. ;    Receive data
  981.  
  982. rdata:    cmp    numtry, maxtry    ;Get the number of tries.
  983.     jl    rdata1
  984.     mov    dx, offset erms10 ;Print this error and die.
  985.     jmp    fatal
  986.  
  987. rdata1:    inc    numtry        ;Save the updated number of tries.
  988.     call    rpack        ;Get a packet.
  989.      jmp    nak        ; Trashed packet: nak, retry.
  990.  
  991.     cmp    ah, 'D'        ;Is it a data packet?
  992.     je    rdat11
  993.     jmp    rdata2        ; No, try next type.
  994. rdat11:    call    chkpeq        ;Packet numbers equal?
  995.      jmp    rdat12        ; No, check if previous packet.
  996.     call    incpkt        ;Increment the number of packets.
  997.     mov    ax, argbk1    ;Get the length of the data.
  998.     cmp    cxzflg, 0    ;[19f] interrupt requested?
  999.     jne    rdat1a        ;[19f] yes - skip put to file.
  1000.     call    ptchr
  1001.      jmp    abort        ; Unable to write out chars;abort.
  1002.     call    upack        ;ACK the packet.
  1003.      jmp    abort
  1004.     ret
  1005. rdat1a:    mov    bx, offset data    ;[19f] data location
  1006.     mov    ah, cxzflg    ;[19f] get the ^X/^Z flag
  1007.     mov    [bx], ah    ;[19f] stick it in the packet
  1008.     mov    argbk1, 1    ;[19f] data length is 1
  1009.     call    uupack        ;[19f] ACK the packet (without zeroing argbk1)
  1010.      jmp    abort        ;[19f]
  1011.     ret            ;[19f]
  1012.  
  1013. rdat12:    cmp    oldtry, maxtry    ;Have we reached the maximum number of tries?
  1014.     jl    rdat13        ;If not proceed.
  1015.     mov    dx, offset erms10 ;Print this error and die.
  1016.     jmp    fatal
  1017. rdat13:    call    chkpol        ;Check the packet number, is it right?
  1018.      jmp    nak        ;No, NAK it and try again.
  1019.     mov    argbk1, 0    ;No data.
  1020.     call    reack        ;Re-ACK the previous packet.
  1021.      jmp    abort
  1022.     ret
  1023.  
  1024. rdata2:    cmp    ah, 'F'        ;Start of file?
  1025.     jne    rdata3        ; No, try next type.
  1026.     cmp    oldtry, maxtry    ;Have we reached the maximum number of tries?
  1027.     jl    rdat21        ;If not proceed.
  1028.     mov    dx, offset ermes8 ;Print this error and die.
  1029.     jmp    fatal
  1030. rdat21:    call    chkpol        ;Check the packet number, is it right?
  1031.      jmp    nak        ; No, NAK it and try again.
  1032.     mov    argbk1, 0    ;No data.
  1033.     call    reack        ;Re-ACK the previous packet
  1034.      jmp    abort
  1035.     ret
  1036.  
  1037. rdata3:    cmp    ah, 'Z'        ;Is it a EOF packet?
  1038.     je    rdat32
  1039.     jmp    rdata4        ;Try and see if its an error.
  1040. rdat32:    call    chkpeq        ;Packet numbers equal?
  1041.      jmp    nak        ; No, NAK it and try again.
  1042.     call    incpkt        ;Increment the packet number.
  1043.     cmp    cxzflg, 0    ;This file interrupted?    [19f] start
  1044.     jne    rdat3a        ;yes jump
  1045.     cmp    argbk1, 1    ;1 byte of data in EOF packet?
  1046.     jmp    rdat3b        ;no - finish up file
  1047.     mov    bx, offset data    ;pointer to data
  1048.     mov    ah, [bx]    ;get the data
  1049.     cmp    ah, 'D'        ;is it D as in Discard?
  1050.     jne    rdat3b        ;no - finish writing file
  1051. rdat3a:    mov    dx, offset fcb    ;get file's fcb
  1052.     call    delete        ;delete the file.
  1053.     cmp    cxzflg, 'X'    ;Kill one file or batch?
  1054.     jne    rdat37        ;whole batch - leave flag
  1055.     mov    cxzflg, 0    ;clear flag
  1056.     call    intmsg        ;clear message
  1057.     jmp    rdat37        ;go to clean up.        [19f] end
  1058. rdat3b:    mov    bx, bufpnt    ;Get the dma pointer.
  1059.     mov    ax, 80H
  1060.     sub    ax, chrcnt    ;Get the number of chars left in the DMA.
  1061.     cmp    ax, 80H
  1062.     jne    rdat34
  1063.     call    outbuf        ;Write out buffer if no room for ^Z.
  1064.      jmp    abort
  1065.     jmp    rdat36        ;Go close the file.
  1066. rdat34:    mov    cl, 'Z'-100O    ;Put in a ^Z for EOF.
  1067.     mov    [bx], cl
  1068.     inc    ax
  1069.     dec    chrcnt
  1070.     mov    cx, chrcnt
  1071.     mov    temp, cx
  1072.     inc    bx
  1073. rdt3:    inc    ax
  1074.     cmp    ax, 80H
  1075.     jg    rdat35        ;Pad till full.
  1076.     mov    cl, 1AH        ;Use control-Z's        ;[13]
  1077.     mov    [bx], cl
  1078.     inc    bx
  1079.     jmp    rdt3
  1080. rdat35:    call    outbuf        ;Output the last buffer.
  1081.      jmp    abort        ; Give up if the disk is full.
  1082. rdat36:    mov    dx, offset fcb
  1083.     call    closf        ;Close up the file.
  1084. rdat37:    call    upack        ;ACK the packet.
  1085.      jmp    abort
  1086.     mov    state, 'F'
  1087.     ret
  1088.  
  1089. rdata4:    cmp    ah, 'E'        ;Is it an error packet.
  1090.     jne    rdata5
  1091.     call    error
  1092. rdata5:    jmp    abort
  1093.  
  1094.  
  1095. ; Send a file.
  1096.  
  1097. send:    cmp    wldflg,0FFh
  1098.     je    send12
  1099.     mov    dircnt,0    ;If not wild, just use the name in the FCB
  1100.     mov    dindex,0
  1101.     call    getopn        ;Open the file
  1102.     jmps    send19
  1103. send12:    call    getwld        ;If wild, get sorted list of matching names
  1104.      jmp    r        ;  on error, message already printed
  1105.     mov    dindex,0    ;Start at first one
  1106.     call    getfil        ;Get and open first file
  1107.      jmp    r
  1108. send19:    call    init        ;Paint the screen and initialize file buffers.
  1109.     call    cfibf        ;Clear out any stacked NAKs.
  1110.     mov    pktnum, 0    ;Set the packet number to zero.
  1111.     mov    numtry, 0    ;Set the number of tries to zero.
  1112.     mov    numpkt, 0    ;Set the number of packets to zero.
  1113.     mov    numrtr, 0    ;Set the number of retries to zero.
  1114.     call    pretry        ;Print the number of retries.
  1115.     mov    state,'S'    ;Set the state to receive initiate.
  1116. send2:    call    pnmpkt        ;Print the number of packets.
  1117.     cmp    state, 'S'    ;Are we in the send initiate state?
  1118.     jne    send3
  1119.     call    sinit
  1120.     jmp    send2
  1121. send3:    cmp    state, 'F'    ;Are we in the file send state?
  1122.     jne    send4
  1123.     call    sfile        ;Call send file.
  1124.     jmp    send2
  1125. send4:    cmp    state, 'D'    ;Are we in the data send state?
  1126.     jne    send5
  1127.     call    sdata
  1128.     jmp    send2
  1129. send5:    cmp    state, 'Z'    ;Are we in the EOF state?
  1130.     jne    send6
  1131.     call    seof
  1132.     jmp    send2
  1133. send6:    cmp    state, 'B'    ;Are we in the eot state?
  1134.     jne    send7
  1135.     call    seot
  1136.     jmp    send2
  1137. send7:    cmp    state, 'C'    ;Are we in the send complete state?
  1138.     jne    send8
  1139.     mov    dx, offset infms3 ;Plus a little cuteness.
  1140.     cmp    cxzflg, 0    ;[19f] Interrupted?
  1141.     je    send7a        ;[19f] no 
  1142.     mov    dx, offset infms7 ;[19f] substitute "interrupted" message
  1143. send7a:    call    fnstat
  1144.     ret
  1145. send8:    mov    dx, offset infms4 ;Plus a little cuteness.
  1146.     call    fnstat
  1147.     ret
  1148.  
  1149.  
  1150. ;    Send routines
  1151.  
  1152. ;    Send initiate
  1153.  
  1154.  
  1155. sinit:    cmp    numtry, imxtry    ;Have we reached the maximum number of tries?
  1156.     jl    sinit2
  1157.     mov    dx, offset erms14
  1158.     jmp    fatal
  1159. sinit2:    mov    ah, 'Y'        ;Reset our quote capability    ;[29g] begin
  1160.     cmp    parflg, parnon    ;If we have parity,
  1161.     je    sini21        ;  send our quote preference
  1162.     mov    ah, dqbin
  1163. sini21:    mov    ebquot, ah    ;Set our quote capability    ;[29g] end
  1164.     inc    numtry        ;Save the updated number of tries.
  1165.     mov    bx, offset data    ;Get a pointer to our data block.
  1166.     call    rpar        ;Set up the parameter information.
  1167.     xchg    ah, al
  1168.     mov    ah, 0
  1169.     mov    argbk1, ax    ;Save the number of arguments.
  1170.     mov    ax, numpkt    ;Get the packet number.
  1171.     mov    argblk, ax
  1172.     mov    ah, 'S'        ;Send initiate packet.
  1173.     call    spack        ;Send the packet.
  1174.      jmp    abort
  1175.     call    rpack        ;Get a packet.
  1176.      jmp    r        ; Trashed packet don't change state, retry.
  1177.     cmp    ah, 'Y'        ;ACK?
  1178.     jne    sinit3        ;If not try next.
  1179.     call    chkpeq        ;Is it the right packet number?
  1180.      jmp    nretry        ;Increment the retries and go try again.
  1181.     call    incpkt        ;Increment the packet number.
  1182.     mov    ax, argbk1    ;Get the number of pieces of data.
  1183.     mov    bx, offset data    ;Pointer to the data.
  1184.     call    spar        ;Read in the data.
  1185.     mov    ah, numtry    ;Get the number of tries.
  1186.     mov    oldtry, ah    ;Save it.
  1187.     mov    numtry, 0    ;Reset the number of tries.
  1188.     mov    state, 'F'    ;Set the state to file send.
  1189.     ret
  1190.  
  1191. sinit3:    cmp    ah, 'N'        ;NAK?
  1192.     jne    sinit4        ;If not see if its an error.
  1193.     call    nretry
  1194.     ret
  1195.  
  1196. sinit4:    cmp    ah, 'E'        ;Is it an error packet?
  1197.     jne    sinit5
  1198.     call    error
  1199. sinit5:    jmp    abort
  1200.  
  1201.  
  1202. ;    Send file header
  1203.  
  1204. sfile:    cmp    numtry, maxtry    ;Have we reached the maximum number of tries?
  1205.     jl    sfile1
  1206.     mov    dx, offset erms14
  1207.     jmp    fatal
  1208. sfile1:    inc    numtry        ;Increment it.
  1209.     mov    cxzflg, 0    ;[19f] clear ^X/^Z flag
  1210.     push    ds
  1211.     pop    es
  1212.     mov    di, offset data    ;Get a pointer to our data block.
  1213.     mov    si, offset fcb+1 ;Pointer to file name in FCB.
  1214.     mov    cx,11
  1215. sfil11:    cmp    cx,3        ;Separate file type with period
  1216.     jne    sfil12
  1217.     mov    al,'.'
  1218.     stosb
  1219. sfil12:    lodsb
  1220.     and    al,7Fh        ;Strip off attribute bits
  1221.     cmp    al,' '        ;Printable, nonspace characters only
  1222.     jbe    sfil13
  1223.     cmp    al,7Fh
  1224.     jae    sfil13
  1225.     stosb
  1226. sfil13:    loop    sfil11
  1227.     mov    byte ptr [di],'$' ;Terminate filename for printing
  1228.     sub    di, offset data
  1229.     mov    argbk1, di    ;Save number of characters in name
  1230.     call    clrfln
  1231.     mov    dx, offset data    ;Print file name.
  1232.     call    tmsg
  1233.  
  1234.     mov    ax, pktnum    ;Get the packet number.
  1235.     mov    argblk, ax
  1236.     mov    ah, 'F'        ;File header packet.
  1237.     call    spack        ;Send the packet.
  1238.      jmp    abort
  1239.     call    rpack        ;Get a packet.
  1240.      jmp    r        ; Trashed packet don't change state, retry.
  1241.     cmp    ah, 'Y'        ;ACK?
  1242.     jne    sfile2        ;If not try next.
  1243.     call    chkpeq        ;Packet number right.
  1244.      jmp    nretry        ;Increment the retries and go try again.
  1245. sfil14:    call    incpkt        ;Increment the packet number.
  1246.     call    updat        ;Update the number of tries.
  1247.  
  1248. sfil15:    mov    byte ptr fcb+20h,0 ;Set the record number to zero.
  1249.     mov    eoflag, 0    ;Indicate not EOF.
  1250.     mov    filflg, 0FFh    ;Indicate file buffer empty.
  1251.     call    gtchr
  1252.      jmp    sfil16        ;Error go see if its EOF.
  1253.     jmp    sfil18        ;Got the chars, proceed.
  1254. sfil16:    cmp    ah, 0FFH    ;Is it EOF?
  1255.     je    sfil17
  1256.     jmp    abort        ;If not give up.
  1257. sfil17:    mov    state, 'Z'    ;Set the state to EOF.
  1258.     ret
  1259. sfil18:    mov    siz, ax
  1260.     mov    state, 'D'    ;Set the state to data send.
  1261.     ret
  1262.  
  1263. sfile2:    cmp    ah, 'N'        ;NAK?
  1264.     jne    sfile3        ;Try if error packet.
  1265.     call    chkpom        ;Is the packet's number one more than now?
  1266.      jmp    nretry        ;Increment the retries and go try again.
  1267.     jmp    sfil14        ;If so, join the ACK.
  1268.  
  1269. sfile3:    cmp    ah, 'E'        ;Is it an error packet.
  1270.     jne    sfile4
  1271.     call    error
  1272. sfile4:    jmp    abort
  1273.  
  1274.  
  1275. ;    Send data
  1276.  
  1277. sdata:    cmp    cxzflg, 0    ;[19f] Interrupt flag on?
  1278.     je    sdata0        ;[19f] no
  1279.     mov    state, 'Z'    ;[19f] yes - abort sending file
  1280.     ret
  1281. sdata0:    cmp    numtry, maxtry    ;Have we reached the maximum number of tries?
  1282.     jl    sdata1
  1283.     mov    dx, offset erms14
  1284.     jmp    fatal
  1285. sdata1:    inc    numtry        ;Increment it.
  1286.     mov    dx, offset data    ;Get a pointer to our data block.
  1287.     mov    datptr, dx
  1288.     mov    dx, offset filbuf ;Pointer to chars to be sent.
  1289.     mov    cbfptr, dx
  1290.     mov    cx, 1        ;First char.
  1291. sdat11:    mov    bx, cbfptr
  1292.     mov    ah, [bx]
  1293.     inc    cbfptr
  1294.     mov    bx, datptr
  1295.     mov    [bx], ah    ;Put the char in the data packet.
  1296.     inc    datptr        ;Save position in data packet.
  1297.     inc    cx        ;Increment the count.
  1298.     cmp    cx, siz        ;Have we transfered that many?
  1299.     jle    sdat11        ;If not get another.
  1300.     mov    ax, siz        ;Number of char in char buffer.
  1301.     mov    argbk1, ax
  1302.     mov    ax, pktnum    ;Get the packet number.
  1303.     mov    argblk, ax
  1304.     mov    ah, 'D'        ;Data packet.
  1305.     call    spack        ;Send the packet.
  1306.      jmp    abort
  1307.     call    rpack        ;Get a packet.
  1308.      jmp    r        ; Trashed packet don't change state, retry.
  1309.     cmp    ah, 'Y'        ;ACK?
  1310.     jne    sdata2        ;If not try next.
  1311.     call    chkpeq        ;Right packet number?
  1312.      jmp    nretry        ;Increment the retries and go try again.
  1313. sdat12:    call    incpkt        ;Increment the packet number.
  1314.     call    updat        ;Update the number of tries.
  1315.     cmp    argbk1,1    ;1 byte of data there?        [19f] start
  1316.     jne    sdt12b        ;no - go on
  1317.     mov    bx, offset data    ;pointer to data
  1318.     mov    ah, [bx]    ;get the data
  1319.     cmp    ah, 'X'        ;an 'X'?
  1320.     je    sdt12a        ;yes - go
  1321.     cmp    ah, 'Z'        ;or a 'Z'
  1322.     je    sdt12a        ;also go
  1323.     jmp    sdt12b        ;neither one - go on
  1324. sdt12a:    mov    cxzflg, ah    ;'X' or 'Z' - set the interrupt flag [19f] end
  1325.     ret
  1326. sdt12b:    call    gtchr
  1327.      jmp    sdat13        ;Error go see if its EOF.
  1328.     mov    siz, ax        ;Save the size of the data gotten.
  1329.     ret
  1330.  
  1331. sdat13:    cmp    ah, 0FFH    ;Is it EOF?
  1332.     je    sdat14
  1333.     jmp    abort        ;If not give up.
  1334.  
  1335. sdat14:    mov    state, 'Z'    ;Set the state to EOF.
  1336.     ret
  1337. sdata2:    cmp    ah, 'N'        ;NAK?
  1338.     jne    sdata3        ;See if is an error packet.
  1339.     call    chkpom        ;Is the packet's number one more than now?
  1340.      jmp    nretry        ;Increment the retries and go try again.
  1341.     jmp    sdat12
  1342.  
  1343. sdata3:    cmp    ah, 'E'        ;Is it an error packet.
  1344.     jne    sdata4
  1345.     call    error
  1346. sdata4:    jmp    abort
  1347.  
  1348.  
  1349. ;    Send EOF
  1350.  
  1351. seof:    cmp    numtry, maxtry    ;Have we reached the maximum number of tries?
  1352.     jl    seof1
  1353.     mov    dx, offset erms14
  1354.     jmp    fatal
  1355. seof1:    inc    numtry        ;Increment it.
  1356.     mov    ax, pktnum    ;Get the packet number.
  1357.     mov    argblk, ax
  1358.     mov    argbk1, 0    ;No data.
  1359.     cmp    cxzflg, 0    ;[19f] interrupt flag set?
  1360.     je    seof1a        ;[19f] no - go on
  1361.     mov    bx, offset data    ;[19f] point to data
  1362.     mov    ah, 'D'        ;[19f] get 'D' as in Discard
  1363.     mov    [bx], ah    ;[19f] stuff it into packet
  1364.     mov    argbk1, 1    ;[19f] set data length of 1
  1365. seof1a:    mov    ah, 'Z'        ;EOF packet.
  1366.     call    spack        ;Send the packet.
  1367.     jmp    abort
  1368.     call    rpack        ;Get a packet.
  1369.      jmp    r        ; Trashed packet don't change state, retry.
  1370.     cmp    ah, 'Y'        ;ACK?
  1371.     jne    seof2        ;If not try next.
  1372.     call    chkpeq        ;Is it the right packet number?
  1373.      jmp    nretry        ;Increment the retries and go try again.
  1374. seof12:    call    incpkt        ;Increment the packet number.
  1375.     call    updat        ;Update the number of tries.
  1376.     mov    dx, offset fcb    ;Close the file.
  1377.     call    closf
  1378.     call    getfil        ;Get and open the next file.
  1379.      jmp    seof13        ; No more.
  1380.     mov    state, 'F'    ;Set the state to file send.
  1381.     cmp    cxzflg, 'X'    ;[19f] 'X' in interrupt flag?
  1382.     mov    cxzflg, 0    ;[19f] meantime reset it
  1383.     jne    sef13a        ;[19f] no - go on
  1384.     call    intmsg        ;[19f] clear interrupt message
  1385. sef13a:    ret            ;[19f] goodbye
  1386. seof13:    mov    state, 'B'    ;Set the state to EOT.
  1387.     ret
  1388.  
  1389. seof2:    cmp    ah, 'N'        ;NAK?
  1390.     jne    seof3        ;Try and see if its an error packet.
  1391.     call    chkpom        ;Is the packet's number one more than now?
  1392.      jmp    nretry        ;Increment the retries and go try again.
  1393.     jmp    seof12
  1394.  
  1395. seof3:    cmp    ah, 'E'        ;Is it an error packet?
  1396.     jne    seof4
  1397.     call    error
  1398. seof4:    jmp    abort
  1399.  
  1400.  
  1401. ;    Send EOT
  1402.  
  1403. seot:    cmp    numtry, maxtry    ;Have we reached the maximum number of tries?
  1404.     jl    seot1
  1405.     mov    dx, offset erms14
  1406.     jmp    fatal
  1407. seot1:    inc    numtry        ;Increment it.
  1408.     mov    ax, pktnum    ;Get the packet number.
  1409.     mov    argblk, ax
  1410.     mov    argbk1, 0    ;No data.
  1411.     mov    ah, 'B'        ;EOF packet.
  1412.     call    spack        ;Send the packet.
  1413.      jmp    abort
  1414.     call    rpack        ;Get a packet.
  1415.      jmp    r        ;Trashed packet don't change state, retry.
  1416.     cmp    ah, 'Y'        ;ACK?
  1417.     jne    seot2        ;If not try next.
  1418.     call    chkpeq        ;Is it the right packet number.
  1419.      jmp    nretry        ;Increment the retries and go try again.
  1420. seot12:    call    incpkt        ;Increment the packet number.
  1421.     call    updat        ;Update the number of tries.
  1422.     mov    state, 'C'    ;Set the state to file send.
  1423.     ret
  1424.  
  1425. seot2:    cmp    ah, 'N'        ;NAK?
  1426.     jne    seot3        ;Is it error.
  1427.     call    chkpom        ;Is the packet's number one more than now?
  1428.      jmp    nretry        ;Increment the retries and go try again.
  1429.     jmp    seot12
  1430.  
  1431. seot3:    cmp    ah, 'E'        ;Is it an error packet.
  1432.     jne    seot4
  1433.     call    error
  1434. seot4:    jmp    abort
  1435.  
  1436.  
  1437.