home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol016 / aplmodem.asm < prev    next >
Assembly Source File  |  1984-04-29  |  36KB  |  1,613 lines

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