home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / MODEMS / MODEM / CP405SRC.ARK / CP4PKT.ASM < prev    next >
Assembly Source File  |  1986-12-25  |  64KB  |  2,210 lines

  1. ; CP4PKT.ASM
  2. ;    KERMIT - (Celtic for "FREE")
  3. ;
  4. ;    This is the CP/M-80 implementation of the Columbia University
  5. ;    KERMIT file transfer protocol.
  6. ;
  7. ;    Version 4.0
  8. ;
  9. ;    Copyright June 1981,1982,1983,1984
  10. ;    Columbia University
  11. ;
  12. ; Originally written by Bill Catchings of the Columbia University Center for
  13. ; Computing Activities, 612 W. 115th St., New York, NY 10025.
  14. ;
  15. ; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben,
  16. ; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many
  17. ; others. 
  18. ;
  19. ;    This file contains the (system-independent) routines that implement
  20. ;    the KERMIT protocol, and the commands that use them:
  21. ;    RECEIVE, SEND, FINISH, and LOGOUT.
  22. ;
  23. ; revision history:
  24. ; edir 6: November 22, 1984
  25. ;    Change SEND's 'Unable to find file' error exit from calling
  26. ;    error3 to calling prtstr instead.  I don't know about you, but
  27. ;    I greatly dislike having messages dumped into pre-existing
  28. ;    junk on the screen where I have to spend lots of time hunting
  29. ;    for them.  [Hal Hostetler]
  30. ;
  31. ; edit 5: September 9, 1984
  32. ;    Call flsmdm in init to flush old input when starting transfers.
  33. ;    Select console before returning from inpkt.
  34. ;    Replace inline code with calls to makfil/clofil to set up for
  35. ;    multisector buffering on output.
  36. ;    Remove superfluous call to clrlin in error3.
  37. ;
  38. ; edit 4: August 21, 1984 (CJC)
  39. ;    Fix comment in inpkt: packet is terminated by NUL on return, not CR.
  40. ;    If debugging, display the outgoing packet before putting the EOL
  41. ;    character on, so the dumped packet doesn't get overwritten.
  42. ;
  43. ; edit 3: July 27, 1984
  44. ;    add link directive for LASM.  CP4PKT is linked by CP4MIT, and links
  45. ;    to CP4TT.  Add Toad Hall TACtrap to permit operations through a TAC.
  46. ;
  47. ; edit 2: June 8, 1984
  48. ;    formatting and documentation; remove some unused labels; move setpar
  49. ;    to cp4mit.m80; add module version string; make all arithmetic on
  50. ;    'pktnum' modulo 64; apply defaults correctly for missing parameters
  51. ;    in send-init packet (and corresponding ack).
  52. ;
  53. ; edit 1: May, 1984
  54. ;    extracted from CPMBASE.M80 version 3.9; modifications are described
  55. ;    in the accompanying .UPD file.
  56. ;
  57. pktver:    db    'CP4PKT.ASM (6)  22-Nov-84$'    ; name, edit number, date
  58.  
  59. ;    RECEIVE command
  60. ;    here from: kermit
  61.  
  62. read:    lxi    d,data        ;Where to put the text (if any.)
  63.     mvi    a,cmtxt
  64.     call    comnd        ;Get either some text or a confirm.
  65.      jmp    kermt3        ; Didn't get anything.
  66.     ora    a        ;Get any chars?
  67.     jz    read1        ;Nope, just a regular send.
  68.     sta    argblk+1    ;Store the number of chars.
  69.     xchg            ;Get pointer into HL.
  70.     mvi    m,'$'        ;Put in a dollar sign for printing.
  71.     call    init        ;Clear the line and initialize the buffers.
  72.     call    scrfln        ;Position cursor
  73.     lxi    d,data        ;Print the file name
  74.     call    prtstr
  75.     mvi    a,'1'        ;Start with single character checksum
  76.     sta    curchk        ;Save the type
  77.     xra    a        ;Start a packet zero.
  78.     sta    argblk
  79.     mvi    a,'R'        ;Receive init packet.
  80.     call    spack        ;Send the packet.
  81.      jmp    kermt3        ; Die!
  82.     jmp    read12
  83.  
  84. read1:    call    init        ;Clear the line and initialize the buffers.
  85. read12:    xra    a
  86.     sta    czseen        ;Clear the ^X/^Z flag initially.
  87.     lxi    h,0
  88.     shld    numpkt        ;Set the number of packets to zero.
  89.     shld    numrtr        ;Set the number of retries to zero.
  90.     sta    pktnum        ;Set the packet number to zero.
  91.     sta    numtry        ;Set the number of tries to zero.
  92.     call    scrnrt        ;Position cursor
  93.     lxi    h,0
  94.     call    nout        ;Write the number of retries.
  95.     mvi    a,'R'
  96.     sta    state        ;Set the state to receive initiate.
  97.     ;...
  98. ;
  99. ;RECEIVE state table switcher.
  100.  
  101. read2:    call    scrnp        ;Position cursor
  102.     lhld    numpkt
  103.     call    nout        ;Write the current packet number.
  104.     lda    state        ;Get the state.
  105.     cpi    'D'        ;Are we in the DATA receive state?
  106.     jnz    read3
  107.     call    rdata
  108.     jmp    read2
  109.  
  110. read3:    cpi    'F'        ;Are we in the FILE receive state?
  111.     jnz    read4
  112.     call    rfile        ;Call receive file.
  113.     jmp    read2
  114.  
  115. read4:    cpi    'R'        ;Are we in the Receive-Initiate state?
  116.     jnz    read5
  117.     call    rinit
  118.     lda    state        ;[jd] get new state
  119.     cpi    'F'        ;[jd] went into receive state?
  120.     jnz    read2        ;[jd] no
  121.     lxi    d,inms24    ;[jd] yes, get receiving... message
  122.     call    finmes        ;[jd] go print it
  123.     jmp    read2
  124.  
  125. read5:    cpi    'C'        ;Are we in the Receive-Complete state?
  126.     jnz    read6
  127.     lxi    d,infms3    ;Put in "Complete" message.
  128.     lda    czseen        ;Or was it interrupted?
  129.     ora    a        ; .  .  .
  130.     jz    read5a        ;No.
  131.     xra    a        ;Yes, clear flag.
  132.     sta    czseen        ; ...
  133.     lxi    d,inms13    ;Issue "interrupted" message.
  134. read5a:    call    finmes        ;Print completion message in right place.
  135.     jmp    kermit
  136.  
  137. read6:    cpi    'A'        ;Are we in the Receive-"Abort" state?
  138.     jnz    read7
  139. read7:    lxi    d,infms4    ;Anything else is equivalent to "abort".
  140.     call    finmes
  141.     jmp    kermit
  142. ;
  143. ;    Receive routines
  144.  
  145. ;    Receive init
  146. ;    called by: read
  147.  
  148. rinit:    lda    numtry        ;Get the number of tries.
  149.     cpi    imxtry        ;Have we reached the maximum number of tries?
  150.     jm    rinit2
  151.     lxi    d,ermes4
  152.     call    error3        ;Move cursor and print an error message.
  153.     jmp    abort        ;Change the state to abort.
  154.  
  155. rinit2:    inr    a        ;Increment it.
  156.     sta    numtry        ;Save the updated number of tries.
  157.     mvi    a,'1'        ;Reset block check type to single character
  158.     sta    curchk        ;Store as current type for initialization
  159.     call    rpack        ;Get a packet.
  160.      jmp    nak        ; Trashed packet: nak, retry.
  161.     cpi    'S'        ;Is it a send initiate packet?
  162.     jnz    rinit3        ;If not see if its an error.
  163.     lda    numtry        ;Get the number of tries.
  164.     sta    oldtry        ;Save it.
  165.     xra    a
  166.     sta    numtry        ;Reset the number of tries.
  167.     lda    argblk        ;Returned packet number.  (Synchronize them.)
  168.     call    countp
  169.     lda    argblk+1    ;Get the number of arguments received.
  170.     lxi    h,data        ;Get a pointer to the data.
  171.     call    spar        ;Get the data into the proper variables.
  172.     lxi    h,data        ;Get a pointer to our data block.
  173.     call    rpar        ;Set up the receive parameters.
  174.     sta    argblk+1    ;Store the returned number of arguments.
  175.     mvi    a,'Y'        ;Acknowledge packet.
  176.     call    spack        ;Send the packet.
  177.      jmp    abort        ; Failed, abort.
  178.     lda    inichk        ;Now switch to agreed upon check-type
  179.     sta    curchk        ;For all future packets
  180.     mvi    a,'F'        ;Set the state to file send.
  181.     sta    state
  182.     ret
  183.  
  184. rinit3:    cpi    'E'        ;Is it an error packet.
  185.     jnz    nak0        ;If not NAK whatever it is.
  186.     call    error
  187.     jmp    abort
  188. ;
  189. ;    Receive file
  190. ;    called by: read
  191.  
  192. rfile:    lda    numtry        ;Get the number of tries.
  193.     cpi    maxtry        ;Have we reached the maximum number of tries?
  194.     jm    rfile1
  195.     lxi    d,ermes5
  196.     call    error3        ;Move cursor and print an error message.
  197.     jmp    abort        ;Change the state to abort.
  198.  
  199. rfile1:    inr    a        ;Increment it.
  200.     sta    numtry        ;Save the updated number of tries.
  201.     call    rpack        ;Get a packet.
  202.      jmp    nak        ; Trashed packet: nak, retry.
  203.     cpi    'S'        ;Is it a send initiate packet?
  204.     jnz    rfile2        ; No, try next type.
  205.     lda    oldtry        ;Get the number of tries.
  206.     cpi    imxtry        ;Have we reached the maximum number of tries?
  207.     jm    rfil12        ;If not proceed.
  208.     lxi    d,ermes4
  209.     call    error3        ;Move cursor and print an error message.
  210.     jmp    abort        ;Change the state to abort.
  211.  
  212. rfil12:    inr    a        ;Increment it.
  213.     sta    oldtry        ;Save the updated number of tries.
  214.     lda    pktnum        ;Get the present packet number.
  215.     dcr    a        ;Decrement
  216.     ani    3FH        ; modulo 64
  217.     mov    b,a
  218.     lda    argblk        ;Get the packet's number
  219.     cmp    b        ;Is the packet's number one less than now?
  220.     jnz    nak0        ;No, NAK and try again.
  221.     call    updrtr        ;Update the retry count.
  222.     xra    a
  223.     sta    numtry        ;Reset the number of tries.
  224.     lxi    h,data        ;Get a pointer to our data block.
  225.     call    rpar        ;Set up the parameter information.
  226.     sta    argblk+1    ;Save the number of arguments.
  227.     mvi    a,'Y'        ;Acknowledge packet.
  228.     call    spack        ;Send the packet.
  229.      jmp    abort        ; Failed, abort.
  230.     ret
  231.  
  232. rfile2:    cpi    'Z'        ;Is it an EOF packet?
  233.     jnz    rfile3        ; No, try next type.
  234.     lda    oldtry        ;Get the number of tries.
  235.     cpi    maxtry        ;Have we reached the maximum number of tries?
  236.     jm    rfil21        ;If not proceed.
  237.     lxi    d,ermes6
  238.     call    error3        ;Move cursor and print an error message.
  239.     jmp    abort        ;Change the state to abort.
  240.  
  241. rfil21:    call    tryagn
  242.     ret
  243.  
  244. rfile3:    cpi    'F'        ;Start of file?
  245.     jnz    rfile4
  246.     call    compp
  247.     jnz    nak0        ;No, NAK it and try again.
  248.     call    countp
  249.     call    gofil        ;Get a file to write to, and init output buffer.
  250.      jmp    abort
  251.     lda    numtry        ;Get the number of tries.
  252.     sta    oldtry        ;Save it.
  253.     call    ackp
  254.     mvi    a,'D'        ;Set the state to data receive.
  255.     sta    state
  256.     lda    czseen        ;Check if we punted a file
  257.     cpi    'Z'        ;and didn't want any more
  258.     rz            ;If that was the request, keep telling other end
  259.     xra    a        ;Otherwise, clear flag (^X is only for one file)
  260.     sta    czseen        ;And store the flag back
  261.     ret
  262.  
  263. rfile4:    cpi    'B'        ;End of transmission.
  264.     jnz    rfile5
  265.     call    compp
  266.     jnz    nak0        ;No, NAK it and try again.
  267.     xra    a        ;No data.  (Packet number already in argblk).
  268.     sta    argblk+1
  269.     mvi    a,'Y'        ;Acknowledge packet.
  270.     call    spack        ;Send the packet.
  271.      jmp    abort
  272.     mvi    a,'C'        ;Set the state to complete.
  273.     sta    state
  274.     ret
  275.  
  276. rfile5:    cpi    'E'        ;Is it an error packet.
  277.     jnz    abort
  278.     call    error
  279.     jmp    abort
  280. ;
  281. ;    Receive data
  282. ;    called by: read
  283.  
  284. rdata:    lda    numtry        ;Get the number of tries.
  285.     cpi    maxtry        ;Have we reached the maximum number of tries?
  286.     jm    rdata1
  287.     lxi    d,erms10
  288.     call    error3        ;Display error message.
  289.     jmp    abort        ;Change the state to abort.
  290.  
  291. rdata1:    inr    a        ;Increment it.
  292.     sta    numtry        ;Save the updated number of tries.
  293.     call    rpack        ;Get a packet.
  294.      jmp    nak        ; Trashed packet: nak, retry.
  295.     cpi    'D'        ;Is it a data packet?
  296.     jnz    rdata2        ; No, try next type.
  297.     call    compp
  298.     jz    rdat14
  299.     lda    oldtry        ;Get the number of tries.
  300.     cpi    maxtry        ;Have we reached the maximum number of tries?
  301.     jm    rdat12        ;If not proceed.
  302.     lxi    d,erms10
  303.     call    error3        ;Display err msg.
  304.     jmp    abort        ;Change the state to abort.
  305.  
  306. rdat12:    call    tryagn
  307.     ret
  308.  
  309. rdat14:    call    countp
  310.     lda    numtry        ;Get the number of tries.
  311.     sta    oldtry        ;Save it.
  312.     lda    argblk+1    ;Get the length of the data.
  313.     call    ptchr
  314.      jmp    abort        ; Unable to write out chars;abort.
  315.     xra    a
  316.     sta    numtry        ;Reset the number of tries.
  317.     sta    argblk+1    ;No data.  (Packet number still in argblk.)
  318.     mov    c,a        ;Assume no data
  319.     lda    czseen        ;Check if control-X typed
  320.     ora    a        ; .  .  .
  321.     jz    rdat15        ;Zero if not typed
  322.     mov    c,a        ;Get the type of character typed
  323.     mvi    a,1        ;One data character
  324.     sta    argblk+1    ;Save the count
  325.     mov    a,c        ;Get the possible data character
  326.     sta    data        ;Store in data area
  327. rdat15:    mvi    a,'Y'        ;Acknowledge packet.
  328.     call    spack        ;Send the packet.
  329.      jmp    abort
  330.     ret
  331.  
  332. rdata2:    cpi    'F'        ;Start of file?
  333.     jnz    rdata3        ; No, try next type.
  334.     lda    oldtry        ;Get the number of tries.
  335.     cpi    maxtry        ;Have we reached the maximum number of tries?
  336.     jm    rdat21        ;If not proceed.
  337.     lxi    d,ermes5
  338.     call    error3        ;Display err msg.
  339.     jmp    abort        ;Change the state to abort.
  340.  
  341. rdat21:    call    tryagn
  342.     ret
  343.  
  344. rdata3:    cpi    'Z'        ;Is it a EOF packet?
  345.     jnz    rdata4        ;Try and see if its an error.
  346.     call    compp
  347.     jnz    nak0        ;No, NAK it and try again.
  348.     call    countp
  349.     lda    argblk+1    ;Get the data length
  350.     cpi    1        ;Have one item?
  351.     jnz    rdat33        ;If not, ignore data
  352.     lda    data        ;Yes, get the character
  353.     cpi    'D'        ;Is it a 'D' for discard?
  354.     jz    rdat36        ;If so, punt file
  355. rdat33:    call    clofil        ;Finish off the file.
  356.      jmp    rdat37        ; Give up if the disk is full.
  357.     xra    a        ;Since we kept the file,
  358.     sta    czseen        ;don't say it was discarded.
  359. rdat36:    lda    numtry        ;Get the number of tries.
  360.     sta    oldtry        ;Save it.
  361.     call    ackp
  362.     mvi    a,'F'
  363.     sta    state
  364.     ret
  365.  
  366. rdat37:    lxi    d,erms11    ; "?Disk full"
  367.     call    error3        ; put it on the error line
  368.     jmp    abort        ; abort transfer
  369.  
  370. rdata4:    cpi    'E'        ;Is it an error packet.
  371.     jnz    abort
  372.     call    error
  373.     jmp    abort
  374. ;
  375. ;    SEND command
  376. ;    here from: kermit
  377.  
  378. send:    mvi    a,cmifi        ;Parse an input file spec.
  379.     lxi    d,fcb        ;Give the address for the FCB.
  380.     call    comnd
  381.      jmp    kermit        ; Give up on bad parse.
  382.     call    cfmcmd
  383.     call    mfname        ;handle (multi) files
  384.     jnc    send14        ;got a valid file-name
  385.     lxi    d,erms15
  386.     call    prtstr        ;Display error msg. ([hh] where it's visible)
  387.     jmp    kermit
  388.  
  389. send14:    call    init        ;Clear the line and initialize the buffers.
  390.     xra    a
  391.     sta    pktnum        ;Set the packet number to zero.
  392.     sta    numtry        ;Set the number of tries to zero.
  393.     sta    wrn8        ;[jd] we haven't sent the 8-bit-lost warning
  394.     lxi    h,0
  395.     shld    numpkt        ;Set the number of packets to zero.
  396.     shld    numrtr        ;Set the number of retries to zero.
  397.     call    scrnrt        ;Position cursor
  398.     lxi    h,0
  399.     call    nout        ;Write the number of retries.
  400.     mvi    a,'1'        ;Reset to use single character checksum
  401.     sta    curchk        ;For startup
  402.     mvi    a,'S'
  403.     sta    state        ;Set the state to receive initiate.
  404.     ;...
  405. ;
  406. ;SEND state table switcher
  407.  
  408. send2:    call    scrnp        ;Position cursor
  409.     lhld    numpkt
  410.     call    nout        ;Write the packet number.
  411.     lda    state        ;Get the state.
  412.     cpi    'D'        ;Are we in the data send state?
  413.     jnz    send3
  414.     call    sdata
  415.     jmp    send2
  416.  
  417. send3:    cpi    'F'        ;Are we in the file send state?
  418.     jnz    send4
  419.     call    sfile        ;Call send file.
  420.     jmp    send2
  421.  
  422. send4:    cpi    'Z'        ;Are we in the EOF state?
  423.     jnz    send5
  424.     call    seof
  425.     jmp    send2
  426.  
  427. send5:    cpi    'S'        ;Are we in the send initiate state?
  428.     jnz    send6
  429.     call    sinit
  430.     lda    state        ;[jd] get state back
  431.     cpi    'F'        ;[jd] into file send state yet?
  432.     jnz    send2        ;[jd] no
  433.     lxi    d,inms23    ;[jd] yes, print sending...
  434.     call    finmes        ;[jd] 
  435.     jmp    send2
  436.  
  437. send6:    cpi    'B'        ;Are we in the eot state?
  438.     jnz    send7
  439.     call    seot
  440.     jmp    send2
  441.  
  442. send7:    cpi    'C'        ;Are we in the send complete state?
  443.     jnz    send8        ;No...
  444.     lxi    d,infms3    ;Yes, write "Complete" message.
  445.     lda    czseen        ;Or was it interrupted?
  446.     ora    a        ; .  .  .
  447.     jz    send7a        ;No.
  448.     lxi    d,inms13    ;Yes, then say "Interrupted" instead.
  449. send7a:    call    finmes
  450.     jmp    kermit
  451.  
  452. send8:    cpi    'A'        ;Are we in the send "abort" state?
  453.     jnz    send9
  454.     lxi    d,infms4    ;Print    message.
  455.     call    finmes
  456.     jmp    kermit
  457.  
  458. send9:    lxi    d,infms4    ;Anything else is equivalent to "abort".
  459.     call    finmes
  460.     jmp    kermit
  461. ;
  462. ;    Send routines
  463.  
  464. ;    Send initiate
  465. ;    called by: send
  466.  
  467. sinit:    lda    numtry        ;Get the number of tries.
  468.     cpi    imxtry        ;Have we reached the maximum number of tries?
  469.     jm    sinit2
  470.     lxi    d,erms14
  471.     call    error3        ;Display ermsg
  472.     jmp    abort        ;Change the state to abort.
  473.  
  474. sinit2:    inr    a        ;Increment it.
  475.     sta    numtry        ;Save the updated number of tries.
  476.     mvi    a,'1'        ;Reset to use single character checksum
  477.     sta    curchk        ;For startup
  478.     lda    chktyp        ;Get our desired block check type
  479.     sta    inichk        ;Store so we tell other end
  480.     lxi    h,data        ;Get a pointer to our data block.
  481.     call    rpar        ;Set up the parameter information.
  482.     sta    argblk+1    ;Save the number of arguments.
  483.     lda    numpkt        ;Get the packet number.
  484.     sta    argblk
  485.     mvi    a,'S'        ;Send initiate packet.
  486.     call    spack        ;Send the packet.
  487.      jmp    abort        ; Failed, abort.
  488.     call    rpack        ;Get a packet.
  489.      jmp    r        ; Trashed packet don't change state, retry.
  490.     cpi    'Y'        ;ACK?
  491.     jnz    sinit3        ;If not try next.
  492.     call    compp
  493.     rnz            ;If not try again.
  494.     call    countp
  495.     lda    argblk+1    ;Get the number of pieces of data.
  496.     lxi    h,data        ;Pointer to the data.
  497.     call    spar        ;Read in the data.
  498.     lda    numtry        ;Get the number of tries.
  499.     sta    oldtry        ;Save it.
  500.     xra    a
  501.     sta    numtry        ;Reset the number of tries.
  502.     lda    inichk        ;Get the agreed upon block check type
  503.     sta    curchk        ;Store as type to use for packets now
  504.     mvi    a,'F'        ;Set the state to file send.
  505.     sta    state
  506.     call    getfil        ;Open the file.
  507.     ret            ; assume success; mfname thinks the file exists.
  508.  
  509. sinit3:    cpi    'N'        ;NAK?
  510.     jnz    sinit4        ;If not see if its an error.
  511.     call    updrtr        ;Update the number of retries.
  512.     lda    pktnum        ;Get the present packet number.
  513.     inr    a        ;Increment
  514.     ani    3FH        ; modulo 64
  515.     mov    b,a
  516.     lda    argblk        ;Get the packet's number.
  517.     cmp    b        ;Is the packet's number one more than now?
  518.     rnz            ;If not assume its for this packet, go again.
  519.     xra    a
  520.     sta    numtry        ;Reset number of tries.
  521.     mvi    a,'F'        ;Set the state to file send.
  522.     sta    state
  523.     ret
  524.  
  525. sinit4:    cpi    'E'        ;Is it an error packet.
  526.     jnz    abort
  527.     call    error
  528.     jmp    abort
  529. ;
  530. ;    Send file header
  531. ;    called by: send
  532.  
  533. sfile:    lda    numtry        ;Get the number of tries.
  534.     cpi    maxtry        ;Have we reached the maximum number of tries?
  535.     jm    sfile1
  536.     lxi    d,erms14
  537.     call    error3
  538.     jmp    abort        ;Change the state to abort.
  539.  
  540. sfile1:    inr    a        ;Increment it.
  541.     sta    numtry        ;Save the updated number of tries.
  542.     xra    a        ;Clear A
  543.     sta    czseen        ;No control-Z or X seen
  544.     lxi    h,data        ;Get a pointer to our data block.
  545.     shld    datptr        ;Save it.
  546.     lxi    h,fcb+1        ;Pointer to the file name in the FCB.
  547.     shld    fcbptr        ;Save position in FCB.
  548.     mvi    b,0        ;No chars yet.
  549.     mvi    c,0
  550. sfil11:    mov    a,b
  551.     cpi    8H        ;Is this the ninth char?
  552.     jnz    sfil12        ;If not proceed.
  553.     mvi    a,'.'        ;Get a dot.
  554.     lhld    datptr
  555.     mov    m,a        ;Put the char in the data packet.
  556.     inx    h
  557.     shld    datptr        ;Save position in data packet.
  558.     inr    c
  559. sfil12:    inr    b        ;Increment the count.
  560.     mov    a,b
  561.     cpi    0CH        ;Twelve?
  562.     jp    sfil13
  563.     lhld    fcbptr
  564.     mov    a,m
  565.     ani    7fH        ;Turn off CP/M 2 or 3's high bits.
  566.     inx    h
  567.     shld    fcbptr        ;Save position in FCB.
  568.     cpi    '!'        ;Is it a good character?
  569.     jm    sfil11        ;If not get the next.
  570.     lhld    datptr
  571.     mov    m,a        ;Put the char in the data packet.
  572.     inx    h
  573.     shld    datptr        ;Save position in data packet.
  574.     inr    c
  575.     jmp    sfil11        ;Get another.
  576.  
  577. sfil13:    mov    a,c        ;Number of char in file name.
  578.     sta    argblk+1
  579.     lhld    datptr
  580.     mvi    a,'$'
  581.     mov    m,a        ;Put in a dollar sign for printing.
  582.     call    scrfln        ;Position cursor
  583.     lxi    d,data        ;Print the file name
  584.     call    prtstr
  585.     lda    pktnum        ;Get the packet number.
  586.     sta    argblk
  587.     mvi    a,'F'        ;File header packet.
  588.     call    spack        ;Send the packet.
  589.      jmp    abort        ; Failed, abort.
  590.     call    rpack        ;Get a packet.
  591.      jmp    r        ; Trashed packet don't change state, retry.
  592.     cpi    'Y'        ;ACK?
  593.     jnz    sfile2        ;If not try next.
  594.     call    compp
  595.     rnz            ;If not hold out for the right one.
  596. sfil14:    call    countp
  597.     lda    numtry        ;Get the number of tries.
  598.     sta    oldtry        ;Save it.
  599.     xra    a
  600.     sta    numtry        ;Reset the number of tries.
  601.     call    gtchr        ;Fill the first data packet
  602.      jmp    sfil16        ;Error go see if its EOF.
  603. ;                ;Got the chars, proceed.
  604.     sta    size        ;Save the size of the data gotten.
  605.     mvi    a,'D'        ;Set the state to data send.
  606.     sta    state
  607.     ret
  608.  
  609. sfil16:    cpi    0FFH        ;Is it EOF?
  610.     jnz    abort        ;If not give up.
  611.     mvi    a,'Z'        ;Set the state to EOF.
  612.     sta    state
  613.     ret
  614.  
  615. sfile2:    cpi    'N'        ;NAK?
  616.     jnz    sfile3        ;Try if error packet.
  617.     call    updrtr        ;Update the number of retries.
  618.     lda    pktnum        ;Get the present packet number.
  619.     inr    a        ;Increment
  620.     ani    3FH        ; modulo 64
  621.     mov    b,a
  622.     lda    argblk        ;Get the packet's number.
  623.     cmp    b        ;Is the packet's number one more than now?
  624.     rnz            ;If not go try again.
  625.     jmp    sfil14        ;Just as good as a ACK;go to the ACK code.
  626.  
  627. sfile3:    cpi    'E'        ;Is it an error packet.
  628.     jnz    abort
  629.     call    error
  630.     jmp    abort
  631. ;
  632. ;    Send data
  633. ;    called by: send
  634.  
  635. sdata:    lda    numtry        ;Get the number of tries.
  636.     cpi    maxtry        ;Have we reached the maximum number of tries?
  637.     jm    sdata1
  638.     lxi    d,erms14
  639.     call    error3
  640.     jmp    abort        ;Change the state to abort.
  641.  
  642. sdata1:    inr    a        ;Increment it.
  643.     sta    numtry        ;Save the updated number of tries.
  644.     lxi    h, data        ;Get a pointer to our data block.
  645.     shld    datptr        ;Save it.
  646.     lxi    h,filbuf    ;Pointer to chars to be sent.
  647.     shld    cbfptr        ;Save position in char buffer.
  648.     mvi    b,1        ;First char.
  649. sdat11:    lhld    cbfptr
  650.     mov    a,m
  651.     inx    h
  652.     shld    cbfptr        ;Save position in char buffer.
  653.     mov    c,a        ;[jd] preserve character temporarily
  654.     lda    quot8        ;[jd] doing eighth-bit quoting?
  655.     ora    a        ;[jd] 
  656.     mov    a,c        ;[jd] restore char
  657.     jnz    sdat4        ;[jd] using eighth-bit quoting, no warning
  658.     lda    parity        ;[jd] get parity
  659.     cpi    parnon        ;[jd] none?
  660.     mov    a,c        ;[jd] restore character
  661.     jz    sdat4        ;[jd] no parity, leave char alone
  662.     lda    wrn8        ;[jd] look at warning flag
  663.     ora    a        ;[jd] have we already given the warning?
  664.     jnz    sdat5        ;[jd] yes, skip this
  665.     mov    a,c        ;[jd] restore character...
  666.     ani    80h        ;[jd] examine parity
  667.     jz    sdat5        ;[jd] no parity, no warning.
  668.     call    parwrn        ;[jd] ...print warning - parity lost
  669.     mvi    a,0ffh        ;[jd] remember that we sent the message
  670.     sta    wrn8        ;[jd]
  671. sdat5:    mov    a,c        ;[jd] restore character again
  672.     ani    7fh        ;[jd] strip parity so not checksummed
  673. sdat4:    lhld    datptr
  674.     mov    m,a        ;Put the char in the data packet.
  675.     inx    h
  676.     shld    datptr        ;Save position in data packet.
  677.     inr    b        ;Increment the count.
  678.     lda    size        ;Get the number of chars in char buffer.
  679.     cmp    b        ;Have we transfered that many?
  680.     jp    sdat11        ;If not get another.
  681.     lda    size        ;Number of char in char buffer.
  682.     sta    argblk+1
  683.     lda    pktnum        ;Get the packet number.
  684.     sta    argblk
  685.     mvi    a,'D'        ;Data packet.
  686.     call    spack        ;Send the packet.
  687.      jmp    abort        ; Failed, abort.
  688.     call    rpack        ;Get a packet.
  689.      jmp    r        ; Trashed packet don't change state, retry.
  690.     cpi    'Y'        ;ACK?
  691.     jnz    sdata2        ;If not try next.
  692.     call    compp
  693.     rnz            ;If not hold out for the right one.
  694.     lda    argblk        ;Get the packet number back
  695.     call    countp
  696.     lda    numtry        ;Get the number of tries.
  697.     sta    oldtry        ;Save it.
  698.     xra    a
  699.     sta    numtry        ;Reset the number of tries.
  700.     lda    argblk+1    ;Get the data length
  701.     cpi    1        ;Check if only 1 character?
  702.     jnz    sdat15        ;If not, just continue
  703.     lda    data        ;Got one character, get it from data
  704.     cpi    'Z'        ;Want to abort entire stream?
  705.     jnz    sdat14        ;If not, check for just this file
  706.     sta    czseen        ;Yes, remember it
  707. sdat14:    cpi    'X'        ;Desire abort of current file?
  708.     jnz    sdat15        ;If not, just continue
  709.     sta    czseen        ;Yes, remember that
  710. sdat15:    lda    czseen        ;Also get control-Z flag
  711.     ora    a        ;Check if either given
  712.     jz    sdat12        ;If neither given, continue
  713.     mvi    a,'Z'        ;Change state to EOF
  714.     sta    state        ; .  .  .
  715.     ret            ;And return
  716.  
  717. sdat12:    call    gtchr
  718.      jmp    sdat13        ;Error go see if its EOF.
  719.     sta    size        ;Save the size of the data gotten.
  720.     ret
  721.  
  722. sdat13:    cpi    0FFH        ;Is it EOF?
  723.     jnz    abort        ;If not give up.
  724.     mvi    a,'Z'        ;Set the state to EOF.
  725.     sta    state
  726.     ret
  727.  
  728. sdata2:    cpi    'N'        ;NAK?
  729.     jnz    sdata3        ;See if is an error packet.
  730.     call    updrtr        ;Update the number of retries.
  731.     lda    pktnum        ;Get the present packet number.
  732.     inr    a        ;Increment
  733.     ani    3FH        ; modulo 64
  734.     mov    b,a
  735.     lda    argblk        ;Get the packet's number.
  736.     cmp    b        ;Is the packet's number one more than now?
  737.     rnz            ;If not go try again.
  738.     jmp    sdat12        ;Just as good as a ACK;go to the ACK code.
  739.  
  740. sdata3:    cpi    'E'        ;Is it an error packet.
  741.     jnz    abort
  742.     call    error
  743.     jmp    abort
  744. ;
  745. ;    Send EOF
  746. ;    called by: send
  747.  
  748. seof:    lda    numtry        ;Get the number of tries.
  749.     cpi    maxtry        ;Have we reached the maximum number of tries?
  750.     jm    seof1
  751.     lxi    d,erms14
  752.     call    error3
  753.     jmp    abort        ;Change the state to abort.
  754.  
  755. seof1:    inr    a        ;Increment it.
  756.     sta    numtry        ;Save the updated number of tries.
  757.     lda    pktnum        ;Get the packet number.
  758.     sta    argblk
  759.     xra    a
  760.     sta    argblk+1    ;No data.
  761.     lda    czseen        ;Check if C-Z or C-X typed
  762.     ora    a        ; .  .  .
  763.     jz    seof14        ;If not aborted, just keep going
  764.     mvi    a,'D'        ;Tell other end to discard packet
  765.     sta    data        ;Store in data portion
  766.     mvi    a,1        ;One character
  767.     sta    argblk+1    ;Store the length
  768. seof14:    mvi    a,'Z'        ;EOF packet.
  769.     call    spack        ;Send the packet.
  770.      jmp    abort        ; Failed, abort.
  771.     call    rpack        ;Get a packet.
  772.      jmp    r        ; Trashed packet don't change state, retry.
  773.     cpi    'Y'        ;ACK?
  774.     jnz    seof2        ;If not try next.
  775.     call    compp
  776.     rnz            ;If not hold out for the right one.
  777. seof12:    call    countp
  778.     lda    numtry        ;Get the number of tries.
  779.     sta    oldtry        ;Save it.
  780.     xra    a
  781.     sta    numtry        ;Reset the number of tries.
  782.     mvi    c,closf        ;Close the file.
  783.     lxi    d,fcb
  784.     call    bdos
  785. ;* Check if successful
  786.     lda    czseen        ;Desire abort of entire stream?
  787.     cpi    'Z'        ;Desire abort of entire stream?
  788.     jz    seof13        ;If so, just give up now
  789.     call    mfname        ;Get the next file.
  790.      jc    seof13        ; No more.
  791.     call    getfil        ;and open it (assume success)
  792.     xra    a        ;Clear A
  793.     sta    czseen        ;Since we have not aborted this file
  794.     mvi    a,'F'        ;Set the state to file send.
  795.     sta    state
  796.     ret
  797.  
  798. seof13:    mvi    a,'B'        ;Set the state to EOT.
  799.     sta    state
  800.     ret
  801.  
  802. seof2:    cpi    'N'        ;NAK?
  803.     jnz    seof3        ;Try and see if its an error packet.
  804.     call    updrtr        ;Update the number of retries.
  805.     lda    pktnum        ;Get the present packet number.
  806.     inr    a        ;Increment
  807.     ani    3FH        ; modulo 64
  808.     mov    b,a
  809.     lda    argblk        ;Get the packet's number.
  810.     cmp    b        ;Is the packet's number one more than now?
  811.     rnz            ;If not go try again.
  812.     jmp    seof12        ;Just as good as a ACK;go to the ACK code.
  813.  
  814. seof3:    cpi    'E'        ;Is it an error packet.
  815.     jnz    abort
  816.     call    error
  817.     jmp    abort
  818. ;
  819. ;    Send EOT
  820. ;    called by: send
  821.  
  822. seot:    lda    numtry        ;Get the number of tries.
  823.     cpi    maxtry        ;Have we reached the maximum number of tries?
  824.     jm    seot1
  825.     lxi    d,erms14
  826.     call    error3
  827.     jmp    abort        ;Change the state to abort.
  828.  
  829. seot1:    inr    a        ;Increment it.
  830.     sta    numtry        ;Save the updated number of tries.
  831.     lda    pktnum        ;Get the packet number.
  832.     sta    argblk
  833.     xra    a
  834.     sta    argblk+1    ;No data.
  835.     mvi    a,'B'        ;EOF packet.
  836.     call    spack        ;Send the packet.
  837.      jmp    abort        ; Failed, abort.
  838.     call    rpack        ;Get a packet.
  839.      jmp    r        ; Trashed packet don't change state, retry.
  840.     cpi    'Y'        ;ACK?
  841.     jnz    seot2        ;If not try next.
  842.     call    compp
  843.     rnz            ;If not hold out for the right one.
  844. seot12:    call    countp
  845.     lda    numtry        ;Get the number of tries.
  846.     sta    oldtry        ;Save it.
  847.     xra    a
  848.     sta    numtry        ;Reset the number of tries.
  849.     mvi    a,'C'        ;Set the state to file send.
  850.     sta    state
  851.     ret
  852.  
  853. seot2:    cpi    'N'        ;NAK?
  854.     jnz    seot3        ;Is it error.
  855.     call    updrtr        ;Update the number of retries.
  856.     lda    pktnum        ;Get the present packet number.
  857.     inr    a        ;Increment
  858.     ani    3FH        ; modulo 64
  859.     mov    b,a
  860.     lda    argblk        ;Get the packet's number.
  861.     cmp    b        ;Is the packet's number one more than now?
  862.     rnz            ;If not go try again.
  863.     jmp    seot12        ;Just as good as a ACK;go to the ACK code.
  864.  
  865. seot3:    cpi    'E'        ;Is it an error packet.
  866.     jnz    abort
  867.     call    error
  868.     jmp    abort
  869. ;
  870. ;    This routine sets up the data for init packet (either the
  871. ;    Send_init or ACK packet).
  872. ;    called by: rinit, rfile, sinit
  873.  
  874. rpar:    lda    rpsiz        ;Get the receive packet size.
  875.     adi    ' '        ;Add a space to make it printable.
  876.     mov    m,a        ;Put it in the packet.
  877.     inx    h        ;Point to the next char.
  878.     lda    rtime        ;Get the receive packet time out.
  879.     adi    ' '        ;Add a space.
  880.     mov    m,a        ;Put it in the packet.
  881.     inx    h
  882.     lda    rpad        ;Get the number of padding chars.
  883.     adi    ' '
  884.     mov    m,a
  885.     inx    h
  886.     lda    rpadch        ;Get the padding char.
  887.     adi    100O        ;Uncontrol it.
  888.     ani    7FH
  889.     mov    m,a
  890.     inx    h
  891.     lda    reol        ;Get the EOL char.
  892.     adi    ' '
  893.     mov    m,a
  894.     inx    h
  895.     lda    rquote        ;Get the quote char.
  896.     mov    m,a
  897.     inx    h
  898.     mvi    m,'Y'        ;[jd] we know how to do 8-bit quoting
  899.     lda    parity        ;[jd]
  900.     cpi    parnon        ;[jd] parity none?
  901.     jz    rpar1        ;[jd] yes, keep going
  902.     lda    qbchr        ;[jd] no, better request 8-bit quoting
  903.     mov    m,a
  904.  
  905. rpar1:
  906.     inx    h        ;Advance to next
  907.     lda    chktyp        ;Get desired block check type
  908.     mov    m,a        ;Store it
  909.     inx    h        ;Advance pointer
  910.     mvi    a,08H        ;Six pieces of data.
  911.     ret
  912. ;
  913. ;    This routine reads in all the send_init packet information.
  914. ;    called by: rinit, sinit
  915.  
  916. spar:    sta    temp4        ;Save the number of arguments.
  917. ; Initialize some variables to their required default values, so we use
  918. ; the right values even if the remote Kermit doesn't send the full packet:
  919. ;                ; we don't do anything with timeout values yet.
  920. ;                ; no default pad count/pad character?
  921.     mvi    a,cr        ; EOL character = carriage-return
  922.     sta    seol
  923.     mvi    a,'#'        ; quote character = '#'
  924.     sta    squote
  925.     mvi    a,'&'        ; eighth-bit quote character = '&'
  926.     sta    qbchr
  927.     mvi    a,'1'        ; block-check = 1-character-checksum
  928.     sta    inichk
  929.     mov    a,m        ;Get the max packet size.
  930.     sbi    ' '        ;Subtract a space.
  931.     sta    spsiz        ;Save it.
  932.     lda    temp4
  933.     cpi    3        ;Fewer than three pieces?
  934.     rm            ;If so we are done.
  935.     inx    h
  936.     inx    h        ;Increment past the time out info.
  937.     mov    a,m        ;Get the number of padding chars.
  938.     sbi    ' '
  939.     sta    spad
  940.     lda    temp4
  941.     cpi    4        ;Fewer than four pieces?
  942.     rm            ;If so we are done.
  943.     inx    h
  944.     mov    a,m        ;Get the padding char.
  945.     adi    100O        ;Re-controlify it.
  946.     ani    7FH
  947.     sta    spadch
  948.     lda    temp4
  949.     cpi    5        ;Fewer than five pieces?
  950.     rm            ;If so we are done.
  951.     inx    h
  952.     mov    a,m        ;Get the EOL char.
  953.     sbi    ' '
  954.     sta    seol
  955.     lda    temp4
  956.     cpi    6        ;Fewer than six pieces?
  957.     rm            ;If so we are done.
  958.     inx    h
  959.     mov    a,m        ;Get the quote char.
  960.     sta    squote
  961.     lda    temp4        ;Get the amount of data supplied
  962.     cpi    7        ;Have an 8-bit quote?
  963.     rm            ;If not there, all done
  964.     inx    h        ;Yes, get the character
  965.     mvi    a,0        ;[jd] 
  966.     sta    quot8        ;[jd] assume not quoting
  967.     mov    a,m        ;Get the supplied character
  968.     cpi    'N'        ;[jd] No?
  969.     jz    spar1        ;[jd] then don't try to do it
  970.     cpi    ' '        ;[jd] maybe they don't know about it...
  971.     jz    spar1        ;[jd] then don't try to do it.
  972.     cpi    'Y'        ;[jd] Yes?
  973.     jnz    spar2        ;[jd] if not 'Y', assume it's a quote char.
  974.     lda    parity        ;[jd] using parity?
  975.     cpi    parnon        ;[jd] no, don't need quoting...
  976.     jz    spar1        ;[jd] 
  977.     mvi    a,0ffh        ;[jd] else turn on...
  978.     sta    quot8        ;[jd] ...quote flag
  979.     jmp    spar1
  980.  
  981. spar2:    sta    qbchr        ;[jd] use their quote char (should validate)
  982.     mvi    a,0ffh
  983.     sta    quot8        ;[jd] turn quote flag and fall thru...
  984.  
  985. spar1:    lda    temp4        ;Determine if block check type given
  986.     cpi    8        ;Is the field there?
  987.     rm            ;If not, all done
  988.     inx    h        ;Point to the character
  989.     mov    a,m        ;Get the value
  990.     mov    b,a        ;Copy value
  991.     lda    chktyp        ;Get our type
  992.     cmp    b        ;Is it our desired type?
  993.     rnz            ; If not, use default (1-character-checksum)
  994.     sta    inichk        ; Match, store as type to use after init
  995.     ret            ; and return
  996. ;
  997.  
  998. ;    Copy characters from packet to disk
  999. ;    called by: rdata
  1000.  
  1001. ptchr:    sta    temp1        ;Save the size.
  1002.     lxi    h,data        ;Beginning of received packet data.
  1003.     shld    outpnt        ;Remember where we are.
  1004.     lda    rquote
  1005.     mov    b,a        ;Keep the quote char in b.
  1006.     mvi    c,0        ;[jd] assume no 8-bit quote char
  1007.     lda    quot8        ;[jd] doing 8-bit quoting?
  1008.     ora    a
  1009.     jz    ptchr1        ;[jd] no, keep going
  1010.     lda    qbchr        ;[jd] else get 8-bit quote char
  1011.     mov    c,a        ;[jd] keep this in c
  1012. ptchr1:    lxi    h,temp1
  1013.     dcr    m        ;Decrement # of chars in packet.
  1014.     jm    rskp        ;Return successfully if done.
  1015.     lxi    h,chrcnt    ;Number of chars remaining in dma.
  1016.     dcr    m        ;Decrement.
  1017.     jp    ptchr2        ;Continue if space left.
  1018.     call    outbuf        ;Output it if full.
  1019.      jmp    ptchr9        ; Error return if disk is full.
  1020. ptchr2:    lhld    outpnt        ;Get position in output buffer.
  1021.     mov    a,m        ;Grab a char.
  1022.     inx    h
  1023.     shld    outpnt        ;and bump pointer.
  1024.     mvi    e,0        ;[jd] assume nothing to OR in.
  1025.     cmp    c        ;[jd] is it the binary quote char?
  1026.     jnz    ptch2a        ;[jd] no, keep going
  1027.     mvi    e,80h        ;[jd] include parity bit
  1028.     lda    temp1
  1029.     dcr    a
  1030.     sta    temp1        ;[jd] decrement character count
  1031.     mov    a,m        ;[jd] get next character
  1032.     inx    h
  1033.     shld    outpnt
  1034. ptch2a:    cmp    b        ;Is it the quote char?
  1035.     jnz    ptchr3        ;[jd] changed to ptchr3 so includes parity
  1036.     mov    a,m        ;Get the quoted character
  1037.     inx    h
  1038.     shld    outpnt        ;and bump pointer.
  1039.     lxi    h,temp1
  1040.     dcr    m        ;Decrement # of chars in packet.
  1041.     mov    d,a        ;Save the char.
  1042.     ani    80H        ;Turn off all but the parity bit.
  1043.     ora    e        ;[jd] let parity come from either (???)
  1044.     mov    e,a        ;Save the parity bit.
  1045.     mov    a,d        ;Get the char.
  1046.     ani    7FH        ;Turn off the parity bit.
  1047.     cmp    b        ;Is it the quote char?
  1048.     jz    ptchr3        ;If so just go write it out.
  1049.     cmp    c        ;[jd] maybe it's the 8-bit prefix character?
  1050.     jz    ptchr3        ;[jd] then don't controllify.
  1051.     mov    a,d        ;Get the char.
  1052.     adi    40H        ;Make the character a control char again.
  1053.     ani    7FH        ;Modulo 128.
  1054. ptchr3:    ora    e        ;Or in the parity bit.
  1055.     lhld    bufpnt        ;Destination buffer.
  1056.     mov    m,a        ;Store it.
  1057.     inx    h
  1058.     shld    bufpnt        ;Update the pointer
  1059.     jmp    ptchr1        ;and loop to next char.
  1060.  
  1061. ptchr9:    lxi    d,erms11    ; "?Disk full"
  1062.     call    error3        ; put it on the error line
  1063.     ret            ; take error return.
  1064. ;
  1065. ;    Fill a data packet from file
  1066. ;    called by: sfile, sdata
  1067.  
  1068. gtchr:    lda    squote        ;Get the quote char.
  1069.     mov    c,a        ;Keep quote char in c.
  1070.     lda    curchk        ;Get current block check type
  1071.     sui    '1'        ;Get the extra overhead
  1072.     mov    b,a        ;Get a copy
  1073.     lda    spsiz        ;Get the maximum packet size.
  1074.     sui    5        ;Subtract the overhead.
  1075.     sub    b        ;Determine max packet length
  1076.     sta    temp1        ;This is the number of chars we are to get.
  1077.     lxi    h,filbuf    ;Where to put the data.
  1078.     shld    cbfptr        ;Remember where we are.
  1079.     mvi    b,0        ;No chars.
  1080. gtchr1:    lda    temp1
  1081.     dcr    a        ;Decrement the number of chars left.
  1082.     jp    gtchr2        ;Go on if there is more than one left.
  1083.     mov    a,b        ;Return the count in A.
  1084.     jmp    rskp
  1085.  
  1086. gtchr2:    sta    temp1
  1087.     lda    chrcnt        ;Space left in the DMA.
  1088.     dcr    a
  1089. ;* Can improve order here.
  1090.     jm    gtchr3
  1091.     sta    chrcnt
  1092.     jmp    gtchr4
  1093.  
  1094. gtchr3:    call    inbuf        ;Get another buffer full.
  1095.      jmp    gtch30        ; If no more return what we got.
  1096.     jmp    gtchr4        ;If we got some, proceed.
  1097.  
  1098. gtch30:    mov    a,b        ;Return the count in A.
  1099.     ora    a        ;Get any chars?
  1100.     jnz    rskp        ;If so return them.
  1101.     jmp    gtceof        ;If not, say we found the end of the file.
  1102.  
  1103. gtchr4:    lhld    bufpnt        ;Position in DMA.
  1104.     mov    a,m        ;Get a char from the file.
  1105.     inx    h
  1106.     shld    bufpnt
  1107.     mov    d,a        ;Save the char.
  1108.     ani    80H        ;Turn off all but parity.
  1109.     mov    e,a        ;Save the parity bit.
  1110.     jz    gtch4a        ;[jd] no parity, skip this check...
  1111.     lda    quot8        ;[jd] doing eighth-bit quoting?
  1112.     ora    a
  1113.     jz    gtch4a        ;[jd] no, just proceed normally
  1114.     lda    temp1        ;[jd] get space remaining
  1115.     cpi    2        ;[jd] 3 chrs left (one cnted already)?
  1116.     jm    gtchr9        ;[jd] no, skip this
  1117.     dcr    a        ;[jd] decrement space remaining
  1118.     sta    temp1        ;[jd] put back.
  1119.     lhld    cbfptr        ;[jd] Position in character buffer.
  1120.     lda    qbchr        ;[jd] get quote character
  1121.     mov    m,a        ;]jd] Put the quote char in the buffer.
  1122.     inx    h        ;[jd] increment destination buffer pointer
  1123.     shld    cbfptr        ;[jd] store the pointer back
  1124.     inr    b        ;[jd] Increment the char count.
  1125.     mvi    e,0        ;[jd] no parity bit to OR in.
  1126. ;[jd] fall thru...
  1127.  
  1128. gtch4a:    mov    a,d        ;Restore the char.
  1129.     ani    7FH        ;Turn off the parity.
  1130.     mov    d,a        ;[jd] save here for later...
  1131.     cpi    ' '        ;Compare to a space.
  1132.     jm    gtchr5        ;If less then its a control char, handle it.
  1133.     cpi    del        ;Is the char a delete?
  1134.     jz    gtchr5        ;Go quote it.
  1135.     lda    quot8        ; Are we doing 8th-bit quoting?
  1136.     ora    a
  1137.     jz    gtch4c        ; if not, skip this test and restore character.
  1138.     lda    qbchr        ; get 8th-bit quote character
  1139.     cmp    d        ; same as current character?
  1140.     jz    gtch4b        ; yes, have to quote it...
  1141. gtch4c:    mov    a,d        ; no. get character back again.
  1142.     cmp    c        ;Is it the quote char?
  1143.     jnz    gtchr8        ;If not proceed.
  1144. gtch4b:    lxi    h,temp1        ;[jd] point to char count
  1145.     dcr    m        ;[jd] decrement (know room for at least one)
  1146.     lhld    cbfptr        ;Position in character buffer.
  1147.     mov    m,c        ;Put the (quote) char in the buffer.
  1148.     inx    h
  1149.     shld    cbfptr
  1150.     inr    b        ;Increment the char count.
  1151.     mov    a,d        ;[jd] restore character again
  1152.     jmp    gtchr8
  1153.  
  1154. gtchr5:    ora    e        ;Turn on the parity bit.
  1155.     cpi    ('Z'-100O)    ;Is it a ^Z?
  1156.     jnz    gtchr7        ;If not just proceed.
  1157.     lda    cpmflg        ;Was the file created by CPM...
  1158.     cpi    1        ;in ASCII-mode ?
  1159.     jz    gtch52        ;Control-Z stops text
  1160.     cpi    2        ;in BINARY mode?
  1161.     jz    gtchr6        ;Yes, pass the ^Z
  1162. ;At this point file-mode is DEFAULT.
  1163. ;If the rest of the record is filled with ^Zs, we're at EOF, otherwise
  1164. ;its a regular character.
  1165.     lhld    bufpnt        ;since CHRCNT is ZERO at EOF-time
  1166.     lda    chrcnt        ;(set by INBUF5 B.G.E)
  1167.     mov    d,a        ;Get the number of chars left in the DMA.
  1168. gtch51:    dcr    d
  1169.     mov    a,d
  1170.     jp    gtch53        ;Any chars left?
  1171. gtch52:    xra    a        ;If not, get a zero.
  1172.     sta    chrcnt        ;Say no more chars in buffer.
  1173.     mov    a,b        ;Return the count in A.
  1174.     jmp    rskp
  1175.  
  1176. ;Scan rest of buffer for non ^Z -- If we find a non ^Z, fall into gtchr6.
  1177. ;If we get to the end of the buffer before finding a non ^Z, fall into gtch52.
  1178. gtch53:    mov    a,m        ;Get the next char.
  1179.     inx    h        ;Move the pointer.
  1180.     cpi    ('Z'-100O)    ;Is it a ^Z?
  1181.     jz    gtch51        ;If so see if the rest are.
  1182.  
  1183. gtchr6:    mvi    a,('Z'-100O)    ;Restore the ^Z.
  1184. gtchr7:    sta    temp2        ;Save the char.
  1185.     lxi    h,temp1        ;Point to the char total remaining.
  1186.     dcr    m        ;Decrement it.
  1187.     lhld    cbfptr        ;Position in character buffer.
  1188.     mov    m,c        ;Put the quote in the buffer.
  1189.     inx    h
  1190.     shld    cbfptr
  1191.     inr    b        ;Increment the char count.
  1192.     lda    temp2        ;Get the control char back.
  1193.     adi    40H        ;Make the non-control.
  1194.     ani    7fH        ;Modulo 200 octal.
  1195. gtchr8:    lhld    cbfptr        ;Position in character buffer.
  1196.     ora    e        ;Or in the parity bit.
  1197.     mov    m,a        ;Put the char in the buffer.
  1198.     inx    h
  1199.     shld    cbfptr
  1200.     inr    b        ;Increment the char count.
  1201.     jmp    gtchr1        ;Go around again.
  1202.  
  1203. gtchr9:    ;[jd] not enough room left in buffer...
  1204.     lhld    bufpnt
  1205.     dcx    h
  1206.     shld    bufpnt        ;[jd] back up over last character
  1207.     lxi    h,chrcnt    ;[jd] point to character count
  1208.     inr    m        ;[jd] increment it
  1209.     mov    a,b        ;[jd] count of chars transferred
  1210.     jmp    rskp        ;[jd] return it
  1211.  
  1212. gtceof:    mvi    a,0FFH        ;Get a minus one.
  1213.     ret
  1214. ;
  1215. ;    Get the file name (including host to micro translation)
  1216. ;    called by: rfile
  1217.  
  1218. gofil:    lxi    h,data        ;Get the address of the file name.
  1219.     shld    datptr        ;Store the address.
  1220.     lxi    h,fcb+1        ;Address of the FCB.
  1221.     shld    fcbptr        ;Save it.
  1222.     xra    a
  1223.     sta    temp1        ;Initialize the char count.
  1224.     sta    temp2
  1225.     sta    fcb        ;Set the drive to default to current.
  1226.     mvi    b,' '
  1227. gofil1:    mov    m,b        ;Blank the FCB.
  1228.     inx    h
  1229.     inr    a
  1230.     cpi    0CH        ;Twelve?
  1231.     jm    gofil1
  1232. gofil2:    lhld    datptr        ;Get the NAME field.
  1233.     mov    a,m
  1234.     cpi    'a'        ;Force upper case
  1235.     jm    gofl2a        ;
  1236.     ani    5FH        ;
  1237. gofl2a:    inx    h
  1238.     cpi    '.'        ;Seperator?
  1239.     jnz    gofil3
  1240.     shld    datptr        ;[jd] update ptr (moved from above)
  1241.     lxi    h,fcb+9H
  1242.     shld    fcbptr
  1243.     lda    temp1
  1244.     sta    temp2
  1245.     mvi    a,9H
  1246.     sta    temp1
  1247.     jmp    gofil6
  1248.  
  1249. gofil3:    ora    a        ;Trailing null?
  1250.     jz    gofil7        ;Then we're done.
  1251.     shld    datptr        ;[jd] no, can update ptr now.
  1252.     lhld    fcbptr
  1253.     mov    m,a
  1254.     inx    h
  1255.     shld    fcbptr
  1256.     lda    temp1        ;Get the char count.
  1257.     inr    a
  1258.     sta    temp1
  1259.     cpi    8H        ;Are we finished with this field?
  1260.     jm    gofil2
  1261. gofil4:    sta    temp2
  1262.     lhld    datptr
  1263.     mov    a,m
  1264.     inx    h
  1265.     shld    datptr
  1266.     ora    a
  1267.     jz    gofil7
  1268.     cpi    '.'        ;Is this the terminator?
  1269.     jnz    gofil4        ;Go until we find it.
  1270. gofil6:    lhld    datptr        ;Get the TYPE field.
  1271.     mov    a,m
  1272.     cpi    'a'        ;Force upper case
  1273.     jm    gofl6a        ;
  1274.     ani    5FH        ;
  1275. gofl6a:    ora    a        ;Trailing null?
  1276.     jz    gofil7        ;Then we're done.
  1277. ;[jd] move above two lines so we don't increment pointer if char is null
  1278.     inx    h
  1279.     shld    datptr
  1280.     lhld    fcbptr
  1281.     mov    m,a
  1282.     inx    h
  1283.     shld    fcbptr
  1284.     lda    temp1        ;Get the char count.
  1285.     inr    a
  1286.     sta    temp1
  1287.     cpi    0CH        ;Are we finished with this field?
  1288.     jm    gofil6
  1289. gofil7:    lhld    datptr
  1290.     mvi    m,'$'        ;Put in a dollar sign for printing.
  1291.     call    scrfln        ;Position cursor
  1292.     lxi    d,data        ;Print the file name
  1293.     call    prtstr
  1294.     lda    flwflg        ;Is file warning on?
  1295.     ora    a
  1296.     jz    gofil9        ;If not, just proceed.
  1297.     mvi    c,openf        ;See if the file exists.
  1298.     lxi    d,fcb
  1299.     call    bdos
  1300.     cpi    0FFH        ;Does it exist?
  1301.     jz    gofil9        ;If not create it.
  1302.     lxi    d,infms5
  1303.     call    error3
  1304.     lda    temp2        ;Get the number of chars in the file name.
  1305.     ora    a
  1306.     jnz    gofil8
  1307.     lda    temp1
  1308.     sta    temp2
  1309. gofil8:    mvi    b,0
  1310.     mov    d,b        ;Zero d for dad index into filename
  1311.     inr    a        ;Replace next character after filename
  1312.     cpi    9H        ;Is the first field full?
  1313.     jnz    gofl80
  1314.     mvi    b,0FFH        ;Set a flag saying so.
  1315.     dcr    a
  1316. gofl80:    mov    e,a        ;Keep current, replace index in d,e.
  1317. gofl81:    lxi    h,fcb        ;Get the FCB.
  1318.     dad    d        ;Add in the character number.
  1319.     mvi    m,'&'        ;Replace the char with an ampersand.
  1320.     push    b
  1321.     push    d
  1322.     lxi    h,fcb        ;Trim off any CP/M 2.2 attribute bits
  1323.     mvi    c,1+8+3        ;so they do not affect the new file
  1324. gofl82:    mov    a,m        ;
  1325.     ani    7FH        ;
  1326.     mov    m,a        ;
  1327.     inx    h        ;
  1328.     dcr    c        ;
  1329.     jnz    gofl82        ;
  1330.     mvi    c,openf        ;See if the file exists.
  1331.     lxi    d,fcb
  1332.     call    bdos
  1333.     pop    d
  1334.     pop    b
  1335.     cpi    0FFH        ;Does it exist?
  1336.     jz    gofl89        ;If not create it.
  1337.     mov    a,b        ;Get the field-full flag.
  1338.     ora    a        ;Incr. or decr. ?
  1339.     jz    gofl83        ;Jump if increment
  1340.     dcr    e        ;Decrement the number of chars.
  1341.     mov    a,e
  1342.     ora    a
  1343.     jz    gofl88        ;If no more, die.
  1344.     jmp    gofl81
  1345.  
  1346. gofl83:    inr    e        ;Increment the number of chars.
  1347.     mov    a,e
  1348.     cpi    9H        ;Are we to the end?
  1349.     jm    gofl81        ;If not try again.
  1350.     lda    temp2        ;Get the original size.
  1351.     mov    e,a
  1352.     mvi    b,0FFH        ;Set flag saying field-full, decrement
  1353.     jmp    gofl81
  1354.  
  1355. gofl88:    lxi    d,erms16    ;Tell user that we can't rename it.
  1356.     call    prtstr
  1357.     ret
  1358.  
  1359. gofl89: mvi    c,8        ;[jd] # of chars in name
  1360.     lxi    d,fnbuf        ;[jd] point to destination
  1361.     lxi    h,fcb+1        ;[jd] source of name
  1362.     mvi    b,0        ;[jd] first-time-thru flag
  1363. gof89a:    mov    a,m        ;[jd] get a char from the name
  1364.     inx    h        ;[jd] pass it
  1365.     cpi    ' '        ;[jd] end of this part of name?
  1366.     jz    gof89b        ;[jd] yes, skip rest...
  1367.     stax    d        ;[jd] else drop char off
  1368.     inx    d        ;[jd] increment dest ptr
  1369.     dcr    c        ;[jd] decrement count
  1370.     jnz    gof89a        ;[jd] and continue if more to go
  1371. gof89b:    mov    a,b        ;[jd]
  1372.     ora    a        ;[jd] first time thru?
  1373.     jnz    gof89c        ;[jd] no, no period
  1374.     mvi    a,'.'        ;[jd] period between parts
  1375.     stax    d        ;[jd] 
  1376.     inx    d        ;[jd] 
  1377.     mvi    b,0ffh        ;[jd] not first time thru anymore
  1378.     mvi    c,3        ;[jd] length of this part
  1379.     lxi    h,fcb+9        ;[jd] start of extension
  1380.     jmp    gof89a        ;[jd] keep copying
  1381.  
  1382. gof89c:    mvi    a,'$'
  1383.     stax    d        ;[jd] end the name string
  1384.     lxi    d,fnbuf        ;[jd] Print the file name
  1385.     call    prtstr
  1386. gofil9: call    makfil        ; Create the file.
  1387.      jmp    gofl91        ; Disk was full.
  1388.     jmp    rskp        ; Success.
  1389.     
  1390. gofl91:    lxi    d,erms11
  1391.     call    error3
  1392.     ret
  1393. ;
  1394. ;    This is the FINISH command.  It tells the remote KERSRV to exit.
  1395. ;    here from kermit
  1396.  
  1397. finish:    call    cfmcmd
  1398.     xra    a
  1399.     sta    numtry        ;Inititialize count.
  1400.     mvi    a,'1'        ;Reset block check type to single character
  1401.     sta    curchk        ; .  .  .
  1402.  
  1403. finsh1:    lda    numtry        ;How many times have we tried?
  1404.     cpi    maxtry        ;Too many times?
  1405.     jm    finsh3        ;No, try it.
  1406. finsh2:    lxi    d,erms18    ;Say we couldn't do it.
  1407.     call    prtstr
  1408.     jmp    kermit        ;Go home.
  1409.  
  1410. finsh3:    inr    a        ;Increment the number of tries.
  1411.     sta    numtry
  1412.     xra    a
  1413.     sta    argblk        ;Make it packet number zero.
  1414.     mvi    a,1
  1415.     sta    argblk+1    ;One piece of data.
  1416.     lxi    h,data
  1417.     mvi    m,'F'        ;Finish running Kermit.
  1418.     mvi    a,'G'        ;Generic command packet.
  1419.     call    spack
  1420.      jmp    finsh2        ; Tell the user and die.
  1421.     call    rpack        ;Get an acknowledgement.
  1422.      jmp    finsh1        ; Go try again.
  1423.     cpi    'Y'        ;ACK?
  1424.     jz    kermit        ;Yes, we are done.
  1425.     cpi    'E'        ;Is it an error packet?
  1426.     jnz    finsh1        ;Try sending the packet again.
  1427.     call    error1        ;Print the error message.
  1428.     jmp    kermit
  1429. ;
  1430. ;    This is the LOGOUT command.  It tells the remote KERSRV to logout.
  1431. ;    here from: kermit
  1432.  
  1433. logout:    call    cfmcmd
  1434.     call    logo        ;Send the logout packet.
  1435.      jmp    kermit        ;Go get another command
  1436.     jmp    kermit        ; whether we succeed or not.
  1437.  
  1438. ;    do logout processing.
  1439. ;    called by: bye, logout
  1440.  
  1441. logo:    xra    a
  1442.     sta    numtry        ;Inititialize count.
  1443.     mvi    a,'1'        ;Reset block check type to single character
  1444.     sta    curchk        ; .  .  .
  1445.  
  1446. logo1:    lda    numtry        ;How many times have we tried?
  1447.     cpi    maxtry        ;Too many times?
  1448.     jm    logo3        ;No, try it.
  1449. logo2:    lxi    d,erms19    ;Say we couldn't do it.
  1450.     call    prtstr
  1451.     ret            ;Finished.
  1452.  
  1453. logo3:    inr    a        ;Increment the number of tries.
  1454.     sta    numtry
  1455.     xra    a
  1456.     sta    argblk        ;Make it packet number zero.
  1457.     mvi    a,1
  1458.     sta    argblk+1    ;One piece of data.
  1459.     lxi    h,data
  1460.     mvi    m,'L'        ;Logout the remote host.
  1461.     mvi    a,'G'        ;Generic command packet.
  1462.     call    spack
  1463.      jmp    logo2        ; Tell the user and die.
  1464.     call    rpack        ;Get an acknowledgement
  1465.      jmp    logo1        ; Go try again.
  1466.     cpi    'Y'        ;ACK?
  1467.     jz    rskp        ;Yes, we are done.
  1468.     cpi    'E'        ;Is it an error packet?
  1469.     jnz    logo1        ;Try sending the packet again.
  1470.     call    error1        ;Print the error message.
  1471.     ret            ;All done.
  1472. ;
  1473. ;    Packet routines
  1474.  
  1475. ;    Send_Packet
  1476. ;    This routine assembles a packet from the arguments given and sends it
  1477. ;    to the host.
  1478. ;
  1479. ;    Expects the following:
  1480. ;        A     - Type of packet (D,Y,N,S,R,E,F,Z,T)
  1481. ;        ARGBLK     - Packet sequence number
  1482. ;        ARGBLK+1 - Number of data characters
  1483. ;    Returns: nonskip if failure
  1484. ;         skip if success
  1485. ;    called by: read, rinit, rfile, rdata, sinit, sfile, sdata, seof, seot,
  1486. ;           finish, logout, nak, ackp
  1487.  
  1488. spack:    sta    argblk+2
  1489.     lxi    h,packet    ;Get address of the send packet.
  1490.     mvi    a,soh        ;Get the start of header char.
  1491.     mov    m,a        ;Put in the packet.
  1492.     inx    h        ;Point to next char.
  1493.     lda    curchk        ;Get current checksum type
  1494.     sui    '1'        ;Determine extra length of checksum
  1495.     mov    b,a        ;Copy length
  1496.     lda    argblk+1    ;Get the number of data chars.
  1497.     adi    ' '+3        ;Real packet character count made printable.
  1498.     add    b        ;Determine overall length
  1499.     mov    m,a        ;Put in the packet.
  1500.     inx    h        ;Point to next char.
  1501.     lxi    b,0        ;Zero the checksum AC.
  1502.     mov    c,a        ;Start the checksum.
  1503.     lda    argblk        ;Get the packet number.
  1504.     adi    ' '        ;Add a space so the number is printable.
  1505.     mov    m,a        ;Put in the packet.
  1506.     inx    h        ;Point to next char.
  1507.     add    c
  1508.     mov    c,a        ;Add the packet number to the checksum.
  1509.     mvi    a,0        ;Clear A (Cannot be XRA A, since we can't
  1510.                 ; touch carry flag)
  1511.     adc    b        ;Get high order portion of checksum
  1512.     mov    b,a        ;Copy back to B
  1513.     lda    argblk+2    ;Get the packet type.
  1514.     mov    m,a        ;Put in the packet.
  1515.     inx    h        ;Point to next char.
  1516.     add    c
  1517.     mov    c,a        ;Add the packet number to the checksum.
  1518.     mvi    a,0        ;Clear A
  1519.     adc    b        ;Get high order portion of checksum
  1520.     mov    b,a        ;Copy back to B
  1521. spack2:    lda    argblk+1    ;Get the packet size.
  1522.     ora    a        ;Are there any chars of data?
  1523.     jz    spack3        ; No, finish up.
  1524.     dcr    a        ;Decrement the char count.
  1525.     sta    argblk+1    ;Put it back.
  1526.     mov    a,m        ;Get the next char.
  1527.     inx    h        ;Point to next char.
  1528.     add    c
  1529.     mov    c,a        ;Add the packet number to the checksum.
  1530.     mvi    a,0        ;Clear A
  1531.     adc    b        ;Get high order portion of checksum
  1532.     mov    b,a        ;Copy back to B
  1533.     jmp    spack2        ;Go try again.
  1534.  
  1535. spack3:    lda    curchk        ;Get the current checksum type
  1536.     cpi    '2'        ;Two character?
  1537.     jz    spack4        ;Yes, go handle it
  1538.     jnc    spack5        ;No, go handle CRC if '3'
  1539.     mov    a,c        ;Get the character total.
  1540.     ani    0C0H        ;Turn off all but the two high order bits.
  1541.                 ;Shift them into the low order position.
  1542.     rlc            ;Two left rotates same as 6 rights
  1543.     rlc            ; .  .  .
  1544.     add    c        ;Add it to the old bits.
  1545.     ani    3FH        ;Turn off the two high order bits.  (MOD 64)
  1546.     adi    ' '        ;Add a space so the number is printable.
  1547.     mov    m,a        ;Put in the packet.
  1548.     inx    h        ;Point to next char.
  1549.     jmp    spack7        ;Go store eol character
  1550.  
  1551. ;Here for 3 character CRC-CCITT
  1552.  
  1553. spack5:    mvi    m,0        ;Store a null for current end
  1554.     push    h        ;Save H
  1555.     lxi    h,packet+1    ;Point to first checksumed character
  1556.     call    crcclc        ;Calculate the CRC
  1557.     pop    h        ;Restore the pointer
  1558.     mov    c,e        ;Get low order half for later
  1559.     mov    b,d        ;Copy the high order
  1560.     mov    a,d        ;Get the high order portion
  1561.     rlc            ;Shift off low 4 bits
  1562.     rlc            ; .  .  .
  1563.     rlc            ; .  .  .
  1564.     rlc            ; .  .  .
  1565.     ani    0FH        ;Keep only low 4 bits
  1566.     adi    ' '        ;Put into printing range
  1567.     mov    m,a        ;Store the character
  1568.     inx    h        ;Point to next position
  1569.  
  1570. ;Here for two character checksum
  1571.  
  1572. spack4:    mov    a,b        ;Get high order portion
  1573.     ani    0FH        ;Only keep last four bits
  1574.     rlc            ;Shift up two bits
  1575.     rlc            ; . .  .
  1576.     mov    b,a        ;Copy back into safe place
  1577.     mov    a,c        ;Get low order half
  1578.     rlc            ;Shift    high two bits
  1579.     rlc            ;to low two bits
  1580.     ani    03H        ;Keep only two low bits
  1581.     ora    b        ;Get high order portion in
  1582.     adi    ' '        ;Convert to printing character range
  1583.     mov    m,a        ;Store the character
  1584.     inx    h        ;Point to next character
  1585.     mov    a,c        ;get low order portion
  1586.     ani    3FH        ;Keep only six bits
  1587.     adi    ' '        ;Convert to printing range
  1588.     mov    m,a        ;Store it
  1589.     inx    h        ;Bump the pointer
  1590.  
  1591. spack7:    lda    dbgflg
  1592.     ora    a        ; is debugging enabled?
  1593.     jz    spack8
  1594.     push    h        ; yes. save address of end of packet
  1595.     mvi    m,0        ; null-terminate the packet for display
  1596.     call    sppos        ; position cursor
  1597.     lxi    h,packet+1    ; print the packet
  1598.     call    dmptxt
  1599.     pop    h        ; restore address of end of packet
  1600. spack8:    lda    seol        ;Get the EOL the other host wants.
  1601.     mov    m,a        ;Put in the packet.
  1602.     inx    h        ;Point to next char.
  1603.     xra    a        ;Get a null.
  1604.     mov    m,a        ;Put in the packet.
  1605. ;    Write out the packet.
  1606. outpkt:    call    selmdm        ; Set up for output to comm port if iobyt
  1607.     lda    spad        ;Get the number of padding chars.
  1608.     sta    temp1
  1609. outpk2:    lda    temp1        ;Get the count.
  1610.     dcr    a
  1611.     ora    a
  1612.     jm    outpk6        ;If none left proceed.
  1613.     sta    temp1
  1614.     lda    spadch        ;Get the padding char.
  1615.     call    setpar        ;Set parity appropriately
  1616.     mov    e,a        ;Put the char in right AC.
  1617.     call    outmdm        ;Output it.
  1618.     jmp    outpk2
  1619.  
  1620. outpk6:    lxi    h,packet    ; Point to the packet.
  1621. outlup:    mov    a,m        ; Get the next character.
  1622.     ora    a        ; Is it a null?
  1623.     jz    outlud        ; If so return success.
  1624.     call    setpar        ; Set parity for the character
  1625.     mov    e,a        ; Put it in right AC
  1626.     call    outmdm        ; and output it.
  1627. ; TAC trap: If this character is the TAC intercept character, and the TAC
  1628. ; trap is enabled, we have to output it twice.  If the TAC trap is enabled,
  1629. ; tacflg contains the intercept character.  (The current character cannot
  1630. ; be NUL, so we don't have to worry about doubling nulls in the message)
  1631.     lda    tacflg        ; get current intercept character, or zero.
  1632.     cmp    m        ; compare against current data character.
  1633.     jnz    outpk8        ; if different, do nothing.
  1634.     call    setpar        ; match. set appropriate parity,
  1635.     mov    e,a        ;  put it in the right register,
  1636.     call    outmdm        ;  and output it a second time.
  1637. outpk8:
  1638.     inx    h        ; Increment the char pointer.
  1639.     jmp    outlup
  1640.  
  1641. outlud:    call    selcon        ; select console
  1642.     jmp    rskp        ; and return success
  1643. ;
  1644. ;    Receive_Packet
  1645. ;    This routine waits for a packet to arrive from the host.  It reads
  1646. ;    characters until it finds a SOH.  It then reads the packet into packet.
  1647. ;
  1648. ;    Returns:  nonskip if failure (checksum wrong or packet trashed)
  1649. ;       skip if success, with
  1650. ;        A     - message type
  1651. ;        ARGBLK     - message number
  1652. ;        ARGBLK+1 - length of data
  1653. ;    called by: rinit, rfile, rdata,
  1654. ;           sinit, sfile, sdata, seof, seot, finish, logout
  1655.  
  1656. rpack:    call    inpkt        ;Read up to the end-of-line character
  1657.      jmp    r        ; Return bad.
  1658. rpack0:    call    getchr        ;Get a character.
  1659.      jmp    rpack        ; Hit eol;null line;just start over.
  1660.     cpi    soh        ;Is the char the start of header char?
  1661.     jnz    rpack0        ; No, go until it is.
  1662. rpack1:    call    getchr        ;Get a character.
  1663.      jmp    r        ; Hit end of line, return bad.
  1664.     cpi    soh        ;Is the char the start of header char?
  1665.     jz    rpack1        ; Yes, then go start over.
  1666.     sta    packet+1    ;Store in packet also
  1667.     mov    c,a        ;Start the checksum.
  1668.     lda    curchk        ;Get block check type
  1669.     sui    '1'        ;Determine extra length of block check
  1670.     mov    b,a        ;Get a copy
  1671.     mov    a,c        ;Get back length character
  1672.     sui    ' '+3        ;Get the real data count.
  1673.     sub    b        ;Get total length
  1674.     sta    argblk+1
  1675.     mvi    b,0        ;Clear high order half of checksum
  1676.     call    getchr        ;Get a character.
  1677.      jmp    r        ; Hit end of line, return bad.
  1678.     cpi    soh        ;Is the char the start of header char?
  1679.     jz    rpack1        ; Yes, then go start over.
  1680.     sta    argblk
  1681.     sta    packet+2    ;Save also in packet
  1682.     add    c
  1683.     mov    c,a        ;Add the character to the checksum.
  1684.     mvi    a,0        ;Clear A
  1685.     adc    b        ;Get high order portion of checksum
  1686.     mov    b,a        ;Copy back to B
  1687.     lda    argblk
  1688.     sui    ' '        ;Get the real packet number.
  1689.     sta    argblk
  1690.     call    getchr        ;Get a character.
  1691.      jmp    r        ; Hit end of line, return bad.
  1692.     cpi    soh        ;Is the char the start of header char?
  1693.     jz    rpack1        ; Yes, then go start over.
  1694.     sta    temp1        ;Save the message type.
  1695.     sta    packet+3    ;Save in packet
  1696.     add    c
  1697.     mov    c,a        ;Add the character to the checksum.
  1698.     mvi    a,0        ;Clear A
  1699.     adc    b        ;Get high order portion of checksum
  1700.     mov    b,a        ;Copy back to B
  1701.     lda    argblk+1    ;Get the number of data characters.
  1702.     sta    temp2
  1703.     lxi    h,data        ;Point to the data buffer.
  1704.     shld    datptr
  1705. rpack2:    lda    temp2
  1706.     sui    1        ;Any data characters?
  1707.     jm    rpack3        ; If not go get the checksum.
  1708.     sta    temp2
  1709.     call    getchr        ;Get a character.
  1710.      jmp    r        ; Hit end of line, return bad.
  1711.     cpi    soh        ;Is the char the start of header char?
  1712.     jz    rpack1        ; Yes, then go start over.
  1713.     lhld    datptr
  1714.     mov    m,a        ;Put the char into the packet.
  1715.     inx    h        ;Point to the next character.
  1716.     shld    datptr
  1717.     add    c
  1718.     mov    c,a        ;Add the character to the checksum.
  1719.     mvi    a,0        ;Clear A
  1720.     adc    b        ;Get high order portion of checksum
  1721.     mov    b,a        ;Copy back to B
  1722.     jmp    rpack2        ;Go get another.
  1723.  
  1724. rpack3:    call    getchr        ;Get a character.
  1725.      jmp    r        ; Hit end of line, return bad.
  1726.     cpi    soh        ;Is the char the start of header char?
  1727.     jz    rpack1        ; Yes, then go start over.
  1728.     sui    ' '        ;Turn the char back into a number.
  1729.     sta    temp3
  1730. ;Determine type of checksum
  1731.  
  1732.     lda    curchk        ;Get the current checksum type
  1733.     cpi    '2'        ;1, 2 or 3 character?
  1734.     jz    rpack4        ;If zero, 2 character
  1735.     jnc    rpack5        ;Go handle 3 character
  1736.     mov    a,c        ;Get the character total.
  1737.     ani    0C0H        ;Turn off all but the two high order bits.
  1738.                 ;Shift them into the low order position.
  1739.     rlc            ;Two left rotates same as six rights
  1740.     rlc            ; .  .  .
  1741.     add    c        ;Add it to the old bits.
  1742.     ani    3FH        ;Turn off the two high order bits.  (MOD 64)
  1743.     mov    b,a
  1744.     lda    temp3        ;Get the real received checksum.
  1745.     cmp    b        ;Are they equal?
  1746.     jz    rpack7        ;If so, proceed.
  1747. rpack9:    call    updrtr        ;If not, update the number of retries.
  1748.     ret            ;Return error.
  1749.  
  1750. ;Here for three character CRC-CCITT
  1751.  
  1752. rpack5:    lhld    datptr        ;Get the address of the data
  1753.     mvi    m,0        ;Store a zero in the buffer to terminate packet
  1754.     lxi    h,packet+1    ;Point at start of checksummed region
  1755.     call    crcclc        ;Calculate the CRC
  1756.     mov    c,e        ;Save low order half for later
  1757.     mov    b,d        ;Also copy high order
  1758.     mov    a,d        ;Get high byte
  1759.     rlc            ;Want high four bits
  1760.     rlc            ; .  .  .
  1761.     rlc            ;And shift two more
  1762.     rlc            ; .  .  .
  1763.     ani    0FH        ;Keep only 4 bits
  1764.     mov    d,a        ;Back into D
  1765.     lda    temp3        ;Get first value back
  1766.     cmp    d        ;Correct?
  1767.     jnz    rpack9        ;No, punt
  1768.     call    getchr        ;Get a character.
  1769.      jmp    r        ; Hit end of line, return bad.
  1770.     cpi    soh        ;Is the char the start of header char?
  1771.     jz    rpack1        ; Yes, then go start over.
  1772.     sui    ' '        ;Remove space offset
  1773.     sta    temp3        ;Store for later check
  1774.     ;...
  1775.  
  1776. ;Here for a two character checksum and last two characters of CRC
  1777.  
  1778. rpack4:    mov    a,b        ;Get high order portion
  1779.     ani    0FH        ;Only four bits
  1780.     rlc            ;Shift up two bits
  1781.     rlc            ; .  .  .
  1782.     mov    b,a        ;Save back in B
  1783.     mov    a,c        ;Get low order
  1784.     rlc            ;move two high bits to low bits
  1785.     rlc            ; .  .  .
  1786.     ani    03H        ;Save only low two bits
  1787.     ora    b        ;Get other 4 bits
  1788.     mov    b,a        ;Save back in B
  1789.     lda    temp3        ;Get this portion of checksum
  1790.     cmp    b        ;Check first half
  1791.     jnz    rpack9        ;If bad, go give up
  1792.     call    getchr        ;Get a character.
  1793.      jmp    r        ; Hit end of line, return bad.
  1794.     cpi    soh        ;Is the char the start of header char?
  1795.     jz    rpack1        ; Yes, then go start over.
  1796.     sui    ' '        ;Remove space offset
  1797.     mov    b,a        ;Save in safe place
  1798.     mov    a,c        ;Get low 8 bits of checksum
  1799.     ani    3FH        ;Keep only 6 bits
  1800.     cmp    b        ;Correct value
  1801.     jnz    rpack9        ;Bad, give up
  1802. rpack7:    lhld    datptr
  1803.     mvi    m,0        ;Put a null at the end of the data.
  1804.     lda    temp1        ;Get the type.
  1805.     jmp    rskp
  1806. ;
  1807. ;    inpkt - receive and buffer packet
  1808. ;    returns: nonskip if error (timeout)
  1809. ;        skip if success; packet starts at recpkt (which holds the SOH)
  1810. ;          and is terminated by a null.
  1811. ;        console is selected in either case.
  1812. ;    called by: rpack
  1813.  
  1814. inpkt:    lxi    h,recpkt    ;Point to the beginning of the packet.
  1815.     shld    pktptr
  1816. inpkt1:    call    inchr        ;Get first character
  1817.     jmp    r        ;Return failure
  1818.     cpi    soh        ;is it the beginning of a packet?
  1819.     jnz    inpkt1        ;if not, ignore leading junk
  1820.     jmp    inpkt3        ;else go put it in packet
  1821.  
  1822. inpkt2:    call    inchr        ;Get a character.
  1823.      jmp    r        ; Return failure.
  1824.     cpi    soh        ;is it a new beginning of packet?
  1825.     jnz    inpkt3        ;if not continue
  1826.     lxi    h,recpkt    ;else throw away what we've got so far
  1827.     shld    pktptr        ;
  1828. inpkt3:    lhld    pktptr        ;
  1829.     mov    m,a        ;Put the char in the packet.
  1830.     inx    h
  1831.     shld    pktptr
  1832.     mov    b,a
  1833.     lxi    d,-recpkx    ;Start over if packet buffer overflow
  1834.     dad    d        ;
  1835.     jc    inpkt        ;
  1836.     lda    reol        ;Get the EOL char.
  1837.     cmp    b
  1838.     jnz    inpkt2        ;If not loop for another.
  1839.     ;...
  1840.  
  1841. ;Begin IBM change/fdc
  1842. ;This moved from OUTPK7 -- it appears that waiting until we're
  1843. ;ready to send a packet before looking for turnaround character
  1844. ;is long enough for it to get lost.  Better to look now.
  1845.  
  1846.     lda    ibmflg        ;Is this the IBM?
  1847.     ora    a
  1848.     jz    inpkt6        ;If not then proceed.
  1849.     lda    state        ;Check if this is the Send-Init packet.
  1850.     cpi    'S'
  1851.     jz    inpkt6        ;If so don't wait for the XON.
  1852. inpkt5:    call    inchr        ;Wait for the turn around char.
  1853.      jmp    inpkt6
  1854.     cpi    xon        ;Is it the IBM turn around character?
  1855.     jnz    inpkt5        ;If not, go until it is.
  1856. inpkt6:    lhld    pktptr        ;Reload packet pointer
  1857. ;End IBM change/fdc.
  1858.     dcx    h        ;Back up to end of line character
  1859.     mvi    m,0        ;Replace it with a null to stop rpack:
  1860.     call    selcon        ;We've got the packet. Return to console.
  1861.  
  1862.     lda    dbgflg        ; Is debugging enabled?
  1863.     ora    a
  1864.     jz    inpkt7
  1865.     inx    h        ; Point to next char.
  1866.     call    rppos        ; position cursor
  1867.     lxi    h,recpkt+1    ; print the packet
  1868.     call    dmptxt
  1869. inpkt7:    lxi    h,recpkt
  1870.     shld    pktptr        ;Save the packet pointer.
  1871.     jmp    rskp        ;If so we are done.
  1872.  
  1873. ;    getchr - get next character from buffered packet.
  1874. ;    returns nonskip at end of packet.
  1875. ;    called by: rpack
  1876.  
  1877. getchr:    lhld    pktptr        ;Get the packet pointer.
  1878.     mov    a,m        ;Get the char.
  1879.     inx    h
  1880.     shld    pktptr
  1881.     ora    a        ;Is it the null we put at the end of the packet?
  1882.     jnz    rskp        ;If not return retskp.
  1883.     ret            ;If so return failure.
  1884. ;
  1885. ;
  1886. ;    inchr - character input loop for file transfer
  1887. ;    returns: nonskip if timeout or character typed on console
  1888. ;            (console selected)
  1889. ;        skip with character from modem in A (parity stripped
  1890. ;            if necessary; modem selected)
  1891. ;        preserves bc, de, hl in either case.
  1892. ;    called by: inpkt
  1893.  
  1894. inchr:    push    h        ; save hl and bc
  1895.     push    b
  1896.     lhld    timout        ;Get initial value for timeout
  1897.     shld    timval        ;[jd] 
  1898. inchr0:    call    selmdm        ;select modem
  1899.     call    inpmdm        ;Try to get a character from the modem
  1900.     ora    a
  1901.     jz    inchr2        ;if zero, nothing there.
  1902.     mov    b,a
  1903.     lda    parity        ;Is the parity none?
  1904.     cpi    parnon
  1905.     mov    a,b
  1906.     jz    inchr1        ;If so just return.
  1907.     ani    7FH        ;Turn off the parity bit.
  1908. inchr1:    pop    b        ;restore registers
  1909.     pop    h
  1910.     jmp    rskp        ;take skip return, character in A
  1911.  
  1912. inchr2:    call    selcon        ;select console
  1913.     call    inpcon        ; Try to get a character from the console
  1914.     ora    a
  1915.     jz    inchr6        ;If not go do timer thing
  1916.     cpi    cr        ;Is it a carriage return?
  1917.     jz    inchr4        ;If so return
  1918.     cpi    ('Z'-100O)    ;Control-Z?
  1919.     jz    inchr5        ;Yes, go flag it
  1920.     cpi    ('C'-100O)    ;Control-C?
  1921.     jz    inchr7        ;re-enter, he wants to get out
  1922.     cpi    ('X'-100O)    ;Control-X?
  1923.     jnz    inchr6        ;No, ignore it. do timer thing.
  1924. inchr5:    adi    100O        ;Convert to printing range
  1925.     sta    czseen        ;Flag we saw a control-Z
  1926. inchr4:    pop    b        ; restore registers
  1927.     pop    h
  1928.     ret            ;And return
  1929.  
  1930. inchr6:    lda    timflg        ;[jd] pick up timer flag
  1931.     ora    a        ;[jd] are we allowed to use timer?
  1932.     jz    inchr0        ;[jd] no, don't time out
  1933.     lhld    timval        ; decrement fuzzy time-out
  1934.     dcx    h        ;
  1935.     shld    timval        ;((timout-1) * loop time)
  1936.     mov    a,h        ;(Retry if not time-out)
  1937.     ora    l        ;
  1938.     jnz    inchr0        ;
  1939.     call    updrtr        ;Count as retry (?)
  1940.     pop    b        ;restore registers
  1941.     pop    h
  1942.     ret            ;and return to do retry
  1943.  
  1944. inchr7:    call    clrtop        ;[hh] clear screen and home cursor
  1945.     jmp    kermit        ;[hh] then re-enter kermit
  1946.  
  1947. ;
  1948. ;    CRCCLC - Routine to calculate a CRC-CCITT for a string.
  1949. ;
  1950. ;    This routine will calculate a CRC using the CCITT polynomial for
  1951. ;    a string.
  1952. ;
  1953. ;    call with: HL/ Address of null-terminated string
  1954. ;    16-bit CRC value is returned in DE.
  1955. ;    Registers BC and HL are preserved.
  1956. ;
  1957. ;    called by: spack, rpack
  1958.  
  1959. crcclc:    push    h        ;Save HL
  1960.     push    b        ;And BC
  1961.     lxi    d,0        ;Initial CRC value is 0
  1962.  
  1963. crccl0:    mov    a,m        ;Get a character
  1964.     ora    a        ;Check if zero
  1965.     jz    crccl1        ;If so, all done
  1966.     push    h        ;Save the pointer
  1967.     xra    e        ;Add in with previous value
  1968.     mov    e,a        ;Get a copy
  1969.     ani    0FH        ;Get last 4 bits of combined value
  1970.     mov    c,a        ;Get into C
  1971.     mvi    b,0        ;And make high order zero
  1972.     lxi    h,crctb2    ;Point at low order table
  1973.     dad    b        ;Point to correct entry
  1974.     dad    b        ; .  .  .
  1975.     push    h        ;Save the address
  1976.     mov    a,e        ;Get combined value back again
  1977.     rrc            ;Shift over to make index
  1978.     rrc            ; .  .  .
  1979.     rrc            ; .  .  .
  1980.     ani    1EH        ;Keep only 4 bits
  1981.     mov    c,a        ;Set up to offset table
  1982.     lxi    h,crctab    ;Point at high order table
  1983.     dad    b        ;Correct entry
  1984.     mov    a,m        ;Get low order portion of entry
  1985.     xra    d        ;XOR with previous high order half
  1986.     inx    h        ;Point to high order byte
  1987.     mov    d,m        ;Get into D
  1988.     pop    h        ;Get back pointer to other table entry
  1989.     xra    m        ;Include with new high order half
  1990.     mov    e,a        ;Copy new low order portion
  1991.     inx    h        ;Point to other portion
  1992.     mov    a,m        ;Get the other portion of the table entry
  1993.     xra    d        ;Include with other high order portion
  1994.     mov    d,a        ;Move back into D
  1995.  
  1996.     pop    h        ;And H
  1997.     inx    h        ;Point to next character
  1998.     jmp    crccl0        ;Go get next character
  1999.  
  2000. crccl1:    pop    b        ;Restore B
  2001.     pop    h        ;And HL
  2002.  
  2003.     ret            ;And return, DE=CRC-CCITT
  2004.  
  2005. CRCTAB:    DW    00000H
  2006.     DW    01081H
  2007.     DW    02102H
  2008.     DW    03183H
  2009.     DW    04204H
  2010.     DW    05285H
  2011.     DW    06306H
  2012.     DW    07387H
  2013.     DW    08408H
  2014.     DW    09489H
  2015.     DW    0A50AH
  2016.     DW    0B58BH
  2017.     DW    0C60CH
  2018.     DW    0D68DH
  2019.     DW    0E70EH
  2020.     DW    0F78FH
  2021.  
  2022. CRCTB2:    DW    00000H
  2023.     DW    01189H
  2024.     DW    02312H
  2025.     DW    0329BH
  2026.     DW    04624H
  2027.     DW    057ADH
  2028.     DW    06536H
  2029.     DW    074BFH
  2030.     DW    08C48H
  2031.     DW    09DC1H
  2032.     DW    0AF5AH
  2033.     DW    0BED3H
  2034.     DW    0CA6CH
  2035.     DW    0DBE5H
  2036.     DW    0E97EH
  2037.     DW    0F8F7H
  2038. ;
  2039. ;    This is where we go if we get an error during a protocol communication.
  2040. ;    error prints the error packet on line 6 or so, and aborts the
  2041. ;    transfer.
  2042. ;      called by: rinit, rfile, rdata, sinit, sfile, sdata, seof, seot
  2043. ;    error1 print CRLF followed by the error packet.
  2044. ;      called by: finish, logout
  2045. ;    error2 just prints the error packet.
  2046. ;    error3 positions cursor and prints error message specified in DE.
  2047. ;      called by: rinit, rfile, rdata, sinit, sfile, sdata, seof,
  2048. ;             seot, parwrn, gofil, outbuf
  2049.  
  2050. error:    call    screrr        ;Position the cursor.
  2051.     mvi    a,'A'        ;Set the state to abort.
  2052.     sta    state
  2053.     jmp    error2
  2054.  
  2055. error1:    lxi    d,crlf        ;Print a CRLF.
  2056.     call    prtstr
  2057. error2:    lda    argblk+1    ;Get the length of the data.
  2058.     mov    c,a
  2059.     mvi    b,0        ;Put it into BC
  2060.     lxi    h,data        ;Get the address of the data.
  2061.     dad    b        ;Get to the end of the string.
  2062.     mvi    a,'$'        ;Put a dollar sign at the end.
  2063.     mov    m,a
  2064.     lxi    d,data        ;Print error message
  2065.     call    prtstr
  2066.     ret
  2067.  
  2068. error3:    push    d        ;Save the pointer to the message.
  2069.     call    screrr        ;Position the cursor.
  2070.     pop    d        ;Get the pointer back.
  2071.     call    prtstr        ;Print error message
  2072.     ret
  2073. ;
  2074. ;    Set up for file transfer.
  2075. ;    called by read, send.
  2076.  
  2077. init:    lxi    d,version    ; point at Kermit's version string
  2078.     call    sysscr        ; fix up screen
  2079.     call    selmdm        ; select modem
  2080.     call    flsmdm        ; purge any pending data
  2081.     call    selcon        ; select console again.
  2082.     ret
  2083.  
  2084. ;    Set state to ABORT
  2085. ;    called by: rinit, rfile, rdata, sinit, sfile, sdata, seof, seot,
  2086. ;           nak, ackp
  2087.  
  2088. abort:    mvi    a,'A'        ;Otherwise abort.
  2089.     sta    state
  2090.     ret
  2091.  
  2092. ;    nak - send NAK packet
  2093. ;    here from: rinit, rfile, rdata
  2094. ;    nak0 - update retry count and send NAK packet
  2095. ;    here from: rinit, rfile, rdata, tryagn
  2096.  
  2097. nak0:    call    updrtr        ;Update number of retries.
  2098. nak:    lda    pktnum        ;Get the packet number we're waiting for.
  2099.     sta    argblk
  2100.     xra    a        ;No data.
  2101.     sta    argblk+1
  2102.     mvi    a,'N'        ;NAK that packet.
  2103.     call    spack
  2104.      jmp    abort        ; Give up.
  2105.     ret            ;Go around again.
  2106.  
  2107. ;    increment and display retry count
  2108. ;    called by: rfile, sinit, sfile, sdata, seof, seot,
  2109. ;           nak, rpack, inchr, tryagn
  2110.  
  2111. updrtr:    call    scrnrt        ;Position cursor
  2112.     lhld    numrtr
  2113.     inx    h        ;Increment the number of retries
  2114.     shld    numrtr
  2115.     call    nout        ;Write the number of retries.
  2116.     ret
  2117.  
  2118. ;    [jd] this routine prints parity warnings.  All registers are
  2119. ;    saved except for a.
  2120. ;    called by: sdata
  2121.  
  2122. parwrn:    push    b
  2123.     push    d
  2124.     push    h
  2125.     lxi    d,inms25
  2126.     call    error3
  2127.     pop    h
  2128.     pop    d
  2129.     pop    b
  2130.     ret
  2131. ;[jd] end of addition
  2132.  
  2133. ;    print message in status field.  address of message is in DE.
  2134. ;    called by: read, send
  2135.  
  2136. finmes:    push    d        ;Save message.
  2137.     call    scrst        ;Position cursor
  2138.     pop    d        ;Print the termination message
  2139.     call    prtstr
  2140.     call    scrend        ;Position cursor for prompt
  2141.     ret
  2142.  
  2143. ;    Compare expected packet number against received packet number.
  2144. ;    return with flags set (Z = packet number valid)
  2145. ;    called by: rfile, rdata, sinit, sfile, sdata, seof, seot
  2146.  
  2147. compp:    lda    pktnum        ;Get the packet Nr.
  2148.     mov    b,a
  2149.     lda    argblk
  2150.     cmp    b
  2151.     ret
  2152.  
  2153. ;    Increment the packet number, modulo 64.
  2154. ;    called by: rinit, rfile, rdata, sinit, sfile, sdata, seof, seot
  2155.  
  2156. countp:    inr    a        ;Increment packet Nr.
  2157.     ani    3FH        ;Turn off the two high order bits
  2158.     sta    pktnum        ;Save modulo 64 of number
  2159.     lhld    numpkt
  2160.     inx    h        ;Increment Nr. of packets
  2161.     shld    numpkt
  2162.     ret
  2163.  
  2164. ;    Send an ACK-packet
  2165. ;    called by: rfile, rdata, tryagn
  2166.  
  2167. ackp:    xra    a
  2168.     sta    numtry        ;Reset number of retries
  2169.     sta    argblk+1    ;No data. (The packet number is in argblk)
  2170.     mvi    a,'Y'        ;Acknowledge packet
  2171.     call    spack        ;Send packet
  2172.      jmp    abort
  2173.     ret
  2174.  
  2175. ;    ?
  2176. ;    called with A/ current retry count
  2177. ;    called by: rfile, rdata
  2178.  
  2179. tryagn:    inr    a        ;Increment it.
  2180.     sta    oldtry        ;Save the updated number of tries.
  2181.     lda    pktnum        ;Get the present packet number.
  2182.     dcr    a        ;Decrement
  2183.     ani    3FH        ; modulo 64
  2184.     mov    b,a
  2185.     lda    argblk        ;Get the packet's number
  2186.     cmp    b        ;Is the packet's number one less than now?
  2187.     jnz    nak0        ;No, NAK it and try again.
  2188.     call    updrtr        ;Update the number of retries.
  2189.     call    ackp
  2190.     ret
  2191.  
  2192. ;    Output a null-terminated string to the console.  We assume that the
  2193. ;    console has been selected.  Called with HL = address of string.
  2194. ;    called by: spack, inpkt
  2195.  
  2196. dmptxt:    mov    a,m        ; get character from string
  2197.     ora    a
  2198.     rz            ; done if null
  2199.     push    h        ; save string address
  2200.     mov    e,a        ; move character to E for outcon
  2201.     call    outcon        ; output character to console
  2202.     pop    h        ; restore string address
  2203.     inx    h        ; point past printed character
  2204.     jmp    dmptxt        ; go output rest of string
  2205. ;
  2206. IF lasm
  2207.     LINK    CP4TT
  2208. ENDIF;lasm
  2209.