home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol048 / xmodem46.asm < prev   
Assembly Source File  |  1984-04-29  |  40KB  |  1,581 lines

  1. ;
  2. ;    XMODEM.ASM V4.6, by Keith Petersen, W8SDZ
  3. ;           (revised 10/19/81)
  4. ;
  5. ;    REMOTE CP/M - CP/M FILE TRANSFER PROGRAM
  6. ;
  7. ;Based on MODEM.ASM V2.0, by Ward Christensen.
  8. ;This program is intended for use on remote CP/M
  9. ;systems where it is important that the initialization
  10. ;of the modem not be changed, such as when using
  11. ;the PMMIBYE program. The baud rate and number of bits
  12. ;remains the same as whatever was set previously.
  13. ;There is no disconnect, terminal or echo option.
  14. ;
  15. ;Updates/fixes (in reverse order to minimize reading time):
  16. ;
  17. ;10/19/81 Corrected numerous 'IN MODCTL2' errors for the DC
  18. ;      Hayes modem.  Added DC Hayes detection of framing
  19. ;      errors, overrun errors, and parity errors (if
  20. ;      parity is used) for the receive file routine.
  21. ;      (Bill Aten)
  22. ;
  23. ;10/12/81 Added code to implement Cyclic Redundancy
  24. ;      Checking for both receiving and sending files.
  25. ;      The CRC can only be specified by the operator
  26. ;      on the receive file option as a secondary
  27. ;      option of 'C' (XMODEM RC FN.FT).  When CRC is
  28. ;      in effect, an initial 'C' instead of a NAK will
  29. ;      be sent to the sender to start things off.
  30. ;      The 'C' will be the signal to the sender
  31. ;      (hopefully a version of MODEM that implements
  32. ;      this CRC convention) that CRC is in effect.
  33. ;      CRC will then take the place of the checksum
  34. ;      checking for data validity.  The CRC should
  35. ;      make file transfers as far as data integrity is
  36. ;      concerned better than 99.99% error free.  The
  37. ;      crc macro, CRC120, was used to implement CRC
  38. ;      in this program and its equivalent version of
  39. ;      MODEM.  Acknowledgements and thanks to Paul
  40. ;      Hansknecht who designed and wrote CRC120.
  41. ;
  42. ;07/01/81 REDID H8/H89 EQUATES TESTED PROGRAM USING BOTH
  43. ;      SYSTEMS AND CHANGED VER TO 4.4    (AL OLANDER)
  44. ;
  45. ;06/28/81 INSTALL H8/H89 EQUATES AND CHANGE EXTERNAL
  46. ;      MODEM EQUATES TO "EXTMOD". (L. SHIPINSKI)
  47. ;
  48. ;05/30/81 Added IF PMMI/ENDIF to RCVERR routine to eliminate
  49. ;      'undefined symbol' error when set for DCH modem.
  50. ;      (Dave Hardy)
  51. ;
  52. ;05/07/81 Changed signon revision number.
  53. ;      Cleaned up file. (KBP)
  54. ;
  55. ;05/01/81 Added detection of framing errors, overrun
  56. ;      errors, and parity errors (if parity is used)
  57. ;      for the receive file routine.  This feature
  58. ;      is only active for the PMMI modem, since I
  59. ;      do not know what the modem status bits are
  60. ;      for IDS and D.C. Hayes modems.  If there
  61. ;      is one of the above errors, the line will
  62. ;      be purged for that block and a NAK will be
  63. ;      sent to the sender for that block.  This was
  64. ;      added to help catch those transmission errors
  65. ;      that are not always caught by the checksum.
  66. ;      This error checking is in addition to the
  67. ;      checksum routine. (John Mahr)
  68. ;
  69. ;02/17/81 Added test for "f2" tagged files in OPENOK
  70. ;      for MP/M version 1.1 compatiblity, which
  71. ;      doesn't allow Ctl-C or Ctl-S in "f1" tagged
  72. ;      files. (Tim Nicholas)
  73. ;
  74. ;02/16/81 Added hex to file size display. Now reports
  75. ;      size in both decimal and (xxxxH) hex. Thanks
  76. ;      to Ben Bronson for the idea. (Tim Nicholas)
  77. ;
  78. ;02/15/81 Added a software timer to the carrier test
  79. ;      added in SEND and RECV routines. This will
  80. ;      now abort only if carrier is lost for a 
  81. ;      period of 15 seconds. This is only essential
  82. ;      for those using external modems with certain
  83. ;      SIO's, but will provide the PMMI/DCH user
  84. ;      faster recovery in a lost carrier situation
  85. ;      as well. Approx 15 seconds plus 15 seconds
  86. ;      in BYE.COM, compared to 3 minutes at 300
  87. ;      baud with earlier revisions. Thanks to Ben
  88. ;      Bronson for his aid in developing this
  89. ;      revision. (Tim Nicholas)
  90. ;
  91. ;02/14/81 Corrected error in last update which read
  92. ;      the incorrect port for PMMI in the added
  93. ;      carrier test. (Tim Nicholas)
  94. ;    
  95. ;01/31/81 Added equates and code for a carrier test.
  96. ;      Test performed in modem I/O routines. This
  97. ;      is required since loss of carrier will go
  98. ;      undetected by BYE.COM, if the loss occurs
  99. ;      after a sucessful XMODEM signon, when using
  100. ;      an external modem and SIO. (Tim Nicholas)
  101. ;
  102. ;01/17/81 Re-wrote routine to calculate file size so
  103. ;         that it works correctly on v2.X systems with
  104. ;         extent folding (non-zero extent mask). (BRR)
  105. ;
  106. ;12/06/80 Re-wrote routine to calculate file size,
  107. ;      added decimal print of file size. (KBP)
  108. ;
  109. ;12/05/80 Corrected error in use of ext byte that pre-
  110. ;      vented files greater than one extent from 
  111. ;      being sent.     Ron Fowler
  112. ;
  113. ;12/03/80 Corrected file extent length display. Now
  114. ;      reports correct number of records for files
  115. ;      longer than one extent. Display is now
  116. ;      double precision (xxxxH). Also made some
  117. ;      cosmetic changes by re-arranging the equates.
  118. ;      By Tim Nicholas
  119. ;
  120. ;10/28/80 Cleaned up file. (KBP)
  121. ;
  122. ;10/23/80 Expanded conditional assembly of NOCOM routines
  123. ;      into NOCOMS, NOLBS, and NOCOMR equates, to allow
  124. ;      separate conditional assembly of tests for sending
  125. ;      .COM files, sending .??# files, and receiving .COM
  126. ;      files, respectively.    (Dave Hardy)
  127. ;
  128. ;10/15/80 Added traps for ambiguous file name or
  129. ;      none at all. (KBP)
  130. ;
  131. ;09/09/80 Added conditional assembly to prevent filetypes
  132. ;      '.COM' or '.??#' from being sent to distant end
  133. ;      and added conditional assembly of test for '.COM'
  134. ;      filetype on receive as well. See 'NOCOM' below.
  135. ;      Any filetype ending in '#' will not be sent by
  136. ;      this program if 'NOCOM' is set to TRUE.  J.SEYMOUR
  137. ;
  138. ;NOTE: If you add improvements or otherwise update
  139. ;this program, please modem a copy of the new file
  140. ;to "TECHNICAL CBBS" in Dearborn, Michigan - phone
  141. ;313-846-6127 (110, 300, 450 or 600 baud).  Use the
  142. ;filename XMODEM.NEW.    (KBP)
  143. ;
  144. FALSE    EQU    0
  145. TRUE    EQU    NOT FALSE
  146. ;
  147. ;-----------------------------------------------------
  148. ;     --- Conditional Assembly Options ---          ;
  149. ;------------------------------------------------------
  150. ;
  151. STDCPM    EQU    TRUE    ;TRUE, IS STANDARD CP/M
  152. ALTCPM    EQU    FALSE    ;TRUE, IS TRS-80 OR H8 W/O 0-ORG
  153. ;
  154. PMMI    EQU    FALSE     ;TRUE, IS PMMI
  155. DCH    EQU    TRUE    ;TRUE, IS D.C. HAYES
  156. H8    EQU    FALSE    ;TRUE, IS H8/H89 W/INS8250 MODEM CHIP
  157. EXTMOD    EQU    FALSE    ;TRUE, IS NONE OF THE ABOVE!
  158. ;
  159. NOCOMS    EQU    TRUE    ;TRUE, NO .COM FILES SENT
  160. NOLBS    EQU    TRUE    ;TRUE, NO .??# FILES SENT
  161. NOCOMR    EQU    TRUE    ;TRUE, NO .COM FILES RECEIVED
  162. ;
  163. FASTCLK EQU    TRUE    ;PUT TRUE HERE FOR 4 MHZ CLOCK
  164. ;
  165. FRNTPNL    EQU    FALSE    ;TO DISPLAY STATUS ON FRONT PANEL
  166. PANEL    EQU    0FFH    ;DEFAULT ADDRESS OF FRONT PANEL
  167. ;
  168. ;------------------------------------------------------
  169. ;         --- Modem Port Equates ---           ;
  170. ;------------------------------------------------------
  171. ;
  172.     IF    PMMI
  173. MODCTLP EQU    0C0H    ;PMMI VALUES(base port addr)
  174. MODSNDB EQU    1    ;BIT TO TEST FOR SEND
  175. MODSNDR EQU    1    ;VALUE WHEN READY
  176. MODRCVB EQU    2    ;BIT TO TEST FOR RECEIVE
  177. MODRCVR EQU    2    ;VALUE WHEN READY
  178. MODDCDB    EQU    4    ;CARRIER DETECT BIT
  179. MODDCDA    EQU    0    ;VALUE WHEN ACTIVE
  180. MODPARE    EQU    08H    ;VALUE FOR PARITY ERROR
  181. MODOVRE    EQU    10H    ;VALUE FOR OVERRUN ERROR
  182. MODFRME    EQU    20H    ;VALUE FOR FRAMING ERROR
  183. MODDATP EQU    MODCTLP+1;DATA PORT
  184. BAUDRP    EQU    MODCTLP+2;BAUD RATE OUTPUT/MODEM STATUS
  185. MODCTL2 EQU    MODCTLP+3;SECOND CTL PORT
  186.     ENDIF
  187. ;
  188.     IF    H8
  189. MODCTLP    EQU    0DDH    ;H8/H89 VALUES (LSR-LINE STATUS REG.)
  190. MODSNDB    EQU    20H    ;TEST FOR SEND (LSR-THRE)
  191. MODSNDR    EQU    20H    ;VALUE WHEN READY
  192. MODRCVB    EQU    01H    ;TEST FOR RECIEVE (LSR-DR)
  193. MODRCVR    EQU    01H    ;VALUE WHEN READY
  194. MODDCDB    EQU    20H    ;CARRIER DETECT BIT (MSR-CTS)
  195. MODDCDA    EQU    20H    ;VALUE WHEN ACTIVE
  196. MODPARE    EQU    04H    ;VALUE FOR PARITY ERROR (LSR-PE)
  197. MODOVRE    EQU    02H    ;VALUE FOR OVERRUN ERROR (LSR-OR)
  198. MODFRME    EQU    08H    ;VALUE FOR FRAMING ERROE (LSR-FE)
  199. MODDATP    EQU    0D8H    ;DATA PORT, SEND OR RECIEVE
  200. BAUDRP    EQU    0DDH    ;BAUD RATE PORT (DALB IN LCR MUST=1)
  201. MODCTL2    EQU    0DEH    ;MODEM STATUS REGISTER (MSR)
  202. MODCTL1    EQU    0DBH    ;LINE CONTROL REGISTER (LCR)
  203.     ENDIF
  204. ;
  205.     IF    DCH
  206. MODCTLP EQU    82H    ;D. C. HAYES VALUES
  207. MODSNDB EQU    2    ;BIT TO TEST FOR SEND
  208. MODSNDR EQU    2    ;VALUE WHEN READY
  209. MODRCVB EQU    1    ;BIT TO TEST FOR RECEIVE
  210. MODRCVR EQU    1    ;VALUE WHEN READY
  211. MODDCDB    EQU    40H    ;CARRIER DETECT BIT
  212. MODDCDA    EQU    40H    ;VALUE WHEN ACTIVE
  213. MODPARE    EQU    04H    ;VALUE FOR PARITY ERROR
  214. MODOVRE    EQU    10H    ;VALUE FOR OVERRUN ERROR
  215. MODFRME    EQU    08H    ;VALUE FOR FRAMING ERROR
  216. MODDATP EQU    80H    ;DATA PORT
  217. MODCTL2 EQU    81H    ;SECOND CTL PORT
  218.     ENDIF
  219. ;
  220. ;---> NOTE: DCD (Carrier Detect) values above are for
  221. ;        the Micromodem 100. For DC-Hayes 80-103
  222. ;        the values are different.
  223. ;        MODDCDB  EQU  1  ;Carrier bit (CTS).
  224. ;        MODDCDA  EQU  1  ;Active value.
  225. ;
  226. ;
  227. ;
  228. ;If you are using an external modem (not S-100 plug-in)
  229. ;change these equates for your modem port requirements
  230. ;
  231.     IF    EXTMOD
  232. MODCTLP EQU    35H    ;PUT YOUR MODEM STATUS PORT HERE
  233. MODSNDB EQU    01H    ;YOUR BIT TO TEST FOR SEND
  234. MODSNDR EQU    01H    ;YOUR VALUE WHEN READY
  235. MODRCVB EQU    02H    ;YOUR BIT TO TEST FOR RECEIVE
  236. MODRCVR EQU    02H    ;YOUR VALUE WHEN READY
  237. MODDCDB    EQU    1    ;CARRIER DETECT BIT
  238. MODDCDA    EQU    1    ;VALUE WHEN ACTIVE
  239. MODDATP EQU    34H    ;YOUR MODEM DATA PORT
  240. MODCTL2    EQU    36H    ;SECOND CONTROL/STATUS PORT.
  241.     ENDIF        ;END OF EXTERNAL MODEM EQUATES
  242. ;
  243. ;        --- End of Options ---
  244. ;------------------------------------------------------
  245. ;
  246. ERRLIM    EQU    10    ;MAX ALLOWABLE ERRORS (10 STANDARD)
  247. ;
  248. ;Define ASCII characters used
  249. ;
  250. SOH    EQU    1    ;START OF HEADER
  251. EOT    EQU    4    ;END OF TRANSMISSION
  252. ACK    EQU    6    ;ACKNOWLEDGE
  253. NAK    EQU    15H    ;NEG ACKNOWLEDGE
  254. CRC    EQU    'C'    ;CRC REQUEST CHARACTER
  255. CAN    EQU    18H    ;CONTROL-X FOR CANCEL
  256. LF    EQU    10    ;LINEFEED
  257. CR    EQU    13    ;CARRIAGE RETURN
  258.     IF    STDCPM
  259. BASE    EQU    0    ;CP/M BASE ADDRESS
  260.     ENDIF
  261. ;
  262.     IF    ALTCPM
  263. BASE    EQU    4200H    ;ALTERNATE CP/M BASE ADDRESS
  264.     ENDIF
  265. ;
  266.     ORG    BASE+100H
  267. ;
  268. ;Init private stack
  269.     LXI    H,0    ;HL=0
  270.     DAD    SP    ;HL=STACK FROM CP/M
  271.     SHLD    STACK    ;..SAVE IT
  272.     LXI    SP,STACK ;SP=MY STACK
  273.     CALL    ILPRT    ;PRINT:
  274.     DB    CR,LF
  275.     DB    'XMODEM ver 4.6',CR,LF,0
  276. ;
  277. ;GET OPTION
  278. ;
  279.     LDA    FCB+2    ;SECONDARY OPTION?
  280.     CPI    'C'    ;CRC CHECKING REQUESTED?
  281.     JNZ    CHKOPTN    ;NO, GO CHECK PRIMARY
  282.     LDA    FCB+1    ;GET PRIMARY OPTION
  283.     CPI    'R'    ;CRC VALID ONLY FOR RECEIVE
  284.     JNZ    OPTNERR    ;PRT MSG, ABORT
  285.     XRA    A    ;ZERO ACCUM
  286.     STA    CRCFLG    ;TURN ON CRC FLAG
  287. ;
  288. CHKOPTN    LDA    FCB+1    ;GET OPTION (S or R)
  289.     PUSH    PSW    ;SAVE OPTION
  290. ;
  291. ;Move the filename from FCB2 to FCB1
  292. ;
  293.     CALL    MOVEFCB
  294. ;
  295. ;Gobble up garbage chars from the line
  296. ;prior to receive or send
  297. ;
  298.     IN    MODDATP
  299.     IN    MODDATP
  300. ;
  301. ;Jump to appropriate function
  302. ;
  303.     POP    PSW    ;GET OPTION
  304. ;
  305.     CPI    'S'    ;SEND..
  306.     JZ    SENDFIL ;..A FILE?
  307. ;
  308.     CPI    'R'    ;RECEIVE..
  309.     JZ    RCVFIL    ;..A FILE?
  310. ;
  311. ;Invalid option
  312. ;
  313. OPTNERR    CALL    ERXIT    ;EXIT W/ERROR
  314.     DB    '++INVALID OPTION ON XMODEM '
  315.     DB    'COMMAND++',CR,LF
  316.     DB    'Must be S for SEND; or R or RC '
  317.     DB    'for RECEIVE',CR,LF,'$'
  318. ;
  319. * * * * * * * * * * * * * * * * * * * * *
  320. *                    *
  321. *    SENDFIL: SENDS A CP/M FILE    *
  322. *                    *
  323. * * * * * * * * * * * * * * * * * * * * *
  324. ;
  325. ;The CP/M file specified in the XMODEM command
  326. ;is transferred over the phone to another
  327. ;computer running MODEM with the "R" (receive)
  328. ;option.  The data is sent one sector at a
  329. ;time with headers and checksums, and re-
  330. ;transmission on errors.  
  331. ;
  332. SENDFIL CALL    TRAP    ;CHECK FOR NO NAME OR AMBIG. NAME
  333.     CALL    CNREC    ;COMPUTE # OF RECORDS.
  334.     CALL    OPENFIL ;OPEN THE FILE
  335.     MVI    E,80    ;WAIT 80 SEC..
  336.     CALL    WAITNAK ;..FOR INITIAL NAK
  337. ;
  338. SENDLP    CALL    RDSECT    ;READ A SECTOR
  339.     JC    SENDEOF ;SEND EOF IF DONE
  340.     CALL    INCRSNO ;BUMP SECTOR #
  341.     XRA    A    ;ZERO ERROR..
  342.     STA    ERRCT    ;..COUNT
  343. ;
  344. SENDRPT CALL    SENDHDR ;SEND A HEADER
  345.     CALL    SENDSEC ;SEND DATA SECTOR
  346.     LDA    CRCFLG    ;GET CRC FLAG
  347.     ORA    A    ;CRC IN EFFECT?
  348.     CZ    SENDCRC    ;YES, SEND CRC
  349.     CNZ    SENDCKS ;NO, SEND CKSUM
  350.     CALL    GETACK    ;GET THE ACK
  351.     JC    SENDRPT ;REPEAT IF NO ACK
  352.     JMP    SENDLP    ;LOOP UNTIL EOF
  353. ;
  354. ;File sent, send EOT's
  355. ;
  356. SENDEOF MVI    A,EOT    ;SEND..
  357.     CALL    SEND    ;..AN EOT
  358.     CALL    GETACK    ;GET THE ACK
  359.     JC    SENDEOF ;LOOP IF NO ACK
  360.     JMP    EXIT    ;ALL DONE
  361. ;
  362. * * * * * * * * * * * * * * * * * * * * *
  363. *                    *
  364. *    RCVFIL: RECEIVE A FILE        *
  365. *                    *
  366. * * * * * * * * * * * * * * * * * * * * *
  367. ;
  368. ;Receives a file in block format as sent
  369. ;by another person doing "MODEM S FN.FT".
  370. ;Can be invoked by 'XMODEM R FN.FT' or
  371. ;by 'XMODEM RC FN.FT' if CRC is to be used.
  372. ;
  373. RCVFIL    CALL    TRAP    ;CHECK FOR NO NAME OR AMBIG. NAME
  374. ;
  375.     IF    NOCOMR
  376.     LXI    H,FCB+9 ;POINT TO FILETYPE
  377.     MVI    A,'C'    ;1ST LETTER
  378.     CMP    M    ;IS IT C ?
  379.     JNZ    CONTINU ;IF NOT, CONTINUE NORMALLY
  380.     INX    H    ;GET 2ND LETTER
  381.     MVI    A,'O'    ;2ND LETTER
  382.     CMP    M    ;IS IT O ?
  383.     JNZ    CONTINU ;IF NOT, CONTINUE NORMALLY
  384.     INX    H    ;GET 3RD LETTER
  385.     MVI    A,'M'    ;3RD LETTER
  386.     CMP    M    ;IS IT M ?
  387.     JNZ    CONTINU ;IF NOT, CONTINUE NORMALLY
  388.     CALL    ERXIT    ;EXIT, PRINT ERROR MESSAGE
  389.     DB    '++CAN''T RECEIVE A .COM FILE++'
  390.     DB    CR,LF,CR,LF
  391.     DB    'Rename filetype ".OBJ" and try again'
  392.     DB    CR,LF,'$'
  393.     ENDIF
  394. ;
  395. CONTINU CALL    CHEKFIL ;SEE IF FILE EXISTS
  396.     CALL    MAKEFIL ;..THEN MAKE NEW
  397.     CALL    ILPRT    ;PRINT:
  398.     DB    'FILE OPEN - READY TO RECEIVE',CR,LF,0
  399. ;
  400. RCVLP    CALL    RCVSECT ;GET A SECTOR
  401.     JC    RCVEOT    ;GOT EOT
  402.     CALL    WRSECT    ;WRITE THE SECTOR
  403.     CALL    INCRSNO ;BUMP SECTOR #
  404.     CALL    SENDACK ;ACK THE SECTOR
  405.     JMP    RCVLP    ;LOOP UNTIL EOF
  406. ;
  407. ;Got EOT on sector - flush buffers, end
  408. ;
  409. RCVEOT    CALL    WRBLOCK ;WRITE THE LAST BLOCK
  410.     CALL    SENDACK ;ACK THE SECTOR
  411.     CALL    CLOSFIL ;CLOSE THE FILE
  412.     JMP    EXIT    ;ALL DONE
  413. ;
  414. * * * * * * * * * * * * * * * * * * * * *
  415. *                    *
  416. *        SUBROUTINES        *
  417. *                    *
  418. * * * * * * * * * * * * * * * * * * * * *
  419. ;
  420. ;---->    TRAP: Check for no file name or ambiguous name
  421. ;
  422. TRAP    LXI    H,FCB+1 ;POINT TO FILE NAME
  423.     MOV    A,M    ;GET FIRST CHAR OF FILE NAME
  424.     CPI    ' '    ;ANY THERE?
  425.     JNZ    ATRAP    ;YES, CHECK FOR AMBIGOUS FILE NAME
  426.     CALL    ERXIT    ;PRINT MSG, EXIT
  427.     DB    '++NO FILE NAME SPECIFIED++',CR,LF,'$'
  428. ;
  429. ATRAP    MVI    B,11    ;11 CHARS TO CHECK
  430. ;
  431. TRLOOP    MOV    A,M    ;GET CHAR FROM FCB
  432.     CPI    '?'    ;AMBIGUOUS?
  433.     JZ    TRERR    ;YES, EXIT WITH ERROR MSG
  434.     INX    H    ;POINT TO NEXT CHAR
  435.     DCR    B    ;ONE LESS TO GO
  436.     JNZ    TRLOOP    ;NOT DONE, CHECK SOME MORE
  437.     RET        ;NO AMBIGUOUS NAME, RETURN
  438. ;
  439. TRERR    CALL    ERXIT    ;PRINT MSG, EXIT
  440.     DB    '++CAN''T USE WILD CARD OPTIONS++',CR,LF,'$'
  441. ;
  442. ;---->    RCVSECT: Receive a sector
  443. ;
  444. ;Returns with carry set if EOT received.
  445. ;
  446. RCVSECT XRA    A    ;GET 0
  447.     STA    ERRCT    ;INIT ERROR COUNT
  448. ;
  449. RCVRPT:
  450.     IF    PMMI OR H8 OR DCH
  451.     XRA    A    ;GET 0
  452.     STA    ERRCDE    ;CLEAR RECEIVE ERROR CODE
  453.     ENDIF
  454. ;
  455.     MVI    B,10    ;10 SEC TIMEOUT
  456.     CALL    RECV    ;GET SOH/EOT
  457.     JC    RCVSTOT ;TIMEOUT
  458. ;
  459.     IF    PMMI OR H8 OR DCH
  460.     CALL    RCVERR    ;TRANS ERROR?
  461.     JC    RCVSERR    ;CARRY SET IF ERROR
  462.     ENDIF
  463. ;
  464.     CPI    SOH    ;GET SOH?
  465.     JZ    RCVSOH    ;..YES
  466. ;
  467. ;Earlier versions of MODEM program send some nulls -
  468. ;ignore them
  469. ;
  470.     ORA    A    ;00 FROM SPEED CHECK?
  471.     JZ    RCVRPT    ;YES, IGNORE IT
  472.     CPI    EOT    ;END OF TRANSFER?
  473.     STC        ;RETURN WITH CARRY..
  474.     RZ        ;..SET IF EOT
  475. ;
  476. ;Didn't get SOH or EOT - 
  477. ;    -or-
  478. ;Didn't get valid header - purge the line,
  479. ;then send NAK.
  480. ;
  481. RCVSERR MVI    B,1    ;WAIT FOR 1 SEC..
  482.     CALL    RECV    ;..WITH NO CHARS
  483.     JNC    RCVSERR ;LOOP UNTIL SENDER DONE
  484.     LDA    CRCFLG    ;GET CRC FLAG
  485.     ORA    A    ;CRC IN EFFECT?
  486.     MVI    A,NAK    ;PUT NAK IN ACCUM
  487.     JNZ    RCVSER2    ;NO, SEND THE NAK
  488.     LDA    FIRSTIME;GET FIRST TIME SWITCH
  489.     ORA    A    ;HAS FIRST SOH BEEN RECEIVED?
  490.     MVI    A,NAK    ;PUT NAK IN ACCUM
  491.     JZ    RCVSER2    ;YES, THEN SEND NAK
  492.     MVI    A,CRC    ;TELL SENDER CRC IS IN EFFECT
  493. ;
  494. RCVSER2    CALL    SEND    ;..THE NAK or CRC request
  495.     LDA    ERRCT    ;ABORT IF..
  496.     INR    A    ;..WE HAVE REACHED..
  497.     STA    ERRCT    ;..THE ERROR..
  498.     CPI    ERRLIM    ;..LIMIT?
  499.     JC    RCVRPT    ;..NO, TRY AGAIN
  500. ;
  501. ;10 errors in a row -
  502. ;
  503. RCVSABT CALL    CLOSFIL ;KEEP WHATEVER WE GOT
  504.     CALL    ERXIT
  505.     DB    '++UNABLE TO RECEIVE BLOCK '
  506.     DB    '- ABORTING++',CR,LF,'$'
  507. ;
  508. ;Timed out on receive
  509. ;
  510. RCVSTOT JMP    RCVSERR ;BUMP ERR CT, ETC.
  511. ;
  512. ;---->RCVERR: Checks to see if framing error, overrun, or
  513. ;        parity error occurred.
  514. ;    1. Error code (ERRCDE) was set in recv routine
  515. ;    2. ERRCDE=0 for no errors, ERRCDE<>0 for errors
  516. ;    3. If there has been an error, this routine sets
  517. ;        the carry bit on.
  518. ;
  519.     IF    PMMI OR H8 OR DCH
  520. RCVERR    PUSH    PSW    ;SAVE CHAR TRANSMITTED
  521.     LDA    ERRCDE    ;GET RECEIVE ERR CODE
  522.     ANA    A    ;IS IT ZERO?
  523.     JZ    RCVERR2    ;YES, NO ERROR
  524.     POP    PSW    ;RESTORE CHAR TRANSMITTED
  525.     STC        ;SET CARRY ON FOR ERROR
  526.     RET
  527. ;
  528. RCVERR2    POP    PSW    ;RESTORE CHAR TRANSMITTED
  529.     ORA    A    ;CLEAR CARRY BIT
  530.     RET
  531.     ENDIF
  532. ;
  533. ;Got SOH - get block #, block # complemented
  534. ;
  535. RCVSOH    XRA    A    ;ZERO ACCUM
  536.     STA    FIRSTIME;INDICATE FIRST SOH RECV'D
  537.     MVI    B,1    ;TIMEOUT = 1 SEC
  538.     CALL    RECV    ;GET SECTOR
  539.     JC    RCVSTOT ;GOT TIMEOUT
  540. ;
  541.     IF    PMMI OR H8 OR DCH
  542.     CALL    RCVERR    ;TRANS ERROR?
  543.     JC    RCVSERR    ;CARRY SET IF ERROR
  544.     ENDIF
  545. ;
  546.     MOV    D,A    ;D=BLK #
  547.     MVI    B,1    ;TIMEOUT = 1 SEC
  548.     CALL    RECV    ;GET CMA'D SECT #
  549.     JC    RCVSTOT ;TIMEOUT
  550. ;
  551.     IF    PMMI OR H8 OR DCH
  552.     CALL    RCVERR    ;TRANS ERROR?
  553.     JC    RCVSERR    ;CARRY SET IF ERROR
  554.     ENDIF
  555. ;
  556.     CMA        ;CALC COMPLEMENT
  557.     CMP    D    ;GOOD SECTOR #?
  558.     JZ    RCVDATA ;YES, GET DATA
  559. ;
  560. ;Got bad sector #
  561. ;
  562.     JMP    RCVSERR ;BUMP ERROR CT.
  563. ;
  564. RCVDATA MOV    A,D    ;GET SECTOR #
  565.     STA    RCVSNO    ;SAVE IT
  566.     MVI    C,0    ;INIT CKSUM
  567.     CALL    CLRCRC    ;CLEAR CRC COUNTER
  568.     LXI    H,BASE+80H ;POINT TO BUFFER
  569. ;
  570. RCVCHR    MVI    B,1    ;1 SEC TIMEOUT
  571.     CALL    RECV    ;GET CHAR
  572.     JC    RCVSTOT ;TIMEOUT
  573. ;
  574.     IF    PMMI OR H8 OR DCH
  575.     CALL    RCVERR    ;TRANS ERROR?
  576.     JC    RCVSERR    ;CARRY SET IF ERROR
  577.     ENDIF
  578. ;
  579.     MOV    M,A    ;STORE CHAR
  580.     INR    L    ;DONE?
  581.     JNZ    RCVCHR    ;NO, LOOP
  582.     LDA     CRCFLG    ;GET CRC FLAG
  583.     ORA    A    ;CRC IN EFFECT?
  584.     JZ    RCVCRC    ;YES, TO RECEIVE CRC
  585. ;
  586. ;Verify checksum
  587. ;
  588.     MOV    D,C    ;SAVE CHECKSUM
  589.     MVI    B,1    ;TIMEOUT LEN.
  590.     CALL    RECV    ;GET CHECKSUM
  591.     JC    RCVSTOT ;TIMEOUT
  592. ;
  593.     IF    PMMI OR H8 OR DCH
  594.     CALL    RCVERR    ;TRANS ERROR?
  595.     JC    RCVSERR    ;CARRY SET IF ERROR
  596.     ENDIF
  597. ;
  598.     CMP    D    ;CHECKSUM OK?
  599.     JNZ    RCVSERR ;NO, ERROR
  600. ;
  601. ;Got a sector, it's a duplicate if = previous,
  602. ;    or OK if = 1 + previous sector
  603. ;
  604. CHKSNUM    LDA    RCVSNO    ;GET RECEIVED
  605.     MOV    B,A    ;SAVE IT
  606.     LDA    SECTNO    ;GET PREV
  607.     CMP    B    ;PREV REPEATED?
  608.     JZ    RECVACK ;ACK TO CATCH UP
  609.     INR    A    ;CALC NEXT SECTOR #
  610.     CMP    B    ;MATCH?
  611.     JNZ    ABORT    ;NO MATCH - STOP SENDER, EXIT
  612.     RET        ;CARRY OFF - NO ERRORS
  613. ;
  614. ;---->    RCVCRC:    Receive the cyclic redundancy check
  615. ;        characters (2 bytes), and see if the crc
  616. ;        received matches the one calculated.
  617. ;        If they match, get next sector, else
  618. ;        send a NAK requesting the sector be
  619. ;        resent.
  620. ;
  621. RCVCRC    MVI    E,2    ;NUMBER OF BYTES TO RECEIVE
  622. ;
  623. RCVCRC2    MVI    B,1    ;1 SEC TIMEOUT
  624.     CALL    RECV    ;GET CRC BYTE
  625.     JC    RCVSTOT    ;TIMEOUT
  626. ;
  627.     IF    PMMI OR H8 OR DCH
  628.     CALL    RCVERR    ;TRANSMISSION ERROR?
  629.     JC    RCVSERR    ;YES, IF CARRY IS ON
  630.     ENDIF
  631. ;
  632.     DCR    E    ;DECREMENT NUM OF BYTES
  633.     JNZ    RCVCRC2    ;GET BOTH BYTES
  634.     CALL    CHKCRC    ;CHECK RCVD CRC AGAINST CALC'D CRC
  635.     ORA    A    ;IS CRC OKAY?
  636.     JZ    CHKSNUM    ;YES, GO CHECK SECTOR NUMBERS
  637.     JMP    RCVSERR    ;GO CHECK ERROR LIMIT AND SEND NAK
  638. ;
  639. ;Previous sector repeated, due to the last ACK
  640. ;being garbaged.  ACK it so sender will catch up 
  641. ;
  642. RECVACK CALL    SENDACK ;SEND THE ACK,
  643.     JMP    RCVSECT ;GET NEXT BLOCK
  644. ;
  645. ;Send an ACK for the sector
  646. ;
  647. SENDACK MVI    A,ACK    ;GET ACK
  648.     CALL    SEND    ;..AND SEND IT
  649.     RET
  650. ;
  651. ;---->    SENDHDR: Send the sector header
  652. ;
  653. ;SEND: (SOH) (block #) (complemented block #)
  654. ;
  655. SENDHDR MVI    A,SOH    ;SEND..
  656.     CALL    SEND    ;..SOH,
  657.     LDA    SECTNO    ;THEN SEND..
  658.     CALL    SEND    ;..SECTOR #
  659.     LDA    SECTNO    ;THEN SECTOR #
  660.     CMA        ;..COMPLEMENTED..
  661.     CALL    SEND    ;..SECTOR #
  662.     RET        ;FROM SENDHDR
  663. ;
  664. ;---->    SENDSEC: Send the data sector
  665. ;
  666. SENDSEC MVI    C,0    ;INIT CKSUM
  667.     CALL    CLRCRC    ;CLEAR THE CRC COUNTER
  668.     LXI    H,BASE+80H ;POINT TO BUFFER
  669. ;
  670. SENDC    MOV    A,M    ;GET A CHAR
  671.     CALL    SEND    ;SEND IT
  672.     INR    L    ;POINT TO NEXT CHAR
  673.     JNZ    SENDC    ;LOOP IF <100H
  674.     RET        ;FROM SENDSEC
  675. ;
  676. ;---->    SENDCKS: Send the checksum
  677. ;
  678. SENDCKS MOV    A,C    ;SEND THE..
  679.     CALL    SEND    ;..CHECKSUM
  680.     RET        ;FROM SENDCKS
  681. ;
  682. ;---->    SENDCRC: Send the two Cyclic Redundancy
  683. ;         Check characters.  Call FINCRC
  684. ;         to calc the CRC which will be in
  685. ;         d,e regs upon return.
  686. ;
  687. SENDCRC    CALL    FINCRC    ;CALC THE CRC FOR THIS SECTOR
  688.     MOV    A,D    ;PUT FIRST CRC BYTE IN ACCUM
  689.     CALL    SEND    ;SEND IT
  690.     MOV    A,E    ;PUT SECOND CRC BYTE IN ACCUM
  691.     CALL    SEND    ;SEND IT
  692.     XRA    A    ;SET ZERO RETURN CODE
  693.     RET
  694. ;
  695. ;---->    GETACK: Get the ACK on the sector
  696. ;
  697. ;Returns with carry clear if ACK received.
  698. ;If an ACK is not received, the error count
  699. ;is incremented, and if less than "ERRLIM",
  700. ;carry is set and control returns.  If the
  701. ;error count is at "ERRLIM", the program
  702. ;aborts.
  703. ;
  704. GETACK    MVI    B,10    ;WAIT 10 SECONDS MAX
  705.     CALL    RECVDG    ;RECV W/GARBAGE COLLECT
  706.     JC    GETATOT ;TIMED OUT
  707.     CPI    ACK    ;OK? (CARRY OFF IF =)
  708.     RZ        ;YES, RET FROM GETACK
  709. ;
  710. ;Timeout or error on ACK - bump error count
  711. ;
  712. ACKERR    LDA    ERRCT    ;GET COUNT
  713.     INR    A    ;BUMP IT
  714.     STA    ERRCT    ;SAVE BACK
  715.     CPI    ERRLIM    ;AT LIMIT?
  716.     RC        ;NOT AT LIMIT
  717. ;
  718. ;Reached error limit
  719. ;
  720. CSABORT CALL    ERXIT
  721.     DB    '++CAN''T SEND SECTOR '
  722.     DB    '- ABORTING++',CR,LF,'$'
  723. ;
  724. ;Timeout getting ACK
  725. ;
  726. GETATOT JMP    ACKERR    ;NO MSG
  727. ABORT    LXI    SP,STACK
  728. ;
  729. ABORTL    MVI    B,1    ;1 SEC. W/O CHARS.
  730.     CALL    RECV
  731.     JNC    ABORTL    ;LOOP UNTIL SENDER DONE
  732.     MVI    A,CAN    ;CONTROL X
  733.     CALL    SEND    ;STOP SENDING END
  734. ;
  735. ABORTW    MVI    B,1    ;1 SEC W/O CHARS.
  736.     CALL    RECV
  737.     JNC    ABORTW    ;LOOP UNTIL SENDER DONE
  738.     MVI    A,' '    ;GET A SPACE...
  739.     CALL    SEND    ;TO CLEAR OUT CONTROL X
  740.     CALL    ERXIT    ;EXIT WITH ABORT MSG
  741.     DB    'XMODEM PROGRAM CANCELLED',CR,LF,'$'
  742. ;
  743. ;---->    INCRSNO: Increment sector #
  744. ;
  745. INCRSNO LDA    SECTNO    ;INCR..
  746.     INR    A    ;..SECT..
  747.     STA    SECTNO    ;..NUMBER
  748.     RET
  749. ;
  750. ;---->    CHEKFIL: See if file exists
  751. ;
  752. ;If it exists, say use a different name.
  753. ;
  754. CHEKFIL LXI    D,FCB    ;POINT TO CTL BLOCK
  755.     MVI    C,SRCHF ;SEE IF IT..
  756.     CALL    BDOS    ;..EXISTS
  757.     INR    A    ;FOUND?
  758.     RZ        ;..NO, RETURN
  759.     CALL    ERXIT    ;EXIT, PRINT ERROR MESSAGE
  760.     DB    '++FILE EXISTS - USE A DIFFERENT NAME++'
  761.     DB    CR,LF,'$'
  762. ;
  763. ;---->    MAKEFIL: Makes the file to be received
  764. ;
  765. MAKEFIL    XRA    A    ;SET EXT & REC # TO 0
  766.     STA    FCBEXT
  767.     STA    FCBSNO
  768.     LXI    D,FCB    ;POINT TO FCB
  769.     MVI    C,MAKE    ;GET BDOS FNC
  770.     CALL    BDOS    ;TO THE MAKE
  771.     INR    A    ;FF=BAD?
  772.     RNZ        ;OPEN OK
  773. ;Directory full - can't make file
  774.     CALL    ERXIT
  775.     DB    '++ERROR - CAN''T MAKE FILE++',CR,LF
  776.     DB    'Directory must be full',CR,LF,'$'
  777. ;
  778. ;---->    CNREC: Computes record count, and saves it
  779. ;           until successful file OPEN.
  780. ;
  781. ;LOOK UP THE FCB IN THE DIRECTORY
  782. CNREC    MVI    A,'?'    ;MATCH ALL EXTENTS
  783.     STA    FCBEXT
  784.     MVI    A,0FFH
  785.     STA    MAXEXT    ;INIT MAX EXT NO.
  786.     MVI    C,SRCHF ;GET 'SEARCH FIRST' FNC
  787.     LXI    D,FCB
  788.     CALL    BDOS    ;READ FIRST
  789.     INR    A    ;WERE THERE ANY?
  790.     JNZ    SOME    ;GOT SOME
  791.     CALL    ERXIT
  792.     DB    '++FILE NOT FOUND++$'
  793. ;
  794. ;READ MORE DIRECTORY ENTRIES
  795. MOREDIR    MVI    C,SRCHN ;SEARCH NEXT
  796.     LXI    D,FCB
  797.     CALL    BDOS    ;READ DIR ENTRY
  798.     INR    A    ;CHECK FOR END (0FFH)
  799.     JNZ    SOME    ;NOT END OF DIR...PROCESS EXTENT
  800.     LDA    MAXEXT    ;HIT END...GET HIGHEST EXTENT NO. SEEN
  801.     MOV    L,A    ;WHICH GIVES EXTENT COUNT - 1
  802.     MVI    H,0
  803.     MOV    D,H
  804.     LDA    RCNT    ;GET RECORD COUNT OF MAX EXTENT SEEN
  805.     MOV    E,A    ;SAVE IT IN DE
  806.     DAD    H
  807.     DAD    H    ;MULTIPLY # OF EXTENTS - 1
  808.     DAD    H    ; TIMES 128
  809.     DAD    H
  810.     DAD    H
  811.     DAD    H
  812.     DAD    H
  813.     DAD    D    ;ADD IN SIZE OF LAST EXTENT
  814.     SHLD    RCNT    ;SAVE TOTAL RECORD COUNT
  815.     RET        ;AND EXIT
  816. ;
  817. ;POINT TO DIRECTORY ENTRY 
  818. SOME    DCR    A    ;UNDO PREV 'INR A'
  819.     ANI    3    ;MAKE MODULUS 4
  820.     ADD    A    ;MULTIPLY...
  821.     ADD    A    ;..BY 32 BECAUSE
  822.     ADD    A    ;..EACH DIRECTORY
  823.     ADD    A    ;..ENTRY IS 32
  824.     ADD    A    ;..BYTES LONG
  825.     LXI    H,BASE+80H ;POINT TO BUFFER
  826.     ADD    L    ;POINT TO ENTRY
  827.     ADI    15    ;OFFSET TO RECORD COUNT
  828.     MOV    L,A    ;HL NOW POINTS TO REC COUNT
  829.     MOV    B,M    ;GET RECORD COUNT
  830.     DCX    H
  831.     DCX    H    ;BACK DOWN TO EXTENT NUMBER
  832.     DCX    H
  833.     LDA    MAXEXT    ;COMPARE WITH CURRENT MAX.
  834.     ORA    A    ;IF NO MAX YET
  835.     JM    BIGGER    ;THEN SAVE RECORD COUNT ANYWAY
  836.     CMP    M
  837.     JNC    MOREDIR
  838. ;
  839. BIGGER:    MOV    A,B    ;SAVE NEW RECORD COUNT
  840.     STA    RCNT
  841.     MOV    A,M    ;SAVE NEW MAX. EXTENT NO.
  842.     STA    MAXEXT
  843.     JMP    MOREDIR    ;GO FIND MORE EXTENTS
  844. ;
  845. ;---->    OPENFIL: Opens the file to be sent
  846. ;
  847. OPENFIL    XRA    A    ;SET EXT & REC # TO 0 FOR PROPER OPEN
  848.     STA    FCBEXT
  849.     STA    FCBSNO
  850.     LXI    D,FCB    ;POINT TO FILE
  851.     MVI    C,OPEN    ;GET FUNCTION
  852.     CALL    BDOS    ;OPEN IT
  853.     INR    A    ;OPEN OK?
  854.     JNZ    OPENOK    ;..YES
  855.     CALL    ERXIT    ;..NO, ABORT
  856.     DB    '++OPEN ERROR++',CR,LF,'$'
  857. ;
  858. ;Check for distribution-protected file
  859. ;
  860. OPENOK    LDA    FCB+1    ;FIRST CHAR OF FILE NAME
  861.     ANI    80H    ;CHECK BIT 7
  862.     JNZ    OPENOT    ;If on, file can't be sent.
  863.     LDA    FCB+2    ;Also check "f2" for tag.
  864.     ANI    80H    ;Is it set?
  865.     JZ    OPENOK2    ;If not, ok to send file.
  866. ;
  867. OPENOT    CALL    ERXIT    ;EXIT W/MESSAGE
  868.     DB    '++THIS FILE IS NOT FOR DISTRIBUTION, SORRY++'
  869.     DB    CR,LF,'$'
  870. ;
  871. OPENOK2 EQU    $
  872. ;
  873.     IF    NOLBS OR NOCOMS ;CHECK FOR SEND RESTRICTIONS
  874.     LXI    H,FCB+11
  875.     MOV    A,M    ;CHECK FOR PROTECT ATTR
  876.     ANI    7FH    ;REMOVE CP/M 2.x ATTRS
  877.     ENDIF        ;NOLBS OR NOCOMS
  878. ;
  879.     IF    NOLBS    ;DON'T ALLOW '#' TO BE SENT.
  880.     CPI    '#'    ;CHK FOR '#' AS LAST FIRST
  881.     JZ    OPENOT    ;IF '#', CAN'T SEND, SHOW WHY
  882.     ENDIF        ;NOLBS
  883. ;
  884.     IF    NOCOMS    ;DON'T ALLOW .COM TO BE SENT
  885.     CPI    'M'    ;IF NOT, CHK FOR '.COM'
  886.     JNZ    OPENOK3 ;IF NOT, OK TO SEND
  887.     DCX    H
  888.     MOV    A,M    ;CHK NEXT CHAR
  889.     ANI    7FH    ;STRIP ATTRIBUTES
  890.     CPI    'O'    ; 'O'?
  891.     JNZ    OPENOK3 ;IF NOT, OK TO SEND
  892.     DCX    H
  893.     MOV    A,M    ;NOW CHK FIRST CHAR
  894.     ANI    7FH    ;STRIP ATTRIBUTES
  895.     CPI    'C'    ; 'C' AS IN '.COM'?
  896.     JNZ    OPENOK3 ;IF NOT, CONTINUE
  897.     CALL    ERXIT    ;EXIT W/MESSAGE
  898.     DB    '++CAN''T SEND A .COM FILE++'
  899.     DB    CR,LF,'$'
  900.     ENDIF        ;NOCOMS
  901. ;
  902. OPENOK3 CALL    ILPRT    ;PRINT:
  903.     DB    'FILE OPEN - SIZE: ',0
  904.     LHLD    RCNT    ; Get record count.
  905.     CALL    DECOUT    ;PRINT DECIMAL NUMBER OF SECTORS
  906.     CALL    ILPRT    ;Print:
  907.     DB    ' (',0
  908.     CALL    DHXOUT    ;Now print size in hex.
  909.     CALL    ILPRT    ;PRINT:
  910.     DB    'H) SECTORS',CR,LF,0
  911.     RET
  912. ;
  913. ;---->    CLOSFIL: Closes the received file
  914. ;
  915. CLOSFIL LXI    D,FCB    ;POINT TO FILE
  916.     MVI    C,CLOSE ;GET FUNCTION
  917.     CALL    BDOS    ;CLOSE IT
  918.     INR    A    ;CLOSE OK?
  919.     RNZ        ;..YES, RETURN
  920.     CALL    ERXIT    ;..NO, ABORT
  921.     DB    '++CAN''T CLOSE FILE++',CR,LF,'$'
  922. ;
  923. ;
  924. ;----> DECOUT: Decimal output routine
  925. ;
  926. DECOUT:    PUSH    B
  927.     PUSH    D
  928.     PUSH    H
  929.     LXI    B,-10
  930.     LXI    D,-1
  931. ;
  932. DECOU2:    DAD    B
  933.     INX    D
  934.     JC    DECOU2
  935.     LXI    B,10
  936.     DAD    B
  937.     XCHG
  938.     MOV    A,H
  939.     ORA    L
  940.     CNZ    DECOUT
  941.     MOV    A,E
  942.     ADI    '0'
  943.     CALL    CTYPE
  944.     POP    H
  945.     POP    D
  946.     POP    B
  947.     RET
  948. ;
  949. ;---->    DHXOUT: - double precision hex output routine.
  950. ;    Call with hex value in HL.
  951. ;
  952. DHXOUT    PUSH    H    ;Save H,L
  953.     PUSH    PSW    ;Save A
  954.     MOV    A,H    ;Get MS byte.
  955.     CALL    HEXO    ;Output hi order byte.
  956.     MOV    A,L    ;Get LS byte.
  957.     CALL    HEXO    ;Output lo order byte.
  958.     POP    PSW    ;Restore A
  959.     POP    H    ;Restore H,L
  960.     RET        ;Return to caller.
  961. ;
  962. ;
  963. ;---->    RDSECT: Reads a sector
  964. ;
  965. ;For speed, this routine buffers up 16
  966. ;sectors at a time.
  967. ;
  968. RDSECT    LDA    SECINBF ;GET # SECT IN BUFF.
  969.     DCR    A    ;DECREMENT..
  970.     STA    SECINBF ;..IT
  971.     JM    RDBLOCK ;EXHAUSTED?  NEED MORE.
  972.     LHLD    SECPTR    ;GET POINTER
  973.     LXI    D,BASE+80H ;TO DATA
  974.     CALL    MOVE128 ;MOVE TO BUFFER
  975.     SHLD    SECPTR    ;SAVE BUFFER POINTER
  976.     RET        ;FROM "READSEC"
  977. ;
  978. ;Buffer is empty - read in another block of 16
  979. ;
  980. RDBLOCK LDA    EOFLG    ;GED EOF FLAG
  981.     CPI    1    ;IS IT SET?
  982.     STC        ;TO SHOW EOF
  983.     RZ        ;GOT EOF
  984.     MVI    C,0    ;SECTORS IN BLOCK
  985.     LXI    D,DBUF    ;TO DISK BUFFER
  986. ;
  987. RDSECLP PUSH    B
  988.     PUSH    D
  989.     MVI    C,STDMA ;SET DMA..
  990.     CALL    BDOS    ;..ADDR
  991.     LXI    D,FCB
  992.     MVI    C,READ
  993.     CALL    BDOS
  994.     POP    D
  995.     POP    B
  996.     ORA    A    ;READ OK?
  997.     JZ    RDSECOK ;YES
  998.     DCR    A    ;EOF?
  999.     JZ    REOF    ;GOT EOF
  1000. ;
  1001. ;Read error
  1002. ;
  1003.     CALL    ERXIT
  1004.     DB    '++FILE READ ERROR++',CR,LF,'$'
  1005. ;
  1006. RDSECOK LXI    H,80H    ;ADD LENGTH OF ONE SECTOR...
  1007.     DAD    D    ;...TO NEXT BUFF
  1008.     XCHG        ;BUFF TO DE
  1009.     INR    C    ;MORE SECTORS?
  1010.     MOV    A,C    ;GET COUNT
  1011.     CPI    16    ;DONE?
  1012.     JZ    RDBFULL ;..YES, BUFF IS FULL
  1013.     JMP    RDSECLP ;READ MORE
  1014. ;
  1015. REOF    MVI    A,1
  1016.     STA    EOFLG    ;SET EOF FLAG
  1017.     MOV    A,C
  1018. ;
  1019. ;Buffer is full, or got EOF
  1020. ;
  1021. RDBFULL STA    SECINBF ;STORE SECTOR COUNT
  1022.     LXI    H,DBUF    ;INIT BUFFER..
  1023.     SHLD    SECPTR    ;..POINTER
  1024.     LXI    D,BASE+80H ;RESET..
  1025.     MVI    C,STDMA ;..DMA..
  1026.     CALL    BDOS    ;..ADDR
  1027.     JMP    RDSECT    ;PASS SECT TO CALLER
  1028. ;
  1029. ;---->    WRSECT: Write a sector
  1030. ;
  1031. ;Writes the sector into a buffer.  When 16
  1032. ;have been written, writes the block to disk.
  1033. ;
  1034. ;Entry point "WRBLOCK" flushes the buffer at EOF.
  1035. ;
  1036. WRSECT    LHLD    SECPTR    ;GET BUFF ADDR
  1037.     XCHG        ;TO DE FOR MOVE
  1038.     LXI    H,BASE+80H    ;FROM HERE
  1039.     CALL    MOVE128 ;MOVE TO BUFFER
  1040.     XCHG        ;SAVE NEXT..
  1041.     SHLD    SECPTR    ;..BLOCK POINTER
  1042.     LDA    SECINBF ;BUMP THE..
  1043.     INR    A    ;..SECTOR #..
  1044.     STA    SECINBF ;..IN THE BUFF
  1045.     CPI    16    ;HAVE WE 16?
  1046.     RNZ        ;NO, RETURN
  1047. ;
  1048. ;---->    WRBLOCK: Writes a block to disk
  1049. ;
  1050. WRBLOCK LDA    SECINBF ;# SECT IN BUFFER
  1051.     ORA    A    ;0 MEANS END OF FILE
  1052.     RZ        ;NONE TO WRITE
  1053.     MOV    C,A    ;SAVE COUNT
  1054.     LXI    D,DBUF    ;POINT TO DISK BUFF
  1055. ;
  1056. DKWRLP    PUSH    H
  1057.     PUSH    D
  1058.     PUSH    B
  1059.     MVI    C,STDMA ;SET DMA
  1060.     CALL    BDOS    ;TO BUFFER
  1061.     LXI    D,FCB    ;THEN WRITE
  1062.     MVI    C,WRITE ;..THE..
  1063.     CALL    BDOS    ;..BLOCK
  1064.     POP    B
  1065.     POP    D
  1066.     POP    H
  1067.     ORA    A
  1068.     JNZ    WRERR    ;OOPS, ERROR
  1069.     LXI    H,80H    ;LENGTH OF 1 SECT
  1070.     DAD    D    ;HL= NEXT BUFF
  1071.     XCHG        ;TO DE FOR SETDMA
  1072.     DCR    C    ;MORE SECTORS?
  1073.     JNZ    DKWRLP    ;..YES, LOOP
  1074.     XRA    A    ;GET A ZERO
  1075.     STA    SECINBF ;RESET # OF SECTORS
  1076.     LXI    H,DBUF    ;RESET BUFFER..
  1077.     SHLD    SECPTR    ;..POINTER
  1078. ;
  1079. RSDMA    LXI    D,BASE+80H ;RESET..
  1080.     MVI    C,STDMA ;..DMA..
  1081.     CALL    BDOS    ;..ADDR
  1082.     RET
  1083. ;
  1084. WRERR    CALL    RSDMA    ;RESET DMA TO NORM.
  1085.     MVI    C,CAN    ;CANCEL..
  1086.     CALL    SEND    ;..SENDER
  1087.     CALL    ERXIT    ;EXIT W/MSG:
  1088.     DB    '++ERROR WRITING FILE++',CR,LF,'$'
  1089. ;
  1090. ;---->    RECV: Receive a character
  1091. ;
  1092. ;Timeout time is in B, in seconds.  Entry via
  1093. ;"RECVDG" deletes garbage characters on the
  1094. ;line.    For example, having just sent a sector,
  1095. ;calling RECVDG will delete any line-noise-induced
  1096. ;characters "long" before the ACK/NAK would
  1097. ;be received.
  1098. ;
  1099. RECVDG    EQU    $    ;RECEIVE W/GARBAGE DELETE
  1100.     IN    MODDATP ;GET A CHAR
  1101.     IN    MODDATP ;..TOTALLY PURGE UART
  1102. ;
  1103. RECV    PUSH    D    ;SAVE
  1104. ;
  1105.     IF    FASTCLK ;4MHZ?
  1106.     MOV    A,B    ;GET TIME REQUEST
  1107.     ADD    A    ;DOUBLE IT
  1108.     MOV    B,A    ;NEW TIME IN B
  1109.     ENDIF
  1110. ;
  1111. MSEC    LXI    D,50000 ;1 SEC DCR COUNT
  1112. ;
  1113.     IF    NOT DCH
  1114. MWTI    IN    MODCTLP ;CHECK STATUS
  1115.     ENDIF
  1116. ;
  1117.     IF    DCH
  1118. MWTI    IN    MODCTL2 ;CHECK STATUS
  1119.     ENDIF
  1120. ;
  1121.     IF    PMMI AND FRNTPNL
  1122.     OUT    PANEL    ;DISPLAY STATUS ON PANEL LIGHTS
  1123.     ENDIF
  1124. ;
  1125.     ANI    MODRCVB ;ISOLATE BIT
  1126.     CPI    MODRCVR ;READY?
  1127.     JZ    MCHAR    ;GOT CHAR
  1128.     DCR    E    ;COUNT..
  1129.     JNZ    MWTI    ;..DOWN..
  1130.     DCR    D    ;..FOR..
  1131.     JNZ    MWTI    ;..TIMEOUT
  1132.     DCR    B    ;MORE SECONDS?
  1133.     JNZ    MSEC    ;YES, WAIT
  1134. ;
  1135. ;Test for the presence of carrier - if none, go to 
  1136. ;CARCK and continue testing for 15 seconds. If carrier
  1137. ;returns, continue. If is doesn't return, exit.
  1138. ;
  1139.     IF    EXTMOD OR H8 OR DCH
  1140.     IN    MODCTL2    ;READ MODEM STATUS
  1141.     ENDIF
  1142. ;
  1143.     IF    PMMI
  1144.     IN    BAUDRP    ;READ MODEM STATUS
  1145.     ENDIF
  1146. ;
  1147.     IF    PMMI AND FRNTPNL
  1148.     OUT    PANEL    ;DISPLAY STATUS ON PANEL LIGHTS
  1149.     ENDIF
  1150. ;
  1151.     ANI    MODDCDB    ;CARRIER DETECT MASK
  1152.     CPI    MODDCDA    ;IS IT STILL ON?
  1153.     CNZ    CARCK    ;IF NOT, TEST FOR 15 SECONDS
  1154. ;
  1155. ;Modem timed out receiving - but carrier still on.
  1156. ;
  1157.     POP    D    ;RESTORE D,E
  1158.     STC        ;CARRY SHOWS TIMEOUT
  1159.     RET
  1160. ;
  1161. ;Got character from modem
  1162. ;
  1163. MCHAR:
  1164.     IF    PMMI OR H8 OR DCH
  1165. ;Check to see if there was a framing error,
  1166. ;overrun, or parity error.
  1167. ;
  1168.     IF    PMMI OR H8
  1169.     IN    MODCTLP    ;GET MODEM STATUS
  1170.     ENDIF
  1171. ;
  1172.     IF    DCH
  1173.     IN    MODCTL2    ;GET MODEM STATUS
  1174.     ENDIF
  1175. ;
  1176.     MOV    D,A    ;SAVE STATUS
  1177.     ANI    MODFRME    ;FRAMING ERROR?
  1178.     CPI    MODFRME
  1179.     JNZ    MCHAR2    ;NO, CHECK FOR OVERRUN
  1180.     LDA    ERRCDE    ;GET RECV ERR CODE
  1181.     ORI    MODFRME    ;TURN ON RECV ERR CODE
  1182.     STA    ERRCDE    ;PUT IT BACK
  1183. ;
  1184. MCHAR2:    MOV    A,D    ;RESTORE MODEM STATUS
  1185.     ANI    MODOVRE    ;OVERRUN?
  1186.     CPI    MODOVRE
  1187.     JNZ    MCHAR3    ;NO, CHECK FOR PARITY ERROR
  1188.     LDA    ERRCDE
  1189.     ORI    MODOVRE    ;TURN ON RECV ERR CODE
  1190.     STA    ERRCDE
  1191. ;
  1192. MCHAR3:    MOV    A,D    ;RESTORE MODEM STATUS
  1193.     ANI    MODPARE    ;PARITY ERROR?
  1194.     CPI    MODPARE
  1195.     JNZ    MCHAR4    ;NO, GET DATA CHAR
  1196.     LDA    ERRCDE
  1197.     ORI    MODPARE
  1198.     STA    ERRCDE
  1199. ;
  1200. MCHAR4:
  1201.     ENDIF        ;PMMI OR H8 OR DCH
  1202. ;
  1203. ;Get data char
  1204. ;
  1205.     IN    MODDATP ;READ THE CHAR
  1206.     POP    D    ;RESTORE DE
  1207. ;
  1208. ;Calc checksum and CRC
  1209. ;
  1210.     PUSH    PSW    ;SAVE THE CHAR
  1211.     CALL    UPDCRC    ;CALC CRC
  1212.     ADD    C    ;ADD TO CHECKSUM
  1213.     MOV    C,A    ;SAVE CHECKSUM
  1214.     POP    PSW    ;RESTORE CHAR
  1215.     ORA    A    ;CARRY OFF: NO ERROR
  1216.     RET        ;FROM "RECV"
  1217. ;
  1218. ;CARCK - common 15 second carrier test for RECV and
  1219. ;SEND. If carrier returns within 15 seconds, normal
  1220. ;program execution continues. Else, it will abort
  1221. ;to CP/M via EXIT.
  1222. ;
  1223. CARCK    MVI    E,150    ;VALUE FOR 15 SECOND DELAY
  1224. ;
  1225. CARCK1    CALL    DELAY    ;KILL .1 SECONDS
  1226. ;
  1227.     IF    EXTMOD OR H8 OR DCH
  1228.     IN    MODCTL2    ;READ MODEM STATUS
  1229.     ENDIF
  1230. ;
  1231.     IF    PMMI
  1232.     IN    BAUDRP    ;READ MODEM STATUS
  1233.     ENDIF
  1234. ;
  1235.     IF    PMMI AND FRNTPNL
  1236.     OUT    PANEL    ;DISPLAY STATUS
  1237.     ENDIF
  1238. ;
  1239.     ANI    MODDCDB    ;CARRIER DETECT MASK
  1240.     CPI    MODDCDA    ;IS IT STILL ON?
  1241.     RZ        ;RETURN IF CARRIER ON
  1242.     DCR    E    ;HAS 15 SECONDS EXPIRED?
  1243.     JNZ    CARCK1    ;IF NOT, CONTINUE TESTING
  1244.     JMP    EXIT    ;ELSE, ABORT TO CP/M.
  1245. ;
  1246. ;DELAY - 100 millisecond delay.
  1247. ;
  1248. DELAY    PUSH    B    ;SAVE B,C
  1249. ;
  1250.     IF    FASTCLK    ;IF 4MHZ CLOCK
  1251.     LXI    B,16667    ;VALUE FOR 100MS DELAY
  1252.     ENDIF
  1253. ;
  1254.     IF    NOT FASTCLK
  1255.     LXI    B,8334    ;VALUE FOR 100MS DELAY
  1256.     ENDIF
  1257. ;
  1258. DELAY2    DCX    B    ;UPDATE COUNT
  1259.     MOV    A,B    ;GET MS BYTE
  1260.     ORA    C    ;COUNT = ZERO?
  1261.     JNZ    DELAY2    ;IF NOT, CONTINUE
  1262.     POP    B    ;RESTORE B,C
  1263.     RET        ;RETURN TO CARCK1.
  1264. ;
  1265. ;---->    SEND: Send a character to the modem
  1266. ;
  1267. SEND    PUSH    PSW    ;SAVE THE CHARACTER
  1268.     CALL    UPDCRC    ;calc the crc
  1269.     ADD    C    ;CALC CKSUM
  1270.     MOV    C,A    ;SAVE CKSUM
  1271. ;
  1272.     IF    NOT DCH
  1273. SENDW    IN    MODCTLP ;GET STATUS
  1274.     ENDIF
  1275. ;
  1276.     IF    DCH
  1277. SENDW    IN    MODCTL2 ;GET STATUS
  1278.     ENDIF
  1279. ;
  1280.     IF    PMMI AND FRNTPNL
  1281.     OUT    PANEL    ;DISPLAY STATUS
  1282.     ENDIF
  1283. ;
  1284.     ANI    MODSNDB ;ISOLATE READY BIT
  1285.     CPI    MODSNDR ;READY?
  1286.     JZ    SENDR    ;..YES, GO SEND
  1287. ;
  1288. ;Xmit status not ready, so test for carrier before
  1289. ;looping - if lost, go to CARCK and give it up to 15
  1290. ;seconds to return. If it doesn't return abort via
  1291. ;EXIT.
  1292. ;
  1293.     PUSH    D    ;Save D,E
  1294. ;
  1295.     IF    EXTMOD OR H8 OR DCH
  1296.     IN    MODCTL2    ;READ MODEM STATUS
  1297.     ENDIF
  1298. ;
  1299.     IF    PMMI
  1300.     IN    BAUDRP    ;READ MODEM STATUS
  1301.     ENDIF
  1302. ;
  1303.     IF    PMMI AND FRNTPNL
  1304.     OUT    PANEL    ;DISPLAY STATUS
  1305.     ENDIF
  1306. ;
  1307.     ANI    MODDCDB    ;CARRIER DETECT MASK
  1308.     CPI    MODDCDA    ;IS IT STILL ON?
  1309.     CNZ    CARCK    ;IF NOT, CONTINUE TESTING IT
  1310.     POP    D    ;RESTORE D,E
  1311.     JMP    SENDW    ;ELSE, WAIT FOR XMIT READY.
  1312. ;
  1313. ;Xmit status ready, carrier still on - send the data.
  1314. ;
  1315. SENDR    POP    PSW    ;GET CHAR
  1316.     OUT    MODDATP ;OUTPUT IT
  1317.     RET        ;FROM "SEND"
  1318. ;
  1319. ;---->    WAITNAK: Waits for initial NAK
  1320. ;
  1321. ;To ensure no data is sent until the receiving
  1322. ;program is ready, this routine waits for the
  1323. ;first timeout-NAK or the letter 'C' for CRC
  1324. ;from the receiver.  If CRC is in effect, then
  1325. ;Cyclic Redundancy Checks are used instead of
  1326. ;checksums.
  1327. ;(E) contains the # of seconds to wait.
  1328. ;
  1329. WAITNAK MVI    B,1    ;TIMEOUT DELAY
  1330.     CALL    RECV    ;DID WE GET..
  1331.     CPI    NAK    ;..A NAK?
  1332.     RZ        ;YES, SEND BLOCK
  1333.     CPI    CRC    ;CRC INDICATED?
  1334.     JZ    WAITCRC    ;YES, GO PUT CRC IN EFFECT
  1335.     DCR    E    ;80 TRIES?
  1336.     JZ    ABORT    ;YES, ABORT
  1337.     JMP    WAITNAK ;NO, LOOP
  1338. ;
  1339. ;----> WAITCRC: Turn on CRC Flag
  1340. ;
  1341. WAITCRC    XRA    A    ;ZERO ACCUM
  1342.     STA    CRCFLG    ;TURN ON CRC OPT
  1343.     RET
  1344. ;
  1345. ;---->    MOVEFCB: Moves FCB(2) to FCB
  1346. ;
  1347. ;In order to make the XMODEM command 'natural',
  1348. ;i.e. XMODEM SEND FILENAME (MODEM S FN.FT) rather
  1349. ;than XMODEM FILENAME SEND (MODEM FN.FT S), this
  1350. ;routine moves the filename from the second FCB
  1351. ;to the first.
  1352. ;
  1353. MOVEFCB LXI    H,FCB+16 ;FROM
  1354.     LXI    D,FCB    ;TO
  1355.     MVI    B,16    ;LEN
  1356.     CALL    MOVE    ;DO THE MOVE
  1357.     XRA    A    ;GET 0
  1358.     STA    FCBSNO    ;ZERO SECTOR #
  1359.     STA    FCBEXT    ;..AND EXTENT
  1360.     RET
  1361. ;
  1362. CTYPE    PUSH    B    ;SAVE..
  1363.     PUSH    D    ;..ALL..
  1364.     PUSH    H    ;..REGS
  1365.     MOV    E,A    ;CHAR TO E
  1366.     MVI    C,WRCON ;GET BDOS FNC
  1367.     CALL    BDOS    ;PRIN THE CHR
  1368.     POP    H    ;RESTORE..
  1369.     POP    D    ;..ALL..
  1370.     POP    B    ;..REGS
  1371.     RET        ;FROM "CTYPE"
  1372. ;
  1373. HEXO    PUSH    PSW    ;SAVE FOR RIGHT DIGIT
  1374.     RAR        ;RIGHT..
  1375.     RAR        ;..JUSTIFY..
  1376.     RAR        ;..LEFT..
  1377.     RAR        ;..DIGIT..
  1378.     CALL    NIBBL    ;PRINT LEFT DIGIT
  1379.     POP    PSW    ;RESTORE RIGHT
  1380. ;
  1381. NIBBL    ANI    0FH    ;ISOLATE DIGIT
  1382.     CPI    10    ;IS IT <10?
  1383.     JC    ISNUM    ;YES, NOT ALPHA
  1384.     ADI    7    ;ADD ALPHA BIAS
  1385. ;
  1386. ISNUM    ADI    '0'    ;MAKE PRINTABLE
  1387.     JMP    CTYPE    ;..THEN TYPE IT
  1388. ;
  1389. ;---->    ILPRT: Inline print of message
  1390. ;
  1391. ;The call to ILPRT is followed by a message,
  1392. ;binary 0 as the end.
  1393. ;
  1394. ILPRT    XTHL        ;SAVE HL, GET HL=MSG
  1395. ;
  1396. ILPLP    MOV    A,M    ;GET CHAR
  1397.     ORA    A    ;END OF MSG?
  1398.     JZ    ILPRET    ;..YES, RETURN
  1399.     CALL    CTYPE    ;TYPE THE MSG
  1400.     INX    H    ;TO NEXT CHAR
  1401.     JMP    ILPLP    ;LOOP
  1402. ;
  1403. ILPRET    XTHL        ;RESTORE HL
  1404.     RET        ;PAST MSG
  1405. ;
  1406. ;---->    ERXIT: Exit printing message following call
  1407. ;
  1408. ERXIT    POP    D    ;GET MESSAGE
  1409.     MVI    C,PRINT ;GET BDOS FNC
  1410.     CALL    BDOS    ;PRINT MESSAGE
  1411. ;
  1412. EXIT    LHLD    STACK    ;GET ORIGINAL STACK
  1413.     SPHL        ;RESTORE IT
  1414.     RET        ;--EXIT-- TO CP/M
  1415. ;
  1416. ;Move 128 characters
  1417. ;
  1418. MOVE128 MVI    B,128    ;SET MOVE COUNT
  1419. ;
  1420. ;Move from (HL) to (DE) length in (B)
  1421. ;
  1422. MOVE    MOV    A,M    ;GET A CHAR
  1423.     STAX    D    ;STORE IT
  1424.     INX    H    ;TO NEXT "FROM"
  1425.     INX    D    ;TO NEXT "TO"
  1426.     DCR    B    ;MORE?
  1427.     JNZ    MOVE    ;..YES, LOOP
  1428.     RET        ;..NO, RETURN
  1429. ;
  1430. ;************************************************************************
  1431. ;* CRCSUBS (Cyclic Redundancy Code Subroutines) version 1.20        *
  1432. ;* 8080 Mnemonics                            *
  1433. ;*                                    *
  1434. ;*         These subroutines will compute and check a true 16-bit        *
  1435. ;*    Cyclic Redundancy Code for a message of arbitrary length.    *
  1436. ;*                                    *
  1437. ;*    The  use  of this scheme will guarantee detection of all    *
  1438. ;*    single and double bit errors, all  errors  with  an  odd    *
  1439. ;*    number  of  error bits, all burst errors of length 16 or    *
  1440. ;*    less, 99.9969% of all 17-bit error bursts, and  99.9984%    *
  1441. ;*    of  all  possible  longer  error bursts.  (Ref: Computer    *
  1442. ;*    Networks, Andrew S.  Tanenbaum, Prentiss-Hall, 1981)        *
  1443. ;*                                    *
  1444. ;*                                    *
  1445. ;*    There are four entry points, which are used as follows:        *
  1446. ;*                                    *
  1447. ;*    CLRCRC - A call to this entry resets the CRC accumulator.    *
  1448. ;*         It must be called at the start of each message.    *
  1449. ;*                                    *
  1450. ;*         Entry Parameters: None.                *
  1451. ;*                                    *
  1452. ;*         Exit Conditions:  CRC accumulator cleared.        *
  1453. ;*                   All registers preserved.        *
  1454. ;*                                    *
  1455. ;*                                    *
  1456. ;*    UPDCRC - A call to this entry updates the CRC accumulator.    *
  1457. ;*         It must be called once for each byte in the        *
  1458. ;*         message for which the CRC is being calculated.        *
  1459. ;*                                    *
  1460. ;*         Entry Parameters: (A) = a byte to be included        *
  1461. ;*                     in the CRC calculation.    *
  1462. ;*                                    *
  1463. ;*         Exit Conditions:  CRC accumulator updated.        *
  1464. ;*                   All registers preserved.        *
  1465. ;*                                    *
  1466. ;*                                    *
  1467. ;*    FINCRC - A call to this entry finishes the CRC calculation    *
  1468. ;*         for a message which is to be TRANSMITTED. It must    *
  1469. ;*         be called after the last byte of the message has    *
  1470. ;*         been passed thru UPDCRC. It returns the calculated    *
  1471. ;*         CRC bytes, which must be transmitted as the final    *
  1472. ;*         two bytes of the message (first D, then E).        *
  1473. ;*                                    *
  1474. ;*         Entry Parameters: None.                *
  1475. ;*                                    *
  1476. ;*         Exit Conditions:  (DE) = calculated CRC bytes.        *
  1477. ;*                   All other registers preserved.    *
  1478. ;*                                    *
  1479. ;*                                    *
  1480. ;*    CHKCRC - A call to this routine checks the CRC bytes of        *
  1481. ;*         a RECEIVED message and returns a code to indicate    *
  1482. ;*         whether the message was received correctly. It must    *
  1483. ;*         be called after the message AND the two CRC bytes    *
  1484. ;*         have been received AND passed thru UPDCRC.        *
  1485. ;*                                    *
  1486. ;*         Entry Parameters: None.                *
  1487. ;*                                    *
  1488. ;*         Exit Conditions:  (A) =  0 if message ok.        *
  1489. ;*                   (A) = -1 if message garbled.        *
  1490. ;*                   All other registers preserved.    *
  1491. ;*                                    *
  1492. ;************************************************************************
  1493. ;*                                    *
  1494. ;*    Designed & coded by Paul Hansknecht, June 13, 1981        *
  1495. ;*                                    *
  1496. ;*                                    *
  1497. ;*    Copyright (c) 1981, Carpenter Associates            *
  1498. ;*                Box 451                    *
  1499. ;*                Bloomfield Hills, MI 48013            *
  1500. ;*                313/855-3074                *
  1501. ;*                                    *
  1502. ;*    This program may be freely reproduced for non-profit use.    *
  1503. ;*                                    *
  1504. ;************************************************************************
  1505. ;
  1506. ;    ENTRY    CLRCRC,UPDCRC,FINCRC,CHKCRC
  1507. ;
  1508. CLRCRC:    EQU    $        ; Reset CRC Accumulator for a new message.
  1509.     PUSH    H
  1510.     LXI    H,0
  1511.     SHLD    CRCVAL
  1512.     POP    H
  1513.     RET
  1514. ;
  1515. UPDCRC:    EQU    $        ; Update CRC Accumulator using byte in (A).
  1516.     PUSH    PSW
  1517.     PUSH    B
  1518.     PUSH    H
  1519.     MVI    B,8
  1520.     MOV    C,A
  1521.     LHLD    CRCVAL
  1522. UPDLOOP:MOV    A,C
  1523.     RLC
  1524.     MOV    C,A
  1525.     MOV    A,L
  1526.     RAL
  1527.     MOV    L,A
  1528.     MOV    A,H
  1529.     RAL
  1530.     MOV    H,A
  1531.     JNC    SKIPIT
  1532.     MOV    A,H        ; The generator is X^16 + X^12 + X^5 + 1
  1533.     XRI    10H        ; as recommended by CCITT.
  1534.     MOV    H,A        ; An alternate generator which is often
  1535.     MOV    A,L        ; used in synchronous transmission protocols
  1536.     XRI    21H        ; is X^16 + X^15 + X^2 + 1. This may be
  1537.     MOV    L,A        ; used by substituting XOR 80H for XOR 10H
  1538. SKIPIT:    DCR    B        ; and XOR 05H for XOR 21H in the adjacent code.
  1539.     JNZ    UPDLOOP
  1540.     SHLD    CRCVAL
  1541.     POP    H
  1542.     POP    B
  1543.     POP    PSW
  1544.     RET
  1545. ;
  1546. FINCRC:    EQU    $        ; Finish CRC calc for outbound message.
  1547.     PUSH    PSW
  1548.     XRA    A
  1549.     CALL    UPDCRC
  1550.     CALL    UPDCRC
  1551.     PUSH    H
  1552.     LHLD    CRCVAL
  1553.     MOV    D,H
  1554.     MOV    E,L
  1555.     POP    H
  1556.     POP    PSW
  1557.     RET
  1558. ;
  1559. CHKCRC:    EQU    $        ; Check CRC bytes of received message.
  1560.     PUSH    H
  1561.     LHLD    CRCVAL
  1562.     MOV    A,H
  1563.     ORA    L
  1564.     POP    H
  1565.     RZ
  1566.     MVI    A,0FFh
  1567.     RET
  1568. ;
  1569. ;
  1570. CRCVAL    DW    0
  1571. ;
  1572. ;
  1573. ;
  1574. ;Temporary storage area
  1575. ;
  1576. MAXEXT    DB    0    ;HIGHEST EXTENT NO. SEEN IN FILE SIZE CALC.
  1577. RCNT    DW    0    ;RECORD COUNT
  1578. RCVSNO    DB    0    ;SECT # RECEIVED
  1579. SECTNO    DB    0    ;CURRENT SECTO