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 / BEEHIVE / COMMS / CP411SRC.ARK / cpspk1.asm < prev    next >
Assembly Source File  |  1991-04-23  |  61KB  |  1,905 lines

  1. ; CPSPK1.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. ;
  25. ;edit 23, 16-Jan-1991 by MF. The bug of (22) was not fixed (although
  26. ;    the error described needed to be corrected). Really fixed the bug this:
  27. ;    time. changed "lda 'E'" after "ptch9b" to "mvi a,'E'" -- Zilog
  28. ;    mnemonic thinking must've addled my brain!
  29. ;edit 22, 14-Jan-1991 by MF. Fix bug in the code which sends an "E" packet
  30. ;    to the remote Kermit on encountering "disk full" so that
  31. ;    uncontrollified <CR><LF> is not copied to the packet data area (and
  32. ;    hence sent to the remote Kermit). This should fix a bug reported
  33. ;    by Russell Lang of Monash University in Australia wherein a PC
  34. ;    running Kermit in Server mode complained of invalid characters when
  35. ;    receiving the "disk full" error packet from CP/M Kermit.
  36. ;edit 21 of 3-Jan-1991 by MF. Reverse part of edit 20 which flushes comm
  37. ;    input at EOF send: the problem of multiple copies of packets being
  38. ;    sent when a stream of files being sent is partially interrupted with
  39. ;    ^X has been fixed by modifying "inchr" in CPSPK2.ASM.
  40. ;edit 20, 2-Jan-1991 by MF. Tightened up code just after "sdata1" and around
  41. ;    "sdat14". Added code to flush comm input after user has typed ^X
  42. ;    or ^Z to interrupt file sends so that duplicate packets are not
  43. ;    sent after the interrupt character (especially ^X) has been typed.
  44. ;edit 19, 14-Dec-1990 by MF.  Place "<<>>" around "F" and "X" packets coming
  45. ;    as replies to REMOTE commands a la VMS Bliss Kermit.
  46. ;    Also type each character of "X" or "F" packet explicitly in case
  47. ;    dollar-signs are part of the filename (as in VMS Bliss Kermit
  48. ;    when a REMOTE TYPE is given and SET FILE NAMING FULL is in effect).
  49. ;    Expanded code is at label rfil3f.
  50. ;edit 18, 27-Nov-1990 by MF. Fix bug introduced with edit 17 which resulted
  51. ;    in "E" packet being sent twice when receiving file(s) and disk-full
  52. ;    occurred. Sorry about that, folks!
  53. ;edit 17, 27-Nov-1990 by MF. When receiving files, make the decision as to
  54. ;    whether to delete a partially-received file on a "disk full"
  55. ;    condition subject to the setting of the SET INCOMPLETE-FILES
  56. ;    switch in conformity with the behavior of MSDOS Kermit.
  57. ;    An "E" packet is still sent to the remote Kermit. Also try to close
  58. ;    any incomplete file whether deleting it or not (labels rdat16 and
  59. ;    rdat3a). If keeping incomplete files, try to write outstanding
  60. ;    buffers to disk, giving an error if the disk is full.
  61. ;edit 16, 23-Nov-1990 by MF. When receiving, cause the file being written
  62. ;    to disk to **always** be deleted and an "E" packet to be sent when a
  63. ;    "disk full" condition is encountered (per suggestion of
  64. ;    RJL@MONU1.CC.MONASH.EDU.AU).
  65. ;edit 15, 15-Nov-1990 by MF.  Changed code for the Receive Complete state
  66. ;    to always go into RECEIVE if AUTORECEIVE is on.  This will happen
  67. ;    most of the time anyway as most mainframe Kermits issue a prompt
  68. ;    after a single SEND command (wild-carded or not), thus guaranteeing
  69. ;    that the modem status check of Kermit-80 ver. 4.09 would **always**
  70. ;    have characters ready for input (the mainframe Kermit's prompt),
  71. ;    defeating the status check and the Console input check (originally
  72. ;    intended to drop the user out of the loop if he/she typed a key with
  73. ;    no comm input present).  Eliminate "any key" message there also.
  74. ;    the user can drop out by hitting ^C.
  75. ;    Of course, none of the foregoing applies if the Receive Complete
  76. ;    state occurs as the result of a "Get" command where Autoreceive
  77. ;    is meaningless and we just drop back to Kermit command-level.
  78. ;edit 14, 1-Oct-1990 by MF.  Added code to send an "I" packet before an
  79. ;    "R" packet in GET command.
  80. ;    Modified routine "sinit" to ignore "E" packets when sending an
  81. ;    "i" packet (per KPROTO.DOC).
  82. ;edit 13, 14-Sep-1990 by MF.  Added code to implement SET FILE COLLISION
  83. ;    and SET INCOMPLETE commands.
  84. ;edit 12, 9-Sep-1990 by MF.  Added code to prevent packet counts
  85. ;    from being displayed during Remote commands.  Fixed
  86. ;    AUTORECEIVE     code, file colision Rename algorithm and eliminated
  87. ;    multiple display of initial messages during GET/RECEIVE.
  88. ; edit 11, 28 July, 1987 by OBSchou.  Commented out capas etc support
  89. ;    (Long packets etc) as this is not worth the effort coding... but
  90. ;    I have left what WAS done for any enthusiast.  Also set in a few
  91. ;    to NOT write to screen if SET TERMINAL QUIET set.  Hopefully speeds
  92. ;    up transfers on systems taking forever to update screens.
  93. ;
  94. ; edit 10, 8 April, 1987 by OBSchou.  Tarted up all sorts of bits n bobs
  95. ;    to cope with all the new aditions for Kermit-80 V 4.09
  96. ;    Look for the [10] for most cahnges.  spar and rpar largely replaced
  97. ;
  98. ; edit 9, March 30th by OBSchou.  Set bits for automatically receiving
  99. ;    another file if a remote sender sends files in seperate sessions.
  100. ;    The code simply checks the serial line, and if there is some
  101. ;    activity, assume its another SEND INIT packet.  As there is no
  102. ;    simple way to go to receive with the control-a, just ignore the
  103. ;    packet.  Causes one retry on the sender, but so what.  Really 
  104. ;    should make it a server gizzmo.
  105. ;
  106. ; edit 8: January 28, 1987 by OBSchou
  107. ;    Two major issues: firstly split CPSPKT.ASM into CPSPK(1 2).ASM
  108. ;    making it far easier to handle this file.
  109. ;    Second, some mode to the GET routines to correctly print the file
  110. ;    name instead of the fireworks.  Trouble was with GET <file> <file>
  111. ;    and RECEIVE <file>.  However, new bugs discovered...
  112. ;
  113. ; edit 7: August 11, 1986    Godfrey N. Nix [gnn] Nottingham University
  114. ;       To ignore echoed packets (ie send 'S' receive 'S' before 'A');
  115. ;       To allow character other than SOH for packet header (see also
  116. ;                       updates to CP4MIT and CP4UTL for other code needed);
  117. ;       To permit SEND and RECEIVE to specify a host filename which
  118. ;                       is of a different structure to that of CP/M.
  119. ;
  120. ; edit 6a: [OBSchou] 7 March, 1985.
  121. ;       Edited file with additions from MJ Carter.  He writes:
  122. ;       25th September 1985, M J Carter [majoc], Nottingham University
  123. ;       Code in gofil() amended, for exactly the same reasons to the 
  124. ;       alteration to cmifil() in cpscmd.asm.  If there is any deep
  125. ;       reason why gofil() has to be used instead of a call to comnd(cmofil), 
  126. ;       I can't see it.  The bug (on a British Micro Mimi 803) caused 
  127. ;       gofil() to overwrite existing files in GET and RECEIVE, even 
  128. ;       with file warning SET ON.
  129. ;
  130. ;edir 6: November 22, 1984
  131. ;       Change SEND's 'Unable to find file' error exit from calling
  132. ;       error3 to calling prtstr instead.  I don't know about you, but
  133. ;       I greatly dislike having messages dumped into pre-existing
  134. ;       junk on the screen where I have to spend lots of time hunting
  135. ;       for them.  [Hal Hostetler]
  136. ;
  137. ; edit 5: September 9, 1984
  138. ;       Call flsmdm in init to flush old input when starting transfers.
  139. ;       Select console before returning from inpkt.
  140. ;       Replace inline code with calls to makfil/clofil to set up for
  141. ;       multisector buffering on output.
  142. ;       Remove superfluous call to clrlin in error3.
  143. ;
  144. ; edit 4: August 21, 1984 (CJC)
  145. ;       Fix comment in inpkt: packet is terminated by NUL on return, not CR.
  146. ;       If debugging, display the outgoing packet before putting the EOL
  147. ;       character on, so the dumped packet doesn't get overwritten.
  148. ;
  149. ; edit 3: July 27, 1984
  150. ;       add link directive for LASM.  CP4PKT is linked by CP4MIT, and links
  151. ;       to CP4TT.  Add Toad Hall TACtrap to permit operations through a TAC.
  152. ;
  153. ; edit 2: June 8, 1984
  154. ;       formatting and documentation; remove some unused labels; move setpar
  155. ;       to cp4mit.m80; add module version string; make all arithmetic on
  156. ;       'pktnum' modulo 64; apply defaults correctly for missing parameters
  157. ;       in send-init packet (and corresponding ack).
  158. ;
  159. ; edit 1: May, 1984
  160. ;       extracted from CPMBASE.M80 version 3.9; modifications are described
  161. ;       in the accompanying .UPD file.
  162. ;
  163. pk1ver:    db    'CPSPK1.ASM (23) 16-Jan-1991$'    ; name, edit number, date
  164.  
  165. ;       GET command   [gnn]
  166. ;       here from: kermit
  167.  
  168. read:    mvi    a,0ffh        ;[obs 8] we are doing a get
  169.     sta    getrxflg    ;[obs 8] so set flag
  170.     lxi    d,remdat    ;Where to put the text (if any.)
  171.     mvi    a,cmtxt
  172.     call    comnd        ;Get either some text or a confirm.
  173.     jmp    kermt3        ; Didn't get anything.
  174.     ora    a        ;Get any chars?
  175.     jz    kermt3        ;[gnn] GET must have a filename
  176.     sta    rdl        ;Store the number of chars.
  177.     xchg            ;Get pointer into HL.
  178.     mvi    m,'$'        ;Put in a dollar sign for printing.
  179.     call    init        ;Clear the line and initialize the buffers.
  180.     lda    quietd        ; quiet display?
  181.     ana    a
  182.     jz    read01        ;[MF]No, go ahead and position cursor
  183.     call    prcrlf        ;[MF]Yes, keep from overwriting the prompt
  184.     jmp    read00        ;[MF]and write filename
  185. read01:    call    scrfln        ;Position cursor [MF]
  186. read00:    lxi    d,remdat    ;Print the file name, in either case
  187.     call    prtstr
  188.     jmp    read0a        ;[gnn] go get local name if any
  189.  
  190.  
  191. ; enter here for RECEIVE command  [gnn]
  192. read0:    mvi    a,0        ;[gnn]
  193.     sta    rdl        ;[gnn][MF] flag entry as receive, not get
  194.     sta    getrxflg    ;[obs 8] doing a receive, so reset flag
  195.     call    init        ;clear line, initialise buffers
  196. read0a:    lxi    d,remnam    ;[gnn] save local name here
  197.     mvi    a,cmtxt        ;[gnn]
  198.     call    comnd        ;[gnn] read second filename if present
  199.     jmp    kermt3        ;[gnn]  error exit
  200.     sta    remlen        ;[gnn] save length of name, may be zero
  201.     sta    getrxflg    ;[obs 8] May also be receive <fnam> so 
  202.                 ;[obs 8]pretend get for printing filename
  203.     lda    rdl        ;[gnn] look at first name
  204.     ora    a        ;[gnn] receive or get?
  205.     jz    read1        ;[gnn] receive
  206.  
  207.     mvi    a,'I'        ;[MF]Set state to send "I" packet
  208.     sta    state        ;[MF]...
  209.  
  210. ;       jmp     read12        ;[obs] [gnn] does not want this
  211.  
  212. read1:    ;call   init        ;Clear the line and initialize the buffers.
  213. read12:    xra    a
  214.     sta    czseen        ;Clear the ^X/^Z flag initially.
  215.     lxi    h,0
  216.     shld    numpkt        ;Set the number of packets to zero.
  217.     shld    numrtr        ;Set the number of retries to zero.
  218.     sta    pktnum        ;Set the packet number to zero.
  219.     sta    numtry        ;Set the number of tries to zero.
  220.     lda    quietd        ; quiet display?
  221.     ana    a
  222.     jnz    read13        ; yes, so dont write...
  223.     call    scrnrt        ;Position cursor
  224.     lxi    h,0
  225.     call    nout        ;Write the number of retries.
  226. read13:    lda    rdl        ;[MF]Get or receive?
  227.     ora    a        ;[MF]...
  228.     jnz    read2        ;[MF]Get, don't reset state
  229.     mvi    a,'R'
  230.     sta    state        ;Set the state to receive initiate.
  231.     ;...
  232. ;
  233. ;RECEIVE state table switcher.
  234.  
  235. read2:    lda    quietd        ; noisy display?
  236.     ana    a
  237.     jnz    read21        ; no, a quiet one
  238.     lda    remtxt        ;[MF] In Remote command?
  239.     ora    a
  240.     jnz    read21        ;[MF] Yes, don't write to screen
  241.     call    scrnp        ;Position cursor
  242.     lhld    numpkt
  243.     call    nout        ;Write the current packet number.
  244. read21:    lda    state        ;Get the state.
  245.     cpi    'D'        ;Are we in the DATA receive state?
  246.     jnz    read22
  247.     call    rdata
  248.     jmp    read2
  249.  
  250. read22:    cpi    'X'        ; F packet but not an F packet?
  251.     jnz    read3        ; nope, so try next one
  252.     call    rfile        ; 'get' the filename (but dont open it)
  253.     jmp    read2
  254.  
  255. read3:    cpi    'F'        ;Are we in the FILE receive state?
  256.     jnz    read4
  257.     call    rfile        ;Call receive file.
  258.     jmp    read2
  259.  
  260. read4:    cpi    'R'        ;Are we in the Receive-Initiate state?
  261.     jnz    read5
  262.     call    rinit
  263.     lda    state        ;[jd] get new state
  264.     cpi    'F'        ;[jd] went into receive state?
  265.     jnz    read2        ;[jd] no
  266.     lxi    d,inms24    ;[jd] yes, get receiving... message
  267.     call    finmes        ;[jd] go print it
  268.     jmp    read2
  269.  
  270. read5:    cpi    'C'        ;Are we in the Receive-Complete state?
  271.     jnz    read6
  272.     lxi    d,infms3    ;Put in "Complete" message.
  273.     lda    czseen        ;Or was it interrupted?
  274.     ora    a        ; .  .  .
  275.     jz    read5a        ;No.
  276.     xra    a        ;Yes, clear flag.
  277.     sta    czseen        ; ...
  278.     lxi    d,inms13    ;Issue "interrupted" message.
  279. read5a:    lda    remtxt        ;[MF] Doing a Remote command?
  280.     ora    a
  281.     cz    finmes        ;Print completion message in right place if not
  282. ;
  283.     lda    rdl        ;[MF]Receive or Get?
  284.     ora    a        ;[MF]...
  285.     jnz    kermit        ;[MF]Get, Autoreceive means nothing.
  286.     lda    autorc        ; see if we want autoreceives
  287.     ana    a
  288.     jz    kermit        ;[MF]No autoreceives, so drop out
  289.     lxi    d,autmes    ;[MF]Yes, tell the user what we're doing
  290.     call    prtstr        ;[MF]...
  291.     jmp    read1        ;[MF]Try another Receive (we get one
  292.                 ;[MF]retry from the sender as the ^A is lost)
  293.  
  294. read6:    cpi    'Y'        ;[MF]Simple ack (from remote command)?
  295.     jz    kermit        ;[MF]Yes
  296.  
  297.     cpi    'I'        ;[MF]Exchanging parameters via info packet?
  298.     jnz    read7        ;[MF]No
  299.     call    sinit        ;[MF]Yes, send the packet
  300.     lda    state        ;[MF]Now see what happened
  301.     cpi    'X'        ;[MF]Did we exchange parameters successfully?
  302.     jz    read6a        ;[MF]Yes, go send the filespec
  303.     cpi    'A'        ;[MF]No, are we in abort state?
  304.     jnz    read2        ;[MF]No, try again
  305.     jmp    kermit        ;[MF]Yes, it's a real disaster, we must stop
  306. read6a:    lda    rdl        ;[MF]Get length of filespec
  307.     sta    argblk+1    ;[MF]as length of packet
  308.     mov    c,a        ;[MF]We must copy the filespec
  309.     mvi    b,0        ;[MF]...
  310.     lxi    h,remdat    ;[MF]from the temporary buffer
  311.     lxi    d,data        ;[MF]to the packet data area
  312.     call    mover        ;[MF]Do it.
  313. ; for GET we must send the name of the file we want [gnn]
  314.  
  315.     mvi    a,'1'        ;Start with single character checksum
  316.     sta    curchk        ;Save the type
  317.     xra    a        ;Start a packet zero.
  318.     sta    argblk
  319.     mvi    a,'R'        ;Receive init packet.
  320.     call    spack        ;Send the packet.
  321.     jmp    kermt3        ; Die!
  322.     xra    a
  323.     sta    czseen        ;Clear the ^X/^Z flag initially.
  324.     lxi    h,0
  325.     shld    numpkt        ;Set the number of packets to zero.
  326.     sta    pktnum        ;Set the packet number to zero.
  327.     sta    numtry        ;Set the number of tries to zero.
  328.     mvi    a,'R'        ;[MF]Set state to Receive-Initiate
  329.     sta    state        ;[MF]...
  330.     jmp    read21        ;[MF]and go around again
  331.                 ;[MF]without retyping packet-number
  332.  
  333. read7:    cpi    'A'        ;Are we in the Receive-"Abort" state?
  334.     jnz    read8
  335. read8:    lxi    d,infms4    ;Anything else is equivalent to "abort".
  336.     call    finmes
  337.     jmp    kermit
  338. ;
  339. ;       Receive routines
  340.  
  341. ;       Receive init
  342. ;       called by: read
  343.  
  344. rinit:    lda    numtry        ;Get the number of tries.
  345.     cpi    imxtry        ;Have we reached the maximum number of tries?
  346.     jm    rinit2
  347.     lxi    d,ermes4
  348.     call    error3        ;Move cursor and print an error message.
  349.     jmp    abort        ;Change the state to abort.
  350.  
  351. rinit2:    inr    a        ;Increment it.
  352.     sta    numtry        ;Save the updated number of tries.
  353.     mvi    a,'1'        ;Reset block check type to single character
  354.     sta    curchk        ;Store as current type for initialization
  355.     call    rpack        ;Get a packet.
  356.     jmp    nak        ; Trashed packet: nak, retry.
  357.     cpi    'S'        ;Is it a send initiate packet?
  358.     jnz    rinit3        ;If not see if its an error.
  359. rini2a:    lda    numtry        ;Get the number of tries.
  360.     sta    oldtry        ;Save it.
  361.     xra    a
  362.     sta    numtry        ;Reset the number of tries.
  363.     lda    argblk        ;Returned packet number.  (Synchronize them.)
  364.     call    countp
  365.     lda    argblk+1    ;Get the number of arguments received.
  366.     lxi    h,data        ;Get a pointer to the data.
  367.     call    spar        ;Get the data into the proper variables.
  368.     lxi    h,data        ;Get a pointer to our data block.
  369.     call    rpar        ;Set up the receive parameters.
  370.     sta    argblk+1    ;Store the returned number of arguments.
  371.     mvi    a,'Y'        ;Acknowledge packet.
  372.     call    spack        ;Send the packet.
  373.     jmp    abort        ; Failed, abort.
  374.     lda    inichk        ;Now switch to agreed upon check-type
  375.     sta    curchk        ;For all future packets
  376.     mvi    a,'F'        ;Set the state to file send.
  377.     sta    state
  378.     ret
  379.  
  380. rinit3:    cpi    'E'        ;Is it an error packet.
  381.     jnz    nak0        ;If not NAK whatever it is.
  382.     call    error
  383.     jmp    abort
  384. ;
  385. ;       Receive file
  386. ;       called by: read
  387.  
  388. rfile:    lda    numtry        ;Get the number of tries.
  389.     cpi    maxtry        ;Have we reached the maximum number of tries?
  390.     jm    rfile1
  391.     lxi    d,ermes5
  392.     call    error3        ;Move cursor and print an error message.
  393.     jmp    abort        ;Change the state to abort.
  394.  
  395. rfile1:    inr    a        ;Increment it.
  396.     sta    numtry        ;Save the updated number of tries.
  397.     call    rpack        ;Get a packet.
  398.     jmp    nak        ; Trashed packet: nak, retry.
  399.     cpi    'S'        ;Is it a send initiate packet?
  400.     jnz    rfile2        ; No, try next type.
  401.     lda    oldtry        ;Get the number of tries.
  402.     cpi    imxtry        ;Have we reached the maximum number of tries?
  403.     jm    rfil12        ;If not proceed.
  404.     lxi    d,ermes4
  405.     call    error3        ;Move cursor and print an error message.
  406.     jmp    abort        ;Change the state to abort.
  407.  
  408. rfil12:    inr    a        ;Increment it.
  409.     sta    oldtry        ;Save the updated number of tries.
  410.     lda    pktnum        ;Get the present packet number.
  411.     dcr    a        ;Decrement
  412.     ani    3FH        ; modulo 64
  413.     mov    b,a
  414.     lda    argblk        ;Get the packet's number
  415.     cmp    b        ;Is the packet's number one less than now?
  416.     jnz    nak0        ;No, NAK and try again.
  417.     call    updrtr        ;Update the retry count.
  418.     xra    a
  419.     sta    numtry        ;Reset the number of tries.
  420.     lxi    h,data        ;Get a pointer to our data block.
  421.     call    rpar        ;Set up the parameter information.
  422.     sta    argblk+1    ;Save the number of arguments.
  423.     mvi    a,'Y'        ;Acknowledge packet.
  424.     call    spack        ;Send the packet.
  425.     jmp    abort        ; Failed, abort.
  426.     ret
  427.  
  428. rfile2:    cpi    'Z'        ;Is it an EOF packet?
  429.     jnz    rfile3        ; No, try next type.
  430.     lda    oldtry        ;Get the number of tries.
  431.     cpi    maxtry        ;Have we reached the maximum number of tries?
  432.     jm    rfil21        ;If not proceed.
  433.     lxi    d,ermes6
  434.     call    error3        ;Move cursor and print an error message.
  435.     jmp    abort        ;Change the state to abort.
  436.  
  437. rfil21:    call    tryagn
  438.     ret
  439.  
  440. rfile3:    cpi    'F'        ;Start of file?
  441.     jnz    rfil3b
  442.     mov    c,a        ;[MF]Save packet type
  443.     lda    remtxt        ;[MF]Doing a remote server command?
  444.     ora    a        ;[MF]...
  445.     mov    a,c        ;[MF]Restore packet type
  446.     jnz    rfil3d        ;[MF]If yes, same as x packet
  447.     call    compp
  448.     jnz    nak0        ;No, NAK it and try again.
  449.     call    countp
  450.     mov    c,a        ;[MF]
  451.     lda    remtxt        ;[MF]Doing a remote command?
  452.     ora    a        ;[MF]...
  453.     mov    a,c        ;[MF]
  454.     jnz    rfil3a        ;[MF]Yes, don't open a file
  455.     call    gofil        ;Get a file to write to, and init output buffer.
  456.     jmp    abort
  457. rfil3a:    lda    numtry        ;Get the number of tries.
  458.     sta    oldtry        ;Save it.
  459.     call    ackp
  460.     mvi    a,'D'        ;Set the state to data receive.
  461.     sta    state
  462.     lda    czseen        ;Check if we punted a file
  463.     cpi    'Z'        ;and didn't want any more
  464.     rz            ;If that was the request, keep telling other end
  465.     xra    a        ;Otherwise, clear flag (^X is only for one file)
  466.     sta    czseen        ;And store the flag back
  467.     ret
  468.  
  469. rfil3b:    cpi    'X'        ;Start of 'file?' , but not a file?
  470.     jnz    rfile4
  471. rfil3d:    call    compp
  472.     jnz    nak0        ;No, NAK it and try again.
  473.     call    countp
  474.  
  475.     call    selcon        ;[MF]Select Console
  476.     lda    argblk+1    ; get length
  477.     ora    a        ;[MF]Anything to write?
  478.     jz    rfil3e        ;[MF]No
  479.     push    psw        ;[MF]Yes, save character count
  480.     mvi    e,'<'        ;[MF]Write "<<" as in VMSKermit
  481.     push    d        ;[MF]...
  482.     call    outcon        ;[MF]...
  483.     pop    d        ;[MF]...
  484.     call    outcon        ;[MF]...
  485.     pop    psw        ;[MF]Restore character count
  486.     lxi    h,data        ; lets write the filename (?) to display
  487. rfil3f:    push    psw        ;[MF]Save loop counter
  488.     mov    e,m        ;[MF]Get character to write
  489.     inx    h        ;[MF]and increment character pointer
  490.     push    h        ;[MF]Save the pointer
  491.     call    outcon        ;[MF]Write character to display
  492.     pop    h        ;[MF]Restore pointer
  493.     pop    psw        ;[MF]and loop counter
  494.     dcr    a        ;[MF]Decrement the counter
  495.     jnz    rfil3f        ;[MF]Display entire filename
  496.     mvi    e,'>'        ;[MF]Put in ">>" as in VMSKermit
  497.     push    d        ;[MF]...
  498.     call    outcon        ;[MF]...
  499.     pop    d        ;[MF]...
  500.     call    outcon        ;[MF]...
  501.     call    prcrlf        ;[MF]New line
  502. rfil3e:    lda    numtry        ;Get the number of tries.
  503.     sta    oldtry        ;Save it.
  504.     call    ackp
  505.     mvi    a,'D'        ; expecting a D packet
  506.     sta    state
  507.     lda    czseen        ;Check if we punted a file
  508.     cpi    'Z'        ;and didn't want any more
  509.     rz            ;If that was the request, keep telling other end
  510.     xra    a        ;Otherwise, clear flag (^X is only for one file)
  511.     sta    czseen        ;And store the flag back
  512.     ret
  513.  
  514. rfile4:    cpi    'B'        ;End of transmission.
  515.     jnz    rfile5
  516.     call    compp
  517.     jnz    nak0        ;No, NAK it and try again.
  518.     xra    a        ;No data.  (Packet number already in argblk).
  519.     sta    argblk+1
  520.     mvi    a,'Y'        ;Acknowledge packet.
  521.     call    spack        ;Send the packet.
  522.     jmp    abort
  523.     mvi    a,'C'        ;Set the state to complete.
  524.     sta    state
  525.     ret
  526.  
  527. rfile5:    cpi    'E'        ;Is it an error packet.
  528.     jnz    abort
  529.     call    error
  530.     jmp    abort
  531. ;
  532. ;       Receive data
  533. ;       called by: read
  534.  
  535. rdata:    lda    numtry        ;Get the number of tries.
  536.     cpi    maxtry        ;Have we reached the maximum number of tries?
  537.     jm    rdata1
  538.     lxi    d,erms10
  539.     call    error3        ;Display error message.
  540. rdat16:    lda    remtxt        ;[MF]Is a Remote command in progress?
  541.     ora    a        ;[MF]...
  542.     jnz    abort        ;[MF]Yes, don't worry about file disposition
  543.     lda    incflg        ;[MF]Are we keeping incomplete files?
  544.     ora    a        ;[MF]...
  545.     jnz    rdat17        ;[MF]Yes
  546.     lxi    d,fcb        ;[MF]No, close the file, ignoring errors
  547.     push    d        ;[MF]while protecting the pointer
  548.     mvi    c,closf        ;[MF]...
  549.     call    bdos        ;[MF]...
  550.     pop    d        ;[MF]Now delete the file, ignoring errors
  551.     mvi    c,delf        ;[MF]...
  552.     call    bdos        ;[MF]...
  553.     jmp    abort        ;Change the state to abort.
  554. rdat17:    call    clofil        ;[MF]Try to close the file, writing
  555.                 ;[MF]outstanding buffers to disk
  556.     jmp    rdat37        ;[MF]We can't, the disk is full
  557.     jmp    abort        ;[MF]Change the state to "abort"
  558.  
  559. rdata1:    inr    a        ;Increment it.
  560.     sta    numtry        ;Save the updated number of tries.
  561.     call    rpack        ;Get a packet.
  562.     jmp    nak        ; Trashed packet: nak, retry.
  563.     cpi    'D'        ;Is it a data packet?
  564.     jnz    rdata2        ; No, try next type.
  565.     call    compp        ;check for correct packet number (zero flag = ok)
  566.     jz    rdat14        ;its correct
  567.     lda    oldtry        ;Get the number of tries.
  568.     cpi    maxtry        ;Have we reached the maximum number of tries?
  569.     jm    rdat12        ;If not proceed.
  570.     lxi    d,erms10
  571.     call    error3        ;Display err msg.
  572.     jmp    rdat16        ;[MF]Change the state to abort.
  573.  
  574. rdat12:    call    tryagn
  575.     ret
  576.  
  577. rdat14:    call    countp
  578.     lda    numtry        ;Get the number of tries.
  579.     sta    oldtry        ;Save it.
  580.     lda    argblk+1    ;Get the length of the data.
  581.     call    ptchr
  582.     jmp    rdat3b        ;[MF] Unable to write out chars;abort.
  583.     xra    a
  584.     sta    numtry        ;Reset the number of tries.
  585.     sta    argblk+1    ;No data.  (Packet number still in argblk.)
  586.     mov    c,a        ;Assume no data
  587.     lda    czseen        ;Check if control-X typed
  588.     ora    a        ; .  .  .
  589.     jz    rdat15        ;Zero if not typed
  590.     mov    c,a        ;Get the type of character typed
  591.     mvi    a,1        ;One data character
  592.     sta    argblk+1    ;Save the count
  593.     mov    a,c        ;Get the possible data character
  594.     sta    data        ;Store in data area
  595. rdat15:    mvi    a,'Y'        ;Acknowledge packet.
  596.     call    spack        ;Send the packet.
  597.     jmp    rdat16        ;[MF]
  598.     ret
  599.  
  600. rdata2:    cpi    'F'        ;Start of file?
  601.     jnz    rdata3        ; No, try next type.
  602.     lda    oldtry        ;Get the number of tries.
  603.     cpi    maxtry        ;Have we reached the maximum number of tries?
  604.     jm    rdat21        ;If not proceed.
  605.     lxi    d,ermes5
  606.     call    error3        ;Display err msg.
  607.     jmp    rdat16        ;[MF]Change the state to abort.
  608.  
  609. rdat21:    call    tryagn
  610.     ret
  611.  
  612. rdata3:    cpi    'Z'        ;Is it a EOF packet?
  613.     jnz    rdata4        ;Try and see if its an error.
  614.     call    compp
  615.     jnz    nak0        ;No, NAK it and try again.
  616.     call    countp
  617.     lda    argblk+1    ;Get the data length
  618.     cpi    1        ;Have one item?
  619.     jnz    rdat33        ;If not, ignore data
  620.     lda    data        ;Yes, get the character
  621.     cpi    'D'        ;Is it a 'D' for discard?
  622.     jz    rdat36        ;If so, punt file
  623. rdat33:    lda    remtxt        ;[MF]Writing text to disk?
  624.     ora    a        ;[MF]...
  625.       jnz    rdat38        ;[MF]No, don't close file
  626.     call    clofil        ;Finish off the file.
  627.     jmp    rdat37        ; Give up if the disk is full.
  628. rdat38:    xra    a        ;Since we kept the file,
  629.     sta    czseen        ;don't say it was discarded.
  630.     lda    numtry        ;Get the number of tries. [MF]
  631.     sta    oldtry        ;Save it. [MF]
  632.     call    ackp        ;[MF]
  633.     jmp    rdat39        ;[MF]and get ready to get more files
  634. rdat36:    lda    numtry        ;Get the number of tries.
  635.     sta    oldtry        ;Save it.
  636.     call    ackp
  637.     lda    remtxt        ;[MF]Is a Remote command in progress?
  638.     ora    a        ;[MF]...
  639.     jnz    rdat39        ;[MF]Yes, don't worry about file disposition
  640.     lda    dscflg        ;[MF]Is the file being punted because
  641.     ora    a        ;[MF]of a collision?
  642.     jnz    rdat39        ;[MF]Yes, don't delete the existing file
  643.     lda    incflg        ;[MF]No, are we keeping incomplete files?
  644.     ora    a        ;[MF]...
  645.     jnz    rdat3a        ;[MF]Yes
  646.     lxi    d,fcb        ;[MF]No, close the file,
  647.     mvi    c,closf        ;[MF]ignoring errors
  648.     push    d        ;[MF]...
  649.     call    bdos        ;[MF]...
  650.     pop    d        ;[MF]Now delete the file,
  651.     mvi    c,delf        ;[MF]ignoring errors
  652.     call    bdos        ;[MF]...
  653.     jmp    rdat39        ;[MF]and continue
  654. rdat3a:    call    clofil        ;[MF]Try to close the file, writing
  655.                 ;[MF]outstanding buffers to disk
  656.     jmp    rdat37        ;[MF]Can't, disk is full
  657. rdat39:    mvi    a,'F'
  658.     sta    state
  659.     ret
  660.  
  661. rdat37:    call    ptchr9        ; Send "?Disk full" on the error line [MF]
  662.                 ; and to the remote Kermit [MF]
  663. rdat3b:    lda    remtxt        ;[MF]Doing a Remote command?
  664.     ora    a        ;[MF]...
  665.     jnz    abort        ;[MF]Yes, just abort
  666.     lxi    d,fcb        ;[MF]Close the file, ignoring errors
  667.     push    d        ;[MF]Protect fcb pointer
  668.     mvi    c,closf        ;[MF]...
  669.     call    bdos        ;[MF]...
  670.     pop    d        ;[MF]Restore pointer
  671.     lda    incflg        ;[MF]Are we keeping incomplete files?
  672.     ora    a        ;[MF]...
  673.     jnz    abort        ;[MF]Yes, just abort transfer
  674.     mvi    c,delf        ;[MF]No, delete the file, ignoring errors
  675.     call    bdos        ;[MF]...
  676.     jmp    abort        ;[MF] abort transfer
  677.  
  678. rdata4:    cpi    'E'        ;Is it an error packet.
  679.     jnz    rdat16        ;[MF]
  680.     call    error
  681.     jmp    rdat16        ;[MF]
  682. ;
  683. ;       SEND command
  684. ;       here from: kermit
  685.  
  686. send:    mvi    a,cmifi        ;Parse an input file spec.
  687.     lxi    d,fcb        ;Give the address for the FCB.
  688.     call    comnd
  689.     jmp    kermit        ; Give up on bad parse.
  690. ;       section to get remote filename [gnn]
  691.     lxi    d,remnam    ;[gnn] where to put filename
  692.     mvi    a,cmtxt        ;[gnn] 
  693.     call    comnd        ;[gnn] get the text to end of the line
  694.     jmp    kermt3        ;[gnn] failure in reading buffer
  695.     sta    remlen        ;[gnn] save length (may be zero)
  696. ;
  697.     xra    a
  698.     sta    mfflg1        ; clear flags...
  699.     sta    mfflg2
  700.     sta    mfflg3        ;[gnn]
  701.     sta    fcbcnt        ;[gnn] clear fcbcount
  702.     lxi    h,fcb0        ;[gnn] and fcb pointer
  703.     shld    xfcbptr
  704. ;
  705.     call    mfname        ;handle (multi) files
  706.     jnc    send14        ;got a valid file-name
  707.     lxi    d,erms15
  708.     call    prtstr        ;Display error msg. ([hh] where it's visible)
  709.     jmp    kermit
  710.  
  711. send14:    call    init        ;Clear the line and initialize the buffers.
  712.     xra    a
  713.     sta    pktnum        ;Set the packet number to zero.
  714.     sta    numtry        ;Set the number of tries to zero.
  715.     sta    wrn8        ;[jd] we haven't sent the 8-bit-lost warning
  716.     lxi    h,0
  717.     shld    numpkt        ;Set the number of packets to zero.
  718.     shld    numrtr        ;Set the number of retries to zero.
  719.     lda    quietd        ; a quiet display?
  720.     ana    a
  721.     jnz    send15        ; yup, dont write
  722.     call    scrnrt        ;Position cursor
  723.     lxi    h,0
  724.     call    nout        ;Write the number of retries.
  725. send15:    mvi    a,'1'        ;Reset to use single character checksum
  726.     sta    curchk        ;For startup
  727.     mvi    a,'S'
  728.     sta    state        ;Set the state to receive initiate.
  729.     ;...
  730. ;
  731. ;SEND state table switcher
  732.  
  733. send2:    lda    quietd        ; a quiet display?
  734.     ana    a
  735.     jnz    send21        ; yes, so dont write
  736.     call    scrnp        ;Position cursor
  737.     lhld    numpkt
  738.     call    nout        ;Write the packet number.
  739. send21:    lda    state        ;Get the state.
  740.     cpi    'D'        ;Are we in the data send state?
  741.     jnz    send3
  742.     call    sdata
  743.     jmp    send2
  744.  
  745. send3:    cpi    'F'        ;Are we in the file send state?
  746.     jnz    send4
  747.     call    sfile        ;Call send file.
  748.     jmp    send2
  749.  
  750. send4:    cpi    'Z'        ;Are we in the EOF state?
  751.     jnz    send5
  752.     call    seof
  753.     jmp    send2
  754.  
  755. send5:    cpi    'S'        ;Are we in the send initiate state?
  756.     jnz    send6
  757.     call    sinit
  758.     lda    state        ;[jd] get state back
  759.     cpi    'F'        ;[jd] into file send state yet?
  760.     jnz    send2        ;[jd] no
  761.     lxi    d,inms23    ;[jd] yes, print sending...
  762.     call    finmes        ;[jd] 
  763.     jmp    send2
  764.  
  765. send6:    cpi    'B'        ;Are we in the eot state?
  766.     jnz    send7
  767.     call    seot
  768.     jmp    send2
  769.  
  770. send7:    cpi    'C'        ;Are we in the send complete state?
  771.     jnz    send8        ;No...
  772.     lxi    d,infms3    ;Yes, write "Complete" message.
  773.     lda    czseen        ;Or was it interrupted?
  774.     ora    a        ; .  .  .
  775.     jz    send7a        ;No.
  776.     lxi    d,inms13    ;Yes, then say "Interrupted" instead.
  777. send7a:    call    finmes
  778.     jmp    kermit
  779.  
  780. send8:    cpi    'A'        ;Are we in the send "abort" state?
  781.     jnz    send9
  782.     lxi    d,infms4    ;Print  message.
  783.     call    finmes
  784.     jmp    kermit
  785.  
  786. send9:    lxi    d,infms4    ;Anything else is equivalent to "abort".
  787.     call    finmes
  788.     jmp    kermit
  789. ;
  790. ;       Send routines
  791.  
  792. ;       Send initiate
  793. ;       called by: send
  794.  
  795. sinit:    lda    numtry        ;Get the number of tries.
  796.     cpi    imxtry        ;Have we reached the maximum number of tries?
  797.     jm    sinit2
  798.     lxi    d,erms14
  799.     call    error3        ;Display ermsg
  800.     jmp    abort        ;Change the state to abort.
  801.  
  802. sinit2:    inr    a        ;Increment it.
  803.     sta    numtry        ;Save the updated number of tries.
  804.     mvi    a,'1'        ;Reset to use single character checksum
  805.     sta    curchk        ;For startup
  806.     lda    chktyp        ;Get our desired block check type
  807.     sta    inichk        ;Store so we tell other end
  808.     lxi    h,data        ;Get a pointer to our data block.
  809.     call    rpar        ;Set up the parameter information.
  810.     sta    argblk+1    ;Save the number of arguments.
  811.     lda    numpkt        ;Get the packet number.
  812.     sta    argblk
  813.     lda    state        ; load state (I or S)
  814.  
  815.     call    spack        ;Send the packet.
  816.     jmp    abort        ; Failed, abort.
  817.     call    rpack        ;Get a packet.
  818.     jmp    r        ; Trashed packet don't change state, retry.
  819.     cpi    'Y'        ;ACK?
  820.     jnz    sinit3        ;If not try next.
  821.     call    compp        ;compare packets. If ok, zero flag set
  822.     rnz            ;If not try again.
  823.     call    countp        ;increment packet number modulo 64
  824.     lda    argblk+1    ;Get the number of pieces of data.
  825.     lxi    h,data        ;Pointer to the data.
  826.     call    spar        ;Read in the data. (decode what they want)
  827.     lda    numtry        ;Get the number of tries.
  828.     sta    oldtry        ;Save it.
  829.     xra    a
  830.     sta    numtry        ;Reset the number of tries.
  831.     lda    state        ; se if S or I state
  832.     cpi    'I'        ; I state, so set X as next state
  833.     jnz    sinita
  834. sinitb:    mvi    a,'X'
  835.     sta    state
  836.     ret
  837.  
  838. sinita:    lda    inichk        ;Get the agreed upon block check type
  839.     sta    curchk        ;Store as type to use for packets now
  840.     mvi    a,'F'        ;Set the state to file send. (Assumed)
  841.     sta    state
  842.     call    getfil        ;Open the file.
  843.     ret            ; assume success; mfname thinks the file exists.
  844.  
  845. sinit3:    cpi    'N'        ;NAK?
  846.     jnz    sinit4        ;If not see if its an error.
  847.     call    updrtr        ;Update the number of retries.
  848.     lda    pktnum        ;Get the present packet number.
  849.     inr    a        ;Increment
  850.     ani    3FH        ; modulo 64
  851.     mov    b,a
  852.     lda    argblk        ;Get the packet's number.
  853.     cmp    b        ;Is the packet's number one more than now?
  854.     rnz            ;If not assume its for this packet, go again.
  855.     xra    a
  856.     sta    numtry        ;Reset number of tries.
  857.     mvi    a,'F'        ;Set the state to file send.
  858.     sta    state
  859.     ret
  860.  
  861. sinit4:    cpi    'E'        ;Is it an error packet.
  862.     jnz    abort
  863.     lda    state        ;[MF]Get state
  864.     cpi    'I'        ;[MF]If an "I" packet was sent,
  865.     jz    sinitb        ;[MF]Ignore the error, pretend success
  866.     call    error        ;[MF]else display the error info
  867.     jmp    abort        ;[MF]and abort
  868. ;
  869. ;       Send file header
  870. ;       called by: send
  871. ;[5a] Question [majoc]: Why could not the filename
  872. ;     parsing have been done by comnd, like all the rest?
  873.  
  874. sfile:    lda    numtry        ;Get the number of tries.
  875.     cpi    maxtry        ;Have we reached the maximum number of tries?
  876.     jm    sfile1
  877.     lxi    d,erms14
  878.     call    error3
  879.     jmp    abort        ;Change the state to abort.
  880.  
  881. sfile1:    inr    a        ;Increment it.
  882.     sta    numtry        ;Save the updated number of tries.
  883.     xra    a        ;Clear A
  884.     sta    czseen        ;No control-Z or X seen
  885.     lxi    h,data        ;Get a pointer to our data block.
  886.     shld    datptr        ;Save it.
  887. ; use remote name if given, else use local name [gnn]
  888.     lda    remlen        ;[gnn] anything given?
  889.     ora    a        ;[gnn] 
  890.     jnz    sfile4        ;[gnn] use remote name
  891.  
  892.     lxi    h,fcb+1        ;Pointer to the file name in the FCB.
  893.     shld    fcbptr        ;Save position in FCB.
  894.     mvi    b,0        ;No chars yet.
  895.     mvi    c,0
  896. sfil11:    mov    a,b
  897.     cpi    8H        ;Is this the ninth char?
  898.     jnz    sfil12        ;If not proceed.
  899.     mvi    a,'.'        ;Get a dot.
  900.     lhld    datptr
  901.     mov    m,a        ;Put the char in the data packet.
  902.     inx    h
  903.     shld    datptr        ;Save position in data packet.
  904.     inr    c
  905. sfil12:    inr    b        ;Increment the count.
  906.     mov    a,b
  907.     cpi    0CH        ;Twelve? 
  908.     jp    sfil13
  909.     lhld    fcbptr
  910.     mov    a,m
  911.     ani    7fH        ;Turn off CP/M 2 or 3's high bits.
  912.     inx    h
  913.     shld    fcbptr        ;Save position in FCB.
  914.     cpi    '!'        ;Is it a good character?
  915.     jm    sfil11        ;If not get the next.
  916.     lhld    datptr
  917.     mov    m,a        ;Put the char in the data packet.
  918.     inx    h
  919.     shld    datptr        ;Save position in data packet.
  920.     inr    c
  921.     jmp    sfil11        ;Get another.
  922.  
  923. sfil13:    mov    a,c        ;Number of char in file name.
  924.     sta    argblk+1
  925.     lhld    datptr
  926.     mvi    a,'$'
  927.     mov    m,a        ;Put in a dollar sign for printing.
  928.     lda    quietd        ; a quiet display
  929.     ana    a
  930.     jnz    sfi13a        ; yes, dont write
  931.     call    scrfln        ;Position cursor
  932. sfi13a:    lxi    d,data        ;Print the file name though, in either case
  933.     call    prtstr
  934.     lda    pktnum        ;Get the packet number.
  935.     sta    argblk
  936.     mvi    a,'F'        ;File header packet.
  937.     call    spack        ;Send the packet.
  938.     jmp    abort        ; Failed, abort.
  939.     call    rpack        ;Get a packet.
  940.     jmp    r        ; Trashed packet don't change state, retry.
  941.     cpi    'Y'        ;ACK?
  942.     jnz    sfile2        ;If not try next.
  943.     call    compp
  944.     rnz            ;If not hold out for the right one.
  945. sfil14:    call    countp
  946.     lda    numtry        ;Get the number of tries.
  947.     sta    oldtry        ;Save it.
  948.     xra    a
  949.     sta    numtry        ;Reset the number of tries.
  950.     sta    bytes        ;[10] clear the "bytes transferred" counter
  951.     sta    bytes+1        ;[10]
  952.     sta    bytes+2        ;[10]
  953.     sta    bytes+3        ;[10]
  954.     call    gtchr        ;Fill the first data packet
  955.     jmp    sfil16        ;Error go see if its EOF.
  956. ;                                  ;Got the chars, proceed.
  957.     sta    size        ;Save the size of the data gotten.
  958.     mvi    a,'D'        ;Set the state to data send.
  959.     sta    state
  960.     ret
  961.  
  962. sfil16:    cpi    0FFH        ;Is it EOF?
  963.     jnz    abort        ;If not give up.
  964.     mvi    a,'Z'        ;Set the state to EOF.
  965.     sta    state
  966.     ret
  967.  
  968. sfile2:    cpi    'N'        ;NAK?
  969.     jnz    sfile3        ;Try if error packet.
  970.     call    updrtr        ;Update the number of retries.
  971.     lda    pktnum        ;Get the present packet number.
  972.     inr    a        ;Increment
  973.     ani    3FH        ; modulo 64
  974.     mov    b,a
  975.     lda    argblk        ;Get the packet's number.
  976.     cmp    b        ;Is the packet's number one more than now?
  977.     rnz            ;If not go try again.
  978.     jmp    sfil14        ;Just as good as a ACK;go to the ACK code.
  979.  
  980. sfile3:    cpi    'E'        ;Is it an error packet.
  981.     jnz    abort
  982.     call    error
  983.     jmp    abort
  984.  
  985. ; copy remote name into packet to send [gnn]
  986. sfile4:    xchg            ;[gnn] keep pointer to packet
  987.     lxi    h,remnam    ;[gnn] set pointer to name
  988.     mov    c,a        ;[gnn] keep count of length
  989.     mov    b,a        ;[gnn] and set as loop counter
  990. sfil41:    mov    a,m        ;[gnn] get a character
  991.     stax    d        ;[gnn] copy it to packet
  992.     inx    h        ;[gnn] 
  993.     inx    d        ;[gnn] move pointers
  994.     dcr    b        ;[gnn] 
  995.     mov    a,b        ;[gnn] 
  996.     ora    a        ;[gnn] done them all?
  997.     jnz    sfil41        ;[gnn] repeat until done
  998.     xchg            ;[gnn] get final position
  999.     shld    datptr        ;[gnn] and save it
  1000.     jmp    sfil13        ;[gnn] now go and send packet
  1001.  
  1002. ;
  1003. ;       Send data
  1004. ;       called by: send
  1005.  
  1006. sdata:    lda    numtry        ;Get the number of tries.
  1007.     cpi    maxtry        ;Have we reached the maximum number of tries?
  1008.     jm    sdata1
  1009.     lxi    d,erms14
  1010.     call    error3
  1011.     jmp    abort        ;Change the state to abort.
  1012.  
  1013. sdata1:    inr    a        ;Increment it.
  1014.     sta    numtry        ;Save the updated number of tries.
  1015.     lxi    h, data        ;Get a pointer to our data block.
  1016.     shld    datptr        ;Save it.
  1017.     lxi    h,filbuf    ;Pointer to chars to be sent.
  1018.     shld    cbfptr        ;Save position in char buffer.
  1019.     mvi    b,1        ;First char.
  1020. sdat11:    lhld    cbfptr
  1021.     mov    a,m
  1022.     inx    h
  1023.     shld    cbfptr        ;Save position in char buffer.
  1024.     mov    c,a        ;[jd] preserve character temporarily
  1025.     lda    quot8        ;[jd] doing eighth-bit quoting?
  1026.     ora    a        ;[jd] 
  1027.     mov    a,c        ;[jd] restore char
  1028.     jnz    sdat4        ;[jd] using eighth-bit quoting, no warning
  1029.     lda    parity        ;[jd] get parity
  1030.     cpi    parnon        ;[jd] none?
  1031.     mov    a,c        ;[jd] restore character
  1032.     jz    sdat4        ;[jd] no parity, leave char alone
  1033.     lda    wrn8        ;[jd] look at warning flag
  1034.     ora    a        ;[jd] have we already given the warning?
  1035.     jnz    sdat5        ;[jd] yes, skip this
  1036.     mov    a,c        ;[jd] restore character...
  1037.     ani    80h        ;[jd] examine parity
  1038.     jz    sdat5        ;[jd] no parity, no warning.
  1039.     call    parwrn        ;[jd] ...print warning - parity lost
  1040.     mvi    a,0ffh        ;[jd] remember that we sent the message
  1041.     sta    wrn8        ;[jd]
  1042. sdat5:    mov    a,c        ;[jd] restore character again
  1043.     ani    7fh        ;[jd] strip parity so not checksummed
  1044. sdat4:    lhld    datptr
  1045.     mov    m,a        ;Put the char in the data packet.
  1046.     inx    h
  1047.     shld    datptr        ;Save position in data packet.
  1048.     inr    b        ;Increment the count.
  1049.     lda    size        ;Get the number of chars in char buffer.
  1050.     cmp    b        ;Have we transfered that many?
  1051.     jp    sdat11        ;If not get another.
  1052.     lda    size        ;Number of char in char buffer.
  1053.     sta    argblk+1
  1054.     lda    pktnum        ;Get the packet number.
  1055.     sta    argblk
  1056.     mvi    a,'D'        ;Data packet.
  1057.     call    spack        ;Send the packet.
  1058.     jmp    abort        ; Failed, abort.
  1059.     call    rpack        ;Get a packet.
  1060.     jmp    r        ; Trashed packet don't change state, retry.
  1061.     cpi    'Y'        ;ACK?
  1062.     jnz    sdata2        ;If not try next.
  1063.     call    compp
  1064.     rnz            ;If not hold out for the right one.
  1065.     lda    argblk        ;Get the packet number back
  1066.     call    countp
  1067.     lda    numtry        ;Get the number of tries.
  1068.     sta    oldtry        ;Save it.
  1069.     xra    a
  1070.     sta    numtry        ;Reset the number of tries.
  1071.     lda    argblk+1    ;Get the data length
  1072.     cpi    1        ;Check if only 1 character?
  1073.     jnz    sdat15        ;If not, just continue
  1074.     lda    data        ;Got one character, get it from data
  1075.     cpi    'Z'        ;Want to abort entire stream?
  1076.     jnz    sdat14        ;If not, check for just this file
  1077.     sta    czseen        ;Yes, remember it
  1078.     jmp    sdat16        ;[MF] and set EOF state
  1079. sdat14:    cpi    'X'        ;Desire abort of current file?
  1080.     jnz    sdat15        ;If not, just continue
  1081.     sta    czseen        ;Yes, remember that
  1082.     jmp    sdat16        ;[MF] and set EOF
  1083. sdat15:    lda    czseen        ;Also get control-Z flag
  1084.     ora    a        ;Check if either given
  1085.     jz    sdat12        ;If neither given, continue
  1086. sdat16:    mvi    a,'Z'        ;Change state to EOF
  1087.     sta    state        ; .  .  .
  1088.     ret            ;And return
  1089.  
  1090. sdat12:    call    gtchr
  1091.     jmp    sdat13        ;Error go see if its EOF.
  1092.     sta    size        ;Save the size of the data gotten.
  1093.     ret
  1094.  
  1095. sdat13:    cpi    0FFH        ;Is it EOF?
  1096.     jnz    abort        ;If not give up.
  1097.     mvi    a,'Z'        ;Set the state to EOF.
  1098.     sta    state
  1099.     ret
  1100.  
  1101. sdata2:    cpi    'N'        ;NAK?
  1102.     jnz    sdata3        ;See if is an error packet.
  1103.     call    updrtr        ;Update the number of retries.
  1104.     lda    pktnum        ;Get the present packet number.
  1105.     inr    a        ;Increment
  1106.     ani    3FH        ; modulo 64
  1107.     mov    b,a
  1108.     lda    argblk        ;Get the packet's number.
  1109.     cmp    b        ;Is the packet's number one more than now?
  1110.     rnz            ;If not go try again.
  1111.     jmp    sdat12        ;Just as good as a ACK;go to the ACK code.
  1112.  
  1113. sdata3:    cpi    'E'        ;Is it an error packet.
  1114.     jnz    abort
  1115.     call    error
  1116.     jmp    abort
  1117. ;
  1118. ;       Send EOF
  1119. ;       called by: send
  1120.  
  1121. seof:    lda    numtry        ;Get the number of tries.
  1122.     cpi    maxtry        ;Have we reached the maximum number of tries?
  1123.     jm    seof1
  1124.     lxi    d,erms14
  1125.     call    error3
  1126.     jmp    abort        ;Change the state to abort.
  1127.  
  1128. seof1:    inr    a        ;Increment it.
  1129.     sta    numtry        ;Save the updated number of tries.
  1130.     lda    pktnum        ;Get the packet number.
  1131.     sta    argblk
  1132.     xra    a
  1133.     sta    argblk+1    ;No data.
  1134.     lda    czseen        ;Check if C-Z or C-X typed
  1135.     ora    a        ; .  .  .
  1136.     jz    seof14        ;If not aborted, just keep going
  1137.     mvi    a,'D'        ;Tell other end to discard packet
  1138.     sta    data        ;Store in data portion
  1139.     mvi    a,1        ;One character
  1140.     sta    argblk+1    ;Store the length
  1141. seof14:    mvi    a,'Z'        ;EOF packet.
  1142.     call    spack        ;Send the packet.
  1143.     jmp    abort        ; Failed, abort.
  1144.     call    rpack        ;Get a packet.
  1145.     jmp    r        ; Trashed packet don't change state, retry.
  1146.     cpi    'Y'        ;ACK?
  1147.     jnz    seof2        ;If not try next.
  1148.     call    compp
  1149.     rnz            ;If not hold out for the right one.
  1150. seof12:    call    countp
  1151.     lda    numtry        ;Get the number of tries.
  1152.     sta    oldtry        ;Save it.
  1153.     xra    a
  1154.     sta    numtry        ;Reset the number of tries.
  1155.     mvi    c,closf        ;Close the file.
  1156.     lxi    d,fcb
  1157.     call    bdos
  1158. ;* Check if successful
  1159.     lda    czseen        ;Desire abort of entire stream?
  1160.     cpi    'Z'        ;Desire abort of entire stream?
  1161.     jz    seof13        ;If so, just give up now
  1162.     call    mfname        ;Get the next file.
  1163.     jc    seof13        ; No more.
  1164.     call    getfil        ;and open it (assume success)
  1165.     xra    a        ;Clear A
  1166.     sta    czseen        ;Since we have not aborted this file
  1167.     mvi    a,'F'        ;Set the state to file send.
  1168.     sta    state
  1169.     ret
  1170.  
  1171. seof13:    mvi    a,'B'        ;Set the state to EOT.
  1172.     sta    state
  1173.     ret
  1174.  
  1175. seof2:    cpi    'N'        ;NAK?
  1176.     jnz    seof3        ;Try and see if its an error packet.
  1177.     call    updrtr        ;Update the number of retries.
  1178.     lda    pktnum        ;Get the present packet number.
  1179.     inr    a        ;Increment
  1180.     ani    3FH        ; modulo 64
  1181.     mov    b,a
  1182.     lda    argblk        ;Get the packet's number.
  1183.     cmp    b        ;Is the packet's number one more than now?
  1184.     rnz            ;If not go try again.
  1185.     jmp    seof12        ;Just as good as a ACK;go to the ACK code.
  1186.  
  1187. seof3:    cpi    'E'        ;Is it an error packet.
  1188.     jnz    abort
  1189.     call    error
  1190.     jmp    abort
  1191. ;
  1192. ;       Send EOT
  1193. ;       called by: send
  1194.  
  1195. seot:    lda    numtry        ;Get the number of tries.
  1196.     cpi    maxtry        ;Have we reached the maximum number of tries?
  1197.     jm    seot1
  1198.     lxi    d,erms14
  1199.     call    error3
  1200.     jmp    abort        ;Change the state to abort.
  1201.  
  1202. seot1:    inr    a        ;Increment it.
  1203.     sta    numtry        ;Save the updated number of tries.
  1204.     lda    pktnum        ;Get the packet number.
  1205.     sta    argblk
  1206.     xra    a
  1207.     sta    argblk+1    ;No data.
  1208.     mvi    a,'B'        ;EOF packet.
  1209.     call    spack        ;Send the packet.
  1210.     jmp    abort        ; Failed, abort.
  1211.     call    rpack        ;Get a packet.
  1212.     jmp    r        ; Trashed packet don't change state, retry.
  1213.     cpi    'Y'        ;ACK?
  1214.     jnz    seot2        ;If not try next.
  1215.     call    compp
  1216.     rnz            ;If not hold out for the right one.
  1217. seot12:    call    countp
  1218.     lda    numtry        ;Get the number of tries.
  1219.     sta    oldtry        ;Save it.
  1220.     xra    a
  1221.     sta    numtry        ;Reset the number of tries.
  1222.     mvi    a,'C'        ;Set the state to file send.
  1223.     sta    state
  1224.     ret
  1225.  
  1226. seot2:    cpi    'N'        ;NAK?
  1227.     jnz    seot3        ;Is it error.
  1228.     call    updrtr        ;Update the number of retries.
  1229.     lda    pktnum        ;Get the present packet number.
  1230.     inr    a        ;Increment
  1231.     ani    3FH        ; modulo 64
  1232.     mov    b,a
  1233.     lda    argblk        ;Get the packet's number.
  1234.     cmp    b        ;Is the packet's number one more than now?
  1235.     rnz            ;If not go try again.
  1236.     jmp    seot12        ;Just as good as a ACK;go to the ACK code.
  1237.  
  1238. seot3:    cpi    'E'        ;Is it an error packet.
  1239.     jnz    abort
  1240.     call    error
  1241.     jmp    abort
  1242. ;
  1243. ;       This routine sets up the data for init packet (either the
  1244. ;       Send_init or ACK packet).
  1245. ;       called by: rinit, rfile, sinit
  1246. ;
  1247. ; Called by rinit, rfile and sinit.  See what WE want from the other fella
  1248. ;
  1249. ; [11] by OBS - Stripped out all the new capas code etc and reverted
  1250. ;    to Good Ol' Basic Kermit again!
  1251. ;    Those keen should study the followin gode with care, and remove
  1252. ;    or add semicolons as indicated.
  1253. ;
  1254. ; See also SPAR which decodes what comes in.  It also decodes bits in 
  1255. ;    the "capability" fields.  (Two CAPAS files allowed from remote
  1256. ;    machines, but we will only send one at max.)  Note that not all 
  1257. ;    if any of the capability bits will be used.
  1258. ;
  1259. ; Definitions - init packet (data section only.. rest of header assumed OK)
  1260. ;    Byte 0    Maximum length I want to send
  1261. ;         1    The Timeout I want you to use
  1262. ;         2    Number of PAD characters I want tot use (May be null)
  1263. ;         3    The PAD character I want to use (May be Null)
  1264. ;         4    The End-of-Line character I will use (Carriage Return)
  1265. ;         5    The control character Quote Character I will use (#)
  1266. ;         6    The parity bit Quote Character I will use (&)
  1267. ;         7    The Checktype I will use
  1268. ;         8    The repeat prefix I will use (Null, as we cannot to repeats)
  1269. ;         9    Capability Byte 0 (See SPAR for defs)
  1270. ;        10    Capability byte 1 ( --- " --- but we will not send it.)
  1271. ;        11    The number of packets I will send per window (not used)
  1272. ;        12  MAXL1 - Long packet size, ms count
  1273. ;        13    MAXL2 - Long packet size, ls count
  1274. ;
  1275. ;
  1276. ; Enter with HL pointing to the "data" part of the packet.
  1277.  
  1278. ;
  1279. ; older part of rpar follows...
  1280. ;
  1281. ;
  1282. rpar:    lda    rpsiz        ;Get the receive packet size.
  1283.     adi    space        ;Add a space to make it printable.
  1284.     mov    m,a        ;Put it in the packet.
  1285.     inx    h        ;Point to the next char.
  1286.     lda    rtime        ;Get the receive packet time out.
  1287.     adi    space        ;Add a space.
  1288.     mov    m,a        ;Put it in the packet.
  1289.     inx    h
  1290.     lda    rpad        ;Get the number of padding chars.
  1291.     adi    space
  1292.     mov    m,a
  1293.     inx    h
  1294.     lda    rpadch        ;Get the padding char.
  1295.     adi    100O        ;Uncontrol it.
  1296.     ani    7FH
  1297.     mov    m,a
  1298.     inx    h
  1299.     lda    reol        ;Get the EOL char.
  1300.     adi    space
  1301.     mov    m,a
  1302.     inx    h
  1303.     lda    rquote        ;Get the quote char.
  1304.     mov    m,a
  1305.     inx    h
  1306.     mvi    m,'Y'        ;[jd] we know how to do 8-bit quoting
  1307.     lda    parity        ;[jd]
  1308.     cpi    parnon        ;[jd] parity none?
  1309.     jz    rpar1        ;[jd] yes, keep going
  1310.     lda    qbchr        ;[jd] no, better request 8-bit quoting
  1311.     mov    m,a
  1312.  
  1313. rpar1:
  1314.     inx    h        ;Advance to next
  1315.     lda    chktyp        ;Get desired block check type
  1316.     mov    m,a        ;Store it
  1317.     inx    h        ;Advance pointer
  1318.  
  1319. ; Comment out the next two lines for capas etc.  WILL require debugging
  1320.     mvi    a,8        ; this id the older end for this routine.  May be useful.
  1321.     ret
  1322.  
  1323. ; [11] Rest not needed for now, commented out
  1324. ; [10] (to ret)
  1325. ; New additions to rpar follows...
  1326.  
  1327. ;    lda    rcap1        ; get the first capability byte
  1328. ;    ani    3eh        ; mask out bit 0, ie only one CAPAS byte
  1329. ;    adi    space        ; tochar it
  1330. ;    mov    m,a
  1331. ;    inx    h
  1332. ;    mvi    m,space        ; No windows, ie space to packet
  1333. ;    inx    h
  1334. ;    push    h        ; we need the HL regs for maths.
  1335. ;    lhld    rdpkt        ; get receive packet length
  1336. ;    lxi    d,95        ; we want hl div 95 and hl mod 95
  1337. ;    call    divide        ; return with divsion in hl, remainder in de
  1338. ;    mov    a,l        ; two sets of bytes
  1339. ;    pop    h
  1340. ;    adi    space        ; tochar(maxl1)
  1341. ;    mov    m,a
  1342. ;    inx    h
  1343. ;    mov    a,l
  1344. ;    adi    space        ; tochar(maxl2)
  1345. ;    mov    m,a
  1346. ;
  1347. ; done all, set databytes = 12 and return
  1348. ;    mvi    a,12        ; 12 bits of data
  1349. ;    ret
  1350.  
  1351. ;[11] End of commented out code for rpar
  1352.  
  1353.  
  1354. ;
  1355. ;       This routine reads in all the send_init packet information.
  1356. ;       called by: rinit, sinit
  1357.  
  1358. ;[11] As for rpar, restore the "old" kermit code for non-capas Kermit.
  1359. ;[10] (to ret at end)
  1360. ;
  1361. ; SPAR - routine to decode parameters received from the remote end
  1362. ;
  1363. ;    Called by rinit,sinit
  1364. ;
  1365. ;    Entry:    a: Number of databytes in packet
  1366. ;        hl: Pointer to "data" part of packet
  1367. ;
  1368. ;spar:    sta    temp4        ; save for a while
  1369. ;                ; first clear some variables
  1370. ;    lda    dspsiz        ; get default "send" packet length
  1371. ;    sta    spktl
  1372. ;    lda    dstime        ; get default time-out
  1373. ;    sta    stimeo
  1374. ;    xra    a        ; set no pad characters by default
  1375. ;    sta    spad
  1376. ;    lda    dspadc        ; get the default padding character
  1377. ;    sta    spadc
  1378. ;    mvi    a,cr        ; default end of line character (CR)
  1379. ;    sta    seol
  1380. ;    mvi    a,dsquot    ; default quote character
  1381. ;    sta    squote
  1382. ;    mvi    a,dsbqut    ; default binary quote character
  1383. ;    sta    qbchr
  1384. ;    mvi    a,dschkt    ; set checktype = 1 for inits
  1385. ;    sta    inichk
  1386. ;    mvi    a,space        ; no repeat prefixing ( otherwise ~)
  1387. ;    sta    srept
  1388. ;
  1389. ; Now follows the "capabilities" bits... 5 bits per capas byte.
  1390. ;
  1391. ;     Note: Before extracting any data bits, apply unchar() to get the 
  1392. ;    six ls bits.  If bit 0 = 1 the a subsequent capaa byte follows
  1393. ;
  1394. ;    Byte0:    Bit 0:    Set to 1 if there are subsequent CAPAS bytes
  1395. ;            1:    (Cap. 5) Set to 1 for long packets.  Second byte
  1396. ;            AFTER the last capas byte has packet length DIV 95
  1397. ;            and Thire byte has length MOD 95
  1398. ;            2:    (Cap. 4) Sliding Windows.  If used, first byte AFTER
  1399. ;            last capas byte has TOCHAR(no. of packets in window)
  1400. ;            3:    (Cap. 3) Ability to accept "A" (attribute packets)
  1401. ;            4:    (Cap. 2) Reserved
  1402. ;            5:    (Cap. 1) Reserved
  1403. ;    Byte 2 onward: not used in this implementation. Any capas bytes sent 
  1404. ;        will be stored, however.
  1405. ;
  1406. ;    lda    temp4        ; get the number of bytes to test
  1407. ;    mov    c,a        ; to a count register
  1408. ;    mov    a,m        ; get first byte
  1409. ;    call    decc        ; unchar it, and decrement c
  1410. ;    sta    spsiz        ; save a send packet size
  1411. ;    jz    sparx        ; if no more, exit
  1412. ;
  1413. ;    mov    a,m        ; get timout
  1414. ;    call    decc
  1415. ;    sta    stime        ; save timeout
  1416. ;    jz    sparx
  1417. ;
  1418. ;    mov    a,m        ; get pad characters
  1419. ;    call    decc    
  1420. ;    sta    spadc        ; save it
  1421. ;    jz    sparx
  1422. ;
  1423. ;    mov    a,m        ; get pad character count
  1424. ;    call    decc
  1425. ;    sta    spad
  1426. ;    jz    sparx
  1427. ;
  1428. ;    mov    a,m        ; get send EOL
  1429. ;    call    decc
  1430. ;    sta    seol
  1431. ;    jz    sparx
  1432. ;
  1433. ;    mov    a,m        ; get control quote character
  1434. ;    call    decc
  1435. ;    sta    squote
  1436. ;    jz    sparx
  1437. ;
  1438. ;    mov    a,m        ; get binary (parity) quote char
  1439. ;    mov    b,a        ; this time we actually WANT accumulator
  1440. ;    cpi    space        ; are we doing 8th bit quoteing
  1441. ;    jz    spar1        ; dont know, assume not
  1442. ;    cpi    'N'        ; definately not?
  1443. ;    jz    spar1
  1444. ;    cpi    'Y'        ; definately - use &
  1445. ;    jz    spar2
  1446. ;    sta    squote        ; else save the new character
  1447. ;spar2:    lda    parity        ; see if we are using the parity bit
  1448. ;    cpi    parnon        ; no parity => no quoting
  1449. ;    jz    spar3        ; yup, so use the default quote character &
  1450. ;
  1451. ;spar1:    xra    a        ; save not quoting
  1452. ;    sta    squote
  1453. ;spar3:    call    decc        ; update counters etc
  1454. ;    jz    sparx
  1455. ;
  1456. ;    mov    a,m        ; get repeat prefixing
  1457. ;    call    decc
  1458. ;    push    psw        ; save flags
  1459. ;    cpi    space-32    ; we want it?
  1460. ;    jz    spar4
  1461. ;    sta    srept
  1462. ;spar4:    pop    psw        ; restore flags
  1463. ;    jz    sparx
  1464. ;
  1465. ;    lxi    d,scapas    ; point to start of capability byte(s)
  1466. ;    push    psw        ; must do this...
  1467. ;spar5:    pop    psw        ; cos we restore the spack
  1468. ;    mov    a,m
  1469. ;    call    decc        ; get scap1 (or n)
  1470. ;    sta    scap1
  1471. ;    push    psw
  1472. ;    ani    01        ; another byte following?
  1473. ;    jnz    spar5
  1474. ;    pop    psw        ; see if any other data bytes (Windows etc)
  1475. ;    jz    sparx
  1476. ;
  1477. ;    mov    a,m        ; get window size
  1478. ;    call    decc
  1479. ;    sta    swindo
  1480. ;    jz    sparx
  1481. ;
  1482. ;    mov    a,m        ; get long packets ms bits
  1483. ;    call    decc        ;
  1484. ;    mov    d,a        ; unchared ms bits-ish
  1485. ;    mov    a,m
  1486. ;    call    decc        ; ls bits-ish
  1487. ;    push    h        ; and we are doing maths
  1488. ;    push    b        ; and an intermediate result in c
  1489. ;    push    psw        ; we want flags  and the ls bits...
  1490. ;    mvi    b,0
  1491. ;    mov    c,d        ; get ms bits-ish to bc
  1492. ;    push    b        ; get number to hl
  1493. ;    pop    h
  1494. ; now multipy by 95
  1495. ;    dad    h        ;*2
  1496. ;    dad    h        ;*4
  1497. ;    dad    h        ;*8
  1498. ;    dad    h        ;*16
  1499. ;    push    h        ; *16 to ...
  1500. ;    pop    d        ; ... de
  1501. ;    dad    h        ;*32
  1502. ;    dad    d        ; *(32+16) = *48
  1503. ;    dad    h        ; *96
  1504. ;    mov    a,l        ; *(96-1)
  1505. ;    sub    c
  1506. ;    mov    l,a
  1507. ;    mov    a,0
  1508. ;    sbb    h
  1509. ;    mov    h,a
  1510. ;    pop    psw        ; restore ls bitsish
  1511. ;    mov    e,a
  1512. ;    mvi    d,0
  1513. ;    dad    d        ; *95 + ls bits. Phew.
  1514. ;    shld    sdpkt        ; save long packet length
  1515. ;    pop    b
  1516. ;    pop    h        ; restore regs
  1517. ;
  1518. ;sparx:    ret            ; if here, (assume) no more data to read in
  1519. ;[10] routines required follow
  1520. ;decc:    mov    a,m        ; get data byte
  1521. ;    sui    space        ; unchar it
  1522. ;    inx    h        ; increment input pointer
  1523. ;    dcr    c        ; decrement data counter
  1524. ;    ret            ; return
  1525. ;[10] end or spar replacement
  1526.  
  1527. ;[11] Restore older spar....
  1528. ; Older spar follows...
  1529. spar:    sta    temp4        ;Save the number of arguments.
  1530. ; Initialize some variables to their required default values, so we use
  1531. ; the right values even if the remote Kermit doesn't send the full packet:
  1532. ;                                  ; we don't do anything with timeout values yet.
  1533. ;                                  ; no default pad count/pad character?
  1534.     mvi    a,cr        ; EOL character = carriage-return
  1535.     sta    seol
  1536.     mvi    a,'#'        ; quote character = '#'
  1537.     sta    squote
  1538.     mvi    a,'&'        ; eighth-bit quote character = '&'
  1539.     sta    qbchr
  1540.     mvi    a,'1'        ; block-check = 1-character-checksum
  1541.     sta    inichk
  1542.     mov    a,m        ;Get the max packet size.
  1543.     sbi    space        ;Subtract a space.
  1544.     sta    spsiz        ;Save it.
  1545.     lda    temp4
  1546.     cpi    3        ;Fewer than three pieces?
  1547.     rm            ;If so we are done.
  1548.     inx    h
  1549.     inx    h        ;Increment past the time out info.
  1550.     mov    a,m        ;Get the number of padding chars.
  1551.     sbi    space
  1552.     sta    spad
  1553.     lda    temp4
  1554.     cpi    4        ;Fewer than four pieces?
  1555.     rm            ;If so we are done.
  1556.     inx    h
  1557.     mov    a,m        ;Get the padding char.
  1558.     adi    100O        ;Re-controlify it.
  1559.     ani    7FH
  1560.     sta    spadch
  1561.     lda    temp4
  1562.     cpi    5        ;Fewer than five pieces?
  1563.     rm            ;If so we are done.
  1564.     inx    h
  1565.     mov    a,m        ;Get the EOL char.
  1566.     sbi    space
  1567.     sta    seol
  1568.     lda    temp4
  1569.     cpi    6        ;Fewer than six pieces?
  1570.     rm            ;If so we are done.
  1571.     inx    h
  1572.     mov    a,m        ;Get the quote char.
  1573.     sta    squote
  1574.     lda    temp4        ;Get the amount of data supplied
  1575.     cpi    7        ;Have an 8-bit quote?
  1576.     rm            ;If not there, all done
  1577.     inx    h        ;Yes, get the character
  1578.     mvi    a,0        ;[jd] 
  1579.     sta    quot8        ;[jd] assume not quoting
  1580.     mov    a,m        ;Get the supplied character
  1581.     cpi    'N'        ;[jd] No?
  1582.     jz    spar1        ;[jd] then don't try to do it
  1583.     cpi    space        ;[jd] maybe they don't know about it...
  1584.     jz    spar1        ;[jd] then don't try to do it.
  1585.     cpi    'Y'        ;[jd] Yes?
  1586.     jnz    spar2        ;[jd] if not 'Y', assume it's a quote char.
  1587.     lda    parity        ;[jd] using parity?
  1588.     cpi    parnon        ;[jd] no, don't need quoting...
  1589.     jz    spar1        ;[jd] 
  1590.     mvi    a,0ffh        ;[jd] else turn on...
  1591.     sta    quot8        ;[jd] ...quote flag
  1592.     jmp    spar1
  1593.  
  1594. ;[11] Note: If capas etc required, beware of the next two lables, as these 
  1595. ; are used elswhere.
  1596.  
  1597. spar2:    sta    qbchr        ;[jd] use their quote char (should validate)
  1598.     mvi    a,0ffh
  1599.     sta    quot8        ;[jd] turn quote flag and fall thru...
  1600.  
  1601. spar1:    lda    temp4        ;Determine if block check type given
  1602.     cpi    8        ;Is the field there?
  1603.     rm            ;If not, all done
  1604.     inx    h        ;Point to the character
  1605.     mov    a,m        ;Get the value
  1606.     mov    b,a        ;Copy value
  1607.     lda    chktyp        ;Get our type
  1608.     cmp    b        ;Is it our desired type?
  1609.     rnz            ; If not, use default (1-character-checksum)
  1610.     sta    inichk        ; Match, store as type to use after init
  1611.     ret            ; and return
  1612. ;[10] end of replacement
  1613. ;[11] end of replacement of replacement (ie back to original code)
  1614. ;
  1615.  
  1616. ;       Copy characters from packet to disk (or screen)
  1617. ;       called by: rdata
  1618.  
  1619. ptchr:    sta    temp1        ;Save the size.
  1620.     lda    remtxt        ;[MF]Get remote command flag
  1621.     ora    a        ;[MF]Remote command in progress?
  1622.     jnz    ptchr0        ;[MF]Yes, don't check for file collisions
  1623.     lda    flwflg        ;[MF]Get File Warning (Set Collision) flag
  1624.     cpi    3        ;[MF]SET COLLISION DISCARD?
  1625.     jnz    ptchr0        ;[MF]No
  1626.     lda    dscflg        ;[MF]Yes, get "discard" flag
  1627.     ora    a        ;[MF]Discarding file?
  1628.     jz    ptchr0        ;[MF]No
  1629.     mvi    a,'X'        ;[MF]Yes, simulate a user rejection
  1630.     sta    czseen        ;[MF]...
  1631.     jmp    rskp        ;[MF]and pretend success
  1632. ptchr0:                ;[MF]
  1633.     lxi    h,data        ;Beginning of received packet data.
  1634.     shld    outpnt        ;Remember where we are.
  1635.     lda    rquote
  1636.     mov    b,a        ;Keep the quote char in b.
  1637.     mvi    c,0        ;[jd] assume no 8-bit quote char
  1638.     lda    quot8        ;[jd] doing 8-bit quoting?
  1639.     ora    a
  1640.     jz    ptchr1        ;[jd] no, keep going
  1641.     lda    qbchr        ;[jd] else get 8-bit quote char
  1642.     mov    c,a        ;[jd] keep this in c
  1643. ptchr1:    lxi    h,temp1
  1644.     dcr    m        ;Decrement # of chars in packet.
  1645.     jm    rskp        ;Return successfully if done.
  1646.     lda    remtxt        ; to screen only?
  1647.     ana    a
  1648.     jnz    ptchr2        ; dont do any disk stuff
  1649.     lxi    h,chrcnt    ;Number of chars remaining in dma.
  1650.     dcr    m        ;Decrement.
  1651.     jp    ptchr2        ;Continue if space left.
  1652.     call    outbuf        ;Output it if full.
  1653.     jmp    ptchr9        ; Error return if disk is full.
  1654. ptchr2:    lhld    outpnt        ;Get position in output buffer.
  1655.     mov    a,m        ;Grab a char.
  1656.     inx    h
  1657.     shld    outpnt        ;and bump pointer.
  1658.     mvi    e,0        ;[jd] assume nothing to OR in.
  1659.     cmp    c        ;[jd] is it the binary quote char?
  1660.     jnz    ptch2a        ;[jd] no, keep going
  1661.     mvi    e,80h        ;[jd] include parity bit
  1662.     lda    temp1
  1663.     dcr    a
  1664.     sta    temp1        ;[jd] decrement character count
  1665.     mov    a,m        ;[jd] get next character
  1666.     inx    h
  1667.     shld    outpnt
  1668. ptch2a:    cmp    b        ;Is it the quote char?
  1669.     jnz    ptchr3        ;[jd] changed to ptchr3 so includes parity
  1670.     mov    a,m        ;Get the quoted character
  1671.     inx    h
  1672.     shld    outpnt        ;and bump pointer.
  1673.     lxi    h,temp1
  1674.     dcr    m        ;Decrement # of chars in packet.
  1675.     mov    d,a        ;Save the char.
  1676.     ani    80H        ;Turn off all but the parity bit.
  1677.     ora    e        ;[jd] let parity come from either (???)
  1678.     mov    e,a        ;Save the parity bit.
  1679.     mov    a,d        ;Get the char.
  1680.     ani    7FH        ;Turn off the parity bit.
  1681.     cmp    b        ;Is it the quote char?
  1682.     jz    ptchr3        ;If so just go write it out.
  1683.     cmp    c        ;[jd] maybe it's the 8-bit prefix character?
  1684.     jz    ptchr3        ;[jd] then don't controllify.
  1685.     mov    a,d        ;Get the char.
  1686.     adi    40H        ;Make the character a control char again.
  1687.     ani    7FH        ;Modulo 128.
  1688. ptchr3:    ora    e        ;Or in the parity bit.
  1689.     sta    temp3        ; save for a while
  1690.     lda    remtxt        ; to screen or disk?
  1691.     ana    a
  1692.     lda    temp3
  1693.     jz    ptch31        ; to disk
  1694.     push    h
  1695.     push    d
  1696.     push    b
  1697.     mov    e,a        ; to display
  1698.     mvi    c,dconio
  1699.     call    bdos
  1700.     pop    b
  1701.     pop    d
  1702.     pop    h
  1703.     jmp    ptchr1        ; continue
  1704.  
  1705. ptch31:    lhld    bufpnt        ;Destination buffer.
  1706.     mov    m,a        ;Store it.
  1707.     inx    h
  1708.     shld    bufpnt        ;Update the pointer
  1709.     jmp    ptchr1        ;and loop to next char.
  1710.  
  1711. ptchr9:    lxi    d,erms11    ; "?Disk full"
  1712.     push    d        ;[MF] Save pointer
  1713.     call    error3        ; put it on the error line
  1714.     pop    d        ;[MF] Restore pointer
  1715.     lxi    h,data        ;[MF] Where to put the message for "e" packet
  1716.     lda    argblk        ;[MF] Get packet-number
  1717.     call    countp        ;[MF]Increment it
  1718.     sta    argblk        ;[MF] as packet to send
  1719.     xra    a        ;[MF] Zero length of packet data
  1720.     sta    temp1        ;[MF] ...
  1721. ptch9a:    ldax    d        ;[MF] Get a character to copy
  1722.     cpi    cr        ;[MF] No more to copy?
  1723.     jz    ptch9b        ;[MF] Yes, we can send the packet
  1724.     mov    m,a        ;[MF] No, copy the character
  1725.     inx    d        ;[MF] and increment source/dest pointers
  1726.     inx    h        ;[MF] ...
  1727.     lda    temp1        ;[MF] Get character count
  1728.     inr    a        ;[MF] and increment it
  1729.     sta    temp1        ;[MF] ...
  1730.     jmp    ptch9a        ;[MF] Copy entire error message
  1731. ptch9b:    mvi    m,0        ;[MF]Put in a zero
  1732.     lda    temp1        ;[MF] Get number of characters in the message
  1733.     sta    argblk+1    ;[MF] and store as number of packet data chars
  1734.     mvi    a,'E'        ;[MF] Make it an error packet
  1735.     call    spack        ;[MF] Send the error packet
  1736.     nop            ;[MF] Don't really care if
  1737.     nop            ;[MF] the send fails since we're
  1738.     nop            ;[MF] bombing off anyway
  1739.     ret            ; take error return.
  1740. ;
  1741. ;       Fill a data packet from file
  1742. ;       called by: sfile, sdata
  1743.  
  1744. gtchr:    lda    squote        ;Get the quote char.
  1745.     mov    c,a        ;Keep quote char in c.
  1746.     lda    curchk        ;Get current block check type
  1747.     sui    '1'        ;Get the extra overhead
  1748.     mov    b,a        ;Get a copy
  1749.     lda    spsiz        ;Get the maximum packet size.
  1750.     sui    5        ;Subtract the overhead.
  1751.     sub    b        ;Determine max packet length
  1752.     sta    temp1        ;This is the number of chars we are to get.
  1753.     lxi    h,filbuf    ;Where to put the data.
  1754.     shld    cbfptr        ;Remember where we are.
  1755.     mvi    b,0        ;No chars.
  1756. gtchr1:    lda    temp1
  1757.     dcr    a        ;Decrement the number of chars left.
  1758.     jp    gtchr2        ;Go on if there is more than one left.
  1759.     mov    a,b        ;Return the count in A.
  1760.     jmp    rskp
  1761.  
  1762. gtchr2:    sta    temp1
  1763.     lda    chrcnt        ;Space left in the DMA.
  1764.     dcr    a
  1765. ;* Can improve order here.
  1766.     jm    gtchr3
  1767.     sta    chrcnt
  1768.     jmp    gtchr4
  1769.  
  1770. gtchr3:    call    inbuf        ;Get another buffer full.
  1771.     jmp    gtch30        ; If no more return what we got.
  1772.     jmp    gtchr4        ;If we got some, proceed.
  1773.  
  1774. gtch30:    mov    a,b        ;Return the count in A.
  1775.     ora    a        ;Get any chars?
  1776.     jnz    rskp        ;If so return them.
  1777.     jmp    gtceof        ;If not, say we found the end of the file.
  1778.  
  1779. gtchr4:    lhld    bufpnt        ;Position in DMA.
  1780.     mov    a,m        ;Get a char from the file.
  1781.     inx    h
  1782.     shld    bufpnt
  1783.     mov    d,a        ;Save the char.
  1784.     ani    80H        ;Turn off all but parity.
  1785.     mov    e,a        ;Save the parity bit.
  1786.     jz    gtch4a        ;[jd] no parity, skip this check...
  1787.     lda    quot8        ;[jd] doing eighth-bit quoting?
  1788.     ora    a
  1789.     jz    gtch4a        ;[jd] no, just proceed normally
  1790.     lda    temp1        ;[jd] get space remaining
  1791.     cpi    2        ;[jd] 3 chrs left (one cnted already)?
  1792.     jm    gtchr9        ;[jd] no, skip this
  1793.     dcr    a        ;[jd] decrement space remaining
  1794.     sta    temp1        ;[jd] put back.
  1795.     lhld    cbfptr        ;[jd] Position in character buffer.
  1796.     lda    qbchr        ;[jd] get quote character
  1797.     mov    m,a        ;]jd] Put the quote char in the buffer.
  1798.     inx    h        ;[jd] increment destination buffer pointer
  1799.     shld    cbfptr        ;[jd] store the pointer back
  1800.     inr    b        ;[jd] Increment the char count.
  1801.     mvi    e,0        ;[jd] no parity bit to OR in.
  1802. ;[jd] fall thru...
  1803.  
  1804. gtch4a:    mov    a,d        ;Restore the char.
  1805.     ani    7FH        ;Turn off the parity.
  1806.     mov    d,a        ;[jd] save here for later...
  1807.     cpi    space        ;Compare to a space.
  1808.     jm    gtchr5        ;If less then its a control char, handle it.
  1809.     cpi    del        ;Is the char a delete?
  1810.     jz    gtchr5        ;Go quote it.
  1811.     lda    quot8        ; Are we doing 8th-bit quoting?
  1812.     ora    a
  1813.     jz    gtch4c        ; if not, skip this test and restore character.
  1814.     lda    qbchr        ; get 8th-bit quote character
  1815.     cmp    d        ; same as current character?
  1816.     jz    gtch4b        ; yes, have to quote it...
  1817. gtch4c:    mov    a,d        ; no. get character back again.
  1818.     cmp    c        ;Is it the quote char?
  1819.     jnz    gtchr8        ;If not proceed.
  1820. gtch4b:    lxi    h,temp1        ;[jd] point to char count
  1821.     dcr    m        ;[jd] decrement (know room for at least one)
  1822.     lhld    cbfptr        ;Position in character buffer.
  1823.     mov    m,c        ;Put the (quote) char in the buffer.
  1824.     inx    h
  1825.     shld    cbfptr
  1826.     inr    b        ;Increment the char count.
  1827.     mov    a,d        ;[jd] restore character again
  1828.     jmp    gtchr8
  1829.  
  1830. gtchr5:    
  1831.     ;[gnn] ignore parity for checking
  1832. ;       ora     e        ;Turn on the parity bit.
  1833.  
  1834.     cpi    ('Z'-100O)         ;Is it a ^Z?
  1835.     jnz    gtchr7        ;If not just proceed.
  1836.     lda    cpmflg        ;Was the file created by CPM...
  1837.     cpi    1        ;in ASCII-mode ?
  1838.     jz    gtch52        ;Control-Z stops text
  1839.     cpi    2        ;in BINARY mode?
  1840.     jz    gtchr6        ;Yes, pass the ^Z
  1841. ;At this point file-mode is DEFAULT.
  1842. ;If the rest of the record is filled with ^Zs, we're at EOF, otherwise
  1843. ;its a regular character.
  1844.     lhld    bufpnt        ;since CHRCNT is ZERO at EOF-time
  1845.     lda    chrcnt        ;(set by INBUF5 B.G.E)
  1846.     mov    d,a        ;Get the number of chars left in the DMA.
  1847. gtch51:    dcr    d
  1848.     mov    a,d
  1849.     jp    gtch53        ;Any chars left?
  1850. gtch52:    xra    a        ;If not, get a zero.
  1851.     sta    chrcnt        ;Say no more chars in buffer.
  1852.     mov    a,b        ;Return the count in A.
  1853.     jmp    rskp
  1854.  
  1855. ;Scan rest of buffer for non ^Z -- If we find a non ^Z, fall into gtchr6.
  1856. ;If we get to the end of the buffer before finding a non ^Z, fall into gtch52.
  1857. gtch53:    mov    a,m        ;Get the next char.
  1858.     inx    h        ;Move the pointer.
  1859.     cpi    ('Z'-100O)         ;Is it a ^Z?
  1860.     jz    gtch51        ;If so see if the rest are.
  1861.  
  1862. gtchr6:    mvi    a,('Z'-100O)       ;Restore the ^Z.
  1863. gtchr7:    sta    temp2        ;Save the char.
  1864.     lxi    h,temp1        ;Point to the char total remaining.
  1865.     dcr    m        ;Decrement it.
  1866.     lhld    cbfptr        ;Position in character buffer.
  1867.     mov    m,c        ;Put the quote in the buffer.
  1868.     inx    h
  1869.     shld    cbfptr
  1870.     inr    b        ;Increment the char count.
  1871.     lda    temp2        ;Get the control char back.
  1872.     adi    40H        ;Make the non-control.
  1873.     ani    7fH        ;Modulo 200 octal.
  1874. gtchr8:    lhld    cbfptr        ;Position in character buffer.
  1875.     ora    e        ;Or in the parity bit.
  1876.     mov    m,a        ;Put the char in the buffer.
  1877.     inx    h
  1878.     shld    cbfptr
  1879.     inr    b        ;Increment the char count.
  1880.     jmp    gtchr1        ;Go around again.
  1881.  
  1882. gtchr9:    ;[jd] not enough room left in buffer...
  1883.     lhld    bufpnt
  1884.     dcx    h
  1885.     shld    bufpnt        ;[jd] back up over last character
  1886.     lxi    h,chrcnt    ;[jd] point to character count
  1887.     inr    m        ;[jd] increment it
  1888.     mov    a,b        ;[jd] count of chars transferred
  1889.     jmp    rskp        ;[jd] return it
  1890.  
  1891. gtceof:    mvi    a,0FFH        ;Get a minus one.
  1892.     ret
  1893. ;
  1894.  
  1895. ; Little code to allow some expansion of code without changing
  1896. ;  every futher address, only up to the end of this file.
  1897. ;   TO BE REMOVED FRO RELEASE!
  1898.  
  1899. ;    org ($+100h) AND 0FF00H
  1900.  
  1901. IF    lasm
  1902.     LINK    CPSPK2        ;[obs] Link to part two of the packet file
  1903. ENDIF    ;lasm
  1904.