home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / cpmug / cpmug040.ark / MODEM4.ASM < prev    next >
Encoding:
Assembly Source File  |  1984-04-29  |  39.3 KB  |  1,743 lines

  1. ;
  2. ;MODEM.ASM V4.0, BY WARD CHRISTENSEN
  3. ;    (Revised 8/6/79)
  4. ;
  5. ;CP/M - CP/M FILE TRANSFER PROGRAM, AND
  6. ;TERMINAL PROGRAM.
  7. ;
  8. ;NOTE: THIS FILE WILL ASSEMBLE, WITHOUT NEED FOR
  9. ;EDITING, TO WORK WITH A PMMI MM-103 MODEM.  SEE
  10. ;EQUATES FOR OTHER OPTIONS INCLUDING SYSTEM CLOCK
  11. ;FREQUENCY.
  12. ;
  13. * * * * * * * * * * * * * * * * * * * * * * * * *
  14. *                        *
  15. *    THIS PROGRAM DOCUMENTED IN "MODEM.DOC"    *
  16. *                        *
  17. * * * * * * * * * * * * * * * * * * * * * * * * *
  18. * THIS PROGRAM WAS "MODEM.ASM" BUT IS         *
  19. * TEMPORARILY NAMED "MODEM2.ASM" SO PEOPLE    *
  20. * WILL REALIZE IT IS AN ENHANCEMENT OF        *
  21. * THE ORIGINAL PROGRAM "MODEM.ASM" ON CP/M    *
  22. * USER'S GROUP DISK 25.                *
  23. * * * * * * * * * * * * * * * * * * * * * * * * *
  24. ;
  25. ;PLEASE PASS ON MODS, BUGS, ETC, SO YOUR
  26. ;FIXES OR ENHANCEMENTS MAY BE SHARED BY ALL,
  27. ;         TO:
  28. ;    Ward Christensen
  29. ;    688 E. 154th St. #5D
  30. ;    Dolton, Il. 60419
  31. ;
  32. ;    (312) 849-6279
  33. ;
  34. ;You may send a self-addressed stamped postcard
  35. ;to be informed of changes/bugs as they become
  36. ;known.
  37. ;
  38. ;    --------------
  39. ;
  40. ;    09/23/77
  41. ;ORIGINALLY WRITTEN BY WARD CHRISTENSEN
  42. ;
  43. ;    04/26/79
  44. ;REWRITTEN BY WARD CHRISTENSEN TO COMBINE
  45. ;IMPROVEMENTS TO THE ORIGINAL MADE BY WARD
  46. ;AND BY KEITH PETERSEN, W8SDZ, AND SUGGESTIONS
  47. ;BY JIM BELL WHICH KEITH IMPLEMENTED.  SEE
  48. ;MODEM.DOC FOR ADDITIONAL HISTORICAL
  49. ;INFORMATION AND DOCUMENTATION.
  50. ;
  51. ;    05/09/79
  52. ;ALLOW 'T' AND 'E' SUB-OPTIONS TO GO TO TERMINAL
  53. ;OR ECHO MODEM AFTER TRANSFERRING A FILE.  (WLC)
  54. ;
  55. ;    05/22/79
  56. ;ADD FEATURE TO MAKE RECEIVE FILE ROUTINE SAY
  57. ;FILE SUCCESSFULLY OPENED, WHEN IN QUIET MODE.
  58. ;MOVE INITIAL GOBBLE GARBAGE INPUTS TO BEFORE
  59. ;COMMAND CPI'S SO ALL MODES ARE CLEARED. CHANGE
  60. ;INITIAL SEND WAIT TO 80 SECS TO ALLOW MORE TIME
  61. ;FOR RECEIVING END TO COME UP. ADD 'H' AFTER MSG
  62. ;THAT SHOWS NUMBER OF SECTORS IN EXTENT ABOUT TO
  63. ;BE SENT.  (KBP)
  64. ;
  65. ;    05/24/79
  66. ;FIX MISSING RETURN INSTRUCTION AT END OF
  67. ;INITIALIZATION ROUTINE.  (KBP)
  68. ;
  69. ;    07/01/79
  70. ;MODIFIED PROGRAM TO ALLOW FOR NON-STANDARD VERSIONS OF
  71. ;CP/M. ALL REFERENCES TO ENTRIES INTO CP/M SHOULD BE MADE
  72. ;RELATIVE TO THE VARIABLE SYMBOL CALL "BASE". FOR EXAMPLE,
  73. ;THE EQUATE TO BDOS SHOULD BE BASE+5 INSTEAD OF 5. BASE
  74. ;WILL BE SET TO 0 WHEN THE VARIABLE STDCPM IS SET TO TRUE.
  75. ;(BOB MATHIAS).
  76. ;
  77. ;    07/24/79
  78. ;MOVE INITIALIZE LOCAL STACK TO BEGINNING OF PROGRAM
  79. ;SO DEFAULT STACK IS NOT USED. ADD CONDITIONAL ASSEMBLY
  80. ;OPTION TO TERMINAL ROUTINE FOR TIMESHARE SYSTEMS.
  81. ;CORRECT ERROR IN LOCAL ABORT ROUTINE (WAS LOOKING FOR
  82. ;CONTROL E - NOW CORRECTLY LOOKS FOR CONTROL X). ADD
  83. ;REGISTER SAVES TO CONOUT, KEYIN AND AND KEYBOARD STATUS
  84. ;ROUTINES, AS SOME CBIOS ROUTINES CLOBBER THEM. (KBP)
  85. ;
  86. ;    08/05/79
  87. ;ADDED D. C. HAYES MODEM SUPPORT BY JIM BELL  (KBP)
  88. ;
  89. ;    08/06/79
  90. ;ADDED EQUATES FOR EXTERNAL MODEM (NOT S-100 PLUG-IN)
  91. ;(KBP)
  92. ;
  93. STDCPM    EQU    1    ;TRUE, IS STANDARD CP/M
  94. H8CPM    EQU    0    ;TRUE, IS HEATH H8 CP/M
  95. ;
  96.     IF    STDCPM
  97. BASE    EQU    0    ;CP/M BASE ADDRESS
  98.     ENDIF
  99. ;
  100.     IF    H8CPM
  101. BASE    EQU    4200H    ;CP/M BASE ADDRESS FOR HEATH H8
  102.     ENDIF
  103. ;
  104. PMMI    EQU    1    ;TRUE, IS PMMI
  105. ;
  106. DCH    EQU    0    ;TRUE, IS D.C. HAYES
  107. ;
  108.     IF    STDCPM AND PMMI
  109. MODCTLP    EQU    0C0H    ;PMMI VALUES
  110. MODSNDB EQU    1    ;BIT TO TEST FOR SEND
  111. MODSNDR    EQU    1    ;VALUE WHEN READY
  112. MODRCVB EQU    2    ;BIT TO TEST FOR RECEIVE
  113. MODRCVR    EQU    2    ;VALUE WHEN READY
  114. MODDATP EQU    0C1H    ;DATA PORT
  115. BAUDRP    EQU    0C2H    ;BAUD RATE OUTPUT
  116. MODCTL2    EQU    0C3H    ;SECOND CTL PORT
  117.     ENDIF
  118. ;
  119.     IF    STDCPM AND DCH
  120. MODCTLP    EQU    82H    ;D. C. HAYES VALUES
  121. MODSNDB EQU    2    ;BIT TO TEST FOR SEND
  122. MODSNDR    EQU    2    ;VALUE WHEN READY
  123. MODRCVB EQU    1    ;BIT TO TEST FOR RECEIVE
  124. MODRCVR    EQU    1    ;VALUE WHEN READY
  125. MODDATP EQU    80H    ;DATA PORT
  126. MODCTL2    EQU    81H    ;SECOND CTL PORT
  127.     ENDIF
  128. ;
  129.     IF    H8CPM
  130. MODCTLP    EQU    05H    ;H84 VALUES
  131. MODSNDB    EQU    20H    ;BIT TO TEST FOR SEND
  132. MODSNDR    EQU    20H    ;VALUE WHEN READY
  133. MODRCVB    EQU    01H    ;BIT TO TEST FOR RECEIVE
  134. MODRCVR    EQU    01H    ;VALUE WHEN READY
  135. MODDATP    EQU    00H    ;DATA PORT
  136.     ENDIF
  137. ;
  138. ;IF YOU ARE USING AN EXTERNAL MODEM (NOT S-100 PLUG-IN)
  139. ;CHANGE THESE EQUATES FOR YOUR MODEM PORT REQUIREMENTS
  140. ;
  141. INITREQ    EQU    0    ;TRUE, IF MODEM PORT INIT. REQ'D
  142. INITC1    EQU    64H    ;FIRST INIT CHAR TO CTL PORT
  143. INITC2    EQU    64H    ;2ND INIT CHAR TO CTL PORT
  144. ;
  145.     IF    STDCPM AND NOT PMMI AND NOT DCH
  146. MODCTLP    EQU    02H    ;PUT YOUR MODEM CONTROL PORT HERE
  147. MODSNDB    EQU    80H    ;YOUR BIT TO TEST FOR SEND
  148. MODSNDR    EQU    80H    ;YOUR VALUE WHEN READY
  149. MODRCVB    EQU    40H    ;YOUR BIT TO TEST FOR RECEIVE
  150. MODRCVR    EQU    40H    ;YOUR VALUE WHEN READY
  151. MODDATP    EQU    03H    ;YOUR MODEM DATA PORT
  152.     ENDIF        ;END OF EXTERNAL MODEM EQUATES
  153. ;
  154.     IF    PMMI
  155. ORIGMOD    EQU    1DH    ;8 DATA, NO PARITY, ORIG
  156. ANSWMOD    EQU    1EH    ;8 DATA, NO PARITY, ANSW
  157.     ENDIF
  158. ;
  159. ;NOTE: IF DC HAYES THEN BAUD RATE DEFAULTS TO
  160. ;300 - 1 STOP BIT.  DO NOT CHANGE NEXT EQUATES
  161.     IF    DCH
  162. ORIGMOD EQU    86H    ;OFF HOOK, 110 BAUD, CAR. ON, ORIG.
  163. ANSWMOD    EQU    82H    ;OFF HOOK, 110 BAUD, CAR. ON, ANSW.
  164.     ENDIF
  165. ;
  166. ERRLIM    EQU    10    ;MAX ALLOWABLE ERRORS
  167. EXITCHR    EQU    'E'-40H ;CTL-E EXIT FROM T OR C
  168. DISCCHR    EQU    'D'-40H    ;CTL-D DISCONNECTS MODEM T/C
  169. ;
  170. FASTCLK    EQU    0    ;PUT 1 HERE FOR 4 MHZ CLOCK
  171. ;
  172. ;SOME TIME-SHARE COMPUTERS REQUIRE TERMINALS TO
  173. ;HAVE BIT 7 HIGH (MARKING), SO IN THE TERMINAL
  174. ;MODE WE FORCE IT TO HIGH IF THE FOLLOWING OPTION
  175. ;IS SELECTED:
  176. ;
  177. TIMESHR    EQU    0    ;PUT 1 HERE TO MAKE BIT 7 HIGH
  178. ;DEFINE ASCII CHARACTERS USED
  179. ;
  180. SOH    EQU    1    ;START OF HEADER
  181. EOT    EQU    4    ;END OF TRANSMISSION
  182. ACK    EQU    6    ;ACKNOWLEDGE
  183. NAK    EQU    15H    ;NEG ACKNOWLEDGE
  184. CAN    EQU    18H    ;CANCEL
  185. LF    EQU    10    ;LINEFEED
  186. CR    EQU    13    ;CARRIAGE RETURN
  187.     ORG    BASE+100H
  188. ;
  189. ;INIT PRIVATE STACK
  190.     LXI    H,0    ;HL=0
  191.     DAD    SP    ;HL=STACK FROM CP/M
  192.     SHLD    STACK    ;..SAVE IT
  193.     LXI    SP,STACK ;SP=MY STACK
  194.     CALL    START    ;GO PRINT ID
  195.     DB    'MODEM PROGRAM as of '
  196.     DB    '08/06/79',CR,LF,'$'
  197. START    POP    D    ;GET ID MESSAGE
  198.     MVI    C,PRINT
  199.     CALL    BDOS    ;PRINT ID MESSAGE
  200. ;
  201. ;INITIALIZE THE JMPS TO CP/M BIOS
  202. ;
  203.     CALL    INITADR
  204. ;
  205. ;SAVE PRIMARY OPTION, VALIDATE SECONDARY OPT.
  206. ;
  207.     CALL    PROCOPT
  208. ;
  209. ;INIT THE MODEM OR SERIAL PORT
  210. ;
  211.     CALL    INITMOD
  212. ;
  213. ;MOVE THE FILENAME FROM FCB 2 TO FCB 1
  214. ;
  215.     CALL    MOVEFCB
  216. ;
  217. ;GOBBLE UP GARBAGE CHARS FROM THE LINE
  218. ;PRIOR TO RECEIVE OR SEND
  219. ;
  220.     IN    MODDATP
  221.     IN    MODDATP
  222. ;
  223. ;JMP TO APPROPRIATE FUNCTION
  224. ;
  225.     LDA    OPTION    ;GET PRIMARY OPTION
  226. ;
  227.     CPI    'C'    ;(COMPAT W/EARLIER
  228.     JZ    TRMECHO    ;OPTION "COMPUTER")
  229. ;
  230.     CPI    'E'    ;TERMINAL IN ECHO
  231.     JZ    TRMECHO    ;..MODE?
  232. ;
  233.     CPI    'T'    ;TERMINAL..
  234.     JZ    TERM    ;..MODE?
  235. ;
  236.     CPI    'D'
  237.     JZ    DISCONN
  238. ;
  239.     CPI    'X'
  240.     JZ    EXAM    ;GIVE EXAMPLES
  241. ;
  242.            CPI    'S'    ;SEND..
  243.     JZ    SENDFIL    ;..A FILE?
  244. ;
  245.     CPI    'R'    ;RECEIVE..
  246.     JZ    RCVFIL    ;..A FILE?
  247. ;
  248. ;INVALID OPTION
  249. ;
  250.     JMP    BADOPT
  251. * * * * * * * * * * * * * * * * * * * * *
  252. *                    *
  253. *    TERM: TERMINAL MODE        *
  254. *                    *
  255. * * * * * * * * * * * * * * * * * * * * *
  256. ;
  257. ;THIS PROGRAM SIMPLY SENDS KEYED CHARACTERS
  258. ;DOWN THE LINE, AND DISPLAYS CHARACTERS
  259. ;RECEIVED FROM THE LINE.  THIS MAKES IT
  260. ;SUITABLE FOR COMMUNICATION WITH TIME SHARING
  261. ;COMPUTERS, CBBS'S, OR ANOTHER PROGRAM
  262. ;RUNING "MODEM E" (ECHO MODE)
  263. ;
  264. ;TYPE THE "EXITCHR" (ORIGINALLY CTL-E) TO EXIT.
  265. ;OR THE "DISCCHR" (ORIGINALLY CTL-D) TO DISCONN.
  266. ;
  267. ;A FUTURE ENHANCEMENT WILL BE TO WRITE THE
  268. ;RECEIVED DATA IN MEMORY, AND ALLOW IT TO
  269. ;BE WRITTEN TO DISK
  270. ;
  271. TERM    CALL    STAT    ;LOCAL CHAR KEYED?
  272.     JZ    TERML    ;..NO, CHECK LINE
  273.     CALL    KEYIN    ;GET CHAR
  274.     CPI    EXITCHR    ;TIME TO END?
  275.     JZ    CKDIS    ;YES, CK DISCONN
  276.     CPI    DISCCHR    ;DISCONNECT REQUEST?
  277.     JZ    DISCONN    ;YES, DO IT
  278.     IF    TIMESHR
  279.     ORI    80H    ;FORCE BIT 7 TO HIGH
  280.     ENDIF        ;TIMESHR
  281.     OUT    MODDATP    ;SEND THE CHAR
  282. ;
  283. ;SEE IF CHAR FROM LINE
  284. ;
  285.     IF    NOT DCH
  286. TERML    IN    MODCTLP    ;READ STATUS
  287.     ENDIF
  288.     IF    DCH
  289. TERML    IN    MODCTL2    ;READ STATUS
  290.     ENDIF
  291.     ANI    MODRCVB    ;ISOLATE BIT
  292.     CPI    MODRCVR    ;READY?
  293.     JNZ    TERM    ;..NO, LOOP
  294.     IN    MODDATP    ;READ DATA
  295.     CALL    TYPE    ;TYPE IT
  296.     JMP    TERM    ;LOOP
  297. ;
  298. * * * * * * * * * * * * * * * * * * * * *
  299. *                    *
  300. *    TRMECHO: TERMINAL WITH ECHO    *
  301. *                    *
  302. * * * * * * * * * * * * * * * * * * * * *
  303. ;
  304. ;TERMINAL PROGRAM WITH ECHO - SEE NOTES
  305. ;UNDER "TERM" ABOVE
  306. ;
  307. ;C A U T I O N   DON'T RUN WITH BOTH COMPUTERS
  308. ;IN "ECHO" MODE - LINE ERRORS (OR ANY CHAR)
  309. ;WILL BE ECHOED BACK AND FORTH AD INFINITUM.
  310. ;
  311.     IF    NOT DCH
  312. TRMECHO    IN    MODCTLP    ;GET STATUS
  313.     ENDIF
  314.     IF    DCH
  315. TRMECHO    IN    MODCTL2    ;GET STATUS
  316.     ENDIF
  317.     ANI    MODRCVB    ;ISOLATE READY BIT
  318.     CPI    MODRCVR    ;ARE WE READY?
  319.     JZ    LINECHR    ;YES, READ THE CHR
  320.     CALL    STAT    ;CHECK LOCAL KB
  321.     JZ    TRMECHO    ;..NO CHAR
  322.     CALL    KEYIN    ;GET LOCAL CHAR
  323.     CPI    EXITCHR    ;END?
  324.     JZ    CKDIS    ;YES, CK DISCONN, EXIT
  325.     CPI    DISCCHR    ;DISCONN?
  326.     JZ    DISCONN    ;..YES, DO IT.
  327.     OUT    MODDATP    ;SEND CHAR
  328.     CALL    TYPE    ;ECHO IT LOCALLY
  329.     JMP    TRMECHO    ;..AND LOOP
  330. ;
  331. ;GOT CHAR FROM LINE
  332. ;
  333. LINECHR    IN    MODDATP    ;GET CHAR
  334.     OUT    MODDATP    ;ECHO IT
  335.     CALL    TYPE    ;TYPE IT
  336.     JMP    TRMECHO    ;LOOP
  337. ;
  338. * * * * * * * * * * * * * * * * * * * * *
  339. *                    *
  340. *    SENDFIL: SENDS A CP/M FILE    *
  341. *                    *
  342. * * * * * * * * * * * * * * * * * * * * *
  343. ;
  344. ;THE CP/M FILE SPECIFIED IN THE MODEM COMMAND
  345. ;IS TRANSFERRED OVER THE PHONE TO ANOTHER
  346. ;COMPUTER RUNNING MODEM WITH THE "R" (RECEIVE)
  347. ;OPTION.  THE DATA IS SENT ONE SECTOR AT A
  348. ;TIME WITH HEADERS AND CHECKSUMS, AND RE-
  349. ;TRANSMISSION ON ERRORS.  
  350. ;
  351. SENDFIL    CALL    OPENFIL    ;OPEN THE FILE
  352.     MVI    E,80    ;WAIT 80 SEC..
  353.     CALL    WAITNAK    ;..FOR INITIAL NAK
  354. SENDLP    CALL    RDSECT    ;READ A SECTOR
  355.     JC    SENDEOF    ;SEND EOF IF DONE
  356.     CALL    INCRSNO    ;BUMP SECTOR #
  357.     XRA    A    ;ZERO ERROR..
  358.     STA    ERRCT    ;..COUNT
  359. SENDRPT    CALL    SENDHDR    ;SEND A HEADER
  360.     CALL    SENDSEC    ;SEND DATA SECTOR
  361.     CALL    SENDCKS    ;SEND CKSUM
  362.     CALL    GETACK    ;GET THE ACK
  363.     JC    SENDRPT    ;REPEAT IF NO ACK
  364.     JMP    SENDLP    ;LOOP UNTIL EOF
  365. ;
  366. ;FILE SENT, SEND EOT'S
  367. ;
  368. SENDEOF    MVI    A,EOT    ;SEND..
  369.     CALL    SEND    ;..AN EOT
  370.     CALL    GETACK    ;GET THE ACK
  371.     JC    SENDEOF    ;LOOP IF NO ACK
  372.     JMP    DONE    ;ALL DONE
  373. ;
  374. * * * * * * * * * * * * * * * * * * * * *
  375. *                    *
  376. *    RCVFIL: RECEIVE A FILE        *
  377. *                    *
  378. * * * * * * * * * * * * * * * * * * * * *
  379. ;
  380. ;RECEIVES A FILE IN BLOCK FORMAT AS SENT
  381. ;BY ANOTHER PERSON DOING "MODEM S FN.FT".
  382. ;
  383. RCVFIL    CALL    ERASFIL    ;ERASE THE FILE
  384.     CALL    MAKEFIL    ;..THEN MAKE NEW
  385.     LDA    QFLG    ;SEE IF IN QUIET MODE
  386.     ORA    A
  387.     JNZ    RCVLP    ;NOT IN QUIET MODE, SKIP MSG
  388.     CALL    ILPRT    ;PRINT:
  389.     DB    'FILE OPEN, READY TO RECEIVE',CR,LF,0
  390. RCVLP    CALL    RCVSECT    ;GET A SECTOR
  391.     JC    RCVEOT    ;GOT EOT
  392.     CALL    WRSECT    ;WRITE THE SECTOR
  393.     CALL    INCRSNO    ;BUMP SECTOR #
  394.     CALL    SENDACK    ;ACK THE SECTOR
  395.     JMP    RCVLP    ;LOOP UNTIL EOF
  396. ;
  397. ;GOT EOT ON SECTOR - FLUSH BUFFERS, END
  398. ;
  399. RCVEOT    CALL    WRBLOCK    ;WRITE THE LAST BLOCK
  400.     CALL    SENDACK    ;ACK THE SECTOR
  401.     CALL    CLOSFIL    ;CLOSE THE FILE
  402.     LDA    QFLG    ;QUIET..
  403.     ORA    A    ;..MODE?
  404.     JZ    CKDIS    ;YES, CK DISCONN, END.
  405.     JMP    DONE    ;DISCONN IF REQ'D
  406. ;
  407. * * * * * * * * * * * * * * * * * * * * *
  408. *                    *
  409. *        SUBROUTINES        *
  410. *                    *
  411. * * * * * * * * * * * * * * * * * * * * *
  412. ;
  413. ;
  414. ;---->    RCVSECT: RECEIVE A SECTOR
  415. ;
  416. ;RETURNS WITH CARRY SET IF EOT RECEIVED.
  417. ;
  418. RCVSECT    XRA    A    ;GET 0
  419.     STA    ERRCT    ;INIT ERROR COUNT
  420. RCVRPT    LDA    QFLG    ;QUIET?
  421.     ORA    A
  422.     JZ    RCVSQ    ;YES, NO STAT MSG.
  423.     CALL    ILPRT    ;PRINT:
  424.     DB    'AWAITING #',0
  425.     LDA    SECTNO    ;GET SECTOR #
  426.     INR    A    ;(REAL INR LATER)
  427.     CALL    HEXO    ;PRINT IN HEX
  428.     CALL    CRLF    ;..THEN CRLF
  429. ;
  430. RCVSQ    MVI    B,10    ;10 SEC TIMEOUT
  431.     CALL    RECV    ;GET SOH/EOT
  432.     JC    RCVSTOT    ;TIMEOUT
  433.     CPI    SOH    ;GET SOH?
  434.     JZ    RCVSOH    ;..YES
  435. ;
  436. ;EARLIER VERS. OF MODEM PROG SENT SOME NULLS -
  437. ;IGNORE THEM
  438. ;
  439.     ORA    A    ;00 FROM SPEED CHECK?
  440.     JZ    RCVSQ    ;YES, IGNORE IT
  441.     CPI    EOT    ;END OF TRANSFER?
  442.     STC        ;RETURN WITH CARRY..
  443.     RZ        ;..SET IF EOT
  444. ;
  445. ;DIDN'T GET SOH  OR EOT - 
  446. ;
  447.     MOV    B,A    ;SAVE CHAR
  448.     LDA    VSEEFLG    ;VIEWING..
  449.     ORA    A    ;..MODE?
  450.     JZ    RCVSEH    ;YES, PRT.MSG
  451.     LDA    QFLG    ;QUIET..
  452.     ORA    A    ;..MODE?
  453.     JZ    RCVSERR    ;YES, SKIP MSG
  454. RCVSEH    MOV    A,B    ;GET CHAR
  455.     CALL    HEXO    ;SHOW IN HEX
  456.     CALL    ILPRT    ;PRINT:
  457.     DB    'H RCD, NOT SOH',CR,LF,0
  458. ;
  459. ;DIDN'T GET VALID HEADER - PURGE THE LINE,
  460. ;THEN SEND NAK.
  461. ;
  462. RCVSERR    MVI    B,1    ;WAIT FOR 1 SEC..
  463.     CALL    RECV    ;..WITH NO CHARS
  464.     JNC    RCVSERR    ;LOOP UNTIL SENDER DONE
  465.     MVI    A,NAK    ;SEND..
  466.     CALL    SEND    ;..THE NAK
  467.     LDA    ERRCT    ;ABORT IF..
  468.     INR    A    ;..WE HAVE REACHED..
  469.     STA    ERRCT    ;..THE ERROR..
  470.     CPI    ERRLIM    ;..LIMIT?
  471.     JC    RCVRPT    ;..NO, TRY AGAIN
  472. ;
  473. ;10 ERRORS IN A ROW - 
  474. ;
  475.     LDA    VSEEFLG    ;VIEWING..
  476.     ORA    A    ;..FILE?
  477.     JZ    RCVCKQ    ;YES, ASK RETRY/QUIT
  478.     LDA    QFLG    ;QUIET..
  479.     ORA    A    ;..MODE?
  480.     JZ    RCVSABT    ;ABORT
  481. RCVCKQ    CALL    CKQUIT    ;RETRY/QUIT?
  482.     JZ    RCVSECT    ;TRY AGAIN
  483. ;
  484. RCVSABT    CALL    CLOSFIL    ;KEEP WHATEVER WE GOT
  485.     CALL    ERXIT
  486.     DB    '++UNABLE TO RECEIVE BLOCK'
  487.     DB    CR,LF,'++ABORTING++$'
  488. ;
  489. ;TIMEDOUT ON RECEIVE
  490. ;
  491. RCVSTOT    LDA    VSEEFLG    ;VIEWING..
  492.     ORA    A    ;..MODE?
  493.     JZ    RCVSPT    ;YES, PRT MSG
  494.     LDA    QFLG    ;QUIET..
  495.     ORA    A    ;..MODE?
  496.     JZ    RCVSERR    ;YES, NO MSG
  497. RCVSPT    CALL    ILPRT
  498.     DB    '++TIMEOUT++ ',0
  499. RCVPRN    LDA    ERRCT    ;PRINT ERROR..
  500.     CALL    HEXO    ;..COUNT
  501.     CALL    CRLF
  502.     JMP    RCVSERR    ;BUMP ERR CT, ETC.
  503. ;
  504. ;GOT SOH - GET BLOCK #, BLOCK # COMPLEMENTED
  505. ;
  506. RCVSOH    MVI    B,1    ;TIMEOUT = 1 SEC
  507.     CALL    RECV    ;GET SECTOR
  508.     JC    RCVSTOT    ;GOT TIMEOUT
  509.     MOV    D,A    ;D=BLK #
  510.     MVI    B,1    ;TIMEOUT = 1 SEC
  511.     CALL    RECV    ;GET CMA'D SECT #
  512.     JC    RCVSTOT    ;TIMEOUT
  513.     CMA        ;CALC COMPLEMENT
  514.     CMP    D    ;GOOD SECTOR #?
  515.     JZ    RCVDATA    ;YES, GET DATA
  516. ;
  517. ;GOT BAD SECTOR #
  518. ;
  519.     LDA    VSEEFLG    ;VIEWING..
  520.     ORA    A    ;..MODE?
  521.     JZ    RCVBSE    ;..YES, PRT MSG
  522.     LDA    QFLG    ;QUIET..
  523.     ORA    A    ;..MODE?
  524.     JZ    RCVSERR    ;..YES, NO MSG
  525. ;
  526. RCVBSE    CALL    ILPRT    ;PRINT:
  527.     DB    '++BAD SECTOR # IN HDR',CR,LF,0
  528.     JMP    RCVSERR    ;BUMP ERROR CT.
  529. ;
  530. RCVDATA    MOV    A,D    ;GET SECTOR #
  531.     STA    RCVSNO    ;SAVE IT
  532.     MVI    A,1    ;SHOW..
  533.     STA    DATAFLG    ;GETTING DATA
  534.     MVI    C,0    ;INIT CKSUM
  535.     LXI    H,BASE+80H    ;POINT TO BUFFER
  536. RCVCHR    MVI    B,1    ;1 SEC TIMEOUT
  537.     CALL    RECV    ;GET CHAR
  538.     JC    RCVSTOT    ;TIMEOUT
  539.     MOV    M,A    ;STORE CHAR
  540.     INR    L    ;DONE?
  541.     JNZ    RCVCHR    ;NO, LOOP
  542. ;
  543. ;VERIFY CHECKSUM
  544. ;
  545.     MOV    D,C    ;SAVE CHECKSUM
  546.     XRA    A    ;SHOW..
  547.     STA    DATAFLG    ;..END OF DATA
  548.     MVI    B,1    ;TIMEOUT LEN.
  549.     CALL    RECV    ;GET CHECKSUM
  550.     JC    RCVSTOT    ;TIMEOUT
  551.     CMP    D    ;CHECKSUM OK?
  552.     JNZ    RCVCERR    ;NO, ERROR
  553. ;
  554. ;GOT A SECTOR, IT'S A DUP IF = PREV,
  555. ;    OR OK IF = 1 + PREV SECTOR
  556. ;
  557.     LDA    RCVSNO    ;GET RECEIVED
  558.     MOV    B,A    ;SAVE IT
  559.     LDA    SECTNO    ;GET PREV
  560.     CMP    B    ;PREV REPEATED?
  561.     JZ    RECVACK    ;ACK TO CATCH UP
  562.     INR    A    ;CALC NEXT SECTOR #
  563.     CMP    B    ;MATCH?
  564.     JNZ    ABORT    ;NO MATCH - STOP SENDER, EXIT
  565.     RET        ;CARRY OFF - NO ERRORS
  566. ;
  567. ;GOT CKSUM
  568. ;
  569. RCVCERR    LDA    VSEEFLG    ;VIEWING..
  570.     ORA    A    ;..MODE?
  571.     JZ    RCVCPR    ;..YES, PRT MSG
  572.     LDA    QFLG    ;QUIET..
  573.     ORA    A    ;..MODE?
  574.     JZ    RCVSERR    ;YES, NO MSG
  575. RCVCPR    CALL    ILPRT
  576.     DB    '++CKSUM++ ',0
  577.     JMP    RCVPRN    ;PRINT ERROR #
  578. ;
  579. ;PREV SECT REPEATED, DUE TO THE LAST ACK
  580. ;BEING GARBAGED.  ACK IT SO SENDER WILL CATCH UP 
  581. ;
  582. RECVACK    CALL    SENDACK    ;SEND THE ACK,
  583.     JMP    RCVSECT    ;GET NEXT BLOCK
  584. ;
  585. ;SEND AN ACK FOR THE SECTOR
  586. ;
  587. SENDACK    MVI    A,ACK    ;GET ACK
  588.     CALL    SEND    ;..AND SEND IT
  589.     RET
  590. ;
  591. ;---->    SENDHDR: SEND THE SECTOR HEADER
  592. ;
  593. ;SEND: (SOH) (BLOCK #) (COMPLEMENTED BLOCK #)
  594. ;
  595. SENDHDR    LDA    QFLG    ;QUIET..
  596.     ORA    A    ;..MODE?
  597.     JZ    SENDHNM    ;YES, SKIP STATUS MSG.
  598.     CALL    ILPRT    ;PRINT:
  599.     DB    'SEND # ',0
  600.     LDA    SECTNO    ;PRINT..
  601.     CALL    HEXO    ;..SECT #
  602.     CALL    CRLF    ;..THEN CR/LF
  603. ;
  604. SENDHNM    MVI    A,SOH    ;SEND..
  605.     CALL    SEND    ;..SOH,
  606.     LDA    SECTNO    ;THEN SEND..
  607.     CALL    SEND    ;..SECTOR #
  608.     LDA    SECTNO    ;THEN SECTOR #
  609.     CMA        ;..COMPLEMENTED..
  610.     CALL    SEND    ;..SECTOR #
  611.     RET        ;FROM SENDHDR
  612. ;
  613. ;---->    SENDSEC: SEND THE DATA SECTOR
  614. ;
  615. ;WHILE SENDING THE SECTOR, THE "DATAFLG" IS SET
  616. ;SUCH THAT IF "V" (VIEW THE FILE) WAS REQUESTED,
  617. ;THE "SHOW" ROUTINE WILL PRINT THE DATA, BUT NOT
  618. ;THE HDR OR CKSUM, OR ANY NON-FATAL MSGS.
  619. ;
  620. SENDSEC    MVI    A,1    ;SHOW NOW AT DATA..
  621.     STA    DATAFLG    ;..FOR VIEW COMMAND
  622.     MVI    C,0    ;INIT CKSUM
  623.     LXI    H,BASE+80H    ;POINT TO BUFFER
  624. SENDC    MOV    A,M    ;GET A CHAR
  625.     CALL    SEND    ;SEND IT
  626.     INR    L    ;POINT TO NEXT CHAR
  627.     JNZ    SENDC    ;LOOP IF <100H
  628.     XRA    A    ;SHOW NOT INTO DATA..
  629.     STA    DATAFLG    ;..FOR VIEW COMMAND
  630.     RET        ;FROM SENDSEC
  631. ;
  632. ;---->    SENDCKS: SEND THE CHECKSUM
  633. ;
  634. SENDCKS    MOV    A,C    ;SEND THE..
  635.     CALL    SEND    ;..CHECKSUM
  636.     RET        ;FROM SENDCKS
  637. ;
  638. ;---->    GETACK: GET THE ACK ON THE SECTOR
  639. ;
  640. ;RETURNS WITH CARRY CLEAR IF ACK RECEIVED.
  641. ;IF AN ACK IS NOT RECEIVED, THE ERROR COUNT
  642. ;IS INCREMENTED, AND IF LESS THAN "ERRLIM",
  643. ;CARRY IS SET AND CONTROL RETURNS.  IF THE
  644. ;ERROR COUNT IS AT "ERRLIM", THE PROGRAM
  645. ;ABORTS IF IN "QUIET" MODE, OR ASKS THE
  646. ;USER FOR QUIT/RETRY IF NOT.
  647. ;
  648. GETACK    MVI    B,10    ;WAIT 10 SECONDS MAX
  649.     CALL    RECVDG    ;RECV W/GARBAGE COLLECT
  650.     JC    GETATOT    ;TIMED OUT
  651.     CPI    ACK    ;OK? (CARRY OFF IF =)
  652.     RZ        ;YES, RET FROM GETACK
  653.     MOV    B,A    ;SAVE CHAR
  654.     ANI    7FH    ;STRIP PARITY BIT
  655.     CPI    CAN    ;CANCEL TRANSMISSION?
  656.     JZ    ABORT    ;..YES
  657.     LDA    QFLG    ;QUIET..
  658.     ORA    A    ;..MODE?
  659.     JZ    ACKERR    ;..YES, NO MSG
  660.     MOV    A,B    ;GET CHAR
  661.     CALL    HEXO    ;PRINT IN HEX
  662.     CALL    ILPRT    ;PRINT:
  663.     DB    'H RCD, NOT ACK',CR,LF,0
  664. ;
  665. ;TIMEOUT OR ERROR ON ACK - BUMP ERROR COUNT
  666. ;
  667. ACKERR    LDA    ERRCT    ;GET COUNT
  668.     INR    A    ;BUMP IT
  669.     STA    ERRCT    ;SAVE BACK
  670.     CPI    ERRLIM    ;AT LIMIT?
  671.     RC        ;NOT AT LIMIT
  672. ;
  673. ;REACHED ERROR LIMIT
  674. ;
  675.     LDA    VSEEFLG    ;VIEWING..
  676.     ORA    A    ;..FILE?
  677.     JZ    GACKV    ;YES, ASK QUIT/RETRY
  678.     LDA    QFLG    ;QUIET..
  679.     ORA    A    ;..MODE?
  680.     JZ    CSABORT ;..YES, NO MSG
  681. GACKV    CALL    CKQUIT    ;SEE IF WANT TO QUIT
  682.     STC        ;TO SHOW NO ACK
  683.     RZ        ;KEEP ON TRYIN'
  684. CSABORT    CALL    ERXIT
  685.     DB    'CAN''T SEND SECTOR '
  686.     DB    '- ABORTING',CR,LF,'$'
  687. ;
  688. ;TIMEOUT GETTING ACK
  689. ;
  690. GETATOT    LDA    QFLG    ;QUIET..
  691.     ORA    A    ;..MODE?
  692.     JZ    ACKERR    ;YES, NO MSG
  693.     CALL    ILPRT    ;PRINT:
  694.     DB    'TIMEOUT ON ACK',CR,LF,0
  695.     JMP    ACKERR
  696. ;---->    CKABORT: CHECK FOR LOCAL ABORT
  697. ;
  698. ;IF THE USER WANTS TO CANCEL THE TRANSMISSION,
  699. ;TYPING CTL-X WILL ABORT IT.  NOTE THIS TEST
  700. ;IS NOT MADE IF IN QUIET (NO CONSOLE I/O) MODE.
  701. ;
  702. CKABORT    LDA    VSEEFLG    ;VIEWING?
  703.     ORA    A
  704.     JZ    CKABGO    ;YES, CHECK
  705.     LDA    QFLG    ;SUPPRESSED..
  706.     ORA    A    ;..CONSOLE I/O?
  707.     RZ        ;YES, NO TEST
  708. CKABGO    CALL    STAT    ;KEY PRESSED?
  709.     RZ        ;NOTHING FROM KEYBOARD
  710.     CALL    KEYIN    ;GET DATA
  711.     CPI    CAN    ;TIME TO END?
  712.     RNZ        ;NO, CONTINUE
  713. ABORT    LXI    SP,STACK
  714. ABORTL    MVI    B,1    ;1 SEC. W/O CHARS.
  715.     CALL    RECV
  716.     JNC    ABORTL    ;LOOP UNTIL SENDER DONE
  717.     MVI    A,CAN    ;CONTROL X
  718.     CALL    SEND    ;STOP SENDING END
  719. ABORTW    MVI    B,1    ;1 SEC W/O CHARS.
  720.     CALL    RECV
  721.     JNC    ABORTW    ;LOOP UNTIL SENDER DONE
  722.     MVI    A,' '    ;GET A SPACE...
  723.     CALL    SEND    ;TO CLEAR OUT CONTROL X
  724.     CALL    ILPRT    ;EXIT WITH ABORT MSG
  725.     DB    'MODEM PROGRAM CANCELLED',CR,LF,0
  726.     JMP    CKDIS    ;CHECK FOR DISCONN.
  727. ;
  728. ;---->    INCRSNO: INCREMENT SECTOR #
  729. ;
  730. INCRSNO    LDA    SECTNO    ;INCR..
  731.     INR    A    ;..SECT..
  732.     STA    SECTNO    ;..NUMBER
  733.     RET
  734. ;
  735. ;---->    ERASFIL: ERASE THE INCOMING FILE.
  736. ;
  737. ;IF IT EXISTS, ASK IF IT MAY BE ERASED.
  738. ;
  739. ERASFIL    LXI    D,FCB    ;POINT TO CTL BLOCK
  740.     MVI    C,SRCHF ;SEE IF IT..
  741.     CALL    BDOS    ;..EXISTS
  742.     INR    A    ;FOUND?
  743.     RZ        ;..NO, RETURN
  744.     CALL    ILPRT    ;PRINT:
  745.     DB    '++FILE EXISTS, TYPE Y TO ERASE: ',0
  746.     CALL    KEYIN    ;GET CHAR
  747.     PUSH    PSW
  748.     CALL    TYPE    ;ECHO
  749.     CALL    CRLF    ;BACK TO START OF LINE
  750.     POP    PSW
  751.     ANI    5FH    ;MAKE UPPER CASE
  752.     CPI    'Y'    ;WANT ERASED?
  753.     JNZ    CKDIS    ;QUIT IF NOT ERASE
  754. ;
  755. ;ERASE OLD FILE
  756. ;
  757.     LXI    D,FCB    ;POINT TO FCB
  758.     MVI    C,ERASE    ;GET BDOS FNC
  759.     CALL    BDOS    ;DO THE ERASE
  760.     RET        ;FROM "ERASFIL"
  761. ;
  762. ;---->    MAKEFIL: MAKES THE FILE TO BE RECEIVED
  763. ;
  764. MAKEFIL    LXI    D,FCB    ;POINT TO FCB
  765.     MVI    C,MAKE    ;GET BDOS FNC
  766.     CALL    BDOS    ;TO THE MAKE
  767.     INR    A    ;FF=BAD?
  768.     RNZ        ;OPEN OK
  769. ;DIRECTORY FULL - CAN'T MAKE FILE
  770.     CALL    ERXIT
  771.     DB    '++ERROR - CAN''T MAKE FILE',CR,LF
  772.     DB    '++DIRECTORY MUST BE FULL',CR,LF,'$'
  773. ;
  774. ;---->    OPENFIL: OPENS THE FILE TO BE SENT
  775. ;
  776. OPENFIL    LXI    D,FCB    ;POINT TO FILE
  777.     MVI    C,OPEN    ;GET FUNCTION
  778.     CALL    BDOS    ;OPEN IT
  779.     INR    A    ;OPEN OK?
  780.     JNZ    OPENOK    ;..YES
  781.     CALL    ERXIT    ;..NO, ABORT
  782.     DB    'CAN''T OPEN FILE$'
  783. ;
  784. OPENOK    CALL    ILPRT    ;PRINT:
  785.     DB    'FILE OPEN, EXTENT LENGTH: ',0
  786.     LDA    FCB+15    ;GET # SECTORS
  787.     CALL    HEXO    ;PRINT IN HEX
  788.     MVI    A,'H'
  789.     CALL    TYPE    ;PRINT 'H' AFTER NUMBER
  790.     CALL    CRLF    ;..THEN CRLF
  791.     RET
  792. ;
  793. ;---->    CLOSFIL: CLOSES THE RECEIVED FILE
  794. ;
  795. CLOSFIL    LXI    D,FCB    ;POINT TO FILE
  796.     MVI    C,CLOSE    ;GET FUNCTION
  797.     CALL    BDOS    ;CLOSE IT
  798.     INR    A    ;CLOSE OK?
  799.     RNZ        ;..YES, RETURN
  800.     CALL    ERXIT    ;..NO, ABORT
  801.     DB    'CAN''T CLOSE FILE$'
  802. ;
  803. ;---->    RDSECT: READS A SECTOR
  804. ;
  805. ;FOR SPEED, THIS ROUTINE BUFFERS UP 16
  806. ;SECTORS AT A TIME.
  807. ;
  808. RDSECT    LDA    SECINBF    ;GET # SECT IN BUFF.
  809.     DCR    A    ;DECREMENT..
  810.     STA    SECINBF    ;..IT
  811.     JM    RDBLOCK    ;EXHAUSTED?  NEED MORE.
  812.     LHLD    SECPTR    ;GET POINTER
  813.     LXI    D,BASE+80H    ;TO DATA
  814.     CALL    MOVE128    ;MOVE TO BUFFER
  815.     SHLD    SECPTR    ;SAVE BUFFER POINTER
  816.     RET        ;FROM "READSEC"
  817. ;
  818. ;BUFFER IS EMPTY - READ IN ANOTHER BLOCK OF 16
  819. ;
  820. RDBLOCK    LDA    EOFLG    ;GET EOF FLAG
  821.     CPI    1    ;IS IT SET/
  822.     STC        ;TO SHOW EOF
  823.     RZ        ;GOT EOF
  824.     MVI    C,0    ;SECTORS IN BLOCK
  825.     LXI    D,DBUF    ;TO DISK BUFFER
  826. RDSECLP    PUSH    B
  827.     PUSH    D
  828.     MVI    C,STDMA    ;SET DMA..
  829.     CALL    BDOS    ;..ADDR
  830.     LXI    D,FCB
  831.     MVI    C,READ
  832.     CALL    BDOS
  833.     POP    D
  834.     POP    B
  835.     ORA    A    ;READ OK?
  836.     JZ    RDSECOK    ;YES
  837.     DCR    A    ;EOF?
  838.     JZ    REOF    ;GOT EOF
  839. ;
  840. ;READ ERROR
  841. ;
  842.     CALL    ERXIT
  843.     DB    '++FILE READ ERROR$'
  844. ;
  845. RDSECOK    LXI    H,80H    ;ADD LENGTH OF ONE SECTOR...
  846.     DAD    D    ;...TO NEXT BUFF
  847.     XCHG        ;BUFF TO DE
  848.     INR    C    ;MORE SECTORS?
  849.     MOV    A,C    ;GET COUNT
  850.     CPI    16    ;DONE?
  851.     JZ    RDBFULL    ;..YES, BUFF IS FULL
  852.     JMP    RDSECLP    ;READ MORE
  853. ;
  854. REOF    MVI    A,1
  855.     STA    EOFLG    ;SET EOF FLAG
  856.     MOV    A,C
  857. ;
  858. ;BUFFER IS FULL, OR GOT EOF
  859. ;
  860. RDBFULL    STA    SECINBF    ;STORE SECTOR COUNT
  861.     LXI    H,DBUF    ;INIT BUFFER..
  862.     SHLD    SECPTR    ;..POINTER
  863.     LXI    D,BASE+80H    ;RESET..
  864.     MVI    C,STDMA    ;..DMA..
  865.     CALL    BDOS    ;..ADDR
  866.     JMP    RDSECT    ;PASS SECT TO CALLER
  867. ;
  868. ;---->    WRSECT: WRITE A SECTOR
  869. ;
  870. ;WRITES THE SECTOR INTO A BUFFER.  WHEN 16
  871. ;HAVE BEEN WRITTEN, WRITES THE BLOCK TO DISK.
  872. ;
  873. ;ENTRY POINT "WRBLOCK" FLUSHES THE BUFFER AT EOF.
  874. ;
  875. WRSECT    LHLD    SECPTR    ;GET BUFF ADDR
  876.     XCHG        ;TO DE FOR MOVE
  877.     LXI    H,BASE+80H    ;FROM HERE
  878.     CALL    MOVE128    ;MOVE TO BUFFER
  879.     XCHG        ;SAVE NEXT..
  880.     SHLD    SECPTR    ;..BLOCK POINTER
  881.     LDA    SECINBF    ;BUMP THE..
  882.     INR    A    ;..SECTOR #..
  883.     STA    SECINBF    ;..IN THE BUFF
  884.     CPI    16    ;HAVE WE 16?
  885.     RNZ        ;NO, RETURN
  886. ;
  887. ;---->    WRBLOCK: WRITES A BLOCK TO DISK
  888. ;
  889. WRBLOCK    LDA    SECINBF    ;# SECT IN BUFFER
  890.     ORA    A    ;0 MEANS END OF FILE
  891.     RZ        ;NONE TO WRITE
  892.     MOV    C,A    ;SAVE COUNT
  893.     LXI    D,DBUF    ;POINT TO DISK BUFF
  894. DKWRLP    PUSH    H
  895.     PUSH    D
  896.     PUSH    B
  897.     MVI    C,STDMA    ;SET DMA
  898.     CALL    BDOS    ;TO BUFFER
  899.     LXI    D,FCB    ;THEN WRITE
  900.     MVI    C,WRITE    ;..THE..
  901.     CALL    BDOS    ;..BLOCK
  902.     POP    B
  903.     POP    D
  904.     POP    H
  905.     ORA    A
  906.     JNZ    WRERR    ;OOPS, ERROR
  907.     LXI    H,80H    ;LENGTH OF 1 SECT
  908.     DAD    D    ;HL= NEXT BUFF
  909.     XCHG        ;TO DE FOR SETDMA
  910.     DCR    C    ;MORE SECTORS?
  911.     JNZ    DKWRLP    ;..YES, LOOP
  912.     XRA    A    ;GET A ZERO
  913.     STA    SECINBF    ;RESET # OF SECTORS
  914.     LXI    H,DBUF    ;RESET BUFFER..
  915.     SHLD    SECPTR    ;..POINTER
  916. RSDMA    LXI    D,BASE+80H ;RESET..
  917.     MVI    C,STDMA    ;..DMA..
  918.     CALL    BDOS    ;..ADDR
  919.     RET
  920. ;
  921. WRERR    CALL    RSDMA    ;RESET DMA TO NORM.
  922.     MVI    C,CAN    ;CANCEL..
  923.     CALL    SEND    ;..SENDER
  924.     CALL    ERXIT    ;EXIT W/MSG:
  925.     DB    '++ERROR WRITING FILE',CR,LF,'$'
  926. ;
  927. ;---->    RECV: RECEIVE A CHARACTER
  928. ;
  929. ;TIMEOUT TIME IS IN B, IN SECONDS.  ENTRY VIA
  930. ;"RECVDG" DELETES GARBAGE CHARACTERS ON THE
  931. ;LINE.  FOR EXAMPLE, HAVING JUST SENT A SECTOR,
  932. ;CALLING RECVDG WILL DELETE ANY LINE-NOISE-INDUCED
  933. ;CHARACTERS "LONG" BEFORE THE ACK/NAK WOULD
  934. ;BE RECEIVED.
  935. ;
  936. RECVDG    EQU    $    ;RECEIVE W/GARBAGE DELETE
  937.     IN    MODDATP    ;GET A CHAR
  938.     IN    MODDATP    ;..TOTALLY PURGE UART
  939. ;
  940. RECV    PUSH    D    ;SAVE
  941. ;
  942.     IF    FASTCLK    ;4MHZ?
  943.     MOV    A,B    ;GET TIME REQUEST
  944.     ADD    A    ;DOUBLE IT
  945.     MOV    B,A    ;NEW TIME IN B
  946.     ENDIF
  947. ;
  948. MSEC    LXI    D,50000    ;1 SEC DCR COUNT
  949.     CALL    CKABORT    ;CHECK FOR EXIT REQUEST
  950.     IF    NOT DCH
  951. MWTI    IN    MODCTLP    ;CHECK STATUS
  952.     ENDIF
  953.     IF    DCH
  954. MWTI    IN    MODCTL2    ;CHECK STATUS
  955.     ENDIF
  956.     ANI    MODRCVB    ;ISOLATE BIT
  957.     CPI    MODRCVR    ;READY?
  958.     JZ    MCHAR    ;GOT CHAR
  959.     DCR    E    ;COUNT..
  960.     JNZ    MWTI    ;..DOWN..
  961.     DCR    D    ;..FOR..
  962.     JNZ    MWTI    ;..TIMEOUT
  963.     DCR    B    ;MORE SECONDS?
  964.     JNZ    MSEC    ;YES, WAIT
  965. ;
  966. ;MODEM TIMED OUT RECEIVING
  967. ;
  968.     POP    D    ;RESTORE D,E
  969.     STC        ;CARRY SHOWS TIMEOUT
  970.     RET
  971. ;
  972. ;GOT CHAR FROM MODEM
  973. ;
  974. MCHAR    IN    MODDATP    ;READ THE CHAR
  975.     POP    D    ;RESTORE DE
  976. ;
  977. ;CALC CHECKSUM
  978. ;
  979.     PUSH    PSW    ;SAVE THE CHAR
  980.     ADD    C    ;ADD TO CHECKSUM
  981.     MOV    C,A    ;SAVE CHECKSUM
  982. ;
  983. ;CHECK IF MONITORING REC'D DATA
  984. ;
  985.     LDA    RSEEFLG    ;SEE RECEIVED..
  986.     ORA    A    ;..DATA?
  987.     JZ    MONIN    ;..YES
  988. ;
  989. ;CHECK IF "VIEWING" AND THIS IS A DATA CHAR
  990. ;
  991.     LDA    VSEEFLG    ;VIEWING..
  992.     ORA    A    ;..DATA?
  993.     JNZ    NOMONIN    ;..NO
  994. ;
  995. ;"VIEW" REQUESTED.  SHOW THE CHAR IT IS DATA
  996. ;
  997.     LDA    DATAFLG    ;GET DATA FLAG
  998.     ORA    A    ;TEST IT
  999.     JZ    NOMONIN    ;..OFF, NOT DATA
  1000. MONIN    POP    PSW    ;..IS DATA,
  1001.     PUSH    PSW    ;GET IT,
  1002.     CALL    SHOW    ;..AND SHOW IT
  1003. NOMONIN    POP    PSW    ;RESTORE CHAR
  1004.     ORA    A    ;CARRY OFF: NO ERROR
  1005.     RET        ;FROM "RECV"
  1006. ;
  1007. ;---->    SEND: SEND A CHARACTER TO THE MODEM
  1008. ;
  1009. SEND    PUSH    PSW    ;SAVE THE CHAR
  1010. ;
  1011. ;CHECK IF MONITORING SENT DATA
  1012. ;
  1013.     LDA    SSEEFLG    ;CHECK IF MONITORING..
  1014.     ORA    A    ;..SENT DATA
  1015.     JZ    MONOUT    ;..YES
  1016. ;
  1017. ;CHECK IF "VIEWING" THE FILE
  1018. ;
  1019.     LDA    VSEEFLG    ;GET VIEW FLAG
  1020.     ORA    A    ;TEST IT
  1021.     JNZ    NOMONOT    ;NO
  1022.     LDA    DATAFLG    ;IS THIS
  1023.     ORA    A    ;..DATA?
  1024.     JZ    NOMONOT    ;..NO.
  1025. MONOUT    POP    PSW    ;GET THE CHAR
  1026.     PUSH    PSW    ;SAVE IT
  1027.     CALL    SHOW    ;SHOW IT
  1028. NOMONOT    POP    PSW    ;RESTORE CHAR
  1029.     PUSH    PSW    ;SAVE IT
  1030.     ADD    C    ;CALC CKSUM
  1031.     MOV    C,A    ;SAVE CKSUM
  1032.     IF    NOT DCH
  1033. SENDW    IN    MODCTLP    ;GET STATUS
  1034.     ENDIF
  1035.     IF    DCH
  1036. SENDW    IN    MODCTL2    ;GET STATUS
  1037.     ENDIF
  1038.     ANI    MODSNDB    ;ISOLATE READY BIT
  1039.     CPI    MODSNDR    ;READY?
  1040.     JNZ    SENDW    ;..NO, WAIT
  1041.     POP    PSW    ;GET CHAR
  1042.     OUT    MODDATP    ;OUTPUT IT
  1043.     RET        ;FROM "SEND"
  1044. ;
  1045. ;---->    WAITNAK: WAITS FOR INITIAL NAK
  1046. ;
  1047. ;TO ENSURE NO DATA IS SENT UNTIL THE RECEIVING
  1048. ;PROGRAM IS READY, THIS ROUTINE WAITS FOR THE
  1049. ;THE FIRST TIMEOUT-NAK FROM THE RECEIVER.
  1050. ;(E) CONTAINS THE # OF SECONDS TO WAIT.
  1051. ;
  1052. WAITNAK    LDA    VSEEFLG    ;VIEWING?
  1053.     ORA    A
  1054.     JZ    WAITNPR    ;PRINT MSG
  1055.     LDA    QFLG    ;QUIET..
  1056.     ORA    A    ;..MODE?
  1057.     JZ    WAITNLP    ;YES, SKIP MSG
  1058. WAITNPR    CALL    ILPRT    ;PRINT:
  1059.     DB    'AWAITING INITIAL NAK',CR,LF,0
  1060. WAITNLP    CALL    CKABORT    ;ABORT IF LOCAL CTL-X
  1061.     MVI    B,1    ;TIMEOUT DELAY
  1062.     CALL    RECV    ;DID WE GET..
  1063.     CPI    NAK    ;..A NAK?
  1064.     RZ        ;YES, SEND BLOCK
  1065.     ANI    7FH    ;STRIP PARITY BIT
  1066.     CPI    CAN    ;CTL-X FROM REMOTE?
  1067.     JZ    ABORT    ;..YES, ABORT
  1068.     DCR    E    ;80 TRIES?
  1069.     JZ    ABORT    ;YES, ABORT
  1070.     JMP    WAITNLP    ;NO, LOOP
  1071. ;
  1072. ;---->    INITADR: INIT'S CP/M BDOS ADDRESSES
  1073. ;
  1074. ;THIS ROUTINE FILLS IN THE ADDRESSES OF VARIOUS
  1075. ;JMP AND CALL INSTRUCTIONS, SO THAT CP/M BDOS
  1076. ;IS BYPASSED WHILE ACCESSING THE CONSOLE.  THIS
  1077. ;IS DONE TO ALLOW CHARACTERS SUCH AS CONTROL-C
  1078. ;AND CONTROL-S TO BE KEYED WHILE IN TERMINAL
  1079. ;MODE, WITHOUT CP/M INTERPRETING THEM.
  1080. ;
  1081. INITADR    LHLD    BASE+1    ;GET WARM BOOT ADDR
  1082.     LXI    D,3    ;LENGTH OF A 'JMP'
  1083.     DAD    D    ;TO CONSOLE STAT
  1084.     SHLD    VSTAT+1    ;MODIFY CALL
  1085.     DAD    D    ;TO CONSOLE IN
  1086.     SHLD    VKEYIN+1 ;MODIFY CALL
  1087.     DAD    D    ;TO CONSOLE OUT
  1088.     SHLD    VTYPE+1    ;MODIFY CALL
  1089.     RET
  1090. ;
  1091. ;---->    PROCOPT: PROCESS COMMAND OPTIONS
  1092. ;1) SAVES THE PRIMARY OPTION IN 'OPTION';
  1093. ;2) IF OPTION 'H' (HELP) IS ASKED FOR,
  1094. ;TRANSFERS DIRECTLY TO THE HELP PRINT;
  1095. ;3) SCANS THE SUB-OPTION CHARACTERS, AND FOR
  1096. ;EACH FOUND, ZEROS THE APPROPRIATE ENTRY IN
  1097. ;THE OPTION TABLE.  FOR EXAMPLE, IF 'D' IS 
  1098. ;CODED (DISCONNECT) THEN THE 'D' STORED AT
  1099. ;'DISCFLG' IS SET TO 0 SO IT CAN BE TESTED
  1100. ;LATER.
  1101. ;
  1102. PROCOPT    LXI    D,FCB+1    ;TO PRIMARY OPT.
  1103.     LDAX    D    ;GET PRIMARY
  1104.     STA    OPTION    ;SAVE IT
  1105.     CPI    'H'    ;MODEM H(ELP)?
  1106.     JZ    HELP    ;..YES, GIVE HELP
  1107. ;
  1108. OPTLP    INX    D    ;TO SECONDARY OPTION
  1109.     LDAX    D    ;GET CHAR
  1110. ;
  1111. ;IF YOU MOD THIS PROGRAM FOR >7 OPTIONS,
  1112. ;YOU MUST CHANGE THE FOLLOWING, SINCE
  1113. ;THERE WON'T BE A ' ' AFTER THE OPTION
  1114. ;IF A BAUD RATE WAS SPECIFIED.
  1115. ;
  1116.     CPI    ' '    ;NO MORE OPT'NS?
  1117.     JZ    ENDOPT    ;..YES
  1118. ;SET THE APPROP. OPT: STORE 0 IN IT
  1119.     LXI    H,OPTBL    ;HL = ADDR OF 'OAQDSRV'
  1120.     MVI    B,OPTBE-OPTBL ;OPT TABLE LEN
  1121. OPTCK    CMP    M    ;FOUND THE OPTION?
  1122.     JNZ    OPTNO    ;NO, DON'T SET IT
  1123.     MVI    M,0    ;SET THE OPTION
  1124.     JMP    OPTLP    ;GET NEXT OPTION
  1125. OPTNO    INX    H    ;TO NEXT
  1126.     DCR    B    ;MORE?
  1127.     JNZ    OPTCK
  1128. ;OPTION NOT IN TABLE
  1129.     JMP    BADOPT    ;SHOW BAD SUB OPTION
  1130. ;
  1131. ;IF "VIEW" WAS ASKED FOR, SET QUIET FLAG
  1132. ;
  1133. ENDOPT    LDA    VSEEFLG    ;VIEW..
  1134.     ORA    A    ;..ASKED FOR?
  1135.     RNZ        ;..NO, RET FROM 'PROCOPT'
  1136.     STA    QFLG    ;YES, NO HDR/CKSUM PRT
  1137.     RET        ;FROM 'PROCOPT'
  1138. ;
  1139. ;DONE - CLOSE UP SHOP
  1140. ;
  1141. DONE    LDA    VSEEFLG    ;VIEWING?
  1142.     ORA    A
  1143.     JZ    DONETC    ;SHOW MSG
  1144.     LDA    QFLG    ;QUIET
  1145.     ORA    A    ;..MODE?
  1146.     JZ    DONECTE    ;YES, CK TERM/ECHO
  1147. DONETC    CALL    ILPRT
  1148.     DB    CR,LF,'TRANSFER COMPLETE' 
  1149.     DB    CR,LF,0
  1150. ;
  1151. ;CHECK IF TERMINAL OR ECHO SUB COMMAND
  1152. ;WAS SPECIFIED
  1153. ;
  1154. DONECTE    LDA    TERMFLG    ;TERM?
  1155.     ORA    A
  1156.     JZ    TERM    ;..YES
  1157.     LDA    ECHOFLG    ;ECHO?
  1158.     ORA    A
  1159.     JZ    TRMECHO    ;..YES
  1160. ;
  1161. ;FALL INTO 'CKDIS'
  1162. ;
  1163. ;---->    CKDIS: CHECK IF DISCONNECT REQUESTED
  1164. ;
  1165. ;THIS ROUTINE IS JUMPED TO AT THE END OF
  1166. ;PROCESSING, AND DISCONNECTS THE PHONE IF
  1167. ;'D' WAS SPECIFIED AS A SUB-OPTION.
  1168. ;
  1169. CKDIS    LDA    DISCFLG    ;CHECK 'D' FLAG
  1170.     ORA    A    ;REQUESTED?
  1171. ;
  1172.     IF    PMMI OR DCH
  1173.     JNZ    NDIS    ;..NO, JUST EXIT
  1174.     ENDIF
  1175. ;
  1176.     IF    NOT PMMI AND NOT DCH
  1177.     JNZ    EXIT
  1178.     ENDIF
  1179. ;
  1180. ;AWAIT C/R TO DISC. SO WE DON'T LOSE THE PHONE
  1181. ;
  1182.     CALL    ILPRT
  1183.     DB    CR,LF,'PRESS RETURN TO DISCONNECT:',0
  1184.     CALL    KEYIN
  1185.     PUSH    PSW
  1186.     CALL    CRLF
  1187.     POP    PSW
  1188.     CPI    CR
  1189.     JNZ    CKDIS    ;ASK AGAIN
  1190. ;
  1191. ;---->    DISCONN: DISCONNECT THE PHONE
  1192. ;
  1193. DISCONN    EQU    $
  1194. ;
  1195.     IF    PMMI
  1196.     XRA    A    ;GET DISCONN VALUE
  1197.     OUT    MODCTLP    ;RESET ORIG/ANSW
  1198.     OUT    MODCTL2    ;TURN OFF DTR, DO BREAK
  1199.     ENDIF
  1200. ;
  1201.     IF    DCH
  1202.     XRA    A    ;GET DISCONNECT VALUE
  1203.     OUT    MODCTLP    ;DISCONNECT
  1204.     ENDIF
  1205. ;
  1206.     CALL    ILPRT    ;PRINT:
  1207.     DB    '++DISCONNECTED++',0
  1208.     JMP    EXIT
  1209. ;
  1210. ;NO DISCONNECT, TYPE MSG AS REMINDER THAT PHONE'S
  1211. ;OFF HOOK
  1212. ;
  1213.     IF    PMMI OR DCH
  1214. NDIS    LDA    QFLG    ;QUIET..
  1215.     ORA    A    ;..MODE?
  1216.     JZ    EXIT    ;..YES, NO MSG
  1217.     CALL    ILPRT
  1218.     DB    CR,LF,'++DON''T FORGET - THE MODEM IS '
  1219.     DB    'NOT DISCONNECTED++',CR,LF
  1220.     DB    'USE "MODEM D" TO DISCONNECT',CR,LF,0
  1221.     JMP    EXIT
  1222. ;
  1223.     ENDIF
  1224. ;
  1225. ;---->    INITMOD: INITIALIZES THE MODEM
  1226. ;
  1227. ;THIS ROUTINE IS USED TO INITIALIZE SERIAL
  1228. ;BOARDS, OR SETUP S-100 MODEM BOARDS.
  1229. ;JUST RETURNS IF NO INITIALIZATION REQUIRED.
  1230. ;
  1231. INITMOD:
  1232. ;
  1233.     IF    INITREQ  ;REQUIRE INIT?
  1234.     MVI    A,INITC1 ;GET 1ST INIT CHAR
  1235.     OUT    MODCTLP     ;OUTPUT IT
  1236.     MVI    A,INITC2 ;GET 2ND INIT CHAR
  1237.     OUT    MODCTLP     ;OUTPUT IT
  1238.     ENDIF
  1239. ;
  1240.     IF    PMMI
  1241.     CALL    GETBAUD    ;GET THE BAUD RATE
  1242.     OUT    BAUDRP    ;OUT BAUD RATE PORT
  1243.     ENDIF
  1244. ;
  1245.     IF    DCH
  1246.     CALL    GETBAUD    ;GET BAUD RATE
  1247.     ENDIF
  1248.     IF    PMMI
  1249. ;SET THE MOTOROLA MODEM CHIP BIT FOR >300 IF REQ'D
  1250. ;
  1251.     CPI    52    ;>300?
  1252.     MVI    A,5FH    ;VALUE FOR >300
  1253.     JC    GT300
  1254.     MVI    A,7FH    ;VALUE FOR <= 300
  1255. GT300    OUT    MODCTL2    ;SET IT
  1256. ;
  1257. ;SET ORIG/ANSW IF REQUESTED
  1258. ;
  1259.     LDA    ORIGFLG    ;ORIGINATE..
  1260.     ORA    A    ;..MODE?
  1261.     MVI    A,ORIGMOD 
  1262.     JZ    OFFHOOK    ;..YES, DO IT
  1263.     LDA    ANSWFLG    ;ANSWER..
  1264.     ORA    A    ;..MODE?
  1265.     MVI    A,ANSWMOD
  1266.     RNZ        ;NEITHER ORIG NOR ANSW.
  1267.     ENDIF
  1268. ;
  1269.     IF    DCH
  1270.     LDA    ANSWFLG        ;ANSWER..
  1271.     ORA    A
  1272.     MVI    B,ANSWMOD    ;SET ANSWER MODE
  1273.     JZ    INITM1
  1274.     LDA    ORIGFLG        ;GET ORIGINATE FLAG
  1275.     ORA    A
  1276.     MVI    B,ORIGMOD    ;SET ORIGINATE MODE
  1277.     JZ    INITM1
  1278.     LDA    HOLDD        ;NEITHER - GET LAST VALUE
  1279.     MOV    B,A        ;STORE IN B
  1280. INITM1:    MOV    A,B        ;GET MODE
  1281.     STA    HOLDD        ;SAVE VALUE
  1282.     MOV    A,C        ;GET BAUD RATE INDICATOR
  1283.     ORA    A        ;ZEBO IF 110 BAUD
  1284.     MOV    A,B        ;GET MODE
  1285.     JZ    OFFHOOK        ;DO OFFHOOK
  1286.     ORI    1        ;SET 300 BAUD
  1287.     ENDIF
  1288. ;
  1289.     IF    PMMI OR DCH
  1290. ;
  1291. ;GO OFFHOOK IN REQUESTED (ORIG/ANSW) MODE
  1292. ;
  1293. OFFHOOK    LXI    H,4000    ;DELAY AMT
  1294. OFFDLY    DCR    L
  1295.     JNZ    OFFDLY
  1296.     DCR    H
  1297.     JNZ    OFFDLY
  1298.     OUT    MODCTLP    ;GO OFF HOOK
  1299.     RET
  1300.     ENDIF
  1301. ;
  1302.     IF    PMMI
  1303. ;---->    GETBAUD: GETS BAUD RATE FROM COMMAND
  1304. ;
  1305. ;THIS ROUTINE CHECKS IF A BAUD RATE HAS
  1306. ;BEEN ASKED FOR, (SUCH AS MODEM T.450),
  1307. ;AND IF SO, CALCULATES THE PMMI BAUD RATE
  1308. ;VALUE TO BE OUTPUT.  DEFAULTS TO 300.
  1309. ;
  1310. GETBAUD    LDA    FCB+9    ;GET 'FILETYPE'
  1311.     CPI    ' '    ;DEFAULT?
  1312.     MVI    A,52    ;300 BAUD VALUE
  1313.     RZ        ;NO BAUD RATE, USE 300
  1314. ;
  1315. ;GOT BAUD RATE - CONVERT TO PROPER TIMER VALUE
  1316. ;
  1317. ;FIRST, CONVERT THE NUMBER TO BINARY
  1318. ;
  1319.     CALL    CVBIN
  1320. ;
  1321. ;CALCULATE THE VALUE TO OUTPUT:
  1322. ;
  1323. ;    RATE = 250000/16/BAUD RATE
  1324. ;
  1325. ;    DIVIDE BY REPETITIVE SUBTRACTION
  1326. ;    ------
  1327. ;COMPLEMENT THE BAUD RATE
  1328. ;
  1329.     MOV    A,H    ;GET HI
  1330.     CMA        ;COMPLEMENT
  1331.     MOV    D,A    ;SAVE
  1332.     MOV    A,L    ;GET LO
  1333.     CMA        ;COMPLEMENT
  1334.     MOV    E,A    ;SAVE
  1335.     INX    D    ;DE=2'S COMPLEMENT
  1336. ;DIVIDE
  1337.     LXI    H,15625    ;250000/16 
  1338.     LXI    B,-1    ;INIT QUOTIENT
  1339. DIVLP    INX    B    ;BUMP QUOTIENT
  1340.     DAD    D    ;'SUBTRACT'
  1341.     JC    DIVLP    ;LOOP 'TILL DONE
  1342. ;VALIDATE THE RESULT
  1343.     MOV    A,B    ;CAN'T HAVE >255
  1344.     ORA    A
  1345.     MOV    A,C    ;GET ACTUAL
  1346.     RZ        ;RET IF <256
  1347.     JMP    BADRATE    ;INVALID
  1348.     ENDIF        ;PMMI
  1349. ;
  1350.     IF    DCH
  1351. GETBAUD    LDA    FCB+9    ;GET FILETYPE
  1352.     CPI    ' '    ;DEFAULT?
  1353.     JNZ    GETBAU1    ;NO - DO BAUD RATE STUFF
  1354.     MVI    C,1    ;SET 300 BAUD
  1355.     MVI    B,17H    ;SET 1 STOP BIT
  1356.     JMP    GETBAU2
  1357. ; CONVERT BAUD RATE TO BINARY
  1358. GETBAU1    CALL    CVBIN    ;CONVERT TO BINARY
  1359.     PUSH    H    ;SAVE BAUD RATE
  1360.     MVI    C,0    ;ANTICIPATE 110 BAUD
  1361.     MVI    B,1FH    ;SET 2 STOP BITS
  1362.     LXI    D,-110    ;GET CONSTANT
  1363.     DAD    D    ;SUBTRACT
  1364.     MOV    A,H
  1365.     ORA    L
  1366.     POP    H
  1367.     JZ    GETBAU2    ;110 BAUD
  1368.     MVI    B,17H    ;SET 1 STOP BIT
  1369.     INR    C
  1370.     LXI    D,-300    ;GET CONSTANT
  1371.     DAD    D
  1372.     MOV    A,H
  1373.     ORA    L
  1374.     JNZ    BADRATE    ;INVALID
  1375. GETBAU2    MOV    A,B    ;GET SET UP
  1376.     OUT    MODCTL2    ;INITIALIZE MODEM FOR STOP BITS..
  1377.     RET        ;..DATA BITS, ETC.
  1378.     ENDIF        ;DCHAYES
  1379. ;
  1380.     IF    PMMI OR DCH
  1381. ; ROUTINE TO CONVERT BAUD RATE TO BINARY
  1382. CVBIN:    LXI    D,FCB+9    ;TO ASCII VALUE
  1383.     LXI    H,0    ;INIT BINARY RESULT
  1384. DECLP    LDAX    D    ;GET ASCII DIGIT
  1385.     INX    D    ;TO NEXT DIGIT
  1386.     CPI    ' '    ;BLANK ONE?
  1387.     JZ    DECLP    ;..YES, SKIP IT
  1388.     CPI    '0'    ;VALIDATE IT
  1389.     JC    BADRATE    ;ERROR
  1390.     CPI    '9'+1    ;VALIDATE
  1391.     JNC    BADRATE    ;ERROR
  1392.     SUI    '0'    ;MAKE DIGIT BINARY
  1393. ;
  1394. ;MULTIPLY PREV VALUE BY 10
  1395. ;
  1396.     MOV    B,H    ;SET UP FOR
  1397.     MOV    C,L    ;MULTIPLY BY 10
  1398.     DAD    H    ;MULTIPLY BY 2
  1399.     DAD    H    ;X 2 = 4
  1400.     DAD    B    ;+ 1 = 5
  1401.     DAD    H    ;X 2 = 10
  1402.     ADD    L    ;ADD IN DIGIT
  1403.     MOV    L,A    ;SAVE BACK
  1404.     JNZ    DIGNC    ;NO CARRY?
  1405.     INR    H    ;ADD IN CARRY
  1406. ;CHECK IF DONE?
  1407. DIGNC    MOV    A,E    ;SEE IF PAST
  1408.     CPI    FCB+12    ;..LAST DIGIT
  1409.     JNZ    DECLP    ;NO, LOOP
  1410.     RET
  1411. ;INVALID BAUD RATE
  1412. ;
  1413. BADRATE    CALL    ERXIT
  1414.     DB    '++INVALID BAUD RATE++$'
  1415.     ENDIF        ;PMMI OR DCHAYES
  1416. ;
  1417.     RET        ;**THIS MUST BE HERE**
  1418. ;
  1419. ;-                                                                                                                                T) RATHER
  1420. ;THAT MODEM FILENAME SEND (MODEM FN.FT S) SO THIS
  1421. ;ROUTINE MOVES THE FILENAME FROM THE SECOND FCB
  1422. ;TO THE FIRST
  1423. ;
  1424. MOVEFCB    LXI    H,FCB+16 ;FROM
  1425.     LXI    D,FCB    ;TO
  1426.     MVI    B,16    ;LEN
  1427.     CALL    MOVE    ;DO THE MOVE
  1428.     XRA    A    ;GET 0
  1429.     STA    FCBSNO    ;ZERO SECTOR #
  1430.     STA    FCBEXT    ;..AND EXTENT
  1431.     RET
  1432. ;
  1433. ;---->    SHOW: SHOWS CHAR SENT/RECEIVED
  1434. ;
  1435. ;CR, LF, AND TAB ARE SHOWN.  ALL OTHER
  1436. ;NON-PRINTABLE CHARACTERS ARE SHOWN IN
  1437. ;HEX AS (XX)
  1438. ;
  1439. SHOW    CPI    LF    ;LF?
  1440.     JZ    CTYPE    ;..YES, TYPE IT
  1441.     CPI    CR    ;CR?
  1442.     JZ    CTYPE    ;..YES, TYPE IT
  1443.     CPI    09    ;TAB
  1444.     JZ    CTYPE    ;..YES, TYPE IT
  1445.     CPI    ' '    ;CTL-CHR?
  1446.     JC    SHOWHEX    ;YES, SHOW IN HEX
  1447.     CPI    7FH    ;DEL?
  1448.     JC    CTYPE    ;NO, TYPE THE CHAR
  1449. SHOWHEX    PUSH    PSW    ;SAVE THE CHAR
  1450.     MVI    A,'('    ;TYPE..
  1451.     CALL    CTYPE    ;..'('
  1452.     POP    PSW    ;THEN..
  1453.     CALL    HEXO    ;..THE CHAR
  1454.     MVI    A,')'    ;THEN..
  1455.     JMP    CTYPE    ;..')' AND RETURN.
  1456. ;
  1457. ;---->    CTYPE: TYPES VIA CP/M SO TABS ARE EXPANDED
  1458. ;
  1459. CTYPE    PUSH    B    ;SAVE..
  1460.     PUSH    D    ;..ALL..
  1461.     PUSH    H    ;..REGS
  1462.     MOV    E,A    ;CHAR TO E
  1463.     MVI    C,WRCON    ;GET BDOS FNC
  1464.     CALL    BDOS    ;PRIN THE CHR
  1465.     POP    H    ;RESTORE..
  1466.     POP    D    ;..ALL..
  1467.     POP    B    ;..REGS
  1468.     RET        ;FROM "CTYPE"
  1469. ;
  1470. CRLF    MVI    A,CR
  1471.     CALL    TYPE
  1472.     MVI    A,LF
  1473. ;
  1474. ;---->    TYPE: TYPE VIA DIRECT CBIOS ACCESS
  1475. ;WE ASSUME CBIOS MAY DESTROY SOME REGISTERS,
  1476. ;SO SAVE THEM ALL.
  1477. ;
  1478. ;THIS ROUTINE BYPASSES CP/M'S CTL-S, CTL-C
  1479. ;TESTS.
  1480. ;
  1481. TYPE    PUSH    PSW    ;SAVE CHAR
  1482.     PUSH    B    ;AND OTHER REGISTERS
  1483.     PUSH    D
  1484.     PUSH    H
  1485.     MOV    C,A    ;FOR BIOS
  1486. VTYPE    CALL    $-$    ;MODIFIED AT INIT
  1487.     POP    H    ;RESTORE REGISTERS
  1488.     POP    D
  1489.     POP    B
  1490.     POP    PSW    ;..AND CHAR
  1491.     RET        ;FROM "TYPE"
  1492. ;
  1493. ;---->  STAT: KEYBOARD STATUS
  1494. ;
  1495. ;SAVE ALL REGISTERS, EXCEPT A, IN CASE
  1496. ;CBIOS CLOBBERS THEM.
  1497. ;
  1498. STAT    PUSH    B
  1499.     PUSH    D
  1500.     PUSH    H
  1501. VSTAT    CALL    $-$    ;ADDR SET AT INIT
  1502.     POP    H
  1503.     POP    D
  1504.     POP    B
  1505.     ORA    A    ;0 => NOT READY
  1506.     RET
  1507. ;
  1508. ;---->  KEYIN: KEYBOARD INPUT
  1509. ;
  1510. ;SAVE ALL REGISTERS, EXCEPT A, IN CASE
  1511. ;CBIOS CLOBBERS THEM.
  1512. ;
  1513. KEYIN    PUSH    B
  1514.     PUSH    D
  1515.     PUSH    H
  1516. VKEYIN    CALL    $-$    ;ADDR SET AT INIT
  1517.     POP    H
  1518.     POP    D
  1519.     POP    B
  1520.     ANI    7FH    ;STRIP PARITY IF THERE
  1521.     RET        ;FROM KEYIN
  1522. ;
  1523. ;---->  HEXO: HEX OUTPUT
  1524. ;
  1525. HEXO    PUSH    PSW    ;SAVE FOR RIGHT DIGIT
  1526.     RAR        ;RIGHT..
  1527.     RAR        ;..JUSTIFY..
  1528.     RAR        ;..LEFT..
  1529.     RAR        ;..DIGIT..
  1530.     CALL    NIBBL    ;PRINT LEFT DIGIT
  1531.     POP    PSW    ;RESTORE RIGHT
  1532. NIBBL    ANI    0FH    ;ISOLATE DIGIT
  1533.     CPI    10    ;IS IS <10?
  1534.     JC    ISNUM    ;YES, NOT ALPHA
  1535.     ADI    7    ;ADD ALPHA BIAS
  1536. ISNUM    ADI    '0'    ;MAKE PRINTABLE
  1537.     JMP    TYPE    ;..THEN TYPE IT
  1538. ;
  1539. ;---->    CKQUIT: QUIT/RETRY AFTER MULTIPLE ERRS.
  1540. ;
  1541. ;RETURNS W/ ZERO SET IF "RETRY" ASKED FOR
  1542. ;
  1543. CKQUIT    XRA    A    ;ZERO..
  1544.     STA    ERRCT    ;..ERROR COUNT
  1545.     CALL    ILPRT    ;PRINT:
  1546.     DB    'MULTIPLE ERRORS ENCOUNTERED.  '
  1547.     DB    'TYPE Q TO QUIT, R TO RETRY: ',0
  1548.     CALL    KEYIN    ;QUIT/RETRY
  1549.     PUSH    PSW
  1550.     CALL    TYPE
  1551.     CALL    CRLF
  1552.     POP    PSW
  1553.     ANI    5FH    ;MAKE UPPER CASE
  1554.     CPI    'R'    ;RETRY?
  1555.     RZ        ;'KEEP ON TRUCKIN'
  1556.     CPI    'Q'    ;QUIT?
  1557.     JNZ    CKQUIT    ;NO, ASK AGAIN
  1558.     ORA    A    ;SET NON-ZERO
  1559.     RET
  1560. ;
  1561. ;---->    ILPRT: INLINE PRINT OF MSG
  1562. ;
  1563. ;THE CALL TO ILPRT IS FOLLOWED BY A MESSAGE,
  1564. ;BINARY 0 AS THE END.  BINARY 1 MAY BE USED TO
  1565. ;PAUSE (MESSAGE 'PRESS RETURN TO CONTINUE')
  1566. ;
  1567. ILPRT    XTHL        ;SAVE HL, GET HL=MSG
  1568. ILPLP    MOV    A,M    ;GET CHAR
  1569.     ORA    A    ;END OF MSG?
  1570.     JZ    ILPRET    ;..YES, RETURN
  1571.     CPI    1    ;PAUSE?
  1572.     JZ    ILPAUSE    ;..YES
  1573.     CALL    CTYPE    ;TYPE THE MSG
  1574. ILPNEXT    INX    H    ;TO NEXT CHAR
  1575.     JMP    ILPLP    ;LOOP
  1576. ;
  1577. ;PAUSE WHILE TYPING HELP SO INFO DOESN'T
  1578. ;    SCROLL OFF OF VIDEO SCREENS
  1579. ;
  1580. ILPAUSE    CALL    ILPRT    ;PRINT:
  1581.     DB    CR,LF,'PRESS RETURN TO CONTINUE'
  1582.     DB    CR,LF,0
  1583.     CALL    KEYIN    ;GET ANY CHAR
  1584.     CPI    'C'-40H    ;REBOOT?
  1585.     JZ    EXIT    ;YES.
  1586.     JMP    ILPNEXT    ;LOOP
  1587. ;
  1588. ILPRET    XTHL        ;RESTORE HL
  1589.     RET        ;PAST MSG
  1590. ;
  1591. ;---->    PRTMSG: PRINTS MSG POINTED TO BY (DE)
  1592. ;
  1593. ;A '$' IS THE ENDING DELIMITER FOR THE PRINT.
  1594. ;NO REGISTERS SAVED.
  1595. ;
  1596. PRTMSG    MVI    C,PRINT    ;GET BDOS FNC
  1597.     JMP    BDOS    ;PRINT MESSAGE, RETURN
  1598. ;
  1599. ;---->    ERXIT: EXIT PRINTING MSG FOLLOWING CALL
  1600. ;
  1601. ERXIT    POP    D    ;GET MESSAGE
  1602.     CALL    PRTMSG    ;PRINT IT
  1603.     CALL    CKDIS    ;DISCONNECT?
  1604. ;
  1605. EXIT    LHLD    STACK    ;GET ORIGINAL STACK
  1606.     SPHL        ;RESTORE IT
  1607.     RET        ;--EXIT-- TO CP/M
  1608. ;
  1609. ;MOVE 128 CHARACTERS
  1610. ;
  1611. MOVE128    MVI    B,128    ;SET MOVE COUNT
  1612. ;
  1613. ;MOVE FROM (HL) TO (DE) LENGTH IN (B)
  1614. ;
  1615. MOVE    MOV    A,M    ;GET A CHAR
  1616.     STAX    D    ;STORE IT
  1617.     INX    H    ;TO NEXT "FROM"
  1618.     INX    D    ;TO NEXT "TO"
  1619.     DCR    B    ;MORE?
  1620.     JNZ    MOVE    ;..YES, LOOP
  1621.     RET        ;..NO, RETURN
  1622. ;    ----------------
  1623. OPTION    DB    0    ;PRIMARY OPTION
  1624. ;
  1625. ;DATAFLG IS USED BY THE "V" SUBCOMMAND -
  1626. ;IT IS 0 WHEN A HEADER OR CKSUM IS BEING
  1627. ;SENT/RCD, AND 1 IF "VIEWABLE" DATA (THE
  1628. ;SECTOR ITSELF) IS
  1629. ;
  1630. DATAFLG    DB    0    ;AT HEADER, FIRST
  1631. ;
  1632. ;
  1633. ;SUB-OPTION TABLE.  IF AN OPTION IS IN EFFECT,
  1634. ;    THE CHARACTER IS SET TO BINARY 0
  1635. ;
  1636. OPTBL    EQU    $
  1637. ANSWFLG    DB    'A'    ;ANSWER MODE
  1638. DISCFLG    DB    'D'    ;DISCONNECT WHEN DONE
  1639. ECHOFLG    DB    'E'    ;TO ECHO AFTER XFER
  1640. ORIGFLG    DB    'O'    ;ORIGINATE MODE
  1641. QFLG    DB    'Q'    ;QUIET TRANSFER (NO MSGS)
  1642. RSEEFLG    DB    'R'    ;SEE WHAT'S RECEIVED
  1643. SSEEFLG    DB    'S'    ;SEE WHAT'S SENT
  1644. TERMFLG    DB    'T'    ;TO TERM AFTER XFER
  1645. VSEEFLG    DB    'V'    ;VIEW MESSAGES (NO HDR, ETC)
  1646. OPTBE    EQU    $    ;END OF OPTIONS
  1647. ;
  1648. RCVSNO    DB    0    ;SECT # RECEIVED
  1649. SECTNO    DB    0    ;CURRENT SECTOR NUMBER 
  1650. ERRCT    DB    0    ;ERROR COUNT
  1651. HOLDD    DB    86H    ;HOLD AREA - LAST DC HAYES CONT CHAR.
  1652. ;FOLLOWING 3 USED BY DISK BUFFERING ROUTINES
  1653. EOFLG    DB    0    ;EOF FLAG (1=TRUE)
  1654. SECPTR    DW    DBUF
  1655. SECINBF    DB    0    ;# OF SECTORS IN BUFFER
  1656.     DS    60    ;STACK AREA
  1657. STACK    DS    2    ;STACK POINTER
  1658. ;
  1659. ;16 SECTOR DISK BUFFER (OVERLAYS HELP MSGS)
  1660. ;
  1661. DBUF    EQU    $    ;16 SECTOR DISK BUFFER
  1662. ;
  1663. ;INVALID COMMAND
  1664. ;
  1665. BADOPT    CALL    TYPE
  1666.     CALL    ILPRT    ;EXIT W/ERROR
  1667.     DB    ': INVALID OPTION ON MODEM '
  1668.     DB    'COMMAND - ',CR,LF
  1669.  DB 'PRESS RETURN FOR HELP, CTL-C IF NOT',CR,LF,1,0
  1670. ;
  1671. HELP    CALL    ILPRT
  1672.  DB 'Format for command is:',cr,lf,cr,lf
  1673.  DB 'MODEM # FILENAME',CR,LF,CR,LF
  1674.  DB 'Where # is a 1 character primary option,',cr,lf
  1675.  DB ' which may be followed by sub-options,',cr,lf
  1676.  DB ' and by ".xxx" to set baud rate to xxx'
  1677.  DB cr,lf,cr,lf,1
  1678.  DB 'Primary Options:',cr,lf
  1679.  DB '    S to send a file',cr,lf
  1680.  DB '    R to receive a file',cr,lf
  1681.  DB '    T to act as a terminal',cr,lf
  1682.  DB '    E to act as a computer (echo data)',cr,lf
  1683.  DB '    D to disconnect the phone'
  1684.  DB '    (S100 modems only)',cr,lf
  1685.  DB '    H to print this help file'
  1686.  DB cr,lf,cr,lf,1
  1687.  DB 'Secondary options:',cr,lf
  1688.  DB '    A answer mode',cr,lf
  1689.  DB '    O originate mode',cr,lf
  1690.  DB '    D disconnect after execution',cr,lf
  1691.  DB '    T go to terminal mode after file xfer',cr,lf
  1692.  DB '    E go to echo mode after file xfer',cr,lf
  1693.  DB '    Q quiet mode - no status msgs',cr,lf
  1694.  DB '    R show chars received',cr,lf
  1695.  DB '    S show chars sent',cr,lf
  1696.  DB '    V view file sent/received (no status)',cr,lf
  1697.  DB CR,LF,'FOR EXAMPLES, TYPE: MODEM X',cr,lf,0
  1698.     JMP    EXIT
  1699. ;
  1700. EXAM    CALL    ILPRT
  1701.  DB 'Send file, originate mode, 300 baud:',CR,LF
  1702.  DB '    MODEM SO fn.ft',cr,lf
  1703.  DB 'Send another file:',CR,LF
  1704.  DB '    MODEM S fn.ft',cr,lf
  1705.  DB 'Then send a third file at 450 baud and disconnect'
  1706.  DB CR,LF,'    MODEM SD.450 fn.ft',cr,lf
  1707.  DB 'Act as a terminal at 110 baud',cr,lf
  1708.  DB '    MODEM T.110',CR,LF
  1709.  DB ' Use ctl-D to disconnect)',cr,lf
  1710.  DB 'Receive file, answ mode, view it, 600 baud:',cr,lf
  1711.  DB '    MODEM RAV.600 fn.ft',cr,lf,0
  1712. JMP EXIT
  1713. ;
  1714. ; BDOS EQUATES (VERSION 2)
  1715. ;
  1716. RDCON    EQU    1
  1717. WRCON    EQU    2
  1718. PRINT    EQU    9
  1719. CONST    EQU    11    ;CONSOLE STAT
  1720. OPEN    EQU    15    ;0FFH=NOT FOUND
  1721. CLOSE    EQU    16    ;    "    "
  1722. SRCHF    EQU    17    ;    "    "
  1723. SRCHN    EQU    18    ;    "    "
  1724. ERASE    EQU    19    ;NO RET CODE
  1725. READ    EQU    20    ;0=OK, 1=EOF
  1726. WRITE    EQU    21    ;0=OK, 1=ERR, 2=?, 0FFH=NO DIR SPC
  1727. MAKE    EQU    22    ;0FFH=BAD
  1728. REN    EQU    23    ;0FFH=BAD
  1729. STDMA    EQU    26    ;SET DMA
  1730. BDOS    EQU    BASE+5
  1731. REIPL    EQU    BASE
  1732. FCB    EQU    BASE+5CH    ;SYSTEM FCB
  1733. FCBEXT    EQU    FCB+12    ;FILE EXTENT
  1734. FCBSNO    EQU    FCB+32    ;SECTOR #
  1735. FCB2    EQU    BASE+6CH    ;SECOND FCB
  1736.     END
  1737.