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

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