home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / MODEMS / MODEM7 / MODM700.ASM < prev    next >
Assembly Source File  |  2000-06-30  |  154KB  |  6,498 lines

  1.  
  2. VERSION    EQU    700    ;MODM700 as of 11/04/84 -- CP/M MODEM PROGRAM
  3. ;
  4. ; This modem program uses the Christensen protocol.  It has both 'CRC'
  5. ; and CHECKSUM capability for error detection.  It supports dialing
  6. ; and auto-redialing for the Anchor Automation Signalman Mark XII,
  7. ; US Robotics modems, the Hayes Smartmodem 300 and 1200 and PMMI
  8. ; S-100 modems.  It supports up to two alternate dialing systems
  9. ; such as 'MCI', 'SPRINT', etc.
  10. ;
  11. ; Other external modems may be used, although manual dialing may be
  12. ; necessary.  Many overlays are available to allow easy configuration
  13. ; on various computers using I/O devices including the 2661, 8250, 8251,
  14. ; Z80-SIO, and many others.
  15. ;
  16. ; NOTE:  Current version is 73 sectors long. Use this figure when using
  17. ;     DDT, etc. to merge the appropriate overlay, regardless of what
  18. ;     the overlay may call for (such as 66 sectors for overlays made
  19. ;     when the program was not as lengthy.)
  20. ;
  21. ;***********************************************************************
  22. ;
  23. ;       THIS PROGRAM IS IN THE PUBLIC DOMAIN.
  24. ;
  25. ;***********************************************************************
  26. ;
  27. ; When transferring files modem-to-modem, the batch mode is extremely
  28. ; useful.  It allows automatic transmission of multiple files.  It can
  29. ; be used for single files or with wildcards.  With normal single program
  30. ; transfer, the receiving end switches from CRC to checksum in one minute
  31. ; and times out completely in 120 seconds.  (In batch mode it times out
  32. ; in 3 minutes for receive.)  This allows ample opportunity to transfer
  33. ; programs between individuals.
  34. ;
  35. ;    M7NM-6.ASM can be used to change the telephone overlay numbers
  36. ;       and/or set the alternate dialing system code (also used to
  37. ;       change HEXSHO and SAVSIZ, mentioned below.)
  38. ;
  39. ;    M7LIB.COM can be used to easily change any of the telephone
  40. ;       overlay numbers.
  41. ;
  42. ;    M7FNK.COM can be used to easily change any of the 10 function
  43. ;       key assignments (or the function key intercept character
  44. ;       itself, which is currently the '^' character.
  45. ;
  46. ; Significant address changes now used:
  47. ;
  48. ;    0DFEH  -  HEXSHO  00 = do not show hex record count
  49. ;              FF = show both hex and decimal count
  50. ;    0DFFH  -  SAVSIZ  20 = 4k file transfer buffer size
  51. ;              40 = 8k file transfer buffer size
  52. ;              80 = 16k file transfer buffer size
  53. ;    0E00H  -  NUMLIB  (start of telephone number library)
  54. ;
  55. ;***********************************************************************
  56. ;
  57. ; Many people have contributed ideas for this modem program:
  58. ;
  59. ;    Ward Christensen, Jim Mills, Mark Zeigler, Keith Petersen,
  60. ;    Paul Kelly, Bruce Ratoff, John Mahr, Rich Berg, Bob Clyne,
  61. ;    Bill Earnest, Paul Hansknecht, Ron Fowler, Fred Viles, Bob
  62. ;    Plouffe, Ben Bronson, Sigi Kluger, Irv Hoff, Frank Gaude'
  63. ;    and others.
  64. ;
  65. ;***********************************************************************
  66. ;
  67. PORT    EQU    0C0H    ;your base port (data or status)
  68. ;
  69. MDCTL1    EQU    PORT    ;modem control port
  70. MDDATP    EQU    PORT+1    ;modem data port
  71. MDRCVB    EQU    02H    ;modem receive bit (DAV)
  72. MDRCVR    EQU    02H    ;modem receive ready
  73. MDSNDB    EQU    01H    ;modem send bit
  74. MDSNDR    EQU    01H    ;modem send ready bit
  75. ;
  76. ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  77. ;             special equates for PMMI
  78. ;
  79. MDCTL2    EQU    PORT+3    ;modem status port
  80. ;
  81. BAUDRP    EQU    PORT+2    ;modem baud rate port
  82. BRKMASK    EQU    0FBH    ;mask to set break
  83. EVPAMSK    EQU    20H    ;mask to set even parity
  84. NOPAMSK    EQU    10H    ;mask to reset to no parity
  85. ODPAMSK    EQU    0CFH    ;mask to set odd parity
  86. ;
  87. ANSWMOD    EQU    1EH    ;answer mode
  88. ORIGMOD    EQU    1DH    ;originate mode
  89. WAITCTS    EQU    150    ;number of seconds (x5) to wait for the
  90.             ;computer to answer after PMMI auto-dial
  91.             ;100=20 sec, 150=30 sec, 255=51 seconds
  92.             ;any number 0-255 acceptable
  93. ;
  94. ;          (end of special PMMI equates)
  95. ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  96. ;
  97. YES    EQU    0FFH
  98. NO    EQU    0
  99. ;
  100. BUFSIZ    EQU    16    ;buffer size in Kbytes for ASCII capture to disk
  101.             ;(16k is one file extent)
  102. XFRSIZ    EQU    4    ;file transfer buffer in Kbytes.  Do not make
  103.             ;any larger than BUFSIZ.  16k works fine on all
  104.             ;but very slowest systems
  105. ;
  106. BDNMCH    EQU    75H    ;bad name match
  107. ERRLIM    EQU    10    ;maximum allowable consecutive errors
  108. ERRCRC    EQU    6    ;CRC tries, then switches to CHECKSUM
  109. LIBLEN    EQU    34    ;length of each phone library entry
  110. SHOWHEX    EQU    YES    ;yes, show both decimal and hex record counts
  111.             ;no, show just decimal record count
  112. RUB    EQU    7FH    ;rub
  113. CRC    EQU    'C'    ;requests 'CRC' instead of 'CKSUM'
  114. ESC    EQU    '['-40H    ;^[ = escape
  115. SOH    EQU    'A'-40H    ;^A = start of header
  116. EOT    EQU    'D'-40H    ;^D = end of text
  117. EXITCHR    EQU    'E'-40H    ;^E = exit character
  118. ACK    EQU    'F'-40H    ;^F = acknowledge
  119. OKNMCH    EQU    'F'-40H    ;^F = ok name match
  120. BELL    EQU    'G'-40H    ;^G = bell character
  121. BKSP    EQU    'H'-40H    ;^H = backspace
  122. LF    EQU    'J'-40H    ;^J = linefeed
  123. CR    EQU    'M'-40H    ;^M = carriage return
  124. XON    EQU    'Q'-40H    ;^Q = XON character
  125. XOFF    EQU    'S'-40H    ;^S = XOFF character
  126. NAK    EQU    'U'-40H    ;^U = not acknowledge
  127. CANCEL    EQU    'X'-40H    ;^X = cancel send or receive
  128. EOFCHAR    EQU    'Z'-40H    ;^Z = end of file
  129. ;
  130.     ORG    0100H
  131. ;
  132.     JMP    START    ;skip the data area below
  133. ;
  134. ; These routines and equates are at the beginning of the program so
  135. ; they can be patched by a monitor or overlay file without re-assembling
  136. ; the program.
  137. ;
  138. PMMIMD    DB    YES    ;yes=PMMI modem
  139. AUTDIAL    DB    NO    ;yes=Hayes-type autodial modem
  140. TCHPUL    DB    'T'    ;T=touch, P=pulse (autodial-only)
  141. CLOCK    DB    40    ;clock speed in MHz x 10, 25.5 MHz max.
  142.             ;2 MHz=20, 3.68 MH=37, 4 MHz=40, etc.
  143. MSPEED    DB    1    ;sets display time for sending a file
  144.             ;0=110    1=300  2=450  3=600  4=710
  145.             ;5=1200 6=2400 7=4800 8=9600 9=19200
  146. BYTDLY    DB    5    ;0=0 delay  1=10 ms  5=50 ms - 9=90 ms
  147.             ;defaut time to send character in ter-
  148.             ;minal mode file transfer for slow BBS
  149. CRDLY    DB    5    ;0=0 delay 1=100 ms 5=500 ms - 9=900 ms
  150.             ;default time for extra wait after CRLF
  151.             ;in terminal mode file transfer
  152. NOFCOL    DB    5    ;number of directory columns
  153. STUPTST    DB    NO    ;yes=non-PMMI setup routine
  154. SCRNTST    DB    NO    ;yes=if home cursor and clear screen
  155.             ;routine at CLRSCR
  156. RETRY    DB    YES    ;yes=reset the error limit to try again
  157.             ;no=abort after 10 consecutive errors
  158. BACKUP    DB    NO    ;yes=make .BAK file
  159. CRCDFLT    DB    YES    ;yes=default to CRC checking
  160.             ;no=default to Checksum checking
  161. TGLECRC    DB    YES    ;yes=allow toggling of Checksum to CRC
  162. CONVRUB    DB    NO    ;yes=convert rub to backspace
  163. TGLERUB    DB    YES    ;yes=allow toggling of rub to backspace
  164. ADDLFD    DB    NO    ;no=no LF after CR to send file in
  165.             ;terminal mode (added by remote echo)
  166. TGLELF    DB    YES    ;yes=allow toggling of LF after CR
  167. TRANLOG    DB    NO    ;yes=allow transmission of logon
  168.             ;write logon sequence at location LOGON
  169. SAVCCP    DB    YES    ;yes=do not overwrite CCP
  170. LOCNXT    DB    NO    ;yes=local cmd if EXTCHR precedes
  171.             ;no=not local cmd if EXTCHR precedes
  172. TGLELOC    DB    YES    ;yes=allow toggling of LOCNXT
  173. LSTTST    DB    YES    ;yes=allow toggling of printer on/off
  174.             ;in terminal mode. Set to no if using
  175.             ;the printer port for the modem
  176. XOFFTST    DB    NO    ;yes=allow testing of XOFF from remote
  177.             ;while sending a file in terminal mode
  178. XONWAIT    DB    NO    ;yes=wait for XON after sending CR while
  179.             ;transmitting a file in terminal mode
  180. TGXOFF    DB    YES    ;yes=allow toggling of XOFF testing
  181. IGNRCTL    DB    NO    ;yes=do not send control characters
  182.             ;above CTL-M to CRT in terminal mode
  183.             ;no=send any incoming CTL-char to CRT
  184. EXTRA1    DB    0    ;for future expansion
  185. EXTRA2    DB    0    ;for future expansion
  186. BRKCHR    DB    '@'-40H    ;^@ = Send a 300 ms. break tone
  187. NOCONCT    DB    'N'-40H    ;^N = Disconnect from phone line
  188. LOGCHR    DB    'L'-40H    ;^L = Send logon
  189. LSTCHR    DB    'P'-40H    ;^P = Toggle printer
  190. UNSAVCH    DB    'R'-40H    ;^R = Close input text buffer
  191. TRANCHR    DB    'T'-40H    ;^T = Transmit file to remote
  192. SAVECHR    DB    'Y'-40H    ;^Y = Open input text buffer
  193. EXTCHR    DB    '^'-40H    ;^^ = Send next character
  194. ;
  195. ; Equates used only by PMMI routines grouped together here
  196. ;
  197. PULRATE    DB    250    ;125=20pps dialing, 250=10pps
  198. CHGBAUD    DB    'B'-40H    ;^B = Used with PMMIMD in terminal
  199.             ;mode to change baud rate on fly
  200. ;
  201. ; Handles in/out ports for data and status
  202. ;
  203. I$MDCTL1 IN    MDCTL1    ! RET        ;in modem control port
  204.      DB    0,0,0,0,0,0,0        ;spares if needed for non-PMMI
  205. ;
  206. O$MDDATP OUT    MDDATP    ! RET        ;out modem data port
  207.      DB    0,0,0,0,0,0,0        ;spares if needed for non=PMMI
  208. ;
  209. I$MDDATP IN    MDDATP    ! RET        ;in modem data port
  210.      DB    0,0,0,0,0,0,0        ;spares if needed for non-PMMI
  211. ;
  212. A$MDRCVB ANI    MDRCVB    ! RET        ;bit to test for receive ready
  213. C$MDRCVR CPI    MDRCVR    ! RET        ;value of receive bit when ready
  214. A$MDSNDB ANI    MDSNDB    ! RET        ;bit to test for send ready
  215. C$MDSNDR CPI    MDSNDR    ! RET        ;value of send bit when ready
  216. ;
  217. ;====================== SPECIAL PMMI PORTS =============================
  218. ;
  219. I$BAUDRP IN    BAUDRP    ! RET        ;in baudrate port
  220. O$BAUDRP OUT    BAUDRP    ! RET        ;out baudrate port
  221. O$MDCTL1 OUT    MDCTL1    ! RET        ;out modem control port #1
  222. O$MDCTL2 OUT    MDCTL2    ! RET        ;out modem control port #2
  223. ;
  224. LOGONPTR DW    LOGON
  225. J$DIAL     JMP    DIAL
  226. J$DSCONT JMP    DSCONT
  227. J$GOODBY JMP    GOODBY
  228. J$INITMD JMP    INITMD
  229. J$NWBAU     JMP    NWBAU
  230. J$NPARIT JMP    NPARIT
  231. J$PRITY     JMP    PRITY
  232. J$STUPR     JMP    STUPR
  233. J$SPMEN     JMP    SPMEN
  234. J$SYSVR     JMP    SYSVR
  235. J$BREAK     JMP    SNDBRK
  236. ;
  237. ; Next six lines should not be changed by user overlay as these go to
  238. ; specific locations in the main program, not in the overlay.
  239. ;
  240. J$ILPRT     JMP    ILPRT
  241. J$INBUF     JMP    INBUF
  242. J$INLNCP JMP    INLNCP
  243. J$INMDM     JMP    INMDM
  244. J$NXTSCR JMP    NXTSCR
  245. J$TIMER     JMP    TIMER
  246. ;
  247. ; Clear sequences are for Televideo, Lear Siegler, etc.  Change to match
  248. ; your terminal.  (Heath uses ESC 4AH for clear to end of screen, ESC 45H
  249. ; to clear screen.  Lear Siegler and others use ESC 79H for clear to end
  250. ; of screen and ESC 3AH to clear screen.)  Room allowed for four bytes.
  251. ; (Last zero needed for stopping the string display.  Any extra 0's just
  252. ; act as NOP's.)
  253. ;
  254. CLREOS    CALL    J$ILPRT
  255.     DB    ESC,79H,0,0,0
  256.     RET
  257. ;
  258. CLRSCR    CALL    J$ILPRT
  259.     DB    ESC,3AH,0,0,0
  260.     RET
  261. ;
  262. ;======================= SIGN-ON MESSAGE ==============================
  263. ;
  264. ; Send version number and date
  265. ;
  266. SYSVR    LDA    PMMIMD        ;using the PMMI S-100 modem?
  267.     ORA    A
  268.     JZ    SYSVR1        ;go if not
  269.     CALL    J$ILPRT
  270.     DB    'Version for PMMI S-100 modem starting at port: ',0
  271.     LDA    I$MDCTL1+1
  272.     CALL    HEXO        ;put in PMMI control port number
  273.     CALL    J$ILPRT
  274.     DB    'H',CR,LF,0
  275.     RET
  276. ;
  277. SYSVR1    CALL    J$ILPRT        ;if not using the PMMI S-100 board
  278.     DB    'Version for Non-PMMI modem',CR,LF,0
  279.     RET
  280. ;
  281. ;==================== LOGON MESSAGE (IF ANY) ===========================
  282. ;
  283. ; Insert your logon message here.  End with a 0 (for"CALL ILPRT").
  284. ; PMMIusers have 59 bytes available, non-PMMI users have approximately
  285. ; 2K bytes available as they can overwrite all the following PMMI rou-
  286. ; tines if they wish.  This method allows the external overlays to have
  287. ; plenty of room.  It keeps the phone number library at a fixed location.
  288. ;
  289. LOGON    DS    59    ;up to 59 characters allowed
  290.     DB    0    ;to terminate the logon message
  291. ;
  292. ;=============== NON-PMMI INITIALIZATION (IF ANY) ======================
  293. ;
  294. ; Insert your initialization routine here if needed.  Can replace the
  295. ; following special PMMI area to set speed and auto-dial.  Over 950
  296. ; bytes are available for this purpose.  (End your routine with a RET.)
  297. ;
  298. INITMD    RET
  299. ;
  300. ;========== NON-PMMI SETUP (SPEED CHANGE, ETC.) IF ANY ==============
  301. ;
  302. ; Insert your speed change and/or auto-dialing routines here.  Over 950
  303. ; bytes are available (INCLUDING INITMD, above).  End your routine with
  304. ; a RET.
  305. ;
  306. STUPR    RET
  307. ;
  308. ; Not needed if using the PMMI board, as it has its own break routine
  309. ;
  310. SNDBRK    RET
  311. ;
  312. ;**************** START OF SPECIAL PMMI ROUTINES **********************
  313. ;
  314. ;=======================================================================
  315. ;            SETS THE BAUD RATE
  316. ;=======================================================================
  317. ;
  318. STBAUD    LDA    ANSWFLG        ;if 'O' or 'A' not requested and
  319.     ORA    A        ;   baudrate not specified, returns
  320.     JZ    FXBAUD        ;   with current mode and rate
  321.     LDA    ORIGFLG        ;if option requested, a blank returns
  322.     ORA    A        ;   with current mode and rate
  323.     RNZ            ;no change if neither 'O' or 'A' shown
  324. ;
  325. FXBAUD    CALL    GTBAUD        ;calculate PMMI baud rate divisor
  326.     CALL    STMSPD        ;set the file time transfer value
  327.     CALL    O$BAUDRP    ;set the PMMI board to that baudrate
  328.     CPI    52
  329.     MVI    A,5FH        ;DTR (filter for over 300 baud)
  330.     JC    GT300        ;yes, greater than
  331.     MVI    A,7FH        ;DTR (filter for 300 and less baud)
  332. ;
  333. GT300    CALL    O$MDCTL2
  334.     STA    MDCTLB        ;save modem control byte
  335. ;
  336. OFHOOK    LXI    H,7500        ;throw in some delay
  337. ;
  338. OFFDLY    DCR    L
  339.     JNZ    OFFDLY
  340.     DCR    H
  341.     JNZ    OFFDLY
  342.     LDA    UARTCT        ;UART control byte for 'A' or 'O'
  343.     CALL    O$MDCTL1    ;now set to answer or originate
  344.     MOV    A,C
  345.     STA    MSPEED        ;set the file transfer time value
  346.     XRA    A        ;clear the flags
  347.     RET
  348. ;
  349. ;=======================================================================
  350. ;         CALCULATES THE BAUD RATE DIVISOR
  351. ;
  352. ; Returns with current baud rate intact if a blank or null in the speed
  353. ; field (extent area).
  354. ;
  355. GTBAUD    LDA    FCB+9        ;get 1st digit of requested baudrate
  356.     CPI    ' '        ;if a space, return with current speed
  357.     LDA    CURRENT
  358.     RZ
  359.     LDA    FCB+9
  360.     ORA    A        ;if a null, return with current speed
  361.     LDA    CURRENT
  362.     RZ
  363. ;
  364.     LXI    D,FCB+9        ;get the requested speed
  365.     LXI    H,0
  366. ;
  367. DECLP    LDAX    D        ;get the ASCII digit
  368.     INX    D
  369.     CPI    ' '
  370.     JZ    DECLP
  371.     CPI    '0'        ;numerals are 0-9
  372.     JC    BADRTE
  373.     CPI    '9'+1
  374.     JNC    BADRTE
  375.     SUI    '0'
  376.     MOV    B,H
  377.     MOV    C,L
  378.     DAD    H
  379.     DAD    H
  380.     DAD    B
  381.     DAD    H
  382.     ADD    L
  383.     MOV    L,A
  384.     JNZ    DIGNC
  385.     INR    H
  386. ;
  387. DIGNC    MOV    A,E
  388.     CPI    FCB+12
  389.     JNZ    DECLP
  390.     MOV    A,H
  391.     CMA
  392.     MOV    D,A
  393.     MOV    A,L
  394.     CMA
  395.     MOV    E,A
  396.     INX    D
  397.     LXI    H,15625        ;250000/16
  398.     LXI    B,-1
  399. ;
  400. DIVLP    INX    B
  401.     DAD    D
  402.     JC    DIVLP
  403.     MOV    A,B
  404.     ORA    A
  405.     MOV    A,C
  406.     STA    CURRENT        ;can use this the next time by default
  407.     RZ
  408. ;
  409. BADRTE    CALL    ERXIT
  410.     DB    '++ INVALID BAUDRATE ++$'
  411. ;
  412. ;=======================================================================
  413. ;            SETS 'MSPEED' TO BAUD RATE
  414. ;
  415. STMSPD    MVI    C,0        ;changes PMMI mspeed for 110-710 bps
  416.     CPI    100        ;<300 bps
  417.     RNC
  418.     INR    C        ;C=1 for 300 bps
  419.     CPI    40        ;<450 bps
  420.     RNC
  421.     INR    C        ;C=2 for 450 bps
  422.     CPI    30        ;<600 bps
  423.     RNC
  424.     INR    C        ;C=3 for 600 bps
  425.     CPI    24        ;<710 bps
  426.     RNC
  427.     INR    C        ;C=4 for 710 bps
  428.     RET
  429. ;
  430. ; Change baudrate on-the-fly with CTL-B (while in terminal mode)
  431. ;
  432. NWBAU    LDA    PMMIMD
  433.     ORA    A
  434.     RZ
  435.     CALL    J$ILPRT
  436.     DB    CR,LF,'Enter new Baudrate: ',0
  437.     LXI    H,FCB+9
  438.     MVI    M,' '        ;keep current baud if none included
  439. ;
  440. NWBAU1    CALL    KEYIN        ;get the baud rate
  441.     CPI    CR        ;carriage ret finishes baud rate entry
  442.     CZ    CRLF        ;if a 'CR', baud rate has been entered
  443.     JZ    FXBAUD        ;go change the baud rate
  444. ;
  445. NWBAU2    CPI    '0'        ;numerals are 0-9
  446.     JC    NWBAU1
  447.     CPI    '9'+1
  448.     JNC    NWBAU1        ;if not a numeral, ignore, ask again
  449.     MOV    M,A        ;store answer starting at FCB+9
  450.     CALL    TYPE        ;show the numeral on the CRT
  451.     INX    H        ;next storage location in FCB
  452.     JMP    NWBAU1        ;get the next numeral
  453. ;
  454. ;======================= PARITY ROUTINES ===============================
  455. ;
  456. ;--->PRITY: Routine to setup PMMI for odd/even parity.
  457. ;
  458. PRITY    LDA    PMMIMD        ;is modem a PMMI?
  459.     ORA    A        ;set flags
  460.     RZ            ;no, return
  461.     LDA    OPRITY        ;get odd parity request byte
  462.     ORA    A        ;set flags
  463.     JNZ    EVNPAR        ;if not odd see if it is even
  464.     LDA    UARTCT        ;get uart/modem control byte
  465.     ANI    ODPAMSK
  466.     JMP    PRITY1
  467. ;
  468. EVNPAR    LDA    EPRITY        ;get even parity request byte
  469.     ORA    A        ;set flags
  470.     RNZ            ;if even parity not specified return
  471.     LDA    UARTCT        ;get uart/modem control byte
  472.     ANI    ODPAMSK        ;set for parity
  473.     ORI    EVPAMSK        ;now set for even parity
  474. ;
  475. PRITY1    STA    UARTCT
  476.     JMP    O$MDCTL1    ;send to PMMI
  477. ;
  478. NPARIT    LDA    PMMIMD
  479.     ORA    A
  480.     RZ
  481.     LDA    UARTCT
  482.     ORI    NOPAMSK        ;reset parity bit on PMMI
  483.     JMP    O$MDCTL1
  484. ;
  485. ;=======================================================================
  486. ;           HAYES/PMMI DIALING ROUTINES
  487. ;=======================================================================
  488. ;
  489.     DS    128    ;for expansion
  490. ;
  491. ; Modem control command words
  492. ;
  493. BRKMSK    EQU    0    ;tele line on hook (break while dialing)
  494. CLEAR    EQU    3FH    ;idle mode
  495. DTMSK    EQU    1    ;dial tone mask
  496. MAKEM    EQU    1    ;tele line make (off hook)
  497. RBLMT    EQU    35    ;7 seconds to wait til no-ring-heard msg
  498. RBWAIT    EQU    50    ;5 second delay before redialing PMMI
  499. SMWAIT    EQU    15    ;1.5 sec delay before redialing HAYES
  500. TMPUL    EQU    80H    ;timer pulses mask bit
  501. TRATE    EQU    250    ;value for 0.1 second
  502. ;
  503. ; Dialing routine
  504. ;
  505. DIAL    LDA    PMMIMD    ;using a PMMI modem?
  506.     ORA    A
  507.     JNZ    DIAL1
  508.     LDA    AUTDIAL
  509.     ORA    A
  510.     RZ            ;return if neither modem
  511.     CALL    SMNSY        ;make sure autodial modem speaker is on
  512. ;
  513. DIAL1    XRA    A
  514.     STA    AUTDIR        ;zero the direct to terminal mode flag
  515.     STA    AUTOFL        ;zero the auto-linking flag
  516.     STA    CRFLAG        ;zero the continuous dial flag
  517.     LXI    H,0
  518.     SHLD    DIALCT        ;zero the dial count
  519.     LXI    H,CMDBUF+1    ;point to the number of characters in
  520.     MOV    A,M        ;  the buffer, then get the number
  521.     CPI    3+1        ;anything typed after 'CAL'?
  522.     JC    DIAL2        ;if not, go through library routine
  523. ;
  524. ; If there were only 3 characters, then "CAL<RET>" was typed -- the user
  525. ; obviously expecting to get a phone number (or letter) from the library
  526. ; file.  If 4 or more, a number (or letter) was typed in from the menu
  527. ; command line, so move the characters down 4 to compensate.  Needed for
  528. ; auto-redialing of menu command line entries.
  529. ;
  530.     MOV    C,A        ;put into the 'C' reg.
  531.     MVI    B,0        ;will move original number down 4
  532.     SUI    4        ;eliminate the 'CAL' portion
  533.     MOV    M,A        ;store new count at cmdbuf+1
  534.     INX    H        ;CMDBUF+2 (first character of string)
  535.     XCHG            ;'DE' now has CMDBUF+2
  536.     LXI    H,CMDBUF+6    ;point to number (or letter) to dial
  537.     CALL    MOVER        ;move the group down 4 places
  538.     JMP    DIAL4        ;check if library number, then dial
  539. ;
  540. ; Comes here if no phone number was manually entered after 'CAL' and if
  541. ; no phone library code was entered.  Displays the phone number library
  542. ; then asks for an entry.
  543. ;
  544. DIAL2    MVI    C,18        ;number of lines to move
  545.     LXI    H,NUMLIB    ;start of phone number library
  546.     LXI    D,BUFFER    ;buffer add. to store them temporarily
  547.     CALL    NEWLINE        ;start with CR/LF
  548.     STAX    D        ;+LF
  549.     INX    D        ;and bump it
  550. ;
  551. DIAL3    MVI    B,LIBLEN    ;number of bytes to move
  552.     CALL    MOVE        ;move to buffer
  553.     CALL    SPACES        ;2 entries + 3 spaces = 71 characters
  554.     PUSH    H        ;save source address
  555.     PUSH    D        ;save destination address
  556.     LXI    D,(17*LIBLEN)    ;get offset of 17 times entry length
  557.     DAD    D        ;add it to source address
  558.     POP    D        ;restore destination address
  559.     MVI    B,LIBLEN    ;get length of library entry
  560.     CALL    MOVE        ;move another entry
  561.     POP    H        ;restore source address
  562.     CALL    NEWLINE
  563.     DCR    C        ;one less line to print
  564.     JNZ    DIAL3        ;if not zero, print another
  565.     MVI    A,'$'        ;BDOS print routine terminate character
  566.     STAX    D        ;store in buffer
  567.     CALL    CLRTST
  568.     MVI    C,PRINT
  569.     LXI    D,BUFFER    ;print the library on the CRT
  570.     CALL    BDOS
  571.     CALL    J$ILPRT        ;ask which one is wanted
  572.     DB    CR,LF,'Enter library code or phone number,',CR,LF
  573.     DB    'Hit RET to abort this function now or',CR,LF
  574.     DB    'CTL-X quits while dialing or ringing: ',0
  575.     LXI    D,CMDBUF
  576.     CALL    INBUF        ;get the answer from the keyboard
  577. ;
  578. ; You now have either a library code or a manually entered phone num-
  579. ; ber.    These either came from the menu command line or from the library
  580. ; command line.  Next we see if a code, if so, get the corresponding
  581. ; line with phone number from the library.  If a number greater than
  582. ; one digit, we ignore the library look-up.  (Ringback numbers must end
  583. ; with letter 'R'.)
  584. ;
  585. DIAL4    LXI    H,CMDBUF+1    ;number of characters in buffer
  586.     MOV    A,M
  587.     ORA    A        ;null means CR was typed
  588.     JZ    DLXIT2        ;abort dialing, return to menu
  589.     STA    NUMBER
  590.     LDA    CMDBUF+3    ;see if at least two characters entered
  591.     CPI    '/'        ;slash for linking, direct to terminal
  592.     CZ    AUTO        ;  mode on answer
  593.     CPI    ','        ;comma used for linking
  594.     CZ    AUTO1        ;if yes, set it up for auto-linking
  595. ;
  596. ; Check to see how many characters were typed.    If more than one, then
  597. ; it was a hand-entered phone number, so exit.
  598. ;
  599. DIAL5    CALL    DIALBG        ;disconnect, reconnect
  600.     LDA    AUTOFL        ;auto-link flag set?
  601.     ORA    A
  602.     JNZ    AUTO2        ;if yes exit
  603.     LDA    NUMBER        ;number of characters in buffer
  604.     STA    CMDBUF+1    ;reset the character count, if needed
  605.     CPI    1+1        ;more than one character?
  606.     JNC    DIAL14        ;if more than one, hand-entered number
  607.     LXI    H,CMDBUF+2    ;first character in phone number line
  608. ;
  609. ; If just one character entered, see if a (A-Z) letter
  610. ;
  611. DIAL6    MOV    A,M
  612.     MVI    B,'A'        ;first letter of alphabet
  613.     MVI    E,0        ;counts number of letters to match
  614.     MVI    C,26        ;number of letters in alphabet
  615. ;
  616. DIAL7    CMP    B        ;letter from table?
  617.     JZ    DIAL9        ;if yes, get phone number, else
  618.     INR    B        ;make next letter (A-Z)
  619.     INR    E        ;count up
  620.     DCR    C        ;count down
  621.     JNZ    DIAL7        ;try next one in (A-Z) table
  622. ;
  623. ; If not (A-Z) then should be (0-9)
  624. ;
  625.     MVI    B,'0'        ;first digit to check
  626.     MVI    E,26        ;point past alpha codes
  627.     MVI    C,10        ;number of digits in table
  628. ;
  629. DIAL8    CMP    B        ;number from table?
  630.     JZ    DIAL9        ;if yes, go dial, else
  631.     INR    B        ;make next digit to compare
  632.     INR    E        ;make next table line number
  633.     DCR    C        ;count down - loop counter
  634.     JNZ    DIAL8        ;loop
  635.     JMP    DIALBD        ;error if not a number or a letter
  636. ;
  637. ; Now have a match between the requested code and one in the library.
  638. ; E-reg. holds the library line number (1-36) that matches the requested
  639. ; code (A-Z or 0-9).
  640. ;
  641. DIAL9    LXI    H,NUMLIB    ;phone number library
  642.     LXI    B,LIBLEN    ;length of library entry
  643.     MOV    A,E        ;number of times to library length to HL
  644.     ORA    A        ;set flags
  645.     JZ    DIAL11
  646. ;
  647. DIAL10    MOV    A,M        ;get first char of selected lib entry
  648.     ORA    A        ;set flags
  649.     JZ    DIALBD        ;send bad library msg and abort
  650.     DAD    B        ;increment 'HL' by library length
  651.     DCR    E        ;countdown
  652.     JNZ    DIAL10        ;not there yet, loop
  653. ;
  654. ; Now have the line in the phone number library matching the requested
  655. ; letter so store that line starting at 'CMDBUF+1'
  656. ;
  657. DIAL11    MVI    B,LIBLEN    ;number of characters to get from table
  658.     LXI    D,CMDBUF+1    ;point to buffer
  659.     XCHG            ;'HL' points to CMDBUF+1
  660.     MOV    M,B        ;length of each table entry
  661.     XCHG            ;restore the registers
  662.     INX    D        ;point to first char position in buffer
  663.     CALL    MOVE        ;move the table entry to the buffer
  664. ;
  665. ; Now have the full line including phone number in 'CMDBUF' area.  Scan
  666. ; past the descriptive portion of library entry - terminate scan at the
  667. ; first '.'  This allows commas and numbers to be part of the text, such
  668. ; as:
  669. ;         'A=DataTech, Node 7..1-408-238-9621'
  670. ;
  671. DIAL12    LDA    AUTDIAL        ;using a Hayes-type modem?
  672.     ORA    A
  673.     CNZ    SMINIT        ;if yes, initialize
  674.     LXI    H,CMDBUF+1
  675.     MOV    E,M        ;number of chars in buffer
  676.     INX    H        ;point to 1st character in buffer
  677. ;
  678. DIAL13    MOV    A,M        ;get next character
  679.     CALL    TYPE        ;show it
  680.     INX    H        ;bump pointer
  681.     DCR    E        ;decrement count
  682.     JZ    DLXIT        ;exit if no '.' (bad library entry)
  683.     CPI    '.'        ;dot?
  684.     JZ    DIAL15        ;yes, go dial the phone
  685.     JMP    DIAL13        ;no, loop for next character
  686. ;
  687. ; There is a user entered phone number in 'CMDBUF' area
  688. ;
  689. DIAL14    LDA    AUTDIAL        ;using a Hayes-type modem?
  690.     ORA    A
  691.     CNZ    SMINIT        ;if yes, initialize
  692.     LXI    H,CMDBUF+1    ;get the number of characters in buffer
  693.     MOV    A,M
  694.     MOV    E,M
  695.     INX    H        ;point to 1st character to dial
  696. ;
  697. ; Loop to dial the phone number pointed to by 'HL', character count in
  698. ; the 'E' register.
  699. ;
  700. DIAL15    MOV    A,M        ;get first number from the buffer
  701.     ORA    A        ;set flags
  702.     JZ    DIALBD        ;bad number if a null
  703. ;
  704. ; Dial a digit, check keyboard for abort
  705. ;
  706.     CALL    DL        ;dial a digit, show on CRT
  707.     CALL    STAT        ;keypress?
  708.     JZ    DIAL17        ;if not, exit
  709.     CALL    KEYIN        ;yes, go get it
  710.     CPI    CANCEL        ;CTL-X?
  711.     JNZ    DIAL17        ;if not, exit
  712.     LDA    AUTDIAL        ;using a Hayes-type modem?
  713.     ORA    A
  714.     JZ    DLXIT        ;if not, exit now, otherise clear line
  715. ;
  716. ; If using an autodial modem, backspace 30 tims to make sure the entire
  717. ; number plus 'DT' part of 'ATDT' is erased.
  718. ;
  719.     MVI    C,30
  720. ;
  721. DIAL16    MVI    B,BKSP
  722.     CALL    SNDCHR        ;send to the modem to cancel call
  723.     DCR    C
  724.     JNZ    DIAL16        ;if not zero, do another
  725.     MVI    B,CR
  726.     CALL    SNDCHR
  727.     MVI    A,' '
  728.     CALL    TYPE        ;show on CRT
  729.     JMP    DLXIT        ;now go abort
  730. ;
  731. DIAL17    INX    H        ;bump pointer
  732.     DCR    E        ;one less character to go
  733.     JNZ    DIAL15        ;if not done, send the next digit
  734. ;
  735. ; Show the number of dial attempts
  736. ;
  737.     CALL    J$ILPRT
  738.     DB    ' - try #',0
  739.     LHLD    DIALCT        ;increment the dial count
  740.     INX    H
  741.     SHLD    DIALCT
  742.     CALL    DECOUT        ;show number of attempts so far
  743.     MVI    A,' '        ;extra space to position cursor
  744.     CALL    TYPE
  745.     LDA    AUTDIAL        ;using a Hayes-type modem?
  746.     ORA    A
  747.     JZ    DIAL19        ;if not, exit
  748.     MVI    B,CR        ;tells the modem the number is done
  749.     CALL    SNDCHR        ;just have one character to send
  750. ;
  751. DIAL18    CALL    J$INMDM        ;catch any output from the modem
  752.     JNC    DIAL18
  753.     JMP    SMRSLT        ;number sent to modem, now get results
  754. ;
  755. ; Dialing is all done, this section is PMMI-only
  756. ;
  757. DIAL19    MVI    A,07FH        ;turn on PMMI 'DTR'
  758.     CALL    O$MDCTL2    ;timer rate?
  759.     MVI    B,1        ;0.1 second per interval
  760.     CALL    J$TIMER
  761.     MVI    A,5DH        ;2 stop bits, nor parity, 8 data bits
  762.     CALL    O$MDCTL1
  763.     MVI    D,4        ;clear to send mask
  764.     MVI    C,WAITCTS    ;wait time for CTS
  765.     CALL    WAIT        ;(30 seconds, can set 'WAITCTS' for
  766.                 ;up to 51 seconds for European use)
  767. ;
  768. ; If PMMI connection made, go get options for starting communications
  769. ;
  770.     JNC    CONMD        ;connection made
  771. ;
  772. ; Connection not made, see if a redial is desired
  773. ;
  774. ;    CALL    DSCONT        ;hang-up so we can redial
  775. ;
  776. DLGN    LXI    SP,STACK    ;reset the stack to normal, just in case
  777.     LDA    CRFLAG        ;continuous redial flag
  778.     ORA    A
  779.     JNZ    DLGN2        ;if already set, go dial again
  780.     CALL    J$ILPRT        ;see if we should keep trying
  781.     DB    CR,LF,CR,LF,'     Redial? (C/Y/N/Q): ',BELL,0
  782.     CALL    KBDCHR
  783.     CALL    CRLF        ;turn up a line
  784.     CPI    'Y'        ;redial?
  785.     JZ    DLGN2        ;yes, redial
  786.     CPI    'C'        ;continuous redial?
  787.     JZ    DLGN1        ;if yes, set continuous redial flag
  788.     CPI    'Q'
  789.     JNZ    DLXIT1        ;none of these, quit
  790.     CALL    SMQT        ;turn off the loud speaker for 'Quiet'
  791. ;
  792. DLGN1    MVI    A,1
  793.     STA    CRFLAG        ;continuous redial flag
  794. ;
  795. DLGN2    LDA    AUTDIAL        ;using a Hayes-type modem?
  796.     ORA    A
  797.     JNZ    DLGN3        ;if yes, exit
  798.     MVI    B,RBWAIT    ;wait for PMMI reset (or busy)
  799.     CALL    J$TIMER        ;or busy tone may be sensed as dialtone
  800.     JMP    DLGN4
  801. ;
  802. DLGN3    MVI    B,SMWAIT
  803.     CALL    J$TIMER
  804. ;
  805. DLGN4    CALL    CRLF        ;start a new line
  806.     JMP    DIAL5        ;redial entry point
  807. ;
  808. ; Connection has been made
  809. ;
  810. CONMD    LDA    PMMIMD
  811.     ORA    A
  812.     JZ    CONMD1
  813.     LDA    CURRENT        ;get curret baud rate
  814.     CALL    O$BAUDRP    ;set baudrate
  815. ;
  816. CONMD1    MVI    B,2
  817.     CALL    J$TIMER
  818.     CALL    J$ILPRT
  819.     DB    BELL,CR,LF,CR,LF,'     CONNECTED',0
  820.     LDA    AUTDIR        ;going direct to terminal mode?
  821.     ORA    A
  822.     JNZ    RETRN
  823.     LDA    CRFLAG        ;in continuous redial or first time try?
  824.     ORA    A
  825.     JZ    RETRN        ;go to terminal mode if first time
  826.     CALL    J$ILPRT
  827.     DB    ' - any key for terminal mode ',0
  828. ;
  829. CONMD2    MVI    E,10
  830. ;
  831. CONMD3    CALL    STAT        ;keypress?
  832.     JZ    CONMD4        ;exit if no keys pressed
  833.     CALL    KEYIN
  834.     XRA    A
  835.     JMP    RETRN        ;key pressed, go to terminal mode
  836. ;
  837. CONMD4    MVI    B,1        ;wait 0.1 second
  838.     CALL    J$TIMER
  839.     DCR    E        ;one less loop to make
  840.     JNZ    CONMD3        ;see if a keyboard character yet
  841.     MVI    A,BELL        ;sound a bell
  842.     CALL    TYPE
  843.     JMP    CONMD2        ;reset the counter
  844. ;
  845. ; Automatic dialing routine, prints the number being dialed.  If we find
  846. ; 'R', it either has to be the final character for ringback or toss it.
  847. ;
  848. DL    CALL    TYPE        ;print whatever character, dashes, etc.
  849.     CPI    'R'        ;could it be a ringback character?
  850.     JNZ    DL1        ;if not, probably a number so exit
  851.     MOV    A,E        ;get the character count.  Is this "R"
  852.     CPI    1        ;  the last character in the string?
  853.     JZ    RNGBK        ;if yes, set up ringback
  854.     RET            ;if not, ignore the 'R'
  855. ;
  856. DL1    MOV    B,A        ;store the character for now
  857.     CALL    DLD        ;check for alternate dialing like 'MCI'
  858.     MOV    A,B        ;get the original character back
  859. ;
  860. DL2    CPI    '*'        ;* is a valid dial digit
  861.     JZ    DL3
  862.     CPI    '#'        ;# is a valid dial digit
  863.     JZ    DL3
  864.     CPI    ','        ;comma indicates a short delay-time
  865.     JZ    DL3
  866.     CPI    '0'        ;digits are (0-9)
  867.     RC            ;exit less than ASCII '0'
  868.     CPI    '9'+1
  869.     RNC            ;exit if more than ASCII '9'
  870.     SUI    '0'        ;strip ASCII - could also do 'ANI 0FH'
  871.     JNZ    DL3
  872.     MVI    A,10        ;convert zero to 10 pulses
  873. ;
  874. ; Sends the digit to the modem.  Waits 100 ms. after each digit to in-
  875. ; sure it gets to the modem ok.
  876. ;
  877. DL3    MOV    C,A
  878.     LDA    PMMIMD        ;using a PMMI?
  879.     ORA    A
  880.     JNZ    DL4        ;if yes, exit
  881.     CALL    SNDCHR        ;character is already in the 'B' reg.
  882.     MVI    B,1        ;slight delay to let modem settle down
  883.     JMP    J$TIMER
  884. ;
  885. DL4    LDA    PULRATE
  886.     CALL    O$BAUDRP
  887. ;
  888. DL5    CALL    I$BAUDRP
  889.     ANI    TMPUL
  890.     JNZ    DL5
  891. ;
  892. DL6    CALL    I$BAUDRP
  893.     ANI    TMPUL
  894.     JZ    DL6
  895. ;
  896. DL7    MVI    A,MAKEM
  897.     CALL    O$MDCTL1
  898. ;
  899. DL8    CALL    I$BAUDRP
  900.     ANI    TMPUL
  901.     JNZ    DL8
  902.     MVI    A,BRKMSK
  903.     CALL    O$MDCTL1
  904. ;
  905. DL9    CALL    I$BAUDRP
  906.     ANI    TMPUL
  907.     JZ    DL9
  908.     DCR    C
  909.     JNZ    DL7
  910.     MVI    A,MAKEM
  911.     CALL    O$MDCTL1
  912.     MVI    B,2
  913.     JMP    J$TIMER
  914. ;
  915. ; Print bad library number message and abort if a null is encountered.
  916. ;
  917. DIALBD    CALL    J$ILPRT
  918.     DB    CR,LF,CR,LF,'++ Bad library number called ++',CR,LF,0
  919. ;
  920. DLXIT    CALL    CRLF        ;turn up a new line
  921. ;
  922. DLXIT1    LXI    SP,STACK    ;make sure the stack is normal again
  923. ;;;    CALL    J$GOODBY    ;user routine to disable DTR, if any
  924.     DB    0,0,0        ;(PREVENT DOUBLE TIME FOR DISCONNECT)
  925.     CALL    J$DSCONT    ;hang up the phone and reset the modem
  926. ;
  927. DLXIT2    XRA    A
  928.     STA    CRFLAG        ;reset the continuous redial flag
  929.     JMP    MENU
  930. ;
  931. ; Disconnect from the line, reconnect and wait for the dialtone.
  932. ;
  933. DIALBG    LDA    AUTDIAL        ;Hayes-type autodial modem?
  934.     ORA    A
  935.     RNZ            ;if yes, finished
  936.     MVI    A,MAKEM        ;go off-hook
  937.     CALL    O$MDCTL1
  938.     MVI    D,DTMSK        ;dial tone mask
  939.     MVI    C,50        ;waits up to 10 seconds for dial tone
  940.     CALL    WAIT        ;wait for dial tone
  941. ;
  942. ; Wait subroutine will return with carry set if unable to get dialtone.
  943. ; If carry is not set, the dialtone was received.
  944. ;
  945.     RNC            ;if dial tone within 10 seconds
  946.     CALL    J$ILPRT        ;otherwise print error message
  947.     DB    CR,LF,CR,LF,'++ NO DIAL TONE ++ ',BELL,0
  948.     POP    H        ;restore the stack to normal
  949.     JMP    DLXIT        ;forget it.
  950. ;
  951. ; Do any alternate dialing such as 'MCI' or 'SPRINT'
  952. ;
  953. DLD    LDA    AUTDIAL        ;using a Hayes-type modem?
  954.     ORA    A
  955.     RZ            ;if not, exit
  956.     LDA    TCHPUL        ;using touch tone dialing?
  957.     CPI    'T'
  958.     RNZ            ;if not, ignore
  959.     MOV    A,B        ;get the character back
  960.     CPI    '<'        ;alternate dialing system #1 (MCI?)
  961.     JNZ    DLD1        ;if not, exit
  962.     PUSH    H        ;save the current values
  963.     LXI    H,ALTDL1    ;alternate dialing area
  964.     JMP    DLD2
  965. ;
  966. DLD1    CPI    '>'        ;alternate dialing system #2 (Sprint?)
  967.     RNZ            ;if neither, exit
  968.     PUSH    H        ;save the current values
  969.     LXI    H,ALTDL2
  970. ;
  971. DLD2    MOV    A,M
  972.     CPI    '$'        ;ready to terminate?
  973.     JZ    DLD3        ;if yes, exit
  974. ;
  975. ; Move the semicolons up one line if you do not want to see the Sprint
  976. ; number dialed.
  977. ;
  978.     CALL    TYPE        ;display the character
  979. ;;;    DB    0,0,0        ;(keeps the total bytes similar)
  980.     MOV    B,A        ;need the char. in 'B' to send to modem
  981.     CALL    DL2        ;send proper characters to the modem
  982.     INX    H        ;next location
  983.     CALL    STAT        ;keypress?
  984.     JZ    DLD2        ;if not, do the next character
  985.     CALL    KEYIN        ;yes, go get it
  986.     CPI    CANCEL        ;CTL-X?
  987.     JNZ    DLD2        ;if not, handle the next character
  988.     POP    H        ;if yes, reset the stack
  989.     JMP    DLXIT        ;if yes, exit
  990. ;
  991. DLD3    MVI    A,' '
  992.     MOV    B,A        ;clears 'B' from last digit sent
  993.     CALL    TYPE
  994.     POP    H        ;restore the stack
  995.     RET
  996. ;
  997. ; Disconnect the autodial modem from the phone line.  Sends 'I, CR' to
  998. ; the Racal-Vadic to return to IDLE mode
  999. ;
  1000. GOODBY
  1001. DSCONT    LDA    AUTDIAL        ;using a Hayes-type autodial modem?
  1002.     ORA    A
  1003.     JNZ    DSCON1        ;if yes, skip PMMI section
  1004.     XRA    A
  1005.     CALL    O$MDCTL1    ;hang up
  1006.     CALL    O$MDCTL2    ;clear DAV, ESD, etc.
  1007.     PUSH    B
  1008.     MVI    B,10        ;1 second for PMMI to disconnect
  1009.     CALL    J$TIMER
  1010.     POP    B
  1011.     RET
  1012. ;
  1013. ; Disconnect the autodial modem from the phone line
  1014. ;
  1015. DSCON1    MVI    B,12        ;1.2 seconds pause
  1016.     CALL    J$TIMER
  1017.     LXI    H,SM$DISC    ;get into command mode
  1018.     CALL    SNDOUT
  1019.     MVI    B,12        ;another 1.2 seconds pause
  1020.     CALL    J$TIMER
  1021.     MVI    A,' '        ;space character
  1022. ;
  1023. ; If printing +++ and ATH, ATD, etc. move the three semicolons up one
  1024. ; line to include a space on the CRT to look better.
  1025. ;
  1026.     DB    0,0,0
  1027. ;;;    CALL    TYPE        ;show on local CRT only
  1028.     LXI    H,SM$DISC1    ;now disconnect the modem
  1029.     CALL    SNDOUT
  1030. ;
  1031. DSCON2    CALL    J$INMDM        ;wait 0.1 seconds after last character
  1032.     JNC    DSCON2
  1033.     RET
  1034. ;
  1035. ;-----------------------------------------------------------------------
  1036. ;               Hayes Stuff
  1037. ;
  1038. SMQT    LDA    SPKRFLG        ;speaker flag set to quiet?
  1039.     ORA    A
  1040.     RNZ            ;if yes, forget it
  1041.     MVI    A,YES
  1042.     STA    SPKRFLG        ;flip the flag to quiet, now
  1043.     LXI    H,SM$SOFF
  1044.     CALL    SNDOUT
  1045.     MVI    B,6
  1046.     JMP    J$TIMER        ;time for an 'OK' from modem and return
  1047. ;
  1048. SMNSY    LDA    SPKRFLG        ;speaker already turned on?
  1049.     ORA    A
  1050.     RZ            ;if yes, forget it
  1051.     MVI    A,NO        ;set for noisey, now
  1052.     STA    SPKRFLG
  1053.     LXI    H,SM$SON
  1054.     CALL    SNDOUT
  1055.     MVI    B,6
  1056.     JMP    J$TIMER
  1057. ;
  1058. ; Hayes-like autodial modem control codes
  1059. ;
  1060. SM$DIAL     DB    'ATDT $'    ;set for touch (or pulse) dialing
  1061. SM$DISC     DB    '+++$'        ;puts the modem in local command mode
  1062. SM$DISC1 DB    'ATH',CR,'$'    ;disconnects the modem
  1063. SM$SOFF     DB    'ATM0',CR,'$'    ;turns the speaker off
  1064. SM$SON     DB    'ATM1',CR,'$'    ;turns the speaker on
  1065. SPKRFLG     DB    0        ;0 = speaker has not been silenced
  1066. ;
  1067. ; Set the autodial modem for pulse dialing
  1068. ;
  1069. SMINIT    LDA    TCHPUL        ;touch or pulse dialing for autodial?
  1070.     STA    SM$DIAL+3    ;store
  1071.     LXI    H,SM$DIAL
  1072.     CALL    SNDOUT
  1073. ;
  1074. SMINT1    CALL    J$INMDM        ;wait for modem to finish, if needed
  1075.     JNC    SMINT1
  1076.     RET
  1077. ;
  1078. ; Send the string pointed to by 'HL' to both the CRT and the modem
  1079. ;
  1080. SNDOUT    CALL    SNDNOW        ;wait until modem is ready
  1081.     MOV    A,M        ;get the character
  1082.     CPI    '$'
  1083.     RZ            ;if yes, finished
  1084.     MOV    A,M
  1085.     CALL    O$MDDATP    ;send to modem
  1086. ;
  1087. ; If you want to print the +++ ATD, etc. from Hayes-type units, move the
  1088. ; three semi-colons down one line.
  1089. ;
  1090. ;;;    CALL    TYPE        ;show on CRT
  1091.     DB    0,0,0        ;(PREVENT SHOWING THE +++ ATD)
  1092.     INX    H
  1093.     JMP    SNDOUT
  1094. ;
  1095. ; Checks for answer from Hayes-type autodial modem
  1096. ;
  1097. SMRSLT    CALL    RCVRDY        ;see if any incoming character yet
  1098.     JZ    SMRSL1        ;if yes, exit and look at it
  1099.     CALL    STAT        ;else see if want to abort ringing
  1100.     JZ    SMRSLT        ;if neither, wait for one of them
  1101.     CALL    KEYIN        ;get character from keyboard
  1102.     CPI    CANCEL        ;CTL-X to terminate dialing?
  1103.     JNZ    SMRSLT        ;if not, keep going
  1104.     MVI    B,CR
  1105.     CALL    SNDCHR        ;tells the modem to hang up right away
  1106.     JMP    DLXIT        ;abort dialing routine
  1107. ;
  1108. SMRSL1    CALL    I$MDDATP    ;get the character, then
  1109.     ANI    7FH        ;remove any parity
  1110.     MOV    B,A        ;store for 'GIVLF' area if needed
  1111.     CPI    'B'        ;'BUSY' (for Anchor modems, etc.)
  1112.     JZ    BUSY        ;if busy, flush string and retry
  1113.     CPI    '0'        ;'OK' single digit result code
  1114.     JZ    SMRSL1        ;ok, loop for next response
  1115.     CPI    'O'        ;'OK' verbose digit result coe
  1116.     JZ    SMRSL1        ;ok, loop for next response
  1117.     CPI    '1'        ;'CONNECT', single digit result code
  1118.     JZ    ON$LIN        ;connected, reset redial flags
  1119.     CPI    'C'        ;'CONNECT', verbose result code
  1120.     JZ    ON$LIN        ;connected, reset redial flags
  1121.     CPI    '3'        ;'NO CARRIER', single digit result code
  1122.     JZ    NO$CAR        ;no carrier, flush string and retry
  1123.     CPI    'N'        ;'NO CARRIER', verbose result code
  1124.     JZ    NO$CAR        ;no carrier, flush string and retry
  1125.     CPI    '4'        ;'ERROR', single digit result code
  1126.     JZ    FAILED        ;error, go display
  1127.     CPI    'E'        ;'ERROR', verbose result code
  1128.     JZ    FAILED        ;error, go display
  1129.     CPI    '5'        ;'CONNECT 1200' single digit result code
  1130.     JZ    ON$120        ;connected, reset redial flags
  1131. ;
  1132. SMDM1    CPI    LF        ;<LF> is end-of-line for verbose mode
  1133.     JZ    SMRSLT        ;yes, go get the next response
  1134.     CPI    CR        ;<CR> may precede digit in digit mode
  1135.     JZ    SMRSLT        ;yes, go get the next response
  1136. ;
  1137.     CALL    STAT        ;else, see if want to abort ringing
  1138.     JZ    SMDM1A        ;if not, get next character
  1139.     CALL    KEYIN        ;else, get character from keyboard
  1140.     CPI    CANCEL        ;CTL-X to terminate dialing?
  1141.     JNZ    SMDM1A        ;if not, keep going
  1142.     MVI    B,CR
  1143.     CALL    SNDCHR        ;tells the modem to hang up right away
  1144.     JMP    DLXIT        ;abort dialing routine
  1145. ;
  1146. SMDM1A    CALL    J$INMDM        ;get next character
  1147.     JMP    SMDM1        ;loop until end of response encountered
  1148. ;
  1149. ; The Anchor modem gives a busy result code, although still waits the
  1150. ; normal time-out period to do it.
  1151. ;
  1152. BUSY    CALL    J$ILPRT
  1153.     DB    'busy! ',0
  1154.     JMP    DLGN
  1155. ;
  1156. ; Failed call is usually caused by continuous ringing with no answer.
  1157. ; The modem times out (can be set to either 30 seconds or 60 seconds.)
  1158. ;
  1159. FAILED    CALL    J$ILPRT
  1160.     DB    'abort ',0
  1161.     JMP    DLGN
  1162. ;
  1163. NO$CAR    CALL    J$ILPRT
  1164.     DB    'no carrier ',0
  1165.     JMP    DLGN
  1166. ;
  1167. ON$LIN    CALL    J$ILPRT
  1168.     DB    'on line',0
  1169.     JMP    CONMD
  1170. ;
  1171. ON$120    CALL    J$ILPRT
  1172.     DB    'on at 1200',0
  1173.     JMP    CONMD
  1174. ;
  1175. ;        end of special Hayes-like handling
  1176. ;-----------------------------------------------------------------------
  1177. ;
  1178. ; Handles the special ringback numbers.  Dials, lets it ring only once,
  1179. ; hangs up and then redials.
  1180. ;
  1181. RNGBK    LDA    AUTDIAL        ;using a Hayes-type modem?
  1182.     ORA    A
  1183.     JNZ    RNGBK2        ;if yes, ringback not possible
  1184.     LDA    CMDBUF+1    ;get the number of chars. in the buffer
  1185.     DCR    A        ;subtract 1 to avoid the ringback char
  1186.     STA    CMDBUF+1    ;store the new value
  1187.     MVI    D,DTMSK        ;load tone detect mask
  1188.     MVI    C,RBLMT        ;waits up to 7 seconds for a ring
  1189.     CALL    WAIT
  1190.     JNC    RNGBK0        ;if no ring detected, pretend we got one
  1191.     JMP    RNGBK1        ;hangup, redial, & listen for carrier
  1192. ;
  1193. RNGBK0    MVI    B,25        ;got a ring, wait 2.5 seconds
  1194.     CALL    TIMER
  1195.     CALL    I$BAUDRP    ;is tone still present?
  1196.     ANA    D
  1197.     JZ    DLGN        ;yes, must be busy, do a normal redial
  1198. ;
  1199. ; Hang up, redial and listen for dial tone
  1200. ;
  1201. RNGBK1    CALL    HANGUP        ;hang up the phone
  1202.     CALL    J$ILPRT
  1203.     DB    'ringback set, first ring ',0
  1204.     MVI    B,RBWAIT    ;wait 5 seconds before redialing
  1205.     CALL    J$TIMER        ;  for line to clear, etc.
  1206.     CALL    DIALBG        ;disconnect, reconnect, wait for tone
  1207.     JC    DLXIT
  1208.     LDA    NUMBER        ;number of characters in buffer
  1209.     CPI    1+1        ;more than one character?
  1210.     JNC    DIAL14        ;if more than one, hand-entered number
  1211.     JMP    DIAL12        ;go redial for the table ringback number
  1212. ;
  1213. RNGBK2    CALL    J$ILPRT
  1214.     DB    CR,LF,'++ No ringback for autodial modem ++',0
  1215.     POP    H        ;reset the stack
  1216.     JMP    DLXIT
  1217. ;
  1218. HANGUP    MVI    A,CLEAR
  1219.     CALL    O$MDCTL2
  1220.     XRA    A
  1221.     JMP    O$MDCTL1    ;turn off DTR, originate/answer tones
  1222. ;
  1223. ; This is the auto-linking area.  Up to 32 numbers may be linked, each
  1224. ; should have a comma for a separator, such as:
  1225. ;
  1226. ;    B>>COMMAND: CAL A,F,3,A,G,A,H
  1227. ;
  1228. AUTO    STA    AUTDIR        ;direct to terminal mode on answer
  1229. ;
  1230. AUTO1    MVI    A,0FFH        ;set the flags to -1
  1231.     STA    AUTOFL        ;set the auto-linking flag
  1232.     STA    CRFLAG        ;set the continuous redial flag
  1233.     MVI    B,64        ;maximum number of characters to move
  1234.     LXI    H,CMDBUF+1    ;start with number in the string
  1235.     LXI    D,CMDBUF+65    ;move to aft part of buffer
  1236.     JMP    MOVE        ;when finished return to caller
  1237. ;
  1238. ; Linking routine
  1239. ;
  1240. AUTO2    LDA    AUTOFL        ;increment the flag for each new try
  1241.     INR    A
  1242.     INR    A
  1243.     STA    AUTOFL
  1244.     MOV    C,A        ;hold momentarily
  1245.     MVI    B,0
  1246.     LDA    CMDBUF+65    ;see how many characters typed
  1247.     CMP    C
  1248.     JNC    AUTO3
  1249.     MVI    A,1        ;reset the flag to start over
  1250.     MOV    C,A
  1251.     STA    AUTOFL
  1252. ;
  1253. AUTO3    LXI    H,CMDBUF+65
  1254.     DAD    B
  1255.     JMP    DIAL6        ;go to work
  1256. ;
  1257. AUTDIR    DB    0        ;direct to terminal mode on answer
  1258. AUTOFL    DB    0        ;auto-linking flag
  1259. NUMBER    DB    0        ;number of characters in CMDBUF
  1260. ;
  1261. ; Time-out routine.  Must be called with mask in 'D' reg. for input at
  1262. ; relative port 2 and number of seconds (times 10) in 'C' reg.
  1263. ;
  1264. WAIT    MVI    B,2
  1265.     CALL    TIMER        ;wait for timer to go high then low
  1266.     CALL    I$BAUDRP    ;PMMIADDR+2 (modem status port)
  1267.     ANA    D        ;(CTS or dialtone mask)
  1268.     RZ            ;active low, so return on 0
  1269.     PUSH    B        ;save the registers
  1270.     PUSH    D
  1271.     CALL    STAT        ;keypress?
  1272.     JZ    WAIT1        ;if not, exit
  1273.     CALL    KEYIN        ;yes, get char
  1274.     CPI    CANCEL        ;CTL-X to intentionally abort?
  1275.     JZ    WAIT2        ;yes, disconnect, jmp to menu
  1276. ;
  1277. WAIT1    POP    D        ;restore the registers
  1278.     POP    B
  1279.     DCR    C        ;count-down
  1280.     JNZ    WAIT
  1281.     STC            ;set carry to indicate mask not set
  1282.     RET
  1283. ;
  1284. WAIT2    POP    D        ;restore the registers
  1285.     POP    B
  1286.     JMP    DONETD        ;disconnect
  1287. ;
  1288. ;=======================================================================
  1289. ;            SPECIAL PMMI MENU
  1290. ;
  1291. SPMEN    LDA    PMMIMD
  1292.     ORA    A
  1293.     RZ
  1294.     CALL    J$NXTSCR
  1295.     CALL    J$ILPRT
  1296.     DB    '        Additional Subcommands for PMMI Modems'
  1297.     DB    CR,LF,LF
  1298.     DB    '  Modem control:',CR,LF
  1299.     DB    '    A - Answer tone for send or receive',CR,LF
  1300.     DB    '    O - Originate tone for send or receive',CR,LF,LF
  1301.     DB    '  Parity option:',CR,LF
  1302.     DB    '    1 - Set and check for odd parity',CR,LF
  1303.     DB    '    0 - Set and check for even parity',CR,LF
  1304.     DB    '           Both ends must be capable of these options'
  1305.     DB    CR,LF
  1306.     DB    '           which are available only in R and S modes.'
  1307.     DB    CR,LF
  1308.     DB    '           The parity checking will be part of the'
  1309.     DB    CR,LF
  1310.     DB    '           file transfer protocol.',CR,LF,LF
  1311.     DB    '  Speed Options:',CR,LF
  1312.     DB    '        After entering your primary and secondary '
  1313.     DB    'options,',CR,LF
  1314.     DB    '        you can set the modem speed by placing a '
  1315.     DB    ' "." after',CR,LF
  1316.     DB    '        the options followed by the speed e.g., '
  1317.     DB    '300, 600.',CR,LF,LF
  1318.     DB    '        EXAMPLE:  SBO.600 will set the modem for '
  1319.     DB    '600 baud',CR,LF,0
  1320.     RET            ;all done
  1321. ;
  1322. ;=======================================================================
  1323. ;
  1324. ; Timer routine.  Waits 0.1 seconds for each unit in 'B' reg.
  1325. ;
  1326. TIMER    PUSH    H
  1327. ;
  1328. TIMER1    PUSH    B
  1329. ;
  1330. TIMER2    CALL    J$INMDM        ;100 ms. delay per loop
  1331.     JNC    TIMER2
  1332.     POP    B
  1333.     DCR    B
  1334.     JNZ    TIMER1
  1335.     POP    H
  1336.     RET
  1337. ;
  1338. ; CALCULATES DISK SPACE REMAINING IF CP/M+
  1339. ;
  1340. CKCPM3    CALL    CRLF
  1341.     MVI    C,CPMVER    ;check version #
  1342.     CALL    BDOS
  1343.     MOV    A,L
  1344.     CPI    30H        ;version 3.0?
  1345.     RC            ;use normal method if not CP/M 3.0
  1346.     POP    H        ;remove 'CALL CKCPM3' from stack
  1347.     MVI    C,CURDSK
  1348.     CALL    BDOS
  1349.     MOV    E,A
  1350.     MVI    C,46        ;CP/M 3.0 compute free space call
  1351.     CALL    BDOS
  1352.     MVI    C,3        ;answer is 3 bytes long (24 bits)
  1353. ;
  1354. FREE30    LXI    H,TBUF+2    ;answer is located here
  1355.     MVI    B,3        ;convert to 'K' length
  1356.     ORA    A
  1357. ;
  1358. FREE31    MOV    A,M
  1359.     RAR
  1360.     MOV    M,A
  1361.     DCX    H
  1362.     DCR    B
  1363.     JNZ    FREE31        ;loop for 3 bytes
  1364.     DCR    C
  1365.     JNZ    FREE30        ;shift 3 times
  1366.     LHLD    TBUF        ;get result in 'K'
  1367.     JMP    PRTFREE        ;display result
  1368. ;
  1369. ;=======================================================================
  1370. ;
  1371.     ORG    (($+255+50)/256*256)-50    ;so 'NUMLIB' starts on even page
  1372. ;
  1373. ;-----------------------------------------------------------------------
  1374. ;
  1375. ; Long distance alternate dialing such as MCI, SPRINT, etc.  Must end
  1376. ; with a '$', use as many commas (2 seconds delay, each) as needed to
  1377. ; let the alternate dialing code return with a new dial tone.  Fill in
  1378. ; any character (periods are fine) after the $ to keep number of columns
  1379. ; to 24, i.e.,    '1234567,,,,12345,,$.....'   --   the first group is the
  1380. ; MCI or SPRINT access number, the second group is the user number.  A
  1381. ; small delay is usually required after the billing number also.
  1382. ;
  1383. ALTDL1    DB    'xxxxxxx,,,,,,xxxxxxxx,,$'    ;accessed by a < character
  1384. ;
  1385. ALTDL2    DB    'xxxxxxx,,,,,,xxxxxxxx,,$'    ;accessed by a > character
  1386. ;
  1387. ;=======================================================================
  1388. ;
  1389. HEXSHO    DB    SHOWHEX        ;can easily change SHOWHEX via DDT
  1390. ;
  1391. SAVSIZ    DB    XFRSIZ*8    ;can easily change buffer size for file
  1392.                 ;transfers with DDT for "NUMLIB-1" ad-
  1393.                 ;dress.  Normally 4k (32 records or 4k).
  1394. ;
  1395. ;=======================================================================
  1396. ;
  1397. ; Phone number library table for auto-dialing.    Each number must be as
  1398. ; long as"LIBLEN" (EQU at start of program).  Some areas require extra
  1399. ; characters such as:    1-313-846-7127.  Room is left for those.  Use
  1400. ; a (<) for alternate dialing system #1, and a (>) for alternate dialing
  1401. ; System #2.  Either would preceed the actual number, for example:
  1402. ;
  1403. ;    DB    'A=Alan Alda..........<123-456-7890'    ;'A'
  1404. ;
  1405. ; -    -     -     -      -    -     -     -      -    -     -     -
  1406. ;
  1407. ; NOTE: At least one dot (.) MUST precede the actual phone number
  1408. ;
  1409. ;        '----5---10---15---20---25---30--34'
  1410. NUMLIB    DB    'A=Bob Robesky.......1-209-227-2083'    ;'A'
  1411.     DB    'B=Byron McKay.......1-415-965-4097'    ;'B'
  1412.     DB    'C=Chuck Metz........1-408-354-5934'    ;'C'
  1413.     DB    'D=Bruce Jorgens.....1-509-255-6324'    ;'D'
  1414.     DB    'E=Bill Earnest......1-215-398-3937'    ;'E'
  1415.     DB    'F=Chuck Forsberg....1-503-621-3193'    ;'F'
  1416.     DB    'G=Ron Fowler........1-414-563-9932'    ;'G'
  1417.     DB    'H=Kirk De Haan......1-408-296-5078'    ;'H'
  1418.     DB    'I=Jack Kinn.........1-817-547-8890'    ;'I'
  1419.     DB    'J=Walt Jung.........1-301-661-2175'    ;'J'
  1420.     DB    'K=Keith Petersen....1-313-759-6569'    ;'K'
  1421.     DB    'L=Larry Snyder......1-305-671-2330'    ;'L'
  1422.     DB    'M=Wayne Masters.....1-408-378-7474'    ;'M'
  1423.     DB    'N=Dick Mead.........1-213-799-1632'    ;'N'
  1424.     DB    'O=Al Mehr...........1-408-238-9621'    ;'O'
  1425.     DB    'P=Pasadena RBBS.....1-213-577-9947'    ;'P'
  1426.     DB    'Q=Mark Pulver.......1-312-789-0499'    ;'Q'
  1427.     DB    'R=Bruce Ratoff......1-201-272-1874'    ;'R'
  1428.     DB    'S=Ken Stritzel......1-201-584-9227'    ;'S'
  1429.     DB    'T=TCBBS, Dearborn...1-313-846-6127'    ;'T'
  1430.     DB    'U=AnaHUG RCPM.......1-714-774-7860'    ;'U'
  1431.     DB    'V=Dave Austin.......1-707-257-6502'    ;'V'
  1432.     DB    'W=Bill Wood.........1-619-256-3914'    ;'W'
  1433.     DB    'X=Charlie Hoffman...1-813-831-7276'    ;'X'
  1434.     DB    'Y=Byron Kantor......1-619-273-4354'    ;'Y'
  1435.     DB    'Z=Spare.............1-xxx-xxx-xxxx'    ;'Z'
  1436.     DB    '0=Paul Bagdonovich..1-201-747-7301'    ;'0'
  1437.     DB    '1=Bill Parrott......1-913-682-3328'    ;'1'
  1438.     DB    '2=Alex Soya.........1-305-676-3573'    ;'2'
  1439.     DB    '3=Tony Stanley......1-912-929-8728'    ;'3'
  1440.     DB    '4=Tampa Bay Bandit..1-813-937-3608'    ;'4'
  1441.     DB    '5=Thousand Oaks.....1-805-492-5472'    ;'5'
  1442.     DB    '6=Spare.............1-xxx-xxx-xxxx'    ;'6'
  1443.     DB    '7=Spare.............1-xxx-xxx-xxxx'    ;'7'
  1444.     DB    '8=Spare.............1-xxx-xxx-xxxx'    ;'8'
  1445.     DB    '9=Spare.............1-xxx-xxx-xxxx'    ;'9'
  1446.     DB    0    ;end
  1447. ;        '----5---10---15---20---25---30--34'
  1448. ;
  1449. ;-----------------------------------------------------------------------
  1450. ;
  1451. ; This is the storage area for the ten function keys.  The M7FNK.COM
  1452. ; program dynamically allocates the storage for the keys.  Thus, no
  1453. ; function key is limited to so-and-so many characters.  Rather, the
  1454. ; total number of bytes in the function key library (including flags)
  1455. ; is 256.
  1456. ;
  1457. INTCPT    DB    '^'        ;intercept character (prefix)
  1458. ;
  1459. FNCTBL    DB    0,'DIR ',CR,0
  1460.     DB    1,'DIR *.* $U0AD ',CR,0
  1461.     DB    2,'XMODEM S ',0
  1462.     DB    3,'XMODEM R ',0
  1463.     DB    4,'BYE ',CR,0
  1464.     DB    5,'RBBS ',CR,0
  1465.     DB    6,'(vacant)',0
  1466.     DB    7,'(vacant)',0
  1467.     DB    8,'(vacant)',0
  1468.     DB    9,'Nice chatting, see you again soon... ',CR,0
  1469.     DS    256-($-FNCTBL)
  1470. ;
  1471. ;
  1472. ;********************************************************************
  1473. ;    PROGRAM STARTS HERE
  1474. ;********************************************************************
  1475. ;
  1476. START    LXI    H,0
  1477.     DAD    SP        ;add the current stack pointer to 'HL'
  1478.     SHLD    STACK
  1479.     LXI    SP,STACK    ;start local stack
  1480. ;
  1481. ; The 'FIXCNT' calculations are done here and the values stored so the
  1482. ; overhead of doing the calculation is not incurred in the RECV routine
  1483. ; where it is desired to pick up a character from the modem data port as
  1484. ; quickly as possible.
  1485. ;
  1486.     LXI    H,624        ;adjust to get 1 second time intervals
  1487.     CALL    FIXCNT
  1488.     SHLD    TIMVAL
  1489.     LXI    H,39        ;should be 1/16 of above value
  1490.     CALL    FIXCNT
  1491.     SHLD    QUIKTIM
  1492. ;
  1493. ; Now display the program name and version number and we are under way
  1494. ;
  1495.     CALL    ILPRT
  1496.     DB    CR,LF,'MODM',VERSION/100+'0',VERSION MOD 100/10+'0'
  1497.     DB    VERSION MOD 10+'0','  (type M for Menu)',CR,LF,0
  1498.     CALL    J$SYSVR        ;give configuration message
  1499.     CALL    CRCGN        ;generate tables for fast 'CRC' check
  1500.     CALL    INITAD        ;initialize addresses
  1501.     CALL    INTRCPT        ;establish the function key intercept
  1502.     CALL    PROCOPT        ;process any options
  1503.     LDA    OPTION        ;any options on the command line?
  1504.     CPI    ' '+1
  1505.     JC    MENU        ;if not, show the menu
  1506. ;
  1507. ; Comes here from menu once the options have been set
  1508. ;
  1509. RSTRT    LXI    SP,STACK    ;make sure we have a clean stack
  1510.     CALL    CKCHAR        ;catch any garbage characters left over
  1511.     LDA    PMMIMD
  1512.     ORA    A
  1513.     JNZ    RSTRT1        ;if yes, accept 'C' or 'D'
  1514.     LDA    AUTDIAL        ;using a Hayes-type modem?
  1515.     ORA    A
  1516.     JZ    RSTRT2        ;exit if neither modem-type
  1517. ;
  1518. RSTRT1    LDA    OPTION        ;get the option
  1519.     CPI    'C'        ;call (dial) function?
  1520.     JZ    J$DIAL        ;yes, go to it
  1521.     LDA    PMMIMD
  1522.     ORA    A
  1523.     CNZ    STBAUD        ;just the PMMI has to check each time
  1524. ;
  1525. RSTRT2    CALL    MOVEFCB
  1526.     LDA    OPTION        ;get main option
  1527.     CPI    'D'        ;disconnect?
  1528.     JZ    DONETD        ;yes, disconnect then back to the menu
  1529.     CPI    'M'        ;menu asked for?
  1530.     JZ    MENU2        ;go display the menu
  1531.     CPI    'R'        ;want to receive a file?
  1532.     JZ    RCVFL        ;exit if yes
  1533.     CPI    'S'        ;want to send a file?
  1534.     JZ    SNDFL        ;exit if yes
  1535.     CPI    'T'        ;want terminal mode?
  1536.     JNZ    RSTRT3        ;if not, exit
  1537.     XRA    A
  1538.     STA    ECHOFLG        ;reset echo flag
  1539.     STA    LOCFLG        ;reset local flag
  1540.     JMP    DSKSV        ;exit if yes
  1541. ;
  1542. RSTRT3    CPI    'E'        ;want echo mode?
  1543.     JNZ    NOECHO        ;if not, exit
  1544.     STA    ECHOFLG        ;set the echo flag
  1545.     XRA    A
  1546.     STA    LOCFLG        ;reset local flag
  1547.     JMP    DSKSV
  1548. ;
  1549. NOECHO    CPI    'L'        ;want local echo mode?
  1550.     JNZ    NOLOCL        ;if not, exit
  1551.     STA    LOCFLG        ;set the local flag
  1552.     XRA    A
  1553.     STA    ECHOFLG        ;reset echo flag
  1554.     JMP    DSKSV
  1555. ;
  1556. NOLOCL    CALL    NVLDMS        ;say not a valid option
  1557.     JMP    MENU        ;then go back to the command mode
  1558. ;
  1559. INITAD    LHLD    0000H+1        ;BIOS warm reboot jump vector
  1560.     LXI    D,3
  1561.     DAD    D
  1562.     SHLD    VSTAT+1        ;BIOS console status jump vector
  1563.     DAD    D
  1564.     SHLD    VKEYIN+1    ;BIOS console keyboard jump vector
  1565.     DAD    D
  1566.     SHLD    VTYPE+1        ;BIOS console CRT jump vector
  1567.     LXI    D,33
  1568.     DAD    D
  1569.     SHLD    GOLIST+1    ;BIOS list device status jump vector
  1570.     CALL    GETUSER        ;get current user number
  1571.     STA    OLDUSER        ;save to restore upon exit
  1572.     CALL    GTMAX        ;find maximum ram for printer use
  1573.     JMP    J$INITMD    ;initialize non-PMMI systems if needed
  1574. ;
  1575. ; Get the function key intercept character and put in appropriate places
  1576. ;
  1577. INTRCPT    LDA    INTCPT        ;get the function key intercept char.
  1578.     ANI    07FH        ;strip off any parity
  1579.     STA    GTCMD1+1    ;store in the menu area
  1580.     CPI    ' '        ;printing character?
  1581.     JNC    INTER2        ;if yes, exit
  1582.     ADI    40H        ;change to printing character
  1583.     JMP    FIXFNK        ;fix-patch area of extra bytes
  1584. ;
  1585. INTER1    MVI    A,'^'
  1586.     STA    MENU3        ;store the "control-" character
  1587.     RET
  1588. ;
  1589. INTER2    STA    MENU3+1
  1590.     RET
  1591. ;
  1592. ; Process any options - put 0 in appropriate place in option table if
  1593. ; option is selected
  1594. ;
  1595. PROCOPT    LXI    D,FCB+1
  1596.     LDAX    D
  1597.     STA    OPTION
  1598.     CPI    ' '        ;exit if no options
  1599.     RZ
  1600. ;
  1601. OPTLP    INX    D
  1602.     LDAX    D
  1603.     CPI    ' '
  1604.     JZ    ENDOPT
  1605.     LXI    H,OPTBL
  1606.     MVI    B,OPTBE-OPTBL
  1607. ;
  1608. OPTCK    CMP    M
  1609.     JNZ    OPTNO
  1610.     CPI    'O'        ;want originate tones?
  1611.     MOV    B,A        ;store momentarily
  1612.     MVI    A,ORIGMOD
  1613.     JZ    OPTCK1
  1614.     MOV    A,B        ;get the option back
  1615.     CPI    'A'        ;want answer tones?
  1616.     JNZ    OPTCK2        ;if not, exit
  1617.     MVI    A,ANSWMOD
  1618. ;
  1619. OPTCK1    STA    UARTCT
  1620. ;
  1621. OPTCK2    MVI    M,0
  1622.     JMP    OPTLP
  1623. ;
  1624. OPTNO    INX    H
  1625.     DCR    B
  1626.     JNZ    OPTCK
  1627.     CALL    NVLDMS
  1628.     POP    H        ;preserve stack
  1629.     JMP    MENU
  1630. ;
  1631. ENDOPT    LDA    VSEEFLG
  1632.     ORA    A
  1633.     JNZ    CKOPT
  1634.     STA    QFLG        ;quiet mode for watching data items
  1635. ;
  1636. CKOPT    LDA    OPTION        ;check on the primary option
  1637.     CPI    'D'        ;going to disconnect?
  1638.     RZ
  1639.     CPI    'E'        ;return if echo option
  1640.     RZ
  1641.     CPI    'M'        ;return if help option
  1642.     RZ
  1643.     CPI    'L'        ;return if local echo option
  1644.     RZ
  1645.     CPI    'T'        ;return if terminal mode
  1646.     RZ
  1647.     MOV    B,A        ;save the primary option for a moment
  1648.     LDA    PMMIMD        ;PMMI modem?
  1649.     ORA    A
  1650.     JNZ    CKOPT0        ;if yes, accept 'C'
  1651.     LDA    AUTDIAL        ;using a Hayes-type modem?
  1652.     ORA    A
  1653.     JZ    CKOPT1        ;exit if neither
  1654. ;
  1655. CKOPT0    MOV    A,B        ;get the character back
  1656.     CPI    'C'        ;going to call a number now?
  1657.     RZ
  1658. ;
  1659. CKOPT1    LDA    NFILFLG        ;saving memory for disk file?
  1660.     ORA    A
  1661.     JZ    CKOPT2        ;if not, continue
  1662.     POP    H        ;reset the stack from 'CALL PROCOPT'
  1663.     JMP    MENU0        ;go show the 'FILE OPEN' message
  1664. ;
  1665. CKOPT2    MOV    A,B        ;get the option back
  1666.     CPI    'S'
  1667.     JZ    CKFILE
  1668.     CPI    'R'
  1669.     JNZ    BDOPT        ;none of these, bad option
  1670.     LDA    BCHFLG        ;see if the batch mode flag is set
  1671.     ORA    A
  1672.     RZ            ;if yes, exit
  1673. ;
  1674. CKFILE    LDA    FCB+17        ;'S' and 'R' need a file name
  1675.     CPI    ' '
  1676.     RNZ            ;exit if a file name is present
  1677. ;
  1678. REENT    CALL    ILPRT
  1679.     DB    '++ Enter primary option plus file name ++'
  1680.     DB    CR,LF,BELL,0
  1681.     POP    H        ;reset stack from 'CALL STFCB
  1682.     JMP    MENU        ;abort to command line
  1683. ;
  1684. BDOPT    CALL    ILPRT
  1685.     DB    CR,LF,'++ Bad option ++',CR,LF,LF,0
  1686. ;
  1687. ; Check for any garbage characters on line - catch and ignore
  1688. ;
  1689. CKCHAR    CALL    RCVRDY        ;any characters ready to receive?
  1690.     RNZ            ;if not, return
  1691.     CALL    I$MDDATP    ;otherwise get the character and ignore
  1692.     JMP    CKCHAR        ;check for any additional characters
  1693. ;
  1694. ; Revised terminal routine allowing memory save.  First checks for bad
  1695. ; options, to prevent wiping out the disk with accidental memory save.
  1696. ;
  1697. DSKSV    LDA    BCHFLG        ;batch flag set?
  1698.     ORA    A
  1699.     JNZ    DSKSV1        ;if not set, everything is normal
  1700.     MVI    A,'B'        ;if set, shouldn't be, so reset it
  1701.     STA    BCHFLG
  1702.     JMP    NOTVLD        ;if set, error for 'E', 'L' or 'T'
  1703. ;
  1704. DSKSV1    STA    XFLG        ;will use the ASCII capture buffer size
  1705.     LDA    NFILFLG        ;already saving for a file?
  1706.     ORA    A
  1707.     JZ    DSKSV2        ;exit if not, and open a file
  1708.     CALL    BUFMS        ;tell if buffer if on or off
  1709.     JMP    TERM
  1710. ;
  1711. DSKSV2    LDA    FCB+1        ;first character of filename (if any)
  1712.     CPI    ' '        ;file specified?
  1713.     JNZ    GOODNM        ;yes, good name
  1714.     XRA    A
  1715.     STA    NFILFLG        ;show no file being saved
  1716.     STA    SAVEFLG        ;reset the flag to zero
  1717.     JMP    TERM
  1718. ;
  1719. GOODNM    CALL    ERASF
  1720.     LXI    H,FCB3
  1721.     CALL    INITFCB
  1722.     LXI    H,FCB        ;move the disk name into FCB3 area
  1723.     LXI    D,FCB3
  1724.     MVI    B,12
  1725.     CALL    MOVE
  1726.     LXI    D,FCB3        ;now make a file from that name
  1727.     MVI    C,MAKE
  1728.     CALL    BDOS
  1729.     LXI    D,FCB3        ;now open the file from FCB3
  1730.     MVI    C,OPEN
  1731.     CALL    BDOS
  1732.     LXI    H,BUFFER    ;reset pointers to start of buffer
  1733.     SHLD    HLSAV
  1734.     MVI    A,1
  1735.     STA    NFILFLG        ;show now saving to memory for disk file
  1736.     CALL    BUFMS2        ;show buffer is available
  1737. ;
  1738. TERM    LDA    LSTTST        ;allowing the printer to be used?
  1739.     ORA    A
  1740.     CNZ    GOLIST        ;if yes, see if anything to print
  1741.     CALL    STAT        ;keyboard have a character?
  1742.     JZ    TERML        ;if not, see if any incoming
  1743.     CALL    KEYIN        ;get character from keyboard
  1744.     MOV    B,A        ;save for now to protect 'A' reg.
  1745.     CPI    RUB        ;test for rub
  1746.     JNZ    NOTRUB        ;exit if not
  1747.     LDA    CONVRUB        ;convert rub to backspace?
  1748.     ORA    A
  1749.     JZ    NOTRUB        ;exit if no conversion
  1750.     MVI    B,BKSP        ;call it a backspace
  1751.     JMP    NTOG        ;go send a backspace
  1752. ;
  1753. NOTRUB    LDA    FNKFLG        ;get function key active flag
  1754.     ORA    A
  1755.     JZ    NOF        ;if not set yet, exit
  1756.     MOV    A,B        ;get character
  1757.     CPI    '0'
  1758.     JC    NOFNK1        ;ignore invalid key codes
  1759.     CPI    '9'+1
  1760.     JNC    NOFNK1
  1761.     ANI    0FH        ;make 0..9
  1762.     JMP    SNDFK
  1763. ;
  1764. NOF    LDA    INTCPT        ;check intercept character
  1765.     CMP    B
  1766.     JNZ    NOFNK1        ;skip if no function key
  1767.     STA    FNKFLG        ;set the function flag
  1768.     JMP    TERML        ;do not send the intercept character
  1769. ;
  1770. NOFNK1    XRA    A        ;reset the flag
  1771.     STA    FNKFLG
  1772.     LDA    EXACFLG
  1773.     ORA    A        ;exact?
  1774.     MVI    A,0        ;(cannot use 'XRA A' here)
  1775.     STA    EXACFLG        ;clear for next time
  1776.     JZ    NTEXAF        ;go if EXACFLG not set 'YES'
  1777.     LDA    LOCNXT
  1778.     ORA    A        ;should we send on exacflg?
  1779.     JZ    NTOG        ;jump if LOCONEXTCHR 'NO'
  1780.     LDA    EXTCHR        ;we want to send EXTCHR in any case
  1781.     CMP    B
  1782.     JZ    NTOG        ;send if EXTCHR
  1783.     JMP    LOCCHK        ;otherwise do local stuff
  1784. ;
  1785. NTEXAF    LDA    EXTCHR        ;treat next character in special way?
  1786.     CMP    B        ;check against this control character
  1787.     JNZ    NTEXA1        ;yes, set exacflg for next character
  1788.     MVI    A,1
  1789.     STA    EXACFLG        ;set the flag
  1790.     JMP    TERM        ;do not send, get next character
  1791. ;
  1792. NTEXA1    LDA    LOCNXT
  1793.     ORA    A        ;should we send if not EXACFLG?
  1794.     JNZ    NTOG        ;jump if loconextchr 'YES'
  1795. ;
  1796. LOCCHK    CALL    XITST1        ;want to exit to menu?
  1797.     LDA    NOCONCT        ;want to disconnect from line?
  1798.     CMP    B
  1799.     JZ    DONETD        ;if yes go disconnect
  1800.     LDA    TRANCHR        ;output text file to remote?
  1801.     CMP    B
  1802.     JZ    TRNSFR
  1803.     LDA    TRANLOG
  1804.     ORA    A
  1805.     JZ    SKPLOG
  1806.     LDA    LOGCHR        ;send logon?
  1807.     CMP    B
  1808.     JZ    SNDLOG
  1809. ;
  1810. SKPLOG    LDA    LSTTST        ;going to use the external printer?
  1811.     ORA    A
  1812.     JZ    NOLST        ;if not, skip this area
  1813.     LDA    LSTCHR        ;get the printer control-character
  1814.     CMP    B        ;did we just ask for printer control?
  1815.     JNZ    NOLST        ;if not, exit
  1816.     LDA    LISTFLG        ;otherwise reset the printer toggle
  1817.     CMA
  1818.     STA    LISTFLG        ;and store
  1819.     CALL    CRLF
  1820.     CALL    CRLF
  1821.     CALL    LSTMS        ;tell if printer is on or off now
  1822.     CALL    CRLF
  1823.     JMP    TERML        ;back to the terminal mode again
  1824. ;
  1825. NOLST    LDA    BRKCHR        ;PMMI break?
  1826.     CMP    B
  1827.     JZ    BREAK
  1828.     LDA    PMMIMD        ;using a PMMI board?
  1829.     ORA    A
  1830.     JZ    NOLST1        ;if not, skip the next few lines
  1831.     LDA    CHGBAUD        ;PMMI change baud?
  1832.     CMP    B
  1833.     PUSH    PSW
  1834.     PUSH    H
  1835.     CZ    J$NWBAU
  1836.     POP    H
  1837.     POP    PSW
  1838.     JZ    TERML
  1839. ;
  1840. NOLST1    LDA    UNSAVCH        ;close input buffer?
  1841.     CMP    B
  1842.     JZ    NOLST2        ;if yes, disable copy
  1843.     LDA    SAVECHR        ;open input buffer?
  1844.     CMP    B
  1845.     JNZ    NTOG
  1846.     LDA    NFILFLG        ;do not allow save if flag is set
  1847.     ORA    A
  1848.     JZ    TERML
  1849.     JMP    NOLST3
  1850. ;
  1851. NOLST2    XRA    A        ;stop copy into file
  1852. ;
  1853. NOLST3    STA    SAVEFLG
  1854.     CALL    BUFMS
  1855.     JMP    TERM        ;get next character
  1856. ;
  1857. ;***********************************************************************
  1858. ;             SEND A CP/M FILE
  1859. ;***********************************************************************
  1860. ;
  1861. SNDFL    XRA    A        ;set to checksum initially on send
  1862.     STA    CRCFLAG        ;  initially on send
  1863.     CALL    CKCHAR        ;catch any garbage characters
  1864. ;
  1865. SNDFL1    LDA    BCHFLG        ;check if multiple file
  1866.     ORA    A        ;  mode is set.
  1867.     JNZ    SNDC1
  1868.     CALL    ILPRT
  1869.     DB    'Ready to send in batch mode',CR,LF,0
  1870. ;
  1871. SNDFL2    CALL    J$PRITY
  1872.     MVI    A,YES        ;indicate send for batch mode
  1873.     STA    SNDFLG
  1874.     LDA    FSTFLG        ;if first time through
  1875.     ORA    A        ;  scan the command line
  1876.     CZ    TNMBUF        ;  for multiple names
  1877.     CALL    SNDFN        ;sends file name to receive
  1878.     PUSH    PSW
  1879.     CALL    CRLF
  1880.     CALL    SHOFIL
  1881.     MVI    A,' '
  1882.     CALL    TYPE
  1883.     POP    PSW
  1884.     JNC    SNDC2        ;carry set means no more files
  1885.     MVI    A,'B'        ;stop batch
  1886.     STA    BCHFLG        ;mode option
  1887.     MVI    A,EOT        ;final transfer end
  1888.     CALL    SND
  1889.     JMP    DONE
  1890. ;
  1891. SNDC1    LDA    FCB+1
  1892.     CPI    ' '
  1893.     JZ    BLKFILE
  1894. ;
  1895. SNDC2    CALL    CNREC        ;get number of records
  1896.     CALL    OPENFIL
  1897.     MVI    E,120        ;wait 2 minutes maximum
  1898.     CALL    WAITNAK
  1899. ;
  1900. SNDLP    CALL    CKABORT        ;want to terminate while sending file?
  1901.     CALL    RDRECD
  1902.     JC    SNDEOF
  1903.     CALL    INCRRNO
  1904.     MVI    A,1
  1905.     STA    ERRCT
  1906. ;
  1907. SNDRPT    CALL    CKABORT        ;want to terminate while sending file?
  1908.     CALL    SNDHDR
  1909.     CALL    SNDREC
  1910.     LDA    CRCFLAG
  1911.     ORA    A
  1912.     CZ    SNDCKS
  1913.     CNZ    SNDCRC
  1914.     CALL    GTACK
  1915.     JC    SNDRPT
  1916.     JMP    SNDLP
  1917. ;
  1918. SNDEOF    MVI    A,EOT
  1919.     CALL    SND
  1920.     CALL    GTACK
  1921.     JC    SNDEOF
  1922.     JMP    DONE
  1923. ;
  1924. ;***********************************************************************
  1925. ;               RECEIVE A CP/M FILE
  1926. ;***********************************************************************
  1927. ;
  1928. RCVFL    LDA    CRCDFLT        ;get mode requested by operator
  1929.     STA    CRCFLAG        ;store it
  1930. ;
  1931. RCVFL1    CALL    J$PRITY
  1932.     LDA    BCHFLG        ;check if multiple file mode
  1933.     ORA    A
  1934.     JNZ    RCVC1        ;if not, exit
  1935.     MVI    A,NO        ;flag where to return
  1936.     STA    SNDFLG        ;  for next file transfer
  1937.     CALL    GETFN        ;get the file name
  1938.     JNC    RCVC2        ;carry set means no more files
  1939.     MVI    A,'B'        ;stop batch
  1940.     STA    BCHFLG        ;mode option
  1941.     JMP    DONE
  1942. ;
  1943. RCVC1    LDA    FCB+1        ;make sure file is named
  1944.     CPI    ' '
  1945.     JZ    BLKFILE
  1946.     JMP    RCVC3
  1947. ;
  1948. RCVC2    CALL    SHOFIL        ;show the file name
  1949.     MVI    A,' '
  1950.     CALL    TYPE
  1951.     CALL    SNDPRG        ;get progress and wait for quiet line
  1952.     CALL    CKCPM2
  1953.     CALL    CRLF
  1954.     CALL    CKBAKUP
  1955. ;
  1956. RCVC3    CALL    ERASF
  1957.     CALL    MAKEFIL
  1958.     CALL    WAITQ1
  1959.     LDA    BCHFLG        ;do not print message if in batch mode
  1960.     ORA    A
  1961.     JZ    RCVFST
  1962.     CALL    ILPRTQ
  1963.     DB    'File open, ready to receive',CR,LF,0
  1964. ;
  1965. RCVFST    LDA    CRCFLAG
  1966.     ORA    A
  1967.     JZ    RCVNKM        ;if in 'CRC' mode
  1968.     CALL    ILPRTQ        ;then say so
  1969.     DB    'CRC in effect',CR,LF,0
  1970.     MVI    A,CRC
  1971.     JMP    RCVLP0
  1972. ;
  1973. RCVNKM    CALL    ILPRTQ        ;else say 'CHECKSUM' mode
  1974.     DB    'Checksum in effect',CR,LF,0
  1975.     MVI    A,NAK
  1976. ;
  1977. RCVLP0    PUSH    PSW
  1978.     CALL    ILPRT
  1979.     DB    'Waiting.....',0
  1980. ;
  1981. NOPRG    POP    PSW
  1982.     CALL    SND
  1983. ;
  1984. RCVLP    CALL    RCVRECD
  1985.     JC    RCVEOT
  1986.     CALL    REPORT        ;show record received if not in quiet
  1987.     CALL    WRRECD
  1988.     CALL    INCRRNO
  1989.     CALL    SNDACK
  1990.     JMP    RCVLP
  1991. ;
  1992. RCVEOT    CALL    WRBLOCK
  1993.     CALL    SNDACK
  1994.     CALL    CLOSFIL
  1995.     JMP    DONE
  1996. ;
  1997. SNDACK    MVI    A,ACK
  1998.     CALL    SND
  1999.     RET
  2000. ;
  2001. ;=================== FILE TRANSFER IN T-MODE ===========================
  2002. ;
  2003. ; File transfer routine - called with CTL-T from terminal mode.  Trans-
  2004. ; fer may be cancelled while sending, by using CTL-X.
  2005. ;
  2006. TRNSFR    LXI    H,FCB4
  2007.     CALL    INITFCB        ;initializes FCBs pointed
  2008.     LXI    H,FCB+16    ;  to by 'HL' register
  2009.     CALL    INITFCB
  2010. ;
  2011. ; Get name of file to send in "T" (terminal) mode
  2012. ;
  2013. GET    CALL    ILPRT
  2014.     DB    CR,LF,'File name to send? (CR to abort): ',0
  2015.     LXI    D,CMDBUF
  2016.     CALL    INBUF
  2017.     LDA    CMDBUF+2    ;was file entered?
  2018.     CPI    ' '
  2019.     JZ    RETRN        ;if not probably wanted to quit
  2020.     LXI    D,CMDBUF
  2021.     LXI    H,FCB4
  2022.     CALL    CMDLINE
  2023.     LXI    D,FCB4
  2024.     MVI    C,OPEN
  2025.     CALL    BDOS
  2026.     CPI    0FFH        ;return with 0FFH means 'NO SUCH FILE'
  2027.     JZ    TRANSL
  2028.     LDA    XONWAIT        ;waiting for X-on to send next line?
  2029.     ORA    A
  2030.     JNZ    DLYSAV        ;if yes, skip additional delays
  2031. ;
  2032. ; Choice of normal speed or delays between characters / lines
  2033. ;
  2034.     CALL    ILPRT
  2035.     DB    'Want to include time delays? (Y/N): ',0
  2036.     CALL    KBDCHR
  2037.     CPI    'N'        ;if 'N' send normal speed
  2038.     JZ    DLYSAV
  2039.     XRA    A        ;otherwise use character/line delays
  2040. ;
  2041. DLYSAV    STA    DLYFLG        ;store the decision
  2042.     CALL    CRLF
  2043.     LXI    D,CMDBUF+2    ;make sure cmdbuf has been selected
  2044.     MVI    C,STDMA
  2045.     CALL    BDOS
  2046. ;
  2047. ; Get 128-byte record
  2048. ;
  2049. READM    LXI    D,FCB4
  2050.     MVI    C,READ
  2051.     CALL    BDOS
  2052.     ORA    A        ;check for a good read
  2053.     JZ    READM1
  2054.     DCR    A        ;check for end of file to send
  2055.     JZ    RETRNS
  2056.     CALL    ERXIT        ;neither of those, was a read error
  2057.     DB    '++ DISK READ ERROR ++','$'
  2058. ;
  2059. ; Successful read, so send the record
  2060. ;
  2061. READM1    CALL    SND80C        ;send one 128-char record
  2062.     CPI    EOFCHAR        ;end of file - omit if object
  2063.     JZ    RETRNS        ;  code is to be sent.
  2064.     CPI    CANCEL        ;cancellation?
  2065.     JNZ    READM
  2066. ;
  2067. RETRN    CALL    ILPRT
  2068.     DB    CR,LF,LF,'(in Terminal-mode now)',CR,LF,LF,0
  2069.     CALL    SNDNOW        ;insures last character is finished
  2070.     CALL    CKCHAR        ;catch any echo character on line
  2071.     JMP    TERM        ;finished, back to t-mode
  2072. ;
  2073. RETRNS    CALL    ILPRT
  2074.     DB    CR,LF,'[Transfer completed]',0
  2075.     JMP    RETRN
  2076. ;
  2077. TRANSL    CALL    ILPRT
  2078.     DB    CR,LF,BELL,'++ FILE NAME ERROR ++ ',CR,LF,0
  2079.     JMP    GET
  2080. ;
  2081. ; Send one 128-byes record
  2082. ;
  2083. SND80C    MVI    B,128        ;will send a maximum of 128 character
  2084.     LXI    H,CMDBUF+2    ;they are in the cmdbuf area
  2085. ;
  2086. SNDCH1    PUSH    D
  2087.     CALL    SPEED        ;0-90 ms. delay between characters
  2088.     POP    D
  2089.     MOV    A,M
  2090.     CPI    EOFCHAR
  2091.     RZ
  2092.     CALL    MDOUT        ;send the character to modem
  2093.     CALL    STAT        ;test to see if
  2094.     ORA    A        ;cancellation requested
  2095.     JZ    SKIP1
  2096.     CALL    KEYIN
  2097.     CPI    CANCEL
  2098.     RZ
  2099. ;
  2100. SKIP1    INX    H
  2101.     DCR    B
  2102.     JNZ    SNDCH1
  2103.     RET
  2104. ;
  2105. ; Send the character to the output
  2106. ;
  2107. MDOUT    PUSH    PSW        ;save the character so can use 'A' reg.
  2108.     CPI    LF
  2109.     JNZ    MDOUTL
  2110.     LDA    ADDLFD        ;going to send the line feed to modem?
  2111.     ORA    A
  2112.     JNZ    MDOUTL        ;if yes, exit
  2113.     POP    PSW        ;get the char. back (a line feed)
  2114.     CALL    TYPE        ;show on CRT, do not send to modem
  2115.     RET
  2116. ;
  2117. MDOUTL    LDA    XOFFTST        ;waiting for X-off, X-on ?
  2118.     ORA    A
  2119.     CNZ    TXOFF        ;if yes, go check
  2120.     CALL    SNDRDY        ;wait until modem is ready to send
  2121.     JNZ    MDOUTL
  2122.     POP    PSW        ;get the character back
  2123.     CALL    TYPE        ;send character to CRT
  2124.     CALL    O$MDDATP    ;send character to modem
  2125.     CPI    CR        ;was it an end of line?
  2126.     RNZ            ;if yes, see if any delay is needed
  2127. ;
  2128. ; Delay to allow slow BBS systems (most use BASIC) to enter the line.
  2129. ; Choice of 0-9 for about 100 ms. each, maximum of 900 ms.
  2130. ;
  2131. MDOUTN    LDA    XONWAIT        ;wait for X-on after CR?
  2132.     ORA    A
  2133.     JNZ    WATXON        ;if yes, handle separately
  2134.     MVI    D,10
  2135. ;
  2136. MDOUTT    PUSH    D
  2137.     CALL    SPEED1        ;10 ms delay
  2138.     POP    D
  2139.     DCR    D
  2140.     JNZ    MDOUTT        ;10 loops for 100 ms.
  2141.     RET
  2142. ;
  2143. ; Add from 0 to 90 ms. delay between characters for slow (most use
  2144. ; BASIC) bulletin board systems.  Also used to add 0-900 ms. delay
  2145. ; between lines.
  2146. ;
  2147. SPEED    LDA    BYTDLY        ;get delay between characters (0-9)
  2148.     JMP    SPEED1+3    ;1=10 ms, 5=50 ms, 9=90 ms, etc.
  2149. ;
  2150. SPEED1    LDA    CRDLY        ;get delay after crlf (0-9)
  2151.     ORA    A        ;100 ms, 5=500 ms, 9=900 ms, etc.
  2152.     RZ            ;if no delay needed, return
  2153.     MOV    C,A        ;store number requested in c-reg.
  2154.     LDA    DLYFLG        ;want any delays this file?
  2155.     ORA    A
  2156.     RNZ            ;if not, skip this section
  2157. ;
  2158. SPEED2    CALL    SPEED3        ;outer loop
  2159.     DCR    C
  2160.     JNZ    SPEED2
  2161.     RET            ;done whenever the c-reg. is zero
  2162. ;
  2163. SPEED3    PUSH    H        ;save current 'HL' value
  2164.     LXI    H,20
  2165.     LDA    XOFFTST
  2166.     ORA    A
  2167.     JZ    SPEED4
  2168.     LXI    H,20        ;adjust for 'X-OFF' testing
  2169.     LDA    ECHOFLG
  2170.     ORA    A
  2171.     JZ    SPEED4
  2172.     LDA    LOCFLG
  2173.     ORA    A
  2174.     JZ    SPEED4
  2175.     LXI    H,25        ;adjust for remote echo
  2176. ;
  2177. SPEED4    CALL    FIXCNT        ;multiply delay by clock speed
  2178.     XCHG            ;transfer delay to 'DE'
  2179.     POP    H        ;restore current 'HL' from"speed3"
  2180. ;
  2181. SPEED5    DCX    D        ;inner loop
  2182.     LDA    XOFFTST
  2183.     ORA    A
  2184.     CNZ    TXOFF
  2185.     MOV    A,E
  2186.     ORA    D
  2187.     JNZ    SPEED5
  2188.     RET
  2189. ;
  2190. TXOFF    CALL    RCVRDY
  2191.     RNZ
  2192.     CALL    I$MDDATP
  2193.     ANI    7FH
  2194.     CPI    XOFF
  2195.     CZ    WATXON
  2196.     RET
  2197. ;
  2198. WATXON    CALL    RCVRDY        ;have a character? (like x-on)
  2199.     JNZ    WATXN1        ;if no character see if want to abort
  2200.     CALL    I$MDDATP
  2201.     ANI    7FH        ;strip off any parity
  2202.     CPI    XON        ;see if character was X-on
  2203.     RZ            ;if yes, keep going
  2204. ;
  2205. WATXN1    CALL    STAT        ;test to see if requesting cancellation
  2206.     JZ    WATXON
  2207.     CALL    KEYIN        ;can abort if the x-on never comes
  2208.     CPI    CANCEL        ;CTL-X to abort?
  2209.     JNZ    WATXON        ;if not, keep going
  2210.     RZ
  2211. ;
  2212. ;***********************************************************************
  2213. ;               SUBROUTINES
  2214. ;***********************************************************************
  2215. ;
  2216. ; Returns with the zero flag set if retry requested.  If using multi-
  2217. ; file (batch) mode, then no questions asked, just quit.
  2218. ;
  2219. CKQIT    LDA    BCHFLG        ;using batch mode now?
  2220.     ORA    A
  2221.     JZ    ABORT        ;quit if using batch mode
  2222. ;
  2223. CKQIT1    MVI    A,1
  2224.     STA    ERRCT
  2225.     CALL    ILPRT
  2226.     DB    CR,LF,'Multiple errors encountered.',CR,LF
  2227.     DB    'Type Q to quit, R to retry:  ',BELL,0
  2228.     CALL    KEYIN
  2229.     PUSH    PSW
  2230.     CALL    CRLF
  2231.     POP    PSW
  2232.     CALL    UCASE        ;instead of 'ANI 5FH'
  2233.     CPI    'R'
  2234.     JZ    RCVRECD        ;if 'R' keep trying
  2235.     CPI    'Q'
  2236.     JNZ    CKQIT1
  2237.     JMP    ABORT
  2238. ;
  2239. ; Show the file name as stored in the FCB but in CP/M format
  2240. ;
  2241. SHOFIL    LDA    QFLG        ;can type it if no 'QFLG'
  2242.     ORA    A
  2243.     RZ
  2244.     LXI    H,FCB+1
  2245. ;
  2246. SHONM    XRA    A
  2247.     STA    FTYCNT
  2248.     MVI    C,11
  2249. ;
  2250. PRNAM    CALL    FTYTST
  2251.     INX    H
  2252.     DCR    C
  2253.     JNZ    PRNAM
  2254.     RET
  2255. ;
  2256. ; Give report of received records as they occur
  2257. ;
  2258. REPORT    LDA    QFLG
  2259.     ORA    A
  2260.     RZ
  2261.     LHLD    RECNO        ;get record number
  2262.     INX    H
  2263.     CALL    ILPRT
  2264.     DB    CR,'Received # ',0
  2265.     CALL    DECOUT        ;print record number in decimal
  2266.     CALL    ILPRT
  2267.     DB    ' ',0
  2268. ;
  2269.     LDA    HEXSHO
  2270.     ORA    A
  2271.     RZ
  2272.     CALL    ILPRT
  2273.     DB    '(', 0
  2274.     CALL    DHXOUT        ;16 bit hex conversion and output
  2275.     CALL    ILPRT
  2276.     DB    'H) ',0
  2277.     RET
  2278. ;
  2279. FTYTST    LDA    FTYCNT
  2280.     INR    A
  2281.     STA    FTYCNT
  2282.     CPI    9        ;are we at the file type?
  2283.     JZ    SPCTST        ;go if so
  2284. ;
  2285. ENDSPT    MOV    A,M
  2286.     CPI    ' '        ;test for space
  2287.     CNZ    TYPE        ;type if not
  2288.     RET
  2289. ;
  2290. SPCTST    MOV    A,M
  2291.     CPI    ' '        ;test for space in 1st file type byte
  2292.     RZ            ;do not output period if space
  2293.     MVI    A,'.'
  2294.     CALL    TYPE
  2295.     JMP    ENDSPT        ;output 1st file type byte
  2296. ;
  2297. ; Get sender's progress report if it is present and wait for line to get
  2298. ; quiet
  2299. ;
  2300. SNDPRG    MVI    B,5        ;wait up to 5 seconds
  2301.     CALL    RECV
  2302.     CALL    TYPE        ;show the progress report from sender
  2303.     JNC    SNDPRG
  2304.     RET
  2305. ;
  2306. SNDFN    CALL    ILPRTQ
  2307.     DB    'Awaiting name NAK  ',CR,LF,0
  2308.     CALL    GTACK
  2309.     CC    SNDACK
  2310.     LXI    H,FILECT
  2311.     DCR    M
  2312.     JM    NOMRN
  2313.     LHLD    NBSAVE        ;get file name in FCB
  2314.     LXI    D,FCB
  2315.     MVI    B,12
  2316.     CALL    MOVE
  2317.     SHLD    NBSAVE
  2318.     CALL    SNDNM        ;send it
  2319.     ORA    A        ;clear carry
  2320.     RET
  2321. ;
  2322. NOMRN    MVI    A,EOT
  2323.     CALL    SND
  2324.     STC
  2325.     RET
  2326. ;
  2327. ; Wait for line to get quiet and gobble characters
  2328. ;
  2329. WAITQ1    MVI    B,1
  2330.     CALL    RECV
  2331.     JNC    WAITQ1
  2332.     RET
  2333. ;
  2334. SNDNM    PUSH    H
  2335. ;
  2336. SNDNM1    MVI    D,11        ;count characters in name
  2337.     MVI    C,0        ;initialize checksum
  2338.     LXI    H,FCB+1        ;address name
  2339. ;
  2340. NAMLPS    MOV    A,M        ;send name
  2341.     ANI    7FH        ;strip high order bit so CP/M 2.x
  2342.     CALL    SND        ;  will not send R/O file designation
  2343. ;
  2344. ACKLP    PUSH    B        ;save checksum
  2345.     MVI    B,5        ;wait for receiver to acknowledge
  2346.     CALL    RECV        ;  getting the letter
  2347.     POP    B
  2348.     JC    SCKSER
  2349.     CPI    ACK
  2350.     JNZ    ACKLP
  2351.     INX    H        ;next character
  2352.     DCR    D
  2353.     JNZ    NAMLPS
  2354.     MVI    A,EOFCHAR    ;tell receiver the end of name
  2355.     CALL    SND
  2356.     MOV    D,C        ;save checksum
  2357. ;
  2358. CKSMLP    MVI    B,5        ;wait up to 5 seconds
  2359.     CALL    RECV        ;get checksum
  2360.     CMP    D
  2361.     JNZ    SCKSER        ;exit if bad name
  2362.     MVI    A,OKNMCH    ;good name-tell receiver
  2363.     CALL    SND
  2364.     POP    H
  2365.     RET
  2366. ;
  2367. SCKSER    MVI    A,BDNMCH    ;bad name-tell receiver
  2368.     CALL    SND
  2369.     CALL    ILPRT
  2370.     DB    CR,LF,'++ ERROR sending name  ++',CR,LF,0
  2371.     MVI    E,120        ;do handshaking over (2 minutes maximum)
  2372.     CALL    WAITNLP        ;don't print "WAITING READY SIGNAL" msg.
  2373.     CALL    SNDACK
  2374.     JMP    SNDNM1
  2375. ;
  2376. ; This patch fixes a problem with the display of the function key
  2377. ; group on the menu.  It uses some of the extra bytes available in
  2378. ; this area from the CKSMLP fix.
  2379. ;
  2380. FIXFNK    STA    MENU3+1        ;store the character in the menu display
  2381.     CPI    '['        ;'ESC' character, printed
  2382.     JNC    INTER2        ;if 'ESC' or more, exit
  2383.     JMP    INTER1        ;otherwise include a '^'
  2384. ;
  2385. ; Patch to close FCB3 instead of FCB when in disk-capture mode.
  2386. ;
  2387. WRERRSP    CALL    WRFIL2        ;close FCB3 file
  2388.     JMP    WRERR1        ;go write 'DISK FULL' message and quit
  2389. ;
  2390. EXTRA    DB    '123456789 '    ;10 extras from CKSMLP (there were 27)
  2391. ;
  2392. GETFN    LXI    H,FCB
  2393.     CALL    INITFCB+2    ;does not initialize drive
  2394.     CALL    ILPRTQ
  2395.     DB    'Awaiting file name',CR,LF,0
  2396.     CALL    HSNAK
  2397.     CALL    GETNM        ;get the name
  2398.     CPI    EOT        ;if EOT, then no more files
  2399.     JZ    NOMRNG
  2400.     ORA    A        ;clear carry
  2401.     RET
  2402. ;
  2403. NOMRNG    STC
  2404.     RET
  2405. ;
  2406. GETNM    PUSH    H
  2407. ;
  2408. GETNM1    MVI    A,0FFH
  2409.     STA    FLTRFLG
  2410.     MVI    C,0        ;initialize checksum
  2411.     LXI    H,FCB+1
  2412. ;
  2413. NAMELPG    MVI    B,5
  2414.     CALL    RECV        ;get the character
  2415.     PUSH    B
  2416.     PUSH    PSW
  2417.     MVI    A,0FFH
  2418.     STA    TIMFLG
  2419.     MVI    B,1
  2420.     CALL    RECV
  2421.     XRA    A
  2422.     STA    TIMFLG
  2423.     POP    PSW
  2424.     POP    B
  2425.     JNC    GETNM3
  2426.     CALL    ILPRTQ
  2427.     DB    'Time out receiving filename',CR,LF,0
  2428.     JMP    GCKSER
  2429. ;
  2430. GETNM3    CPI    EOT        ;if EOT, then no more files
  2431.     JZ    GNRET
  2432.     CPI    EOFCHAR        ;got end of name
  2433.     JZ    ENDNAM
  2434.     PUSH    PSW
  2435.     PUSH    B
  2436.     CALL    SNDACK
  2437.     POP    B
  2438.     POP    PSW
  2439.     MOV    M,A        ;put name in FCB
  2440.     INX    H        ;get next character
  2441.     MOV    A,L        ;do not let noise cause overflow
  2442.     CPI    7FH        ;  into the program area
  2443.     JZ    GCKSER
  2444.     JMP    NAMELPG
  2445. ;
  2446. ENDNAM    XRA    A
  2447.     STA    FLTRFLG
  2448.     MOV    A,C        ;send checksum
  2449.     MOV    D,C
  2450.     CALL    SND
  2451. ;
  2452. NMLP1    MVI    B,5        ;wait up to 5 seconds to see if
  2453.     CALL    RECV        ;  the checksum is good
  2454.     CPI    OKNMCH        ;yes if 'OKNMCH' sent
  2455.     JZ    GNRET
  2456.     CMP    D
  2457.     JZ    NMLP1        ;in case it is echo of send
  2458.     CPI    CR
  2459.     JZ    NMLP1
  2460.     CPI    LF
  2461.     JZ    NMLP1
  2462. ;
  2463. GCKSER    LXI    H,FCB        ;clear FCB (except drive) since it
  2464.     CALL    INITFCB+2    ;  might be damaged
  2465.     CALL    ILPRTQ
  2466.     DB    CR,LF,'**  Checksum error  **',CR,LF,0
  2467.     XRA    A
  2468.     STA    FLTRFLG
  2469.     CALL    HSNAK        ;do handshaking over
  2470.     JMP    GETNM1
  2471. ;
  2472. GNRET    PUSH    PSW
  2473.     XRA    A
  2474.     STA    FLTRFLG
  2475.     POP    PSW
  2476.     POP    H
  2477.     RET
  2478. ;
  2479. HSNAK    MVI    E,180        ;3 minute wait for file name
  2480.     XRA    A
  2481.     STA    FLTRFLG
  2482. ;
  2483. HSNAK1    CALL    CKABORT        ;want to abort?
  2484.     MVI    A,NAK        ;send 'NAK' until receiving 'ACK'
  2485.     CALL    SND
  2486.     MVI    B,1        ;wait up to 1 second for a character
  2487.     CALL    RECV
  2488.     CPI    ACK        ;'ACK' is what we were waiting for
  2489.     RZ
  2490.     DCR    E
  2491.     JNZ    HSNAK1
  2492.     JMP    ABORT        ;back to command line
  2493. ;
  2494. TNMBUF    MVI    A,1        ;call from 'SNDFL' only once
  2495.     STA    FSTFLG
  2496.     XRA    A
  2497.     STA    FILECT
  2498.     CALL    SCAN
  2499.     LXI    H,NAMEBUF
  2500.     SHLD    NBSAVE        ;save address of 1st name
  2501. ;
  2502. TNLP1    CALL    TRTOBUF
  2503.     LXI    H,FCB
  2504.     LXI    D,FCBBUF
  2505.     CALL    CMDLINE        ;parse name to CP/M format
  2506. ;
  2507. TNLP2    CALL    MFNAM        ;search for names (wildcard format)
  2508.     JC    NEXTNM
  2509.     LDA    FCB+10        ;if CP/M 2.x SYS file
  2510.     ANI    80H        ;  do not send
  2511.     JNZ    TNLP2
  2512.     LHLD    NBSAVE        ;get name
  2513.     LXI    D,FCB        ;move it to FCB
  2514.     XCHG
  2515.     MVI    B,12
  2516.     CALL    MOVE
  2517.     XCHG
  2518.     SHLD    NBSAVE        ;address of next name
  2519.     LXI    H,FILECT    ;count files found
  2520.     INR    M
  2521.     JMP    TNLP2
  2522. ;
  2523. NEXTNM    LXI    H,NAMECT    ;count names found
  2524.     DCR    M
  2525.     JNZ    TNLP1
  2526.     LXI    H,NAMEBUF    ;save start of buffer
  2527.     SHLD    NBSAVE
  2528.     LDA    FILECT
  2529.     CPI    64+1        ;no more than 64 transfers
  2530.     RC
  2531.     MVI    A,64        ;only transfer first 64
  2532.     STA    FILECT
  2533.     RET
  2534. ;
  2535. ; Tells when buffer is opened/closed for memory save to write on disk
  2536. ;
  2537. BUFMS    CALL    ILPRT
  2538.     DB    CR,LF,'** Memory buffer ',0
  2539.     LDA    SAVEFLG
  2540.     ORA    A
  2541.     JZ    BUFMS1
  2542.     CALL    ILPRT
  2543.     DB    'open **',CR,LF,LF,';',0
  2544.     RET
  2545. ;
  2546. BUFMS1    CALL    ILPRT
  2547.     DB    'closed **',CR,LF,LF,0
  2548.     RET
  2549. ;
  2550. BUFMS2    CALL    ILPRT
  2551.     DB    CR,LF,'** Memory buffer available **',CR,LF,0
  2552.     RET
  2553. ;
  2554. ; Clear the screen and return to the menu command
  2555. ;
  2556. XITMNU    CALL    CRLF
  2557.     CALL    CLREOS        ;clear line to clean up any mess
  2558.     JMP    MENU0
  2559. ;
  2560. ; Checks to see if the modem has a character ready
  2561. ;
  2562. RCVRDY    CALL    I$MDCTL1
  2563.     CALL    A$MDRCVB
  2564.     JMP    C$MDRCVR
  2565. ;
  2566. ; Checks to see if the modem is ready to receive a character
  2567. ;
  2568. SNDRDY    CALL    I$MDCTL1
  2569.     CALL    A$MDSNDB
  2570.     JMP    C$MDSNDR
  2571. ;
  2572. SNDNOW    CALL    XITST        ;see if want to quit now
  2573.     CALL    SNDRDY        ;ready to send a character?
  2574.     JNZ    SNDNOW        ;if not ready wait some more
  2575.     RET            ;exit if ready
  2576. ;
  2577. ; Send the log-on message when requested
  2578. ;
  2579. SNDLOG    LHLD    LOGONPTR    ;'HL' points to start of logon message
  2580.     CALL    LOGLP
  2581.     JMP    TERML
  2582. ;
  2583. LOGLP    CALL    SNDNOW        ;wait until modem is ready
  2584.     MOV    A,M        ;get logon byte
  2585.     ORA    A        ;last character in string is '0'
  2586.     RZ            ;return if finished
  2587.     CALL    O$MDDATP    ;otherwise send the character
  2588.     CALL    LOGLP1        ;check for echo character and display it
  2589.     INX    H        ;next location in message
  2590.     JMP    LOGLP        ;get next character
  2591. ;
  2592. LOGLP1    CALL    J$INMDM        ;get the echo character
  2593.     CC    J$INMDM        ;if none, try once more
  2594.     RC            ;if no character do not try to print
  2595.     ANI    7FH        ;strip off any parity
  2596.     JMP    TYPE        ;display the character, then return
  2597. ;
  2598. ; Check for exit character
  2599. ;
  2600. XITST    CALL    STAT        ;anything on keyboard?
  2601.     RZ
  2602.     CALL    KEYIN        ;get it, then
  2603.     MOV    B,A        ;save to protect the 'A' register
  2604. ;
  2605. XITST1    MVI    A,EXITCHR    ;exit character
  2606.     CMP    B        ;asking to exit to menu?
  2607.     RNZ            ;if not, back to work
  2608.     POP    H        ;clear the stack from 'CALL'
  2609.     JMP    XITMNU        ;exit to the menu
  2610. ;
  2611. LSTMS    CALL    ILPRT
  2612.     DB    'Printer buffer is ',0
  2613.     LDA    LISTFLG        ;see if printer should be on or off
  2614.     ORA    A
  2615.     JZ    LSTMS1
  2616.     CALL    ILPRT
  2617.     DB    'ON',CR,LF,0
  2618.     RET
  2619. ;
  2620. LSTMS1    CALL    ILPRT
  2621.     DB    'OFF',CR,LF,0
  2622.     RET
  2623. ;
  2624. ; Special function key handler.  This routine is entered with the
  2625. ; function key number (0..9) in A.  The corresponding function key is
  2626. ; then transmitted.
  2627. ;
  2628. SNDFK    PUSH    H        ;save register
  2629.     LXI    H,FNCTBL    ;point to function key codes
  2630. ;
  2631. SFK1    CMP    M        ;this the one?
  2632.     INX    H        ;point to next byte
  2633.     JNZ    SFK1        ;loop until found
  2634.     CALL    LOGLP        ;send the char
  2635.     POP    H
  2636.     XRA    A        ;reset the function flag
  2637.     STA    FNKFLG
  2638.     JMP    TERML
  2639. ;
  2640. ; Send keyboard character to modem, also to console if "E" or "L".  If
  2641. ; "E" include a LF after a CR, if either, include a LF if toggle is set.
  2642. ;
  2643. NTOG    CALL    SNDCHR        ;send char. in 'B' to modem
  2644.     LDA    LOCFLG        ;using the local mode?
  2645.     ORA    A
  2646.     JNZ    LTYPE        ;if yes, show the character
  2647.     LDA    ECHOFLG        ;in echo mode?
  2648.     ORA    A
  2649.     JZ    TERML        ;if not, see if it was a 'CR'
  2650. ;
  2651. LTYPE    MOV    A,B        ;get the character back
  2652.     CALL    TYPE        ;show on the local CRT
  2653.     CALL    CKSAV        ;to store local if buffer open
  2654.     CALL    CHKPRNT        ;put on printer if running
  2655. ;
  2656. CHKCR    MVI    A,CR
  2657.     CMP    B
  2658.     JNZ    TERML        ;if not CR, all done
  2659.     LDA    ECHOFLG        ;in echo mode now?
  2660.     ORA    A
  2661.     JNZ    CHKLF        ;if yes add a line feed
  2662.     LDA    ADDLFD        ;going to add a line feed in 'L' mode?
  2663.     ORA    A
  2664.     JZ    TERM        ;if not, exit
  2665. ;
  2666. CHKLF    MVI    B,LF
  2667.     JMP    NTOG        ;send locally and to remote
  2668. ;
  2669. TERML    CALL    RCVRDY        ;character on the receive-ready line?
  2670.     JNZ    TERM        ;if not, exit
  2671.     CALL    I$MDDATP    ;get the character
  2672.     ANI    7FH        ;strip parity
  2673.     JZ    TERM        ;do not bother with nulls
  2674.     CPI    RUB
  2675.     JZ    TERM        ;do not bother with rubouts for fill
  2676.     MOV    B,A        ;store temporarily
  2677.     LDA    IGNRCTL        ;ignoring all but necessary CTL-chars?
  2678.     ORA    A
  2679.     JZ    GIVLF        ;if zero, display them all
  2680.     MOV    A,B
  2681.     CPI    ' '
  2682.     JNC    GIVLF        ;display all printing characters
  2683.     CPI    'G'-40H        ;^G for bell
  2684.     JC    TERM        ;ignore CTL-characters less than ^G
  2685.     CPI    CR+1
  2686.     JNC    TERM        ;ignore CTL-characters more than ^M
  2687. ;
  2688. GIVLF    MOV    A,B        ;get the character back
  2689.     CALL    TYPE        ;show it on the CRT
  2690.     CALL    CKSAV        ;saving for disk file?
  2691.     CALL    CHKPRNT        ;printer running?
  2692.     LDA    ECHOFLG        ;going to echo the character?
  2693.     ORA    A
  2694.     JZ    NOECH        ;if not, do not resend
  2695. ;
  2696. GIVLF1    CALL    SNDCHR        ;send character in 'B' to modem
  2697. ;
  2698. NOECH    MVI    A,CR
  2699.     CMP    B        ;was it a 'CR' just now?
  2700.     JNZ    TERM        ;if not, all done so exit
  2701.     LDA    ECHOFLG        ;in the echo mode?
  2702.     ORA    A
  2703.     JZ    TERM
  2704.     CALL    SNDNOW        ;modem ready for a character?
  2705.     MVI    B,LF
  2706.     JMP    GIVLF        ;send LF
  2707. ;
  2708. ; See if putting character into memory for a disk file
  2709. ;
  2710. CKSAV    LDA    SAVEFLG        ;saving to disk?
  2711.     ORA    A
  2712.     RZ            ;if not, exit
  2713.     LHLD    HLSAV        ;get last address
  2714.     MOV    M,B        ;store this character
  2715.     INX    H        ;increment for next character
  2716.     SHLD    HLSAV        ;remember that location
  2717.     MVI    A,LF
  2718.     CMP    B        ;this character a line feed?
  2719.     JNZ    CKSAV1        ;  type ";" after each line feed
  2720.     MVI    A,CR        ;insure at left column with a LF
  2721.     CALL    TYPE
  2722.     CALL    TYPSEM        ;show a ';' on CRT
  2723. ;
  2724. CKSAV1    MOV    A,H
  2725.     LXI    H,BUFTOP    ;get the address at top of buffer
  2726.     CMP    H
  2727.     CZ    DCTLS        ;if different, buffer is not full
  2728.     RET
  2729. ;
  2730. ; Memory buffer is full, send a X-OFF (CTL-S, DC3), save any extra in-
  2731. ; coming characters, then dump to disk, reset buffer to include those
  2732. ; characters.
  2733. ;
  2734. DCTLS    CALL    SNDNOW        ;modem ready for a character?
  2735.     MVI    A,XOFF        ;send a CTL-S to stop remote computer
  2736.     CALL    O$MDDATP
  2737.     CALL    CHKPRNT        ;insure character gets to the printer
  2738.     LXI    H,BUFFDSK    ;address of auxiliary buffer
  2739.     CALL    GTDSK        ;put any extra chars. into aux. buffer
  2740.     PUSH    D        ;save the number of aux. chars.
  2741.     MVI    A,1        ;show we put something in the buffer
  2742.     STA    WRFLG        ;  to protect erasing an empty file
  2743.     LHLD    HLSAV        ;find current end of buffer
  2744.     CALL    WRDSK1        ;write the records
  2745.     POP    D        ;get auxiliary character count back
  2746.     LXI    H,BUFFER    ;start again at bottom of buffer
  2747.     XRA    A        ;set 'A' to zero
  2748.     CMP    D        ;see if any count in 'D'
  2749.     JZ    DCTLQ        ;if nothing, exit and continue
  2750.     LXI    B,BUFFDSK    ;address of auxiliary buffer
  2751. ;
  2752. ; Move the characters from the auxiliary buffer to the main buffer and
  2753. ; display
  2754. ;
  2755. DCTLS1    LDAX    B        ;get the character there
  2756.     MOV    M,A        ;store in main buffer
  2757.     CALL    TYPE        ;show on CRT
  2758.     PUSH    H
  2759.     PUSH    D
  2760.     PUSH    B
  2761.     PUSH    PSW
  2762.     MOV    B,A
  2763.     CALL    CHKPRNT
  2764.     POP    PSW        ;get the character again
  2765.     POP    B
  2766.     POP    D
  2767.     POP    H
  2768.     CPI    LF
  2769.     CZ    TYPSEM
  2770.     INX    H        ;next buffer position
  2771.     INX    B        ;next auxiliary buffer position
  2772.     DCR    D        ;one less to go
  2773.     JNZ    DCTLS1        ;if not zero, keep going
  2774.     MVI    B,0        ;falls through to 'CHKPRNT' next
  2775. ;
  2776. DCTLQ    SHLD    HLSAV        ;next position to store in buffer
  2777.     CALL    SNDNOW
  2778.     MVI    A,XON        ;allow remote input to continue
  2779.     JMP    O$MDDATP
  2780. ;
  2781. ; Gets any incoming characters after sending an XOFF and stores at HL.
  2782. ; Returns with number of characters stored in D-reg.
  2783. ;
  2784. GTDSK    MVI    D,0        ;character count in buffer
  2785.     MVI    E,128        ;maximum for buffer length
  2786. ;
  2787. GTDSK1    CALL    J$INMDM        ;get any character
  2788.     RC            ;if none, finished
  2789.     CPI    ' '
  2790.     JNC    GTDSK2        ;if greater, handle normally
  2791.     CPI    CR+1        ;ignore CTL-characters > CR
  2792.     JNC    GTDSK1
  2793. ;
  2794. GTDSK2    MOV    M,A        ;store
  2795.     INX    H        ;next buffer location to use
  2796.     INR    D        ;increment character count
  2797.     DCR    E        ;room for one less
  2798.     JNZ    GTDSK1        ;if room in buffer, keep going
  2799.     RET            ;if buffer is filled, exit
  2800. ;
  2801. ; See if printing the character, if yes, put into buffer
  2802. ;
  2803. CHKPRNT    LDA    LISTFLG        ;printer in use?
  2804.     ORA    A
  2805.     RZ            ;return if not
  2806.     LHLD    HLSAV1        ;get input address
  2807.     MOV    M,B        ;save this character there
  2808.     INX    H        ;increment the buffer location
  2809.     SHLD    HLSAV1        ;store for next character
  2810.     LDA    MAXRAM        ;see if at top of buffer yet
  2811.     CMP    H
  2812.     CZ    PCTLS        ;if different, buffer is not full
  2813.     RET
  2814. ;
  2815. ; Memory buffer is full, send a X-OFF (CTL-S, DC3), save any extra in-
  2816. ; coming characters, then dump to disk, reset buffer to include those
  2817. ; characters.
  2818. ;
  2819. PCTLS    CALL    SNDNOW        ;wait until modem is ready
  2820.     MVI    A,XOFF        ;send a CTL-S to stop remote computer
  2821.     CALL    O$MDDATP
  2822.     LXI    H,BUFFPNT    ;address of auxiliary buffer
  2823.     CALL    GTDSK        ;put any extra chars. into aux. buffer
  2824.     MOV    A,D        ;get the aux. buffer character count
  2825.     STA    DSTORE        ;save for later
  2826.     RET
  2827. ;
  2828. ; Output has now caught up to the input and both are at top of buffer
  2829. ;
  2830. PCTLS1    LDA    DSTORE        ;get the aux. buffer character count
  2831.     MOV    D,A        ;put into 'D' register
  2832.     XRA    A        ;set 'A' to zero
  2833.     CMP    D        ;see if any count in 'D'
  2834.     LXI    H,PBUFF        ;address at start of printer buffer
  2835.     JZ    PCTLQ        ;if nothing, exit and continue
  2836.     LXI    B,BUFFPNT    ;address of auxiliary buffer
  2837. ;
  2838. ; Move the characters from the aux. buffer to the main buffer and display
  2839. ;
  2840. PCTLS2    LDAX    B        ;get the character there
  2841.     MOV    M,A        ;store in main buffer
  2842.     CALL    TYPE        ;show on CRT
  2843.     PUSH    H
  2844.     PUSH    D
  2845.     PUSH    B
  2846.     PUSH    PSW
  2847.     MOV    B,A
  2848.     CALL    CKSAV
  2849.     POP    PSW
  2850.     POP    B
  2851.     POP    D
  2852.     POP    H
  2853.     CPI    LF
  2854.     CZ    TYPSEM
  2855.     INX    H        ;next buffer position
  2856.     INX    B        ;next auxiliary buffer position
  2857.     DCR    D        ;one less to go
  2858.     JNZ    PCTLS2        ;if not zero, keep going
  2859. ;
  2860. PCTLQ    SHLD    HLSAV1        ;next position to store in buffer
  2861.     LXI    H,PBUFF        ;start of buffer location
  2862.     SHLD    HLSAV2        ;output to start of buffer
  2863.     CALL    SNDNOW        ;wait until modem is ready
  2864.     MVI    A,XON        ;send start character
  2865.     JMP    O$MDDATP    ;  to remote computer, back to work
  2866. ;
  2867. ; List the character on the printer if it is ready, then see if at the
  2868. ; top of the buffer.
  2869. ;
  2870. GOLIST    CALL    $-$        ;get the printer status - filled in
  2871.     ORA    A        ;by 'INITAD' routine
  2872.     RZ            ;return if printer not ready
  2873. ;
  2874. ; Compare input and output pointers.  If at same address, nothing to
  2875. ; print.
  2876. ;
  2877.     CALL    CMP$I$O        ;if the same, nothing to print
  2878.     RZ
  2879. ;
  2880. ; If not the same, print the character
  2881. ;
  2882. GOLIST1    PUSH    H        ;save current buffer address
  2883.     MOV    E,M        ;get the character to display
  2884.     MVI    C,LIST        ;list routine
  2885.     CALL    BDOS
  2886.     POP    H        ;restore current buffer address
  2887.     INX    H        ;increment pointer for next position
  2888.     SHLD    HLSAV2        ;store for next time through here
  2889. ;
  2890. ; See if the output is at the end of the buffer now.  If yes, go put
  2891. ; the auxiliary characters into the start of the buffer.
  2892. ;
  2893.     LDA    MAXRAM        ;check for end of buffer area
  2894.     CMP    H
  2895.     JZ    PCTLS1        ;if at end, restore auxiliary buffer
  2896. ;
  2897. ; See if the output has caught up with the input - if so, reset the
  2898. ; pointers to the start of the buffer
  2899. ;
  2900.     CALL    CMP$I$O
  2901.     RNZ            ;if not, back to work
  2902.     LXI    H,PBUFF        ;if output caught input, reset both
  2903.     SHLD    HLSAV1        ;  to bottom of buffer to start over
  2904.     SHLD    HLSAV2
  2905.     RET
  2906. ;
  2907. ; Compare the input and output pointers to see if the same address
  2908. ;
  2909. CMP$I$O    LHLD    HLSAV1        ;get input pointer address
  2910.     XCHG            ;put in 'DE'
  2911.     LHLD    HLSAV2        ;get output pointer address
  2912.     MOV    A,H
  2913.     CMP    D
  2914.     RNZ            ;return if different
  2915.     MOV    A,L
  2916.     CMP    E
  2917.     RET
  2918. ;
  2919. GTMAX    LDA    SAVCCP        ;going to save 'CCP'?
  2920.     ORA    A
  2921.     LDA    BDOS+2        ;'MSP' of 'BDOS' address
  2922.     JZ    GTMAX1
  2923.     SBI    8        ;'CCP' is 2k or 8 pages
  2924. ;
  2925. GTMAX1    STA    MAXRAM        ;save
  2926.     RET
  2927. ;
  2928. ; This subroutine will loop until the modem receives a character or 100
  2929. ; milliseconds.  It returns with a character in 'A' reg. but if no char-
  2930. ; acter was recieved it returns after a timeout with carry set.
  2931. ;
  2932. INMDM    PUSH    H
  2933.     LXI    H,63        ;about 100 milliseconds
  2934.     CALL    FIXCNT
  2935.     MOV    B,H        ;delay is in 'HL'
  2936.     MOV    C,L        ;transfer to 'BC'
  2937.     POP    H        ;get original value of 'HL' back
  2938. ;
  2939. INMDM1    CALL    RCVRDY        ;see if there is a character ready
  2940.     JNZ    INMDM2        ;if no character, exit
  2941.     CALL    I$MDDATP    ;get the character
  2942.     ANI    7FH        ;strip off any parity
  2943.     RET            ;return with character in 'A' reg.
  2944. ;
  2945. INMDM2    DCX    B        ;otherwise keep timing
  2946.     MOV    A,B
  2947.     ORA    C
  2948.     JNZ    INMDM1        ;loop until timeout if needed
  2949.     STC            ;shows a timeout occured
  2950.     RET
  2951. ;
  2952. ; Send a space tone to the phone line for a short time.
  2953. ;
  2954. BREAK    LDA    PMMIMD        ;using the PMMI modem?
  2955.     ORA    A
  2956.     JZ    BREAK1        ;if not, exit
  2957.     LDA    MDCTLB        ;get the last modem control byte
  2958.     ANI    BRKMASK        ;set the transmit break bit low
  2959.     CALL    O$MDCTL2    ;send it to the modem
  2960.     MVI    B,2
  2961.     CALL    TIMER        ;send a space tone for 200 ms.
  2962.     LDA    MDCTLB        ;get the last modem control byte
  2963.     CALL    O$MDCTL2    ;restore to normal
  2964.     JMP    TERM        ;back to work
  2965. ;
  2966. BREAK1    CALL    J$BREAK        ;get the user's break routine
  2967.     JMP    TERM        ;back to work
  2968. ;
  2969. ;=======================================================================
  2970. ;             WRITE BUFFER TO DISK
  2971. ;
  2972. ; Make sure this record is included in the count.
  2973. ;
  2974. WRDSK    LHLD    HLSAV
  2975.     MVI    M,EOFCHAR    ;ASCII file, store end-of-file char.
  2976.     LXI    D,127
  2977.     DAD    D
  2978. ;
  2979. WRDSK1    LXI    D,-(BUFFER)    ;subtract the start of the buffer
  2980.     DAD    D        ;by adding a minus number to buffer end
  2981.     MOV    A,L        ;divide hl by 128
  2982.     ORA    A
  2983.     RAL            ;  to get the
  2984.     MOV    L,H        ;  number of records
  2985.     MVI    H,0
  2986.     PUSH    PSW
  2987.     DAD    H
  2988.     POP    PSW
  2989.     MVI    A,0
  2990.     ADC    L
  2991.     MOV    L,A        ;number of records in 'HL'
  2992. ;
  2993. ; See if buffer is empty.  If yes, see if we need to erase an empty
  2994. ; file or have already written something.
  2995. ;
  2996.     LXI    D,BUFFER
  2997.     LDAX    D
  2998.     CPI    EOFCHAR        ;'EOF' in first address means
  2999.     JNZ    WRDSK2        ;  nothing in buffer to write
  3000.     LDA    WRFLG        ;first time by this way?
  3001.     ORA    A
  3002.     JZ    NOWRITE        ;if yes, show erasing file
  3003.     RET            ;otherwise go close file
  3004. ;
  3005. ; Write to disk.  Start from BUFFER (in 'DE').    Number of records to
  3006. ; write in 'HL'.
  3007. ;
  3008. WRDSK2    MVI    C,STDMA
  3009.     CALL    BDOSRT
  3010.     PUSH    D
  3011.     MVI    C,WRITE
  3012.     LXI    D,FCB3        ;location of filename to write to
  3013.     CALL    BDOSRT
  3014.     POP    D
  3015.     ORA    A
  3016.     JNZ    WRERRSP        ;error if disk is full ** special patch
  3017.     XCHG            ;put the current address in 'HL'
  3018.     PUSH    D        ;  and number of records left in
  3019.     LXI    D,128        ;  for now
  3020.     DAD    D        ;add for next record write, now in 'HL'
  3021.     POP    D        ;restore number of records left
  3022.     XCHG            ;records to 'HL' again, address to 'DE'
  3023.     DCX    H        ;one less record left
  3024.     MOV    A,H
  3025.     ORA    L        ;done writing when 'H' and 'H' both zero
  3026.     JNZ    WRDSK2        ;otherwise do another disk write
  3027.     RET
  3028. ;
  3029. ; Error while writing a record, show why it is aborting
  3030. ;
  3031. WRERR    MVI    C,CANCEL    ;send cancel char. to sending station
  3032.     CALL    SND
  3033.     CALL    CLOSFIL        ;close the current file
  3034. ;
  3035. WRERR1    CALL    ERXIT        ;also will reset stack
  3036.     DB    '++ DISK FULL, SAVING PARTIAL FILE ++','$'
  3037. ;
  3038. ; If no data to store on the disk, close the empty file and erase it
  3039. ;
  3040. NOWRITE    CALL    WRFIL2        ;close the empty file
  3041.     CALL    NOASK        ;erase the empty file
  3042.     CALL    ILPRT
  3043.     DB    '++ Nothing to save, erasing file ++'
  3044.     DB    CR,LF,BELL,0
  3045.     JMP    DONETA        ;reset any flags, return to menu
  3046. ;
  3047. ; Show you are in memory-save for disk write
  3048. ;
  3049. TYPSEM    MVI    A,';'
  3050.     JMP    TYPE        ;show on CRT, return
  3051. ;
  3052. ; Save the registers, call BDOS then restore the registers
  3053. ;
  3054. BDOSRT    PUSH    B
  3055.     PUSH    D
  3056.     PUSH    H
  3057.     CALL    BDOS
  3058.     POP    H
  3059.     POP    D
  3060.     POP    B
  3061.     RET
  3062. ;
  3063. INITFCB    MVI    M,0        ;entry at +2 will leave drive # intact
  3064.     INX    H        ;will initialize an FCB
  3065.     MVI    B,11        ;pointed to by HL-reg. fills 1st pos.
  3066. ;
  3067. LOOP11    MVI    M,' '        ;  with 0, next 11 with
  3068.     INX    H        ;  with blanks, and last
  3069.     DCR    B        ;  21 with nulls
  3070.     JNZ    LOOP11
  3071.     MVI    B,21
  3072. ;
  3073. LOOP21    MVI    M,0
  3074.     INX    H
  3075.     DCR    B
  3076.     JNZ    LOOP21
  3077.     RET
  3078. ;
  3079. ; Scans CMDBUF counting names and putting delimiter (space) after last
  3080. ; name.
  3081. ;
  3082. SCAN    PUSH    H
  3083.     LXI    H,NAMECT
  3084.     MVI    M,0
  3085.     LXI    H,CMDBUF+1    ;find end of command line, add space
  3086.     MOV    C,M
  3087.     MVI    B,0
  3088.     LXI    H,CMDBUF+2
  3089.     DAD    B
  3090.     MVI    M,' '
  3091.     LXI    H,CMDBUF+1
  3092.     MOV    B,M
  3093.     INR    B
  3094.     INR    B
  3095. ;
  3096. SCANL1    INX    H
  3097.     DCR    B
  3098.     JZ    DNSCAN
  3099.     MOV    A,M
  3100.     CPI    ' '
  3101.     JNZ    SCANL1
  3102. ;
  3103. SCANL2    INX    H        ;eat extra spaces
  3104.     DCR    B
  3105.     JZ    DNSCAN
  3106.     MOV    A,M
  3107.     CPI    ' '
  3108.     JZ    SCANL2
  3109.     SHLD    BGNMS        ;save start of names in CMDBUF
  3110.     INR    B
  3111.     DCX    H
  3112. ;
  3113. SCANL3    INX    H
  3114.     DCR    B
  3115.     JZ    DNSCAN
  3116.     MOV    A,M
  3117.     CPI    ' '
  3118.     JNZ    SCANL3
  3119.     LDA    NAMECT        ;counts names
  3120.     INR    A
  3121.     STA    NAMECT
  3122. ;
  3123. SCANL4    INX    H        ;eat spaces
  3124.     DCR    B
  3125.     JZ    DNSCAN
  3126.     MOV    A,M
  3127.     CPI    ' '
  3128.     JZ    SCANL4
  3129.     JMP    SCANL3
  3130. ;
  3131. DNSCAN    MVI    M,' '        ;space after last character
  3132.     POP    H
  3133.     RET
  3134. ;
  3135. ; Places next name in buffer so 'CMDLINE' may parse it
  3136. ;
  3137. TRTOBUF    LHLD    BGNMS
  3138.     MVI    B,0
  3139.     LXI    D,FCBBUF+2
  3140. ;
  3141. TBLP    MOV    A,M
  3142.     CPI    ' '
  3143.     JZ    TRBFEND
  3144.     STAX    D
  3145.     INX    H
  3146.     INX    D
  3147.     INR    B        ;count characterss in name
  3148.     JMP    TBLP
  3149. ;
  3150. TRBFEND    INX    H
  3151.     MOV    A,M        ;eat extra spaces
  3152.     CPI    ' '
  3153.     JZ    TRBFEND
  3154.     SHLD    BGNMS
  3155.     LXI    H,FCBBUF+1    ;put # chars before name
  3156.     MOV    M,B
  3157.     RET
  3158. ;
  3159. CKCPM2    MVI    C,CPMVER    ;BDOS 12 -- version number -- cp/m 2.x?
  3160.     CALL    BDOS
  3161.     ORA    A
  3162.     RZ
  3163.     MVI    C,STDMA
  3164.     LXI    D,TBUF
  3165.     CALL    BDOS
  3166.     MVI    C,SRCHF
  3167.     LXI    D,FCB
  3168.     CALL    BDOS
  3169.     CPI    0FFH
  3170.     RZ
  3171. ;
  3172.     CALL    GETADD
  3173.     LXI    D,9
  3174.     DAD    D        ;point to R/O attribute byte
  3175.     MOV    A,M
  3176.     ANI    80H        ;test most significant byte
  3177.     JNZ    MKCHG        ;if set, make change
  3178.     INX    H        ;check system attribute byte
  3179.     MOV    A,M
  3180.     ANI    80H
  3181.     RZ            ;not SYS or R/O attribute
  3182.     DCX    H
  3183. ;
  3184. MKCHG    LXI    D,-8
  3185.     DAD    D        ;point HL to filename + 1
  3186.     LXI    D,FCB+1        ;move directory name to FCB
  3187.     MVI    B,11        ;  without changing drive
  3188.     CALL    MOVE
  3189.     LXI    H,FCB+9        ;R/O attribute
  3190.     MOV    A,M
  3191.     ANI    7FH        ;strip R/O attribute
  3192.     MOV    M,A
  3193.     INX    H        ;system attribute
  3194.     MOV    A,M
  3195.     ANI    7FH
  3196.     MOV    M,A
  3197.     LXI    D,FCB
  3198.     MVI    C,30        ;set new attributes in directory
  3199.     CALL    BDOS
  3200. ;
  3201. ; Called by 'CKBAKUP' below, return done here through 'BDOS' jump
  3202. ;
  3203. PLANCHG    LXI    H,FCB        ;change name to type "BAK"
  3204.     LXI    D,FCB2
  3205.     MVI    B,9        ;move drive and name (not type)
  3206.     CALL    MOVE
  3207.     LXI    H,75H        ;start of type in FCB2
  3208.     MVI    M,'B'
  3209.     INX    H
  3210.     MVI    M,'A'
  3211.     INX    H
  3212.     MVI    M,'K'
  3213.     LXI    D,FCB2
  3214.     MVI    C,ERASE        ;erase any previous backups
  3215.     CALL    BDOS
  3216.     LXI    H,FCB2        ;FCB2 drive field should have
  3217.     MVI    M,0
  3218.     LXI    D,FCB
  3219.     MVI    C,23        ;rename
  3220.     JMP    BDOS
  3221. ;
  3222. CKBAKUP    LDA    BACKUP
  3223.     ORA    A
  3224.     RZ
  3225.     MVI    C,SRCHF
  3226.     LXI    D,FCB
  3227.     CALL    BDOS
  3228.     INR    A
  3229.     RZ            ;file not found
  3230.     JMP    PLANCHG        ;in 'CKCPM2' - return done there
  3231. ;
  3232. ;***********************************************************************
  3233. ;        RECEIVE A RECORD FROM SENDING STATION
  3234. ;***********************************************************************
  3235. ;
  3236. ; If CRC is in effect, there is a 10-second timeout to the first SOH.
  3237. ; It then tries six more times to let the sender know the system is
  3238. ; capable of receiving a 'CRC' check.  At the end of that time a NAK is
  3239. ; sent which tells the sender to use CHECKSUM checking instead of CRC.
  3240. ; This allows automatic compatability with systems implementing CRC -
  3241. ; (Cyclic Redundancy Checking).  The search for SOH will cycle through
  3242. ; one record interval and ignore noise or characters sent by the remote
  3243. ; for any purpose (such as progress reporting).  So extraneous characters
  3244. ; that are sometimes sent by remote-end protocol will be gobbled up until
  3245. ; the first SOH.  EOT is tested only as the first returned character af-
  3246. ; ter each sector.
  3247. ;
  3248. SRCHSOH    EQU    160        ;number of times to loop search for SOH
  3249. ;
  3250. RCVRECD    MVI    A,1
  3251.     STA    ERRCT        ;initialize the error count
  3252. ;
  3253. RCVSQ    MVI    B,10        ;10 seconds allowed to receive 1st char.
  3254.     LXI    D,SRCHSOH    ;initialize loop for up to 160 seconds
  3255.     CALL    RECV        ;get the 1st character
  3256.     JC    RCVSTOT        ;timeout error if not rcvd in 10 seconds
  3257.     MOV    C,A        ;save the character for now
  3258.     CPI    EOT        ;see if end of transmission
  3259.     STC            ;set carry
  3260.     RZ            ;return with carry set
  3261. ;
  3262. SOHLUP    MVI    A,0FFH
  3263.     STA    CHRFLG
  3264.     STA    TIMFLG
  3265.     MOV    A,E        ;get search count-down value
  3266.     CPI    SRCHSOH        ;see if it is the 1st returned character
  3267.     MOV    A,C        ;get the first character now
  3268.     JZ    NORECV        ;skip RECV routine if 1st character
  3269.     MVI    B,1
  3270.     CALL    RECV
  3271.     MOV    B,A
  3272.     JNC    TSTSOH
  3273. ;
  3274. NORECV    MOV    B,A
  3275.     XRA    A        ;else set the value that forces timeout
  3276.     STA    CHRFLG
  3277. ;
  3278. TSTSOH    MOV    A,B        ;get the character
  3279.     CPI    SOH        ;see if it is SOH
  3280.     PUSH    PSW
  3281.     XRA    A
  3282.     STA    TIMFLG        ;restore this flag
  3283.     POP    PSW
  3284.     JZ    RCVSOH        ;got SOH, get rcd # and its complement
  3285.     MOV    A,D
  3286.     ORA    E        ;see if counted-down to zero
  3287.     DCX    D
  3288.     JNZ    SOHLUP        ;go around again if not
  3289.     LDA    CHRFLG        ;see if timeout needs to be forced
  3290.     ORA    A
  3291.     JZ    RCVSTOT        ;go do timeout and count them
  3292.     LDA    QFLG
  3293.     ORA    A
  3294.     JZ    RCVSRR
  3295. ;
  3296. RCVSH    CALL    CRLF
  3297.     MOV    A,B
  3298.     CALL    HEXO
  3299.     CALL    ILPRT
  3300.     DB    'H received not SOH - ',0
  3301. ;
  3302. RCVPRN    CALL    SHOERR        ;display error count
  3303. ;
  3304. RCVSRR    CALL    WAITQ1        ;wait for 1 second with no characters
  3305.     CALL    CKABORT        ;want to stop receiving now?
  3306.     LDA    CRCFLAG        ;get 'CRC' flag
  3307.     ORA    A        ;'CRC' in effect?
  3308.     MVI    A,NAK        ;put 'NAK' in 'A' register
  3309.     JZ    RCVSR1        ;no, send the 'NAK'
  3310.     LDA    FIRSTME        ;get first time switch
  3311.     ORA    A        ;has first 'SOH' been received?
  3312.     MVI    A,NAK        ;put 'NAK' in 'A' register
  3313.     JNZ    RCVSR1        ;yes, then send 'NAK'
  3314.     MVI    A,CRC        ;tell sender 'CRC' is in effect
  3315. ;
  3316. RCVSR1    CALL    SND        ;  the 'NAK' or 'CRC' request
  3317.     LDA    ERRCT        ;abort if we have reached error limit
  3318.     INR    A
  3319.     STA    ERRCT        ;store for next time
  3320.     CPI    ERRLIM        ;see if at limit yet
  3321.     JC    RCVSQ        ;if not, keep going
  3322.     LDA    RETRY        ;see if retry after 10 errors is set
  3323.     ORA    A
  3324.     JZ    ABORT        ;if 'YES', abort
  3325.     JMP    CKQIT        ;if 'NO' check for continued use
  3326. ;
  3327. RCVSABT    LXI    SP,STACK    ;reset the stack just in case
  3328.     CALL    CLOSFIL        ;close the partial file
  3329.     CALL    NOASK        ;delete partial file
  3330.     CALL    ILPRT
  3331.     DB    CR,LF,LF
  3332.     DB    '++ RECEIVED FILE CANCELLED ++',CR,LF,BELL
  3333.     DB    '++ UNFINISHED FILE DELETED ++',CR,LF,0
  3334.     JMP    DONETA
  3335. ;
  3336. RCVSTOT    LDA    QFLG
  3337.     ORA    A
  3338.     JZ    RCVSCC
  3339. ;
  3340. RCVSPT    CALL    ILPRT
  3341.     DB    CR,LF,'++ Timeout ',0
  3342.     CALL    SHOERR
  3343. ;
  3344. RCVSCC    CALL    RCVSCC2
  3345.     JMP    RCVSRR
  3346. ;
  3347. ; Routine will switch from 'CRC' to Checksum if 'ERCNT' reaches 'ERRCRC'
  3348. ; and 'FIRSTIME' is false.
  3349. ;
  3350. RCVSCC2    LDA    ERRCT
  3351.     CPI    ERRCRC
  3352.     RNZ
  3353.     LDA    FIRSTME
  3354.     ORA    A
  3355.     RNZ
  3356.     LDA    CRCFLAG
  3357.     ORA    A
  3358.     RZ
  3359.     CMA
  3360.     STA    CRCFLAG
  3361.     STA    CRCDFLT
  3362.     CALL    ILPRTQ
  3363.     DB    '** Switching to Checksum mode **',CR,BELL,LF,0
  3364.     RET
  3365. ;
  3366. ; Got SOH - get block #, block # complemented
  3367. ;
  3368. RCVSOH    MVI    A,0FFH
  3369.     STA    FIRSTME        ;indicate 1st soh was received
  3370.     MVI    B,5        ;timeout = 5 seconds
  3371.     CALL    RECV        ;get record
  3372.     JC    RCVSTOT        ;got timeout
  3373.     MOV    D,A
  3374.     MVI    B,5        ;timeout = 5 seconds
  3375.     CALL    RECV
  3376.     JC    RCVSTOT
  3377.     CMA
  3378.     CMP    D
  3379.     JZ    RCVDATA
  3380.     LDA    QFLG
  3381.     ORA    A
  3382.     JZ    RCVSRR
  3383. ;
  3384. RCVBSE    CALL    ILPRT
  3385.     DB    CR,LF,'++ Bad record # in header ',0
  3386.     JMP    RCVPRN
  3387. ;
  3388. RCVDATA    MOV    A,D
  3389.     STA    RCVRNO
  3390.     MVI    A,1
  3391.     STA    DATAFLG
  3392.     MVI    C,0
  3393.     LXI    H,0
  3394.     SHLD    CRCVAL
  3395.     LXI    H,80H
  3396. ;
  3397. RCVCHR    MVI    B,5        ;wait up to 5 seconds for a character
  3398.     CALL    RECV
  3399.     JC    RCVSTOT
  3400.     MOV    M,A
  3401.     INR    L
  3402.     JNZ    RCVCHR
  3403.     XRA    A
  3404.     STA    DATAFLG
  3405.     LDA    CRCFLAG
  3406.     ORA    A
  3407.     JNZ    RCVCR
  3408.     MOV    D,C
  3409.     MVI    B,5        ;wait up to 5 seconds for an answer
  3410.     CALL    RECV
  3411.     JC    RCVSTOT
  3412.     CMP    D
  3413.     JNZ    RCVCERR
  3414. ;
  3415. CHKSNUM    LDA    RCVRNO
  3416.     MOV    B,A
  3417.     LDA    RECNO
  3418.     CMP    B
  3419.     JZ    RCVACK
  3420.     INR    A
  3421.     CMP    B
  3422.     JNZ    ABORT
  3423.     RET
  3424. ;
  3425. RCVCR    MVI    E,2        ;number of 'CRC' bytes
  3426. ;
  3427. RCVCR2    MVI    B,5        ;wait up to 5 seconds for a character
  3428.     CALL    RECV
  3429.     JC    RCVSTOT
  3430.     DCR    E
  3431.     JNZ    RCVCR2
  3432.     CALL    CRCCHK
  3433.     ORA    A
  3434.     JZ    CHKSNUM
  3435.     LDA    QFLG
  3436.     ORA    A
  3437.     JZ    RCVSRR
  3438. ;
  3439. RCVCRER    CALL    ILPRT
  3440.     DB    '++ CRC error ',0
  3441.     JMP    RCVPRN
  3442. ;
  3443. RCVCERR    LDA    QFLG
  3444.     ORA    A
  3445.     JZ    RCVSRR
  3446. ;
  3447. RCVCPR    CALL    ILPRT
  3448.     DB    '++ CHECKSUM error ',0
  3449.     JMP    RCVPRN
  3450. ;
  3451. RCVACK    CALL    SNDACK
  3452.     JMP    RCVRECD
  3453. ;
  3454. ; Get the error count and display on CRT
  3455. ;
  3456. SHOERR    PUSH    H
  3457.     LHLD    ERRCT
  3458.     MVI    H,0
  3459.     CALL    DECOUT
  3460.     POP    H
  3461.     CALL    ILPRT
  3462.     DB    ' ++',CR,LF,0
  3463.     LDA    ERRCT
  3464.     CPI    ERRLIM
  3465.     JNC    ABORT
  3466.     RET
  3467. ;
  3468. SNDHDR    LDA    QFLG
  3469.     ORA    A
  3470.     JZ    SNDHNM
  3471.     CALL    ILPRT
  3472.     DB    CR,'Sending # ',0
  3473.     PUSH    H        ;store current address
  3474.     LHLD    RECNO        ;get record number
  3475.     CALL    DECOUT        ;print it in decimal
  3476.     CALL    ILPRT
  3477.     DB    ' ',0
  3478. ;
  3479.     LDA    HEXSHO
  3480.     ORA    A
  3481.     JZ    SNDHNM-1
  3482.     CALL    ILPRT
  3483.     DB    '(',0
  3484.     CALL    DHXOUT        ;16 bit hex conversion & output
  3485.     CALL    ILPRT
  3486.     DB    'H) ',0
  3487. ;
  3488.     POP    H        ;restore current address
  3489. ;
  3490. SNDHNM    MVI    A,SOH        ;send 'SOH' character to the output
  3491.     CALL    SND
  3492.     LDA    RECNO        ;send record number to the output
  3493.     CALL    SND
  3494.     LDA    RECNO
  3495.     CMA            ;complement the record number
  3496.     JMP    SND        ;send this value to the output
  3497. ;
  3498. SNDREC    MVI    A,1
  3499.     STA    DATAFLG
  3500.     MVI    C,0
  3501.     LXI    H,0        ;new record, clear 'CHECKSUM' value
  3502.     SHLD    CRCVAL        ;new record, clear 'CRC' value
  3503.     LXI    H,TBUF        ;store at 0080H
  3504. ;
  3505. SNDC    MOV    A,M
  3506.     CALL    SND
  3507.     INR    L
  3508.     JNZ    SNDC
  3509.     XRA    A
  3510.     STA    DATAFLG
  3511.     RET
  3512. ;
  3513. SNDCKS    MOV    A,C
  3514.     JMP    SND
  3515. ;
  3516. SNDCRC    PUSH    H
  3517.     LHLD    CRCVAL
  3518.     MOV    A,H
  3519.     CALL    SND
  3520.     MOV    A,L
  3521.     CALL    SND
  3522.     POP    H
  3523.     XRA    A        ;reset the carry bit
  3524.     RET
  3525. ;
  3526. ; After a record is sent, a character is returned telling if it was re-
  3527. ; ceived properly or not.  An ACK allows the next record to be sent.  A
  3528. ; NAK causes the current record to be resent.  If no character (or any
  3529. ; character other than ACK or NAK) is received after a short wait (10
  3530. ; to 12 seconds), a timeout error message is shown and the record will
  3531. ; be resent.  The GTACK routine can gobble up a string of up to 191
  3532. ; characters while searching for an 'ACK' or a 'NAK'.
  3533. ;
  3534. GTACK    MVI    E,192        ;number of characters to gobble
  3535. ;
  3536. ACKLUP    MVI    A,0FFH
  3537.     STA    CHRFLG        ;set the character flag
  3538.     STA    TIMFLG        ;set the time flag
  3539.     MVI    B,1
  3540.     CALL    RECV
  3541.     MOV    B,A        ;save the character
  3542.     JNC    ACKTST
  3543.     XRA    A
  3544.     STA    CHRFLG        ;reset the character flag, was none
  3545. ;
  3546. ACKTST    XRA    A
  3547.     STA    TIMFLG
  3548.     MOV    A,B        ;get the character back
  3549.     CPI    ACK
  3550.     RZ
  3551.     CPI    NAK
  3552.     JZ    GTACK1
  3553. ;
  3554. NOAKNK    DCR    E        ;one less to go
  3555.     JNZ    ACKLUP        ;loop around again if not zero
  3556.     LDA    CHRFLG
  3557.     ORA    A
  3558.     JZ    GETATOT
  3559. ;
  3560. GTACK1    LDA    BENHERE
  3561.     XRA    B
  3562.     JZ    ACKER0        ;do not say 'ACK error' if 1st 'NAK'
  3563.     LDA    QFLG
  3564.     ORA    A
  3565.     JZ    ACKER
  3566.     CALL    ILPRT
  3567.     DB    '++ ',0
  3568.     MOV    A,B
  3569.     CPI    NAK
  3570.     JZ    GTACK3
  3571.     CALL    HEXO
  3572.     CALL    ILPRT
  3573.     DB    'H',0
  3574.     JMP    GTACK4
  3575. ;
  3576. GTACK3    CALL    ILPRT
  3577.     DB    'NAK',0
  3578. ;
  3579. GTACK4    CALL    ILPRT
  3580.     DB    ' received not ACK - ',0
  3581.     CALL    SHOERR
  3582. ;
  3583. ACKER0    XRA    A
  3584.     STA    BENHERE
  3585. ;
  3586. ACKER    LDA    ERRCT
  3587.     INR    A
  3588.     STA    ERRCT
  3589.     CPI    ERRLIM+1    ;at error limit yet?
  3590.     RC            ;if not, return
  3591. ;
  3592. ACKER1    CALL    ERXIT
  3593.     DB    CR,LF,'++ SEND-FILE CANCELLED ++','$'
  3594. ;
  3595. ; Reached error limit
  3596. ;
  3597. GETATOT    CALL    ILPRT
  3598.     DB    CR,'++ TIMEOUT - no ACK - ',0
  3599.     CALL    SHOERR        ;display error count
  3600.     JMP    ACKER
  3601. ;
  3602. CKABORT    LDA    QFLG
  3603.     ORA    A
  3604.     RZ
  3605.     CALL    STAT
  3606.     RZ
  3607.     CALL    KEYIN
  3608.     CPI    CANCEL
  3609.     RNZ
  3610. ;
  3611. ; Aborts send or receive routines and returns to command line
  3612. ;
  3613. ABORT    LXI    SP,STACK
  3614. ;
  3615. ABORTL    MVI    B,1        ;1-second delay to clear input
  3616.     CALL    RECV
  3617.     JNC    ABORTL
  3618.     MVI    A,CANCEL    ;show you are cancelling
  3619.     CALL    SND
  3620. ;
  3621. ABORTW    MVI    B,1        ;1-second delay to clear input
  3622.     CALL    RECV
  3623.     JNC    ABORTW
  3624.     MVI    A,' '
  3625.     CALL    SND
  3626.     MVI    A,'B'        ;turn multi-file mode
  3627.     STA    BCHFLG        ;  off so routine ends
  3628.     STA    ABTFLG        ;shows an abort was made
  3629.     XRA    A
  3630.     STA    NFILFLG        ;stop copy into memory for disk file
  3631.     LDA    OPTION        ;receiving a file now?
  3632.     CPI    'R'
  3633.     JZ    RCVSABT        ;if yes, cancel the unfinished file
  3634.     CALL    ILPRT
  3635.     DB    CR,LF,LF,'++ FILE CANCELLED ++',CR,LF,BELL,0
  3636.     JMP    DONETA
  3637. ;
  3638. ; Increment the record count
  3639. ;
  3640. INCRRNO    PUSH    H
  3641.     LHLD    RECNO        ;get record number
  3642.     INX    H        ;bump it
  3643.     SHLD    RECNO        ;store it
  3644.     MOV    A,L
  3645.     POP    H
  3646.     RET
  3647. ;
  3648. ; First check for any wild cards and disallow, just to be safe.  Do not
  3649. ; want a group of files being accidently erased.
  3650. ;
  3651. ERASF    LXI    H,FCB        ;file name is stored here
  3652.     MVI    B,11        ;maximum of 11 chars for filename.ext
  3653. ;
  3654. ERASF1    INX    H        ;next location in file name
  3655.     MOV    A,M        ;get the char.
  3656.     CPI    '?'        ;check for any wild card characters
  3657.     JZ    ERRORW        ;error if one is found
  3658.     DCR    B        ;number of tries left
  3659.     JNZ    ERASF1        ;if not zero, keep checking
  3660.     LDA    BCHFLG        ;do not ask for erase
  3661.     ORA    A        ;  in multi-file mode,
  3662.     JZ    NOASK        ;  just do it
  3663.     LXI    D,FCB
  3664.     MVI    C,SRCHF
  3665.     CALL    BDOS
  3666.     INR    A
  3667.     RZ            ;file erased ok, return
  3668.     CALL    ILPRT        ;otherwise make sure it is ok
  3669.     DB    'File exists - erase?  (Y/N): ',BELL,0
  3670.     CALL    KBDCHR
  3671.     CPI    'Y'
  3672.     JNZ    MENU        ;if not a 'Y' do not erase
  3673.     CALL    CRLF        ;otherwise erase the file
  3674. ;
  3675. NOASK    LXI    D,FCB
  3676.     MVI    C,ERASE
  3677.     JMP    BDOS
  3678. ;
  3679. ERRORW    POP    H        ;restore stack from "call ERASF"
  3680.     CALL    ILPRT
  3681.     DB    '++ NO WILDCARDS ALLOWED FOR TEXT FILES ++'
  3682.     DB    CR,LF,BELL,0
  3683.     JMP    MENU
  3684. ;
  3685. BLKFILE    CALL    ILPRT        ;no file named for send or receive
  3686.     DB    '++ NO FILE SPECIFIED ++',CR,LF,BELL,0
  3687.     JMP    MENU
  3688. ;
  3689. MAKEFIL    LXI    D,FCB
  3690.     MVI    C,MAKE
  3691.     CALL    BDOS
  3692.     INR    A
  3693.     RNZ
  3694.     CALL    ERXIT
  3695.     DB    '++ ERROR -- Can''t open file ++',CR,LF
  3696.     DB    '++ Directory is perhaps full ++','$'
  3697. ;
  3698. CNREC    MVI    C,FILSIZ    ;compute file size function in CP/M 2.x
  3699.     LXI    D,FCB        ;point to file control block
  3700.     CALL    BDOS
  3701.     LHLD    FCB+33        ;get record count
  3702.     SHLD    RCNT        ;store it
  3703.     LXI    H,0        ;zero 'HL'
  3704.     SHLD    FCB+33        ;reset random record in FCB
  3705.     RET
  3706. ;
  3707. OPENFIL    XRA    A
  3708.     STA    FCBEXT
  3709.     LXI    D,FCB
  3710.     MVI    C,OPEN
  3711.     CALL    BDOS
  3712.     INR    A
  3713.     JNZ    SNDTM        ;send transfer time, # of records, etc.
  3714.     CALL    ERXIT        ;file did not open
  3715.     DB    '++ FILE NOT FOUND ++','$'
  3716. ;
  3717. CLOSFIL    LXI    D,FCB        ;get the file name
  3718.     MVI    C,CLOSE
  3719.     CALL    BDOS        ;close the file
  3720.     INR    A
  3721.     RNZ
  3722.     JMP    ERXIT1        ;no file to close, exit
  3723. ;
  3724. ; Update record read
  3725. ;
  3726. RDRECD    LDA    RECINBF        ;decrement 'RECORDS IN BUFFER' count
  3727.     DCR    A
  3728.     STA    RECINBF
  3729.     JM    RDBLOCK
  3730.     LHLD    RECPTR        ;find where last move stopped
  3731.     LXI    D,128
  3732.     CALL    MOVE128        ;move 128 characters
  3733.     SHLD    RECPTR        ;store new address for next move
  3734.     RET
  3735. ;
  3736. ; Buffer empty so read in another block from the disk
  3737. ;
  3738. RDBLOCK    LDA    EOFLG
  3739.     CPI    1
  3740.     STC
  3741.     RZ
  3742.     MVI    C,0
  3743.     LXI    D,BUFFER
  3744. ;
  3745. RDRECLP    PUSH    B
  3746.     PUSH    D
  3747.     MVI    C,STDMA
  3748.     CALL    BDOS
  3749.     LXI    D,FCB
  3750.     MVI    C,READ
  3751.     CALL    BDOS
  3752.     POP    D
  3753.     POP    B
  3754.     ORA    A
  3755.     JZ    RDRECOK
  3756.     DCR    A
  3757.     JZ    REOF
  3758.     CALL    ERXIT
  3759.     DB    '++ FILE READ ERROR ++','$'
  3760. ;
  3761. RDRECOK    LXI    H,128
  3762.     DAD    D
  3763.     XCHG
  3764.     INR    C
  3765.     CALL    DSKSIZ        ;establish buffer size
  3766.     JZ    RDBFULL
  3767.     JMP    RDRECLP
  3768. ;
  3769. REOF    MVI    A,1
  3770.     STA    EOFLG
  3771.     MOV    A,C
  3772. ;
  3773. ; Buffer full or received "End Of File (EOF)"
  3774. ;
  3775. RDBFULL    STA    RECINBF
  3776.     LXI    H,BUFFER
  3777.     SHLD    RECPTR
  3778.     MVI    C,STDMA
  3779.     LXI    D,TBUF
  3780.     CALL    BDOS
  3781.     JMP    RDRECD
  3782. ;
  3783. ; Write a record
  3784. ;
  3785. WRRECD    LHLD    RECPTR
  3786.     XCHG
  3787.     LXI    H,128
  3788.     CALL    MOVE128
  3789.     XCHG
  3790.     SHLD    RECPTR        ;new record pointer
  3791.     LDA    RECINBF        ;increment 'RECORDS IN BUFFER' count
  3792.     INR    A
  3793.     STA    RECINBF
  3794.     MOV    C,A        ;store the record count for now
  3795.     CALL    DSKSIZ        ;establish buffer size
  3796.     RNZ            ;buffer not full, return
  3797. ;
  3798. ; Write a block to disk
  3799. ;
  3800. WRBLOCK    LDA    RECINBF        ;get the number of records in the buffer
  3801.     ORA    A
  3802.     RZ            ;if zero, don't try to move to disk
  3803.     MOV    C,A        ;otherwise store in 'C' register
  3804.     LXI    D,BUFFER    ;start of buffer to move to disk
  3805. ;
  3806. DSKWRT    PUSH    B
  3807.     PUSH    D
  3808.     PUSH    H
  3809.     MVI    C,STDMA
  3810.     CALL    BDOS
  3811.     MVI    C,WRITE
  3812.     LXI    D,FCB
  3813.     CALL    BDOS
  3814.     POP    H
  3815.     POP    D
  3816.     POP    B
  3817.     ORA    A
  3818.     JNZ    WRERR        ;error if disk is full
  3819.     LXI    H,128        ;add in another page
  3820.     DAD    D
  3821.     XCHG
  3822.     DCR    C        ;one less record left to move to disk
  3823.     JNZ    DSKWRT
  3824.     XRA    A
  3825.     STA    RECINBF        ;zero the 'RECORDS IN BUFFER' count
  3826.     LXI    H,BUFFER    ;reset location to next buffer start
  3827.     SHLD    RECPTR
  3828.     RET
  3829. ;
  3830. ; Determine if the buffer size is for file transfer or for ASCII capture
  3831. ; to disk then compare with current record length
  3832. ;
  3833. DSKSIZ    LDA    XFLG        ;see if transferring files now
  3834.     ORA    A
  3835.     MOV    A,C        ;get the current record count
  3836.     JZ    DSKSIZ1        ;if yes, exit
  3837.     MOV    A,C
  3838.     CPI    BUFSIZ*8    ;buffer size for ASCII capture to disk
  3839.     RET            ;return with flag set for the compare
  3840. ;
  3841. DSKSIZ1    LDA    SAVSIZ        ;get the file transfer buffer size..
  3842.     CMP    C        ;..from special storage area and compare
  3843.     RET            ;return with flag set for the compare
  3844. ;
  3845. ; Timeout time is in B, in seconds.  Entry via 'RECVDG' deletes garbage
  3846. ; characters on the line.  For example, having just sent a record, cal-
  3847. ; ling RECVDG will delete any line noise induced characters LONG before
  3848. ; the ACK/NAK would be received.
  3849. ;
  3850. RECVDG    CALL    CKCHAR        ;catch any garbage characters
  3851. ;
  3852. RECV    PUSH    D
  3853. ;
  3854. ; Get back quickly to gobble 2nd character if TIMFLG is set by the GETNM
  3855. ; routine - or just step through quickly after the first wait for 'SOH'
  3856. ; in the 'SOHLUP' routine.
  3857. ;
  3858. MSEC    PUSH    H
  3859.     LXI    H,TIMFLG
  3860.     MOV    E,M
  3861.     INR    E
  3862.     LHLD    QUIKTIM
  3863.     JZ    DOQUIK
  3864.     LHLD    TIMVAL
  3865. ;
  3866. DOQUIK    XCHG
  3867.     POP    H
  3868. ;
  3869. MWTI    CALL    RCVRDY
  3870.     JZ    MCHAR
  3871.     MOV    A,D
  3872.     ORA    E
  3873.     DCX    D
  3874.     JNZ    MWTI
  3875.     DCR    B
  3876.     JNZ    MSEC
  3877.     POP    D
  3878.     CALL    CKABORT
  3879.     STC
  3880.     RET
  3881. ;
  3882. ; Get the character from the modem, but filter out 'ACK' and '.' chars.
  3883. ; if receiving a file name.  ('FILTRFLG' is set by the 'GETNM' routine.)
  3884. ;
  3885. MCHAR    CALL    I$MDDATP    ;get the character that is waiting
  3886.     POP    D
  3887.     PUSH    PSW        ;save the character for later use also
  3888.     CPI    ACK        ;see if it is 'ACK'
  3889.     JZ    ISACK
  3890.     CPI    '.'        ;see if it is a period
  3891.     JNZ    DOUPD        ;neither, so update 'CRC'
  3892. ;
  3893. ISACK    PUSH    H
  3894.     PUSH    D
  3895.     LXI    H,FLTRFLG    ;see if need to each 'ACK' or period
  3896.     MOV    E,M
  3897.     INR    E
  3898.     POP    D
  3899.     POP    H
  3900.     JZ    MWTI        ;yes, so do it
  3901. ;
  3902. DOUPD    CALL    CRCUPD        ;calculate 'CRC'
  3903.     ADD    C
  3904.     MOV    C,A
  3905.     LDA    RSEEFLG
  3906.     ORA    A
  3907.     JZ    MONIN
  3908.     LDA    VSEEFLG
  3909.     ORA    A
  3910.     JNZ    NOMONIN
  3911.     LDA    DATAFLG
  3912.     ORA    A
  3913.     JZ    NOMONIN
  3914. ;
  3915. MONIN    POP    PSW        ;get the character again
  3916.     PUSH    PSW        ;resave it for later use also
  3917.     CALL    SHOW        ;show the character on the CRT
  3918. ;
  3919. NOMONIN    CALL    CKABORT
  3920.     POP    PSW        ;get the character back once more
  3921.     ORA    A        ;reset the carry flag
  3922.     RET            ;return with the character and flag set
  3923. ;
  3924. ; Send a character to the modem
  3925. ;
  3926. SND    PUSH    PSW
  3927.     LDA    SSEEFLG
  3928.     ORA    A
  3929.     JZ    MONOUT
  3930.     LDA    VSEEFLG
  3931.     ORA    A
  3932.     JNZ    NOMONOT
  3933.     LDA    DATAFLG
  3934.     ORA    A
  3935.     JZ    NOMONOT
  3936. ;
  3937. MONOUT    POP    PSW
  3938.     PUSH    PSW
  3939.     CALL    SHOW
  3940. ;
  3941. NOMONOT    POP    PSW
  3942.     PUSH    PSW
  3943.     CALL    CRCUPD        ;update the 'CRC' calcuation
  3944.     ADD    C
  3945.     MOV    C,A
  3946. ;
  3947. SNDW    CALL    SNDRDY
  3948.     JNZ    SNDW
  3949.     POP    PSW
  3950.     JMP    O$MDDATP    ;send character to modem, done
  3951. ;
  3952. ; Waits for the first character received while waiting to send a file.
  3953. ; If a character is not received in one second, it loops again until a
  3954. ; char. is received or it times out.  The count is set for two minutes
  3955. ; before timeout.  This gives the receiving station ample time to name
  3956. ; a file, etc.
  3957. ;
  3958. WAITNAK    CALL    ILPRT
  3959.     DB    'Waiting ready signal',CR,LF,0
  3960.     CALL    CRLF
  3961. ;
  3962. WAITNLP    CALL    CKABORT
  3963.     MVI    B,1        ;wait up to 1 second for a character
  3964.     CALL    RECV
  3965.     CPI    CANCEL        ;want to quit?
  3966.     JZ    ABORT
  3967.     CPI    CRC        ;'CRC' request?
  3968.     JZ    WAITCRC        ;yes, go set 'CRC' flag
  3969.     CPI    NAK
  3970.     JZ    WAICK
  3971.     DCR    E
  3972.     JNZ    WAITNLP
  3973.     JMP    ABORT
  3974. ;
  3975. WAITCRC    CALL    ILPRTQ
  3976.     DB    'CRC request received',CR,LF,0
  3977.     MVI    A,1
  3978.     STA    CRCFLAG        ;make sure in 'CRC' mode then
  3979.     RET
  3980. ;
  3981. WAICK    LDA    BCHFLG        ;in batch mode?
  3982.     ORA    A
  3983.     RZ
  3984.     CALL    ILPRTQ
  3985.     DB    'Got checksum request',CR,LF,0
  3986.     RET
  3987. ;
  3988. WAICK1    CALL    ILPRTQ
  3989.     DB    'Name NAK received',CR,LF,0
  3990.     RET
  3991. ;
  3992. ; Finished with the file transfer
  3993. ;
  3994. DONE    LDA    BCHFLG        ;in batch mode?
  3995.     ORA    A
  3996.     JNZ    DONET        ;exit if not
  3997.     LDA    QFLG
  3998.     ORA    A
  3999.     JZ    NMSTRNS
  4000.     MVI    B,12        ;zero out FTRNM
  4001.     LXI    H,FTRNM
  4002.     MVI    A,0
  4003. ;
  4004. ZEROLP    MOV    M,A
  4005.     INX    H
  4006.     DCR    B
  4007.     JNZ    ZEROLP
  4008.     MVI    B,12        ;put file name in FTRNM
  4009.     LXI    H,FCB+1
  4010.     LXI    D,FTRNM
  4011. ;
  4012. LOADMSG    MVI    A,4        ;start of file type?
  4013.     CMP    B
  4014.     JZ    PERIOD        ;put in period if so
  4015.     MOV    A,M
  4016.     CPI    ' '
  4017.     JZ    SKPSP
  4018.     STAX    D        ;store in FTRNM
  4019.     INX    D
  4020. ;
  4021. SKPSP    INX    H
  4022.     DCR    B
  4023.     MOV    A,B
  4024.     ORA    A        ;end of file name?
  4025.     JZ    FTRNM0        ;display file name
  4026.     JMP    LOADMSG        ;loop for another character
  4027. ;
  4028. PERIOD    MOV    A,M
  4029.     CPI    ' '        ;is file type empty?
  4030.     JZ    FTRNM0        ;go if so
  4031.     MVI    A,'.'        ;else put period in message
  4032.     STAX    D
  4033.     INX    D
  4034.     DCR    B
  4035.     JMP    LOADMSG
  4036. ;
  4037. FTRNM0    CALL    ILPRT
  4038.     DB    CR,LF
  4039. ;
  4040. FTRNM    DS    12
  4041.     DB    0
  4042.     CALL    ILPRT
  4043.     DB    ' Transferred',CR,LF,LF,BELL,0
  4044. ;
  4045. NMSTRNS    LDA    FCB        ;save drive number
  4046.     STA    DISKNO
  4047.     LXI    H,FCB        ;blank out file control blocks
  4048.     CALL    INITFCB
  4049.     LDA    DISKNO        ;put drive number back
  4050.     STA    FCB
  4051.     LXI    H,RESTSN    ;restore record numbers
  4052.     LXI    D,RECNOB    ;  for new file transfer
  4053.     MVI    B,RECNOE-RECNOB    ;routine also done in menu
  4054.     CALL    MOVE
  4055.     CALL    SNDNOW        ;insures last character is finished
  4056.     CALL    CKCHAR        ;catch any echo characters on line
  4057.     LDA    SNDFLG        ;goes to either send or
  4058.     ORA    A        ;  receive file, depending
  4059.     JNZ    SNDFL2        ;  upon which routine set
  4060.     JMP    RCVFL1        ;  the flag in multi-file mode
  4061. ;
  4062. DONET    CALL    CKABORT        ;slight delay for next message
  4063.     CALL    ILPRT
  4064.     DB    CR,LF,'[Transfer completed]',CR,LF,BELL,0
  4065. ;
  4066. DONETA    LDA    XITFLG        ;special 'X' flag set?
  4067.     ORA    A
  4068.     JZ    BYEBYE        ;if yes, disconnect and reboot
  4069.     LDA    DISCFLG        ;normal 'D' flag set?
  4070.     ORA    A
  4071.     JZ    DONETD        ;if yes, disconnect, get next command
  4072. ;
  4073. DONETB    CALL    J$NPARIT    ;reset to no parity
  4074.     XRA    A
  4075.     STA    CRCFLAG        ;reset back to checksum
  4076.     STA    FIRSTME        ;reset first-time 'SOH' flag
  4077.     STA    FSTFLG        ;reset multi-file trans
  4078.     STA    NFILFLG        ;turn off the memory save for disk file
  4079.     STA    SAVEFLG        ;stop memory save in term routine.
  4080.     LDA    VSEEFLG        ;view flag set?
  4081.     ORA    A
  4082.     JNZ    DONETC        ;if not, exit
  4083.     CMA
  4084.     STA    QFLG        ;VSEEFLG also sets the QFLG
  4085.     STA    VSEEFLG        ;reset the flag
  4086. ;
  4087. DONETC    LXI    H,QFLG        ;in quiet mode?
  4088.     MOV    A,M
  4089.     ORA    A
  4090.     MVI    M,'Q'        ;reset the flag to normal
  4091.     JZ    MENU        ;if yes, go back to command line
  4092.     LDA    ABTFLG        ;come here from a timeout?
  4093.     ORA    A
  4094.     JNZ    MENU        ;if yes, go to command mode
  4095.     LDA    JMPCMD        ;requesting return to command mode?
  4096.     ORA    A
  4097.     JZ    MENU        ;if yes go to command mode
  4098.     CALL    CRLF        ;turn up a new line
  4099.     JMP    TERM        ;otherwise return to terminal mode
  4100. ;
  4101. DONETD    CALL    ILPRT
  4102.     DB    CR,LF,'<< DISCONNECTED >>',BELL,CR,LF,0
  4103.     CALL    J$GOODBY    ;set 'DTR' low for 300 ms.
  4104.     LDA    PMMIMD
  4105.     ORA    A
  4106. ;;;    CNZ    J$GOODBY
  4107.     DB    0,0,0        ;(PREVENT DOUBLE DISCONNECT)
  4108.     LDA    AUTDIAL        ;using a Hayes-type modem?
  4109.     ORA    A
  4110. ;;;    CNZ    J$GOODBY    ;if yes, disconnect
  4111.     DB    0,0,0        ;(PREVENT DOUBLE DISCONNECT)
  4112.     JMP    MENU0        ;back to command line
  4113. ;
  4114. MOVEFCB    LXI    H,FCB+16
  4115.     LXI    D,FCB
  4116.     MVI    B,16
  4117.     CALL    MOVE
  4118.     XRA    A
  4119.     STA    FCBSNO
  4120.     STA    FCBEXT
  4121.     RET
  4122. ;
  4123. SHOW    CPI    LF
  4124.     JZ    CTYPE
  4125.     CPI    CR
  4126.     JZ    CTYPE
  4127.     CPI    9
  4128.     JZ    CTYPE
  4129.     CPI    ' '
  4130.     JC    SEEHEX
  4131.     CPI    7FH
  4132.     JC    CTYPE
  4133. ;
  4134. SEEHEX    PUSH    PSW
  4135.     MVI    A,'('
  4136.     CALL    CTYPE
  4137.     POP    PSW
  4138.     CALL    HEXO
  4139.     MVI    A,')'
  4140.     JMP    CTYPE
  4141. ;
  4142. CTYPE    PUSH    B
  4143.     PUSH    D
  4144.     PUSH    H
  4145.     MOV    E,A
  4146.     MVI    C,WRCON
  4147.     CALL    BDOS
  4148.     POP    H
  4149.     POP    D
  4150.     POP    B
  4151.     RET
  4152. ;
  4153. CRLF    PUSH    PSW
  4154.     MVI    A,CR
  4155.     CALL    TYPE
  4156.     MVI    A,LF
  4157.     CALL    TYPE
  4158.     POP    PSW
  4159.     RET
  4160. ;
  4161. STAT    PUSH    B
  4162.     PUSH    D
  4163.     PUSH    H
  4164. ;
  4165. VSTAT    CALL    $-$        ;BIOS constat address, filled in
  4166.     POP    H        ;  by 'INITAD' routine
  4167.     POP    D
  4168.     POP    B
  4169.     ORA    A
  4170.     RET
  4171. ;
  4172. KEYIN    PUSH    B
  4173.     PUSH    D
  4174.     PUSH    H
  4175. ;
  4176. VKEYIN    CALL    $-$        ;BIOS 'CONIN' address, filled in
  4177.     POP    H        ;  by 'INITAD' routine
  4178.     POP    D
  4179.     POP    B
  4180.     RET
  4181. ;
  4182. TYPE    PUSH    PSW
  4183.     PUSH    B
  4184.     PUSH    D
  4185.     PUSH    H
  4186.     MOV    C,A
  4187. ;
  4188. VTYPE    CALL    $-$        ;BIOS 'CONOUT' address, filled in
  4189.     POP    H        ;  by 'INITAD' routine
  4190.     POP    D
  4191.     POP    B
  4192.     POP    PSW
  4193.     RET
  4194. ;
  4195. ; Get a character from the keyboard, convert to upper-case if needed,
  4196. ; and show on CRT
  4197. ;
  4198. KBDCHR    CALL    KEYIN        ;get a keyboard character
  4199.     CALL    UCASE        ;convert to upper case if needed
  4200.     CALL    TYPE        ;show on CRT
  4201.     RET
  4202. ;
  4203. UCASE    CPI    61H        ;changes lower case character
  4204.     RC            ;  in 'A'reg. to upper case
  4205.     CPI    7AH+1        ;see if more than small 'Z'
  4206.     RNC
  4207.     ANI    5FH
  4208.     RET
  4209. ;
  4210. DECOUT    PUSH    PSW
  4211.     PUSH    B
  4212.     PUSH    D
  4213.     PUSH    H
  4214.     LXI    B,-10
  4215.     LXI    D,-1
  4216. ;
  4217. DECOU1    DAD    B
  4218.     INX    D
  4219.     JC    DECOU1
  4220.     LXI    B,10
  4221.     DAD    B
  4222.     XCHG
  4223.     MOV    A,H
  4224.     ORA    L
  4225.     CNZ    DECOUT
  4226.     MOV    A,E
  4227.     ADI    '0'
  4228.     CALL    CTYPE
  4229.     POP    H
  4230.     POP    D
  4231.     POP    B
  4232.     POP    PSW
  4233.     RET
  4234. ;
  4235. ;---->    DHXOUT: - double precision hex output routine
  4236. ;
  4237. DHXOUT    PUSH    H
  4238.     PUSH    PSW
  4239.     MOV    A,H        ;get MS byte
  4240.     CALL    HEXO        ;output high order byte
  4241.     MOV    A,L        ;get LS byte
  4242.     CALL    HEXO        ;output low order byte
  4243.     POP    PSW
  4244.     POP    H
  4245.     RET
  4246. ;
  4247. ; Prints a hex value in 'A' on the CRT
  4248. ;
  4249. HEXO    PUSH    PSW
  4250.     RAR
  4251.     RAR
  4252.     RAR
  4253.     RAR
  4254.     CALL    NIBBL
  4255.     POP    PSW
  4256. ;
  4257. NIBBL    ANI    0FH
  4258.     CPI    10
  4259.     JC    ISNUM
  4260.     ADI    7
  4261. ;
  4262. ISNUM    ADI    '0'        ;add in ASCII bias
  4263.     JMP    CTYPE
  4264. ;
  4265. ; Displays the control-characters shown in the menu
  4266. ;
  4267. SHFTYPE    PUSH    PSW
  4268.     CALL    ILPRT
  4269.     DB    'CTL-',0
  4270.     POP    PSW
  4271.     ADI    40H        ;convert binary to ASCII chars.
  4272.     CALL    TYPE        ;show on the CRT
  4273.     JMP    ILPRT
  4274. ;
  4275. ; Write a string of characters to the CRT
  4276. ;
  4277. ILPRT    XTHL
  4278. ;
  4279. ILPRT1    MOV    A,M        ;get the character
  4280.     ORA    A        ;see if a "0" for end of string
  4281.     JZ    ILPRT2        ;if yes, all done
  4282.     CALL    CTYPE        ;show on CRT
  4283.     INX    H        ;get the next location in the string
  4284.     JMP    ILPRT1
  4285. ;
  4286. ILPRT2    XTHL            ;restore the address
  4287.     RET
  4288. ;
  4289. ; Write a string of characters unless in the Quiet mode
  4290. ;
  4291. ILPRTQ    XTHL
  4292. ;
  4293. ILPRTQ1    MOV    A,M        ;get the character
  4294.     ORA    A        ;see if a "0" for end of string
  4295.     JZ    ILPRTQ2        ;if yes, all done
  4296.     LDA    QFLG
  4297.     ORA    A
  4298.     MOV    A,M
  4299.     CNZ    CTYPE        ;show on CRT if not in quiet mode
  4300.     INX    H        ;get the next location in the string
  4301.     JMP    ILPRTQ1
  4302. ;
  4303. ILPRTQ2    XTHL            ;restore the address
  4304.     RET
  4305. ;
  4306. PRTMSG    MVI    C,PRINT        ;print the string
  4307.     JMP    BDOS
  4308. ;
  4309. ; Displays error statement then resturns to command mode
  4310. ;
  4311. ERXIT    POP    D
  4312.     CALL    PRTMSG
  4313.     MVI    A,BELL
  4314.     CALL    TYPE
  4315.     CALL    CRLF
  4316. ;
  4317. ERXIT1    MVI    A,1
  4318.     STA    ABTFLG        ;shows an unintentional abort
  4319.     LDA    BCHFLG        ;in batch mode?
  4320.     ORA    A
  4321.     JNZ    DONETB        ;if not, exit
  4322.     JMP    ABORT        ;abort other computer
  4323. ;
  4324. ; Exits directly to CP/M, with no reboot unless you have selected pos-
  4325. ; sible overwriting of 'CCP'
  4326. ;
  4327. EXIT    LDA    OLDUSER        ;get original user number back
  4328.     MOV    E,A
  4329.     CALL    STUSER
  4330.     MVI    C,STDMA
  4331.     LXI    D,TBUF        ;restore original buffer area
  4332.     CALL    BDOS
  4333.     LXI    B,1A00H        ;a little delay timer
  4334. ;
  4335. EXIT1    DCX    B        ;one less loop to make
  4336.     MOV    A,B
  4337.     ORA    C
  4338.     JNZ    EXIT1        ;loop again till both are zero
  4339.     CALL    CKCON        ;catch any extra keyboard characters
  4340.     LDA    NFILFLG        ;saving for a disk file?
  4341.     ORA    A
  4342.     CNZ    WRFIL1        ;if yes, close the file
  4343.     LDA    SAVCCP        ;was 'CCP' left intact?
  4344.     ORA    A
  4345.     JZ    0000H        ;if not, warm reboot just in case
  4346. ;
  4347. EXIT2    XRA    A        ;clear the 'A' reg. and all flags
  4348.     LHLD    STACK        ;get the original stack pointer back
  4349.     SPHL            ;set the stack pointer to that address
  4350.     RET
  4351. ;
  4352. ; Catch any extra keyboard characters coming through BDOS
  4353. ;
  4354. CKCON    MVI    C,CONST        ;see if any characters waiting
  4355.     CALL    BDOS
  4356.     ORA    A
  4357.     RZ            ;if not, exit
  4358.     MVI    C,RDCON        ;otherwise get the character
  4359.     CALL    BDOS
  4360.     XRA    A        ;discard the character
  4361.     JMP    CKCON        ;see if any others
  4362. ;
  4363. MOVE128    MVI    B,128
  4364. ;
  4365. MOVE    MOV    A,M
  4366.     STAX    D
  4367.     INX    H
  4368.     INX    D
  4369.     DCR    B
  4370.     JNZ    MOVE
  4371.     RET
  4372. ;
  4373. ; Sends the character in 'A' to the modem
  4374. ;
  4375. SNDCHR    CALL    SNDNOW        ;wait until modem is ready for character
  4376.     MOV    A,B        ;get the original character back
  4377.     JMP    O$MDDATP    ;send the character to modem, return
  4378. ;
  4379. ; Initializes CP/M file control blocks AT 5CH and 6CH
  4380. ;
  4381. STFCB    LXI    D,CMDBUF
  4382.     LXI    H,FCB
  4383.     JMP    CMDLINE
  4384. ;
  4385. ; Adjusts loop counter for the selected clock speed.  Returns with delay
  4386. ; in 'HL'.
  4387. ;
  4388. FIXCNT    LDA    CLOCK        ;get the user's clock speed
  4389.     PUSH    D        ;save the current 'DE' value
  4390.     PUSH    H
  4391.     POP    D        ;get same value into 'DE' as in 'HL'
  4392. ;
  4393. CNTMUL    DAD    D        ;add 'DE' to 'HL'
  4394.     DCR    A        ;one less to go
  4395.     JNZ    CNTMUL
  4396.     POP    D        ;restore current 'DE', delay in 'HL'
  4397.     RET
  4398. ;
  4399. ;=======================================================================
  4400. ;
  4401. ; Loads a command line addressed by 'DE' registers (max # characters in
  4402. ; line in 'DE', number of characters in line in DE+1, line starts in
  4403. ; DE+2) into FCB addressed by 'HL' registers.  The FCB should be at least
  4404. ; 33 bytes in length.  The command line buffer must have a maximum length
  4405. ; at least one more than the greatest number of characters that will be
  4406. ; needed.
  4407. CMDLINE    PUSH    PSW
  4408.     PUSH    B
  4409.     PUSH    D
  4410.     PUSH    H
  4411.     CALL    INITIAL        ;fills FCBs with blanks and nulls
  4412.     XCHG            ;get start of command line in HL
  4413.     INX    H        ;address # bytes in cmd line
  4414.     MOV    E,M        ;load de pair with # bytes
  4415.     MVI    D,0
  4416.     INX    H
  4417.     DAD    D        ;point to byte after last character
  4418.     MVI    M,CR        ;  in cmd line and store delimiter
  4419.     POP    H        ;restore HL and DE
  4420.     POP    D
  4421.     PUSH    D
  4422.     PUSH    H
  4423.     INX    D        ;address start of command
  4424.     INX    D
  4425.     CALL    DRIVE
  4426. ;
  4427. NAME1    MVI    C,8        ;transfer first filename to FCB
  4428.     CALL    TRANS
  4429.     CPI    CR
  4430.     JZ    DONEL
  4431.     CPI    ' '        ;if space, then start of
  4432.     JZ    NAME2        ;  second filename
  4433.     POP    H        ;filetype must be after
  4434.     PUSH    H        ;  eighth byte of name
  4435.     LXI    B,9
  4436.     DAD    B
  4437.     MVI    C,3        ;transfer type of first file
  4438.     CALL    TRANS
  4439.     CPI    CR
  4440.     JZ    DONEL
  4441. ;
  4442. NAME2    LDAX    D        ;eat multiple spaces
  4443.     CPI    ' '        ;  between names
  4444.     JNZ    NAME3
  4445.     INX    D
  4446.     JMP    NAME2
  4447. ;
  4448. NAME3    POP    H        ;second name starts in 16th byte
  4449.     PUSH    H        ;point HL to this byte
  4450.     LXI    B,16
  4451.     DAD    B
  4452.     CALL    DRIVE
  4453.     MVI    C,8
  4454.     CALL    TRANS
  4455.     CPI    CR
  4456.     JZ    DONEL
  4457.     POP    H        ;second type starts in 25th byte
  4458.     PUSH    H
  4459.     LXI    B,25
  4460.     DAD    B
  4461.     MVI    C,3
  4462.     CALL    TRANS
  4463. ;
  4464. DONEL    POP    H
  4465.     PUSH    H
  4466.     INX    H        ;point to 1st char of 1st name in FCB
  4467.     CALL    SCANL        ;check for * (ambiguous names)
  4468.     POP    H
  4469.     PUSH    H
  4470.     LXI    B,17        ;  to 1st char of second name in FCB
  4471.     DAD    B
  4472.     CALL    SCANL
  4473.     POP    H
  4474.     POP    D
  4475.     POP    B
  4476.     POP    PSW
  4477.     RET
  4478. ;
  4479. ; Subroutines for CMDLINE section
  4480. ;
  4481. INITIAL    PUSH    H
  4482.     PUSH    B
  4483.     MVI    M,0
  4484.     INX    H
  4485.     MVI    B,11
  4486.     MVI    A,' '
  4487.     CALL    INITFIL
  4488.     MVI    B,5
  4489.     XRA    A
  4490.     CALL    INITFIL
  4491.     MVI    B,11
  4492.     MVI    A,' '
  4493.     CALL    INITFIL
  4494.     MVI    B,4
  4495.     XRA    A
  4496.     CALL    INITFIL
  4497.     POP    B
  4498.     POP    H
  4499.     RET
  4500. ;
  4501. INITFIL    MOV    M,A
  4502.     INX    H
  4503.     DCR    B
  4504.     JNZ    INITFIL
  4505.     RET
  4506. ;
  4507. DRIVE    INX    D        ;check 2nd byte of filename - if it
  4508.     LDAX    D        ;  is a ":", then drive was specified
  4509.     DCX    D
  4510.     CPI    ':'
  4511.     JNZ    DEFDR        ;else zero for default drive
  4512.     LDAX    D        ;('INIT' put zero)
  4513.     ANI    5FH
  4514.     SUI    40H        ;calculate drive (A=1, B=2,...)
  4515.     MOV    M,A        ;place it in FCB.
  4516.     INX    D        ;address first byte
  4517.     INX    D
  4518. ;
  4519. DEFDR    INX    H        ;name field in FCB
  4520.     RET
  4521. ;
  4522. TRANS    LDAX    D        ;transfer from command line to FCB
  4523.     INX    D        ;up to number of characters specified
  4524.     CPI    CR        ;in 'C' reg. keep scanning field
  4525.     RZ            ;  without transfer until a delimiting
  4526.     CPI    '.'        ;  field char such as '.', blank, or
  4527.     RZ            ;  CR (for end of commmand line)
  4528.     CPI    ' '
  4529.     RZ
  4530.     DCR    C
  4531.     JM    TRANS        ;once C-reg is less than zero, keep
  4532.     MOV    M,A        ;  reading command line but do not
  4533.     INX    H        ;  transfer to FCB
  4534.     JMP    TRANS
  4535. ;
  4536. SCANL    MVI    B,8        ;scan file name addressed by HL
  4537. ;
  4538. TSTNAM    MOV    A,M
  4539.     CPI    '*'        ;if '*' found, fill in rest of field
  4540.     JZ    FILL1        ;  with '?' for ambiguous name
  4541.     INX    H
  4542.     DCR    B
  4543.     JNZ    TSTNAM
  4544.     JMP    TSTTYP
  4545. ;
  4546. FILL1    CALL    FILL
  4547. ;
  4548. TSTTYP    MVI    B,3        ;scan and fill type field for name
  4549. ;
  4550. TSTTYPL    MOV    A,M        ;  specified above
  4551.     CPI    '*'
  4552.     JZ    FILL2
  4553.     INX    H
  4554.     DCR    B
  4555.     JNZ    TSTTYPL
  4556.     RET
  4557. ;
  4558. FILL2    CALL    FILL
  4559.     RET
  4560. ;
  4561. FILL    MVI    M,'?'        ;routine transfers '?'
  4562.     INX    H
  4563.     DCR    B
  4564.     JNZ    FILL
  4565.     RET
  4566. ;
  4567. ;=======================================================================
  4568. ; LISTS DIRECTORY AND GIVES FREE SPACE REMAINING ON THE REQUESTED DRIVE.
  4569. ;
  4570. ; Disk system reset - currently bypassed, if you wish this feature, put
  4571. ;    JMP DRLST2 instead of JMP DRLST3 in the eighth line.  The
  4572. ;    current disk (plus the A: drive) will then reset each DIR re-
  4573. ;    quest.    You can also reset the disk with the LOG command when
  4574. ;    when inserting a different one.  This saves a reset each time
  4575. ;    DIR might be requested.
  4576. ;
  4577. DRLST    CALL    GETDISK
  4578.     ADI    'A'        ;change to ASCII
  4579.     STA    DRNAME        ;show for drive name
  4580.     STA    ACTDRV        ;show for space remaining on drive
  4581. ;
  4582. DRLST1    JMP    DRLST3
  4583. ;
  4584. DRLST2    MVI    C,RESET        ;13 reset disk system (RESETDK)
  4585.     CALL    BDOS
  4586. ;
  4587. ; Directory list routine
  4588. ;
  4589. DRLST3    LXI    D,CMDBUF    ;put command line in FCB
  4590.     LXI    H,FCB        ;  addressed by HL-reg
  4591.     CALL    CMDLINE        ;  and then
  4592.     LXI    H,FCB4
  4593.     CALL    INITFCB
  4594.     LDA    FCB2        ;get drive number
  4595.     STA    FCB4
  4596.     LDA    FCB2+1
  4597.     CPI    ' '        ;if a space (blank) get all names
  4598.     PUSH    PSW
  4599.     CZ    QSTMARK
  4600.     POP    PSW
  4601.     CNZ    MOVNAME        ;else move name into FCB
  4602.     CALL    DRIVEL
  4603.     MVI    C,STDMA
  4604.     LXI    D,TBUF
  4605.     CALL    BDOS
  4606.     LDA    NOFCOL        ;number of columns into 'A' reg.
  4607.     STA    NAMECT        ;CRLF after 'NOFCOL' number of columns
  4608.     LXI    D,FCB4
  4609.     MVI    C,SRCHF        ;do first search
  4610.     CALL    BDOS
  4611.     INR    A        ;0FFH --> 0 if no file(s) found
  4612.     JNZ    DIRLOOP
  4613.     CALL    ILPRT
  4614.     DB    '++ FILE NOT FOUND ++',0
  4615.     JMP    STORAGE        ;still show storage on default drive
  4616. ;
  4617. DIRLOOP    CALL    GETADD
  4618.     INX    H        ;point to first letter of filename
  4619.     LXI    D,PRTNAME
  4620.     LXI    B,8
  4621.     CALL    MOVER
  4622.     INX    D
  4623.     LXI    B,3
  4624.     CALL    MOVER
  4625.     CALL    ILPRT
  4626. ;
  4627. PRTNAME    DB    '        ','.','   ',0    ; 8 spaces, period, 3 spaces
  4628. ;
  4629. NEXTSR    LXI    D,FCB4
  4630.     MVI    C,SRCHN        ;do next search
  4631.     CALL    BDOS
  4632.     INR    A        ;if 0FFH --> 0 then
  4633.     JZ    STORAGE        ;  directory-read finished
  4634.     PUSH    PSW
  4635.     PUSH    D
  4636.     PUSH    H
  4637.     LDA    NAMECT
  4638.     DCR    A
  4639.     STA    NAMECT        ;name count updated
  4640.     ORA    A
  4641.     CZ    CRLF        ;terminate line of file names
  4642.     JNZ    FENCE
  4643.     LDA    NOFCOL        ;restart columns-per-line count
  4644.     STA    NAMECT
  4645.     JMP    NOFENCE        ;fence not needed
  4646. ;
  4647. FENCE    CALL    ILPRT
  4648.     DB    ' : ',0        ;fence if not at end of line or
  4649. ;                ;  LAST FILENAME
  4650. NOFENCE    POP    H
  4651.     POP    D
  4652.     POP    PSW
  4653.     JMP    DIRLOOP
  4654. ;
  4655. ; Determine storage remaining on default drive
  4656. ;
  4657. STORAGE    CALL    CKCPM3
  4658.     MVI    C,DSKPAR    ;current disk parameter block
  4659.     CALL    BDOS
  4660.     INX    H
  4661.     INX    H
  4662.     MOV    A,M        ;get block shift factor
  4663.     STA    BSHIFTF
  4664.     INX    H        ;bump to block mask
  4665.     MOV    A,M        ;get it
  4666.     STA    BMASK
  4667.     INX    H
  4668.     INX    H
  4669.     MOV    E,M        ;get max block number
  4670.     INX    H
  4671.     MOV    D,M
  4672.     XCHG
  4673.     SHLD    BMAX        ;put it away
  4674.     MVI    C,DSKALL    ;address of cp/m allocation vector
  4675.     CALL    BDOS
  4676.     XCHG            ;get its length
  4677.     LHLD    BMAX
  4678.     INX    H
  4679.     LXI    B,0        ;initialize block count to zero
  4680. ;
  4681. GSPBYT    PUSH    D        ;save allocation address
  4682.     LDAX    D
  4683.     MVI    E,8        ;set to process 8 blocks
  4684. ;
  4685. GSPLUP    RAL            ;test bit
  4686.     JC    NOTFRE
  4687.     INX    B
  4688. ;
  4689. NOTFRE    MOV    D,A        ;save bits
  4690.     DCX    H
  4691.     MOV    A,L
  4692.     ORA    H
  4693.     JZ    ENDALC        ;quit if out of blocks
  4694.     MOV    A,D        ;restore bits
  4695.     DCR    E        ;count down 8 bits
  4696.     JNZ    GSPLUP        ;do another bit
  4697.     POP    D        ;bump to next count
  4698.     INX    D        ; of allocation vector
  4699.     JMP    GSPBYT        ;process it
  4700. ;
  4701. ENDALC    POP    D        ;clear alloc vector pointer from stack
  4702.     MOV    L,C        ;copy block to HL
  4703.     MOV    H,B
  4704.     LDA    BSHIFTF        ;get block shift factor
  4705.     SUI    3        ;convert from records to thousands (k)
  4706.     JZ    PRTFREE        ;skip shifts if 1k blocks
  4707. ;
  4708. FREKLP    DAD    H        ;multiply blocks by k per block
  4709.     DCR    A
  4710.     JNZ    FREKLP
  4711. ;
  4712. PRTFREE    CALL    DECOUT        ;(# of free k bytes now in 'HL')
  4713.     LXI    D,FREEMSG
  4714.     JMP    PRTMSG
  4715. ;
  4716. ; Subroutines for 'DRLST' section
  4717. ;
  4718. QSTMARK    MVI    A,'?'        ;if blank in FCB, put in 11 '?' chars.
  4719.     MVI    B,11
  4720.     LXI    H,FCB4+1
  4721. ;
  4722. QSTLP    MOV    M,A
  4723.     INX    H
  4724.     DCR    B
  4725.     JNZ    QSTLP
  4726.     RET
  4727. ;
  4728. MOVNAME    LXI    H,FCB2+1
  4729.     LXI    D,FCB4+1
  4730.     LXI    B,11
  4731.     CALL    MOVER
  4732.     RET
  4733. ;
  4734. GETADD    DCR    A        ;un-do the INR above
  4735.     ADD    A        ;times 32
  4736.     ADD    A
  4737.     ADD    A
  4738.     ADD    A
  4739.     ADD    A
  4740.     ADI    TBUF        ;add buffer offset
  4741.     MOV    L,A
  4742.     MVI    H,0
  4743.     RET
  4744. ;
  4745. DRIVEL    LDA    FCB4        ;if no drive, use
  4746.     ORA    A        ;  default drive in DRNAME
  4747.     JZ    PRNTHD
  4748.     PUSH    PSW
  4749.     DCR    A
  4750.     MOV    E,A
  4751.     MVI    C,SELDSK
  4752.     CALL    BDOS
  4753.     POP    PSW
  4754.     ADI    40H        ;make 1=A, 2=B, etc., and
  4755.     STA    DRNAME        ; overwrite default stored below
  4756.     STA    ACTDRV
  4757. ;
  4758. PRNTHD    CALL    ILPRT
  4759.     DB    'Drive '
  4760. ;
  4761. DRNAME    DB    ' :',CR,LF,0
  4762.     RET
  4763. ;
  4764. ; Initialized storage
  4765. ;
  4766. FREEMSG    DB    'k bytes free on drive '
  4767. ACTDRV    DB    ' :',CR,LF,'$'
  4768. ;
  4769. ; Uninitialized storage
  4770. ;
  4771. BMAX    DS    2        ;highest block number on drive
  4772. BMASK    DS    1        ;rec/blk - 1
  4773. BSHIFTF    DS    1        ;number of shifts to multiply by rec/blk
  4774. ;
  4775. ;=======================================================================
  4776. ;
  4777. ; Duplicates 'READ BUFFER' routine same as CP/M function 10, but does
  4778. ; not use CTL-C (reason for the routine).  Does allow controls U, R, E
  4779. ; and H (BACKSPACE).  Outputs bell if the input is greater than the
  4780. ; buffer.
  4781. ;
  4782. INBUF    PUSH    PSW
  4783.     PUSH    H
  4784.     PUSH    B
  4785.     PUSH    D        ;'DE' registers must be pushed last
  4786. ;
  4787. INBUFA    CALL    CLRBUF        ;clear the buffer area
  4788.     POP    D        ;get address of buffer on retries
  4789.     PUSH    D        ;restore stack
  4790.     XRA    A
  4791.     INX    D        ;address count field
  4792.     STAX    D        ;initialize with a zero in count byte
  4793.     INX    D
  4794.     XCHG            ;address first buffer byte with 'HL'
  4795. ;
  4796. INBUFB    CALL    KEYIN        ;(waits for char)
  4797.     CALL    UCASE        ;convert to upper case if needed
  4798.     CPI    CR        ;is it <return> (enter command)?
  4799.     JZ    INBUFR        ;if so, then return.
  4800.     CPI    08H        ;CTL-H backspaces over deleted character
  4801.     JZ    DELETE
  4802.     CPI    7FH        ;is it a delete?
  4803.     JZ    DELETE
  4804.     CPI    'U'-40H        ;is it a CTL-U?
  4805.     JZ    INBUFO        ;output #, CR, LF, and start over
  4806.     CPI    'R'-40H        ;CTL-R retypes line
  4807.     JZ    RETYPE
  4808. ;
  4809. INBUFC    MOV    B,A        ;save inputted character
  4810.     XCHG            ;save 'HL' in 'DE'
  4811.     POP    H        ;get address of buffer in 'HL'
  4812.     PUSH    H        ;restore stack
  4813.     INX    H        ;address count byte
  4814.     INR    M        ;increase count byte
  4815.     DCX    H        ;address maximum
  4816.     MOV    A,M        ;put maximum in 'A'
  4817.     INX    H        ;address count
  4818.     CMP    M        ;compare count to maximum
  4819.     JC    ALERTL        ;if maximum, ring bell and wait for cr.
  4820.     XCHG            ;restore buffer pointer to 'HL'
  4821.     MOV    M,B        ;put inputted character in buffer
  4822.     MOV    A,B        ;output it
  4823.     CPI    EXITCHR        ;exit character?
  4824.     JZ    INBUFR        ;if yes, all done
  4825.     CPI    20H        ;printing character?
  4826.     CNC    TYPE        ;if yes, print it
  4827.     INX    H        ;bump pointer
  4828.     JMP    INBUFB        ;get next character
  4829. ;
  4830. DELETE    XCHG            ;save buffer pointer in 'DE'
  4831.     POP    H        ;address beginning of buffer
  4832.     PUSH    H        ;restore stack
  4833.     INX    H        ;address count field
  4834.     MOV    A,M
  4835.     SUI    1        ;decrease count
  4836.     MOV    M,A
  4837.     JC    NODEL        ;don't delete past beginning of buffer
  4838.     XCHG            ;restore buffer pointer to 'HL'
  4839.     DCX    H        ;point to last byte inputted
  4840.     MOV    A,M        ;get the character being deleted
  4841.     MVI    M,' '        ;restore blank
  4842.     CPI    ' '        ;see if a non-printing character
  4843.     JC    INBUFB        ;if yes, skip the CRT backup
  4844.     MVI    A,BKSP
  4845.     CALL    TYPE        ;true erase if 08H
  4846.     MVI    A,' '
  4847.     CALL    TYPE
  4848.     MVI    A,BKSP
  4849.     CALL    TYPE
  4850.     JMP    INBUFB
  4851. ;
  4852. MORE    DB    '12345'        ;5 bytes extra from DELETE routine fix
  4853. ;
  4854. NODEL    INR    M        ;do not leave count negative
  4855.     XCHG            ;restore pointer to 'HL'
  4856.     MVI    A,BELL        ;says can go no further
  4857.     CALL    TYPE
  4858.     JMP    INBUFB
  4859. ;
  4860. INBUFO    MVI    A,'#'        ;announces the line has been removed
  4861.     CALL    TYPE
  4862.     CALL    CRLF
  4863.     JMP    INBUFA
  4864. ;
  4865. RETYPE    POP    D
  4866.     PUSH    D
  4867.     INX    D        ;point to current number of characters
  4868.     LDAX    D
  4869.     MOV    B,A
  4870.     MVI    A,'#'
  4871.     CALL    TYPE
  4872.     CALL    CRLF
  4873.     MOV    A,B        ;test if zero input
  4874.     ORA    A
  4875.     JZ    INBUFB
  4876. ;
  4877. CTLRLP    INX    D
  4878.     LDAX    D
  4879.     CALL    TYPE
  4880.     DCR    B
  4881.     JNZ    CTLRLP
  4882.     JMP    INBUFB
  4883. ;
  4884. ALERTL    MVI    A,BELL        ;alarm for full buffer
  4885.     CALL    TYPE
  4886.     DCR    M
  4887.     XCHG
  4888.     JMP    INBUFB
  4889. ;
  4890. PCRLF    CALL    CRLF
  4891.     JMP    INBUFB
  4892. ;
  4893. INBUFR    CALL    CRLF        ;1st new line after a command character
  4894.     POP    D
  4895.     POP    B
  4896.     POP    H
  4897.     POP    PSW
  4898.     RET
  4899. ;
  4900. CLRBUF    POP    D        ;accounts for call
  4901.     POP    H        ;restore the registers
  4902.     PUSH    H
  4903.     PUSH    D
  4904.     MOV    B,M        ;save maximum in 'B'
  4905.     INX    H        ;point to first buffer byte
  4906.     INX    H
  4907.     MVI    A,' '
  4908. ;
  4909. CLEARL    MOV    M,A
  4910.     INX    H
  4911.     DCR    B
  4912.     JNZ    CLEARL
  4913.     RET
  4914. ;
  4915. ;=======================================================================
  4916. ;
  4917. ; In-line compare.  Compares string addressed by 'DE' to string after
  4918. ; call (ends with zero).  Return with carry set means strings not the
  4919. ; same.  All registers except 'A'-reg are unaffected.
  4920. ;
  4921. INLNCP    XTHL            ;point 'HL' to 1st character
  4922.     PUSH    D
  4923. ;
  4924. ILCOMPL    MOV    A,M        ;'HL' points to in-line string
  4925.     ORA    A        ;end of string if zero
  4926.     JZ    SAME
  4927.     LDAX    D
  4928.     CMP    M
  4929.     JNZ    NOTSAME
  4930.     INX    H
  4931.     INX    D
  4932.     JMP    ILCOMPL
  4933. ;
  4934. NOTSAME    XRA    A        ;if not same, finish through
  4935. ;
  4936. NSLP    INX    H        ;  string so return will
  4937.     CMP    M        ;  go to instruction after
  4938.     JNZ    NSLP        ;  string and not remainder of string
  4939.     STC
  4940. ;
  4941. SAME    POP    D
  4942.     INX    H        ;avoids a NOP instruction
  4943.     XTHL            ;  when returning
  4944.     RET
  4945. ;
  4946. ;=======================================================================
  4947. ;          MULTI-FILE ACCESS ROUTINE
  4948. ;
  4949. ; Multi-file access subroutine.  Allows processing of multiple files
  4950. ; (i.e., *.ASM) from disk.  Builds the correct name in the FCB each time
  4951. ; it is called.  The command is used in programs to process single or
  4952. ; multiple files.  The FCB is set up with the next name, ready to do
  4953. ; normal processing (open, read, etc.) when routine is called.    Carry is
  4954. ; set if no more names are found.
  4955. MFNAM    PUSH    B
  4956.     PUSH    D
  4957.     PUSH    H
  4958.     MVI    C,STDMA
  4959.     LXI    D,TBUF
  4960.     CALL    BDOS
  4961.     POP    H
  4962.     POP    D
  4963.     POP    B
  4964.     XRA    A
  4965.     STA    FCBEXT
  4966.     LDA    MFFLG1
  4967.     ORA    A
  4968.     JNZ    MFNAM1
  4969.     MVI    A,1
  4970.     STA    MFFLG1
  4971.     LXI    H,FCB
  4972.     LXI    D,MFNAM5
  4973.     LXI    B,12
  4974.     CALL    MOVER
  4975.     LDA    FCB
  4976.     STA    MFNAM6        ;save disk in current FCB
  4977.     LXI    H,MFNAM5
  4978.     LXI    D,FCB
  4979.     LXI    B,12
  4980.     CALL    MOVER
  4981.     PUSH    B
  4982.     PUSH    D
  4983.     PUSH    H
  4984.     MVI    C,SRCHF
  4985.     LXI    D,FCB
  4986.     CALL    BDOS
  4987.     POP    H
  4988.     POP    D
  4989.     POP    B
  4990.     JMP    MFNAM2
  4991. ;
  4992. MFNAM1    LXI    H,MFNAM6
  4993.     LXI    D,FCB
  4994.     LXI    B,12
  4995.     CALL    MOVER
  4996.     PUSH    B
  4997.     PUSH    D
  4998.     PUSH    H
  4999.     MVI    C,SRCHF
  5000.     LXI    D,FCB
  5001.     CALL    BDOS
  5002.     POP    H
  5003.     POP    D
  5004.     POP    B
  5005.     LXI    H,MFNAM5
  5006.     LXI    D,FCB
  5007.     LXI    B,12
  5008.     CALL    MOVER
  5009.     PUSH    B
  5010.     PUSH    D
  5011.     PUSH    H
  5012.     MVI    C,SRCHN
  5013.     LXI    D,FCB
  5014.     CALL    BDOS
  5015.     POP    H
  5016.     POP    D
  5017.     POP    B
  5018. ;
  5019. MFNAM2    INR    A
  5020.     STC
  5021.     JNZ    MFNAM3
  5022.     STA    MFFLG1
  5023.     RET
  5024. ;
  5025. MFNAM3    DCR    A
  5026.     ANI    3
  5027.     ADD    A
  5028.     ADD    A
  5029.     ADD    A
  5030.     ADD    A
  5031.     ADD    A
  5032.     ADI    81H
  5033.     MOV    L,A
  5034.     MVI    H,0
  5035.     PUSH    H        ;save name pointer
  5036.     LXI    D,MFNAM6+1
  5037.     LXI    B,11
  5038.     CALL    MOVER
  5039.     POP    H
  5040.     LXI    D,FCB+1
  5041.     LXI    B,11
  5042.     CALL    MOVER
  5043.     XRA    A
  5044.     STA    FCBEXT
  5045.     STA    FCBRNO
  5046.     RET
  5047. ;
  5048. MOVER    MVI    A,2
  5049.     INR    A
  5050.     JPE    MFNAM4
  5051.     DB    0EDH,0B0H    ;Z-80 'LDIR' instruction
  5052.     RET
  5053. ;
  5054. MFNAM4    MOV    A,M        ;used if an 8080 CPU is active
  5055.     STAX    D
  5056.     INX    H
  5057.     INX    D
  5058.     DCX    B
  5059.     MOV    A,B
  5060.     ORA    C
  5061.     JNZ    MFNAM4
  5062.     RET
  5063. ;
  5064. ;=======================================================================
  5065. ;         CALCULATE FILE TRANSFER TIME
  5066. ; Shows the time to transfer a file at various baud rates.  (110-19200)
  5067. ;
  5068. SNDTM    CALL    ILPRT
  5069.     DB    'File open: ',0
  5070.     LHLD    RCNT        ;get record count
  5071.     CALL    DECOUT        ;print decimal number of records
  5072. ;
  5073.     LDA    HEXSHO
  5074.     ORA    A
  5075.     JZ    SNDTM1
  5076.     CALL    ILPRT
  5077.     DB    ' (',0
  5078.     CALL    DHXOUT        ;now print size in hex
  5079.     CALL    ILPRT
  5080.     DB    'H)',0
  5081. ;
  5082. SNDTM1    CALL    ILPRT
  5083.     DB    ' records'
  5084.     DB    CR,LF,'Send time: ',0
  5085.     LDA    MSPEED        ;get the speed indicator
  5086.     MVI    D,0
  5087.     MOV    E,A        ;set up for table access
  5088.     LXI    H,BTABLE    ;point to baud factor table
  5089.     DAD    D        ;index to proper factor
  5090.     DAD    D        ;factor in 'DE'
  5091.     MOV    E,M
  5092.     INX    H
  5093.     MOV    D,M
  5094.     LHLD    RCNT        ;get # of records
  5095.     CALL    DVHLDE        ;divide HL by value in DE (records/min)
  5096.     PUSH    H
  5097.     MOV    L,C
  5098.     MOV    H,B
  5099.     CALL    DECOUT        ;print the minutes portion
  5100.     CALL    ILPRT
  5101.     DB    ' mins, ',0
  5102.     LXI    H,RECDBL    ;point to divisors for seconds
  5103.     LXI    D,0        ;   calculation
  5104.     LDA    MSPEED        ;get index for baud rate
  5105.     MOV    E,A
  5106.     DAD    D        ;index into table
  5107.     MOV    A,M        ;get multiplier
  5108.     POP    H        ;get remainder
  5109.     CALL    MULHLA        ;multiply the 'HL' x 'A'
  5110.     CALL    SHFTHL
  5111.     CALL    SHFTHL
  5112.     CALL    SHFTHL
  5113.     CALL    SHFTHL
  5114.     MVI    H,0
  5115.     CALL    DECOUT        ;print the seconds portion
  5116.     CALL    ILPRT
  5117.     DB    ' secs at ',0
  5118.     CALL    PRTBAUD
  5119.     CALL    ILPRTQ
  5120.     DB    'To cancel: use CTL-X',CR,LF,0
  5121.     RET
  5122. ;
  5123. BTABLE    DW    5,13,20,26,29,48,85,152,280,480,0    ;records/min for..
  5124. RECDBL    DB    192,74,48,37,33,20,11,6,3,2,0        ;110-19200 baud
  5125. ;
  5126. ; Shows baud rates set for 'time to send' file transfer
  5127. ;
  5128. PRTBAUD    LXI    H,BAUDSPD
  5129.     MVI    D,0
  5130.     LDA    MSPEED        ;get baud rate code
  5131.     MOV    E,A        ;x1
  5132.     ADD    A        ;x2
  5133.     ADD    A        ;x4
  5134.     ADD    E        ;x5
  5135.     ADD    E
  5136.     MOV    E,A
  5137.     DAD    D        ;point to correct rate
  5138.     XCHG
  5139.     MVI    C,PRINT
  5140.     CALL    BDOS
  5141.     CALL    ILPRT
  5142.     DB    ' bps ',CR,LF,0
  5143.     RET
  5144. ;
  5145. BAUDSPD    DB    '110$',0,0,'300$',0,0,'450$',0,0,'600$',0,0,'710$',0,0
  5146.     DB    '1200$',0,'2400$',0,'4800$',0,'9600$',0,'19200$'
  5147. ;
  5148. ;---->    DVHLDE: Divides 'HL' by value in 'DE',
  5149. ;    Upon exit: 'BC'=quotient,'L'=remainder
  5150. ;
  5151. DVHLDE    PUSH    D        ;save divisor
  5152.     MOV    A,E
  5153.     CMA            ;negate divisor
  5154.     MOV    E,A
  5155.     MOV    A,D
  5156.     CMA
  5157.     MOV    D,A
  5158.     INX    D        ;'DE' is now two's complemented
  5159.     LXI    B,0        ;init quotient
  5160. ;
  5161. DIVL1    DAD    D        ;subtract divisor from dividend
  5162.     INX    B        ;bump quotient
  5163.     JC    DIVL1        ;loop till sign changes
  5164.     DCX    B        ;adjust quotient
  5165.     POP    D        ;retrieve divisor
  5166.     DAD    D        ;adjust remainder
  5167.     RET
  5168. ;
  5169. ;---->    MULHLA:  Multiply the value in 'HL' by the value in 'A'
  5170. ;         Return with answer in 'HL'
  5171. ;
  5172. MULHLA    XCHG            ;multiplicand to 'DE'
  5173.     LXI    H,0        ;init product
  5174.     INR    A        ;adjust multiplier for zero test
  5175. ;
  5176. MULLP    DCR    A
  5177.     RZ
  5178.     DAD    D
  5179.     JMP    MULLP
  5180. ;
  5181. ; Shift 'HL' register pair one bit to the right
  5182. ;
  5183. SHFTHL    MOV    A,L
  5184.     RAR
  5185.     MOV    L,A
  5186.     ORA    A        ;clear the carry
  5187.     MOV    A,H
  5188.     RAR
  5189.     MOV    H,A
  5190.     RNC
  5191.     MVI    A,128
  5192.     ORA    L
  5193.     MOV    L,A
  5194.     RET
  5195. ;
  5196. ;=======================================================================
  5197. ;             CRC SUBROUTINES
  5198. ;
  5199. ; Check 'CRC' bytes of record just received
  5200. ;
  5201. CRCCHK    PUSH    H
  5202.     LHLD    CRCVAL
  5203.     MOV    A,H
  5204.     ORA    L
  5205.     POP    H
  5206.     RZ
  5207.     MVI    A,0FFH
  5208.     RET
  5209. ;
  5210. ; Generate the CRC tables for fast calculations
  5211. ;
  5212. CRCGN    LXI    H,CRCTBL    ;address at start of 'CRC' lookup table
  5213.     MVI    C,0
  5214. ;
  5215. CRCGN1    XCHG            ;store table location into 'DE'
  5216.     LXI    H,0        ;clear 'HL' pair
  5217.     MOV    A,C
  5218.     PUSH    B
  5219.     MVI    B,8
  5220.     XRA    H
  5221.     MOV    H,A
  5222. ;
  5223. CRCGN2    DAD    H        ;index into the table
  5224.     JNC    CRCGN3
  5225.     MVI    A,16        ;using x^ 16 + x^12 + x^5 + 1 algorithm
  5226.     XRA    H        ;(called 'SDLC' networking algorithm)
  5227.     MOV    H,A
  5228.     MVI    A,32+1
  5229.     XRA    L
  5230.     MOV    L,A
  5231. ;
  5232. CRCGN3    DCR    B
  5233.     JNZ    CRCGN2        ;make 8 loops, one for each bit
  5234. ;
  5235. ; Value now in 'HL', table address still stored in 'DE'.  Exchange, and
  5236. ; store the 'CRC' value in the two tables after splitting.
  5237. ;
  5238.     POP    B        ;finished borrowing the 'B' register
  5239.     XCHG            ;address back in 'HL', 'CRC' in 'DE'
  5240.     MOV    M,D        ;store 1st part of 'CRC' value
  5241.     INR    H        ;move up 256 bytes
  5242.     MOV    M,E        ;store 2nd part of 'CRC' value
  5243.     DCR    H        ;move back 256 bytes
  5244.     INX    H        ;increment to next location
  5245.     INR    C        ;done when 'C' reg. turns zero again
  5246.     JNZ    CRCGN1        ;now go do the next location
  5247.     RET
  5248. ;
  5249. ; Update the CRC value from a character in the 'A' register
  5250. ;
  5251. CRCUPD    PUSH    PSW        ;save all registers just in case
  5252.     PUSH    B
  5253.     PUSH    D
  5254.     PUSH    H
  5255.     LHLD    CRCVAL        ;get current value
  5256.     XCHG            ;put in 'DE' for now
  5257.     MVI    B,0
  5258.     XRA    D
  5259.     MOV    C,A        ;now have the character in 'BC' pair
  5260.     LXI    H,CRCTBL    ;start of 'CRC' lookup-table
  5261.     DAD    B        ;index into the 'CRC' table
  5262.     MOV    A,M        ;get the value from the table
  5263.     XRA    E
  5264.     MOV    D,A
  5265.     INR    H        ;move 256 bytes for 2nd table location
  5266.     MOV    E,M        ;put value there into 'E' register
  5267.     XCHG            ;put 'DE' into 'HL'
  5268.     SHLD    CRCVAL        ;updated 'CRC' value with this character
  5269.     POP    H        ;restore all registers
  5270.     POP    D
  5271.     POP    B
  5272.     POP    PSW
  5273.     RET
  5274. ;
  5275. ;=========================START OF MENU ================================
  5276. ;
  5277. MENU0    LDA    NFILFLG
  5278.     ORA    A
  5279.     JZ    MENU        ;exit if not saving memory for disk file
  5280.     CALL    ILPRT        ;else print message
  5281.     DB    CR,LF,'** File still open, use DEL, DIR, WRT, E, L '
  5282.     DB    'or T ** ',CR,LF,BELL,0
  5283.     JMP    MENU1
  5284. ;
  5285. MENU    XRA    A
  5286.     STA    ABTFLG        ;null the flag
  5287. ;
  5288. MENU1    LXI    H,RESTSN    ;restore record numbers for new file
  5289.     LXI    D,RECNOB    ;  transfer
  5290.     MVI    B,RECNOE-RECNOB
  5291.     CALL    MOVE
  5292.     LXI    H,RSTOPT    ;restore option table
  5293.     LXI    D,OPTBL
  5294.     MVI    B,OPTBE-OPTBL
  5295.     CALL    MOVE
  5296.     XRA    A
  5297.     STA    FSTFLG
  5298.     STA    TIMFLG
  5299.     STA    FLTRFLG        ;reset multi-file trans
  5300.     STA    MFFLG1
  5301.     JMP    XPRT
  5302. ;
  5303. ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  5304. ;               MENU OF COMMANDS
  5305. ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  5306. ;
  5307. MENU2    CALL    CLRTST
  5308.     CALL    ILPRT
  5309.     DB    '                  Single Letter Commands',CR,LF,LF
  5310.     DB    ' ?  - Display current settings',CR,LF
  5311. MENU3    DB    ' ^  - Function key intercept character, '
  5312.     DB    'then (0-9)',CR,LF
  5313.     DB    ' M  - Display the menu',CR,LF
  5314.     DB    ' E  - Terminal mode with echo',CR,LF
  5315.     DB    ' L  - Terminal mode with local echo',CR,LF
  5316.     DB    ' T  - Terminal mode',CR,LF
  5317.     DB    '         For copying text to disk use T (E or L) '
  5318.     DB    'FILENAME.TYP',CR,LF
  5319.     DB    '         Start or Stop toggles described on subsequent'
  5320.     DB    ' screen.',CR,LF
  5321.     DB    ' R  - Receive CP/M file using Christensen Protocol'
  5322.     DB    CR,LF
  5323.     DB    ' S  - Send CP/M file using Christensen Protocol',CR,LF
  5324.     DB    '         COMMAND: R (or S) FILENAME.TYP',CR,LF
  5325.     DB    '         R and S can use the following subcommands:'
  5326.     DB    CR,LF
  5327.     DB    '            B  - Bulk transfer using wildcards '
  5328.     DB    '(e.g., *.*)',CR,LF
  5329.     DB    '            D  - Disconnect when done'
  5330.     DB    CR,LF
  5331.     DB    '            Q  - Quiet mode (no messages to console)'
  5332.     DB    CR,LF
  5333.     DB    '            V  - View <R> or <S> bytes on console'
  5334.     DB    CR,LF
  5335.     DB    '            X  - When done, disconnect, go to CP/M'
  5336.     DB    CR,LF,LF
  5337.     DB    '      The single letter commands may also be used on '
  5338.     DB    'the',CR,LF
  5339.     DB    '      command line when the program is initially '
  5340.     DB    'executed.',CR,LF,LF,0
  5341. ;
  5342. THRLTR    CALL    J$NXTSCR
  5343.     CALL    ILPRT
  5344.     DB    '                Three Letter Commands',CR,LF,LF
  5345.     DB    'CPM - Exit from this program to CP/M',CR,LF
  5346.     DB    'DIR - List directory and space free (may specify '
  5347.     DB    'drive)',CR,LF
  5348.     DB    'ERA - Erase file (may specify drive)',CR,LF
  5349.     DB    'LOG - Change default drive/user no. (specify '
  5350.     DB    'drive/user)',CR,LF
  5351.     DB    '      and reset disks.  e.g. LOG A0: or LOG B:  '
  5352.     DB    '(user # unchanged)',CR,LF
  5353.     DB    'SPD - Set file output speed in terminal mode'
  5354.     DB    CR,LF,0
  5355. ;
  5356.     CALL    SORPTST
  5357.     JNZ    NOTIME
  5358.     CALL    ILPRT
  5359.     DB    'TIM - Select Baud rate for "time-to-send" msg.',CR,LF,0
  5360. ;
  5361. NOTIME    LDA    TGLECRC
  5362.     ORA    A
  5363.     JZ    NOTOCRC
  5364.     CALL    ILPRT
  5365.     DB    'TCC - Toggle CRC/Checksum mode on receive',CR,LF,0
  5366. ;
  5367. NOTOCRC    LDA    TGLELOC
  5368.     ORA    A
  5369.     JZ    NTOGOC
  5370.     CALL    ILPRT
  5371.     DB    'TLC - Toggle local command immediate or after ',0
  5372.     LDA    EXTCHR
  5373.     CALL    SHFTYPE
  5374.     DB    CR,LF,0
  5375. ;
  5376. NTOGOC    LDA    TGLELF
  5377.     ORA    A
  5378.     JZ    NTOGUB
  5379.     CALL    ILPRT
  5380.     DB    'TLF - Toggle LF after CR in "L" or "T" mode for '
  5381.     DB    'a disk file',CR,LF,0
  5382. ;
  5383. NTOGUB    LDA    TGLERUB
  5384.     ORA    A
  5385.     JZ    NTOGF
  5386.     CALL    ILPRT
  5387.     DB    'TRB - Toggle rubout to backspace conversion',CR,LF,0
  5388. ;
  5389. NTOGF    LDA    TGXOFF
  5390.     ORA    A
  5391.     JZ    NTOGOF
  5392.     CALL    ILPRT
  5393.     DB    'TXO - Toggle XOFF testing in terminal mode '
  5394.     DB    'file output',CR,LF,0
  5395. ;
  5396. NTOGOF    LDA    PMMIMD        ;using a PMMI modem?
  5397.     ORA    A
  5398.     JNZ    NONUM
  5399.     LDA    AUTDIAL        ;using a Hayes-type modem?
  5400.     ORA    A
  5401.     JNZ    NTOG2
  5402. ;
  5403. NTOG1    CALL    ILPRT
  5404.     DB    'NUM - List remote systems',CR,LF,0
  5405. ;
  5406. NTOG2    LDA    STUPTST
  5407.     ORA    A
  5408.     JZ    NONUM
  5409.     CALL    ILPRT
  5410.     DB    'SET - Set modem baud rate',CR,LF,0
  5411. ;
  5412. NONUM    CALL    ILPRT
  5413.     DB    'BYE - Disconnect, then return to CP/M'
  5414.     DB    CR,LF,0
  5415.     LDA    PMMIMD        ;using a PMMI modem?
  5416.     ORA    A
  5417.     JNZ    NONUM0        ;if yes, display 'CAL'
  5418.     LDA    AUTDIAL        ;using a Hayes-type modem?
  5419.     ORA    A
  5420.     JZ    NOPMMI        ;exit if neither
  5421. ;
  5422. NONUM0    CALL    ILPRT
  5423.     DB    'CAL - Dial number',CR,LF,0
  5424. ;
  5425. NOPMMI    CALL    ILPRT
  5426.     DB    'DSC - Disconnect from the phone line',CR,LF,LF
  5427.     DB    '          The following are terminal text '
  5428.     DB    'buffer commands:',CR,LF,LF,0
  5429. ;
  5430. SKPLF    CALL    ILPRT
  5431.     DB    'DEL - Delete memory buffer and file',CR,LF
  5432.     DB    'WRT - Write memory buffer to disk file',CR,LF,LF,0
  5433.     CALL    NXTSCR
  5434.     CALL    ILPRT
  5435.     DB    '        Local Commands while in Terminal Mode'
  5436.     DB    CR,LF,LF,0
  5437.     LDA    BRKCHR
  5438.     CALL    SHFTYPE
  5439.     DB    '  - Send a break tone for 300 ms.',CR,LF,0
  5440.     LDA    PMMIMD
  5441.     ORA    A
  5442.     JZ    SKPLF1
  5443.     LDA    CHGBAUD
  5444.     CALL    SHFTYPE
  5445.     DB    '  - Change baud rate',CR,LF,0
  5446. ;
  5447. SKPLF1    MVI    A,EXITCHR
  5448.     CALL    SHFTYPE
  5449.     DB    '  - Exit to command mode',CR,LF,0
  5450.     LDA    TRANLOG
  5451.     ORA    A
  5452.     JZ    NOTLOG
  5453.     LDA    LOGCHR
  5454.     CALL    SHFTYPE
  5455.     DB    '  - Send log-on message',CR,LF,0
  5456. ;
  5457. NOTLOG    LDA    NOCONCT
  5458.     CALL    SHFTYPE
  5459.     DB    '  - Disconnect from the phone line',CR,LF,0
  5460.     LDA    LSTTST
  5461.     ORA    A
  5462.     JZ    NOLIS
  5463.     LDA    LSTCHR
  5464.     CALL    SHFTYPE
  5465.     DB    '  - Toggle printer',CR,LF,0
  5466. ;
  5467. NOLIS    MVI    A,LF
  5468.     CALL    TYPE
  5469.     LDA    SAVECHR
  5470.     CALL    SHFTYPE
  5471.     DB    '  - Start copy into buffer',CR,LF,0
  5472.     LDA    UNSAVCH
  5473.     CALL    SHFTYPE
  5474.     DB    '  - Stop copy into buffer',CR,LF,LF
  5475.     DB    '             Start & Stop may be toggled as often as '
  5476.     DB    'desired.',CR,LF
  5477.     DB    '             A ";" at start of line indicates buffer '
  5478.     DB    'is copying.',CR,LF
  5479.     DB    '             XOFF automatically used to stop input '
  5480.     DB    'when writing',CR,LF
  5481.     DB    '                full buffer to disk, XON sent to '
  5482.     DB    'resume.',CR,LF,LF,0
  5483.     LDA    TRANCHR
  5484.     CALL    SHFTYPE
  5485.     DB    '  - Transfer ASCII file to remote',CR,LF,LF,0
  5486.     LDA    LOCNXT
  5487.     ORA    A
  5488.     LDA    EXTCHR
  5489.     JNZ    REMDFLT
  5490.     CALL    SHFTYPE
  5491.     DB    '  - Send local control character to remote'
  5492.     DB    CR,LF,LF,0
  5493.     JMP    CKSPCL
  5494. ;
  5495. REMDFLT    CALL    SHFTYPE
  5496.     DB    '  - Next character will be used for local control'
  5497.     DB    CR,LF,0
  5498. ;
  5499. CKSPCL    CALL    J$SPMEN        ;may have a special menu in the overlay
  5500. ;                ;FALLS ON THROUGH TO 'XPRT'
  5501. ;
  5502. ;=======================================================================
  5503. ;            START OF COMMAND LINE HANDLING
  5504. ;
  5505. ; Check first to see if a file was opened for copying incoming to disk
  5506. ;
  5507. XPRT    CALL    CRLF        ;turn up a blank line to look nice
  5508.     LDA    NFILFLG        ;have a file open for text mode copy?
  5509.     ORA    A
  5510.     JZ    XPRT1        ;if not, exit
  5511. ;
  5512.     CALL    GETSPC        ;otherwise show remaining space
  5513.     CALL    ILPRT
  5514.     DB    ' Bytes of buffer free',CR,LF,LF,0
  5515. ;
  5516. ; Show disk drive and user number, then command line
  5517. ;
  5518. XPRT1    MVI    C,CURDSK    ;current disk function
  5519.     CALL    BDOS
  5520.     ADI    'A'        ;make ASCII
  5521.     CALL    TYPE
  5522.     CALL    GETUSER        ;get current user number
  5523.     ORA    A
  5524.     JZ    XPRT2        ;skip if user 0
  5525.     MVI    H,0
  5526.     MOV    L,A
  5527.     CALL    DECOUT        ;show current user area
  5528. ;
  5529. XPRT2    MVI    A,'>'
  5530.     CALL    TYPE
  5531.     MVI    A,'>'
  5532.     CALL    TYPE
  5533.     CALL    ILPRT
  5534.     DB    'COMMAND: ',0
  5535.     XRA    A
  5536.     STA    XFLG        ;null the buffer-length flag
  5537. ;
  5538. ; Get the command line parameters
  5539. ;
  5540. GTCMD    LXI    D,CMDBUF    ;enter command
  5541.     CALL    INBUF
  5542.     LDA    CMDBUF+2
  5543.     CPI    EXITCHR        ;exit character
  5544.     JZ    XPRT1
  5545. ;
  5546. GTCMD1    CPI    '^'        ;function key intercept character
  5547.     JZ    FUNCT        ;   (supplied from 'INTCPT' table)
  5548.     CPI    '?'
  5549.     JZ    CURPAR
  5550.     CPI    ' '
  5551.     JZ    XPRT+3        ;skip the extra line feed
  5552.     LDA    CMDBUF+3
  5553.     CPI    ':'        ;see if request for new drive/user
  5554.     JZ    STDRV
  5555.     LXI    D,CMDBUF+2    ;point to command
  5556.     CALL    INLNCP
  5557.     DB    'CPM',0
  5558.     JNC    EXIT
  5559.     CALL    CRLF        ;(1st CR/LF at 'INBUFR')
  5560.     CALL    INLNCP
  5561.     DB    'LOG',0
  5562.     JNC    LOGNW
  5563.     CALL    INLNCP
  5564.     DB    'DIR',0
  5565.     JNC    DIR
  5566.     CALL    INLNCP
  5567.     DB    'ERA',0
  5568.     JNC    ERASEF
  5569.     CALL    INLNCP
  5570.     DB    'SPD',0
  5571.     JNC    STSPD
  5572.     CALL    INLNCP
  5573.     DB    'TIM',0
  5574.     JNC    STTIM
  5575.     CALL    INLNCP
  5576.     DB    'TCC',0
  5577.     JNC    TGCRC
  5578.     CALL    INLNCP
  5579.     DB    'TRB',0
  5580.     JNC    TGRUB
  5581.     CALL    INLNCP
  5582.     DB    'TLC',0
  5583.     JNC    TGLOC
  5584.     CALL    INLNCP
  5585.     DB    'TLF',0
  5586.     JNC    TGLF
  5587.     CALL    INLNCP
  5588.     DB    'TXO',0
  5589.     JNC    TGTXOFF
  5590.     LDA    PMMIMD        ;using a PMMI  modem?
  5591.     ORA    A
  5592.     JNZ    NONUM1        ;if yes, exit
  5593.     LDA    AUTDIAL        ;using a Hayes-type modem?
  5594.     ORA    A
  5595.     JNZ    NONUM1        ;if yes, exit
  5596.     CALL    INLNCP
  5597.     DB    'NUM',0
  5598.     JNC    NUMPR
  5599. ;
  5600. NONUM1    LDA    STUPTST
  5601.     ORA    A
  5602.     JZ    NXOPT1
  5603.     CALL    INLNCP
  5604.     DB    'SET',0
  5605.     JNC    STUPENT
  5606. ;
  5607. NXOPT1    CALL    INLNCP
  5608.     DB    'WRT',0
  5609.     JNC    WRFIL
  5610.     CALL    INLNCP
  5611.     DB    'DEL',0
  5612.     JNC    NEWFILE
  5613.     CALL    INLNCP
  5614.     DB    'BYE',0
  5615.     JNC    BYEBYE
  5616.     CALL    INLNCP
  5617.     DB    'DSC',0
  5618.     JNC    DONETD
  5619.     LDA    PMMIMD        ;using a PMMI modem?
  5620.     ORA    A
  5621.     JNZ    NXOPT0        ;if yes, exit
  5622.     LDA    AUTDIAL        ;using a Hayes-type modem?
  5623.     ORA    A
  5624.     JZ    NXOPT2        ;exit if neither modem-type
  5625. ;
  5626. NXOPT0    CALL    INLNCP        ;'DE' set from 1st 'INLNCP' call
  5627.     DB    'CAL',0
  5628.     JC    NXOPT2
  5629.     MVI    A,' '        ;fool the system
  5630.     STA    CMDBUF+3    ;  'TBUF' so that it
  5631.     JMP    DOOPT        ;  looks at option for dial
  5632. ;
  5633. NXOPT2    LDA    CMDBUF+2
  5634.     LXI    H,COMLST
  5635.     CALL    COMPARE        ;compares list pointed to by HL
  5636.     JC    NOTVLD        ;carry set = no match
  5637. ;
  5638. DOOPT    CALL    STFCB        ;loads command buffer into FCB
  5639.     CALL    PROCOPT        ;check out the options
  5640.     JMP    RSTRT        ;go to work
  5641. ;
  5642. NOTVLD    CALL    NVLDMS
  5643.     JMP    XPRT
  5644. ;
  5645. NVLDMS    CALL    ILPRT
  5646.     DB    '++ Invalid command ++',CR,LF,BELL,0
  5647.     RET
  5648. ;
  5649. FUNCT    LDA    INTCPT        ;get the function key intercept char.
  5650.     ANI    07FH        ;strip off any parity
  5651.     PUSH    PSW        ;save the character for now
  5652.     CALL    CLRTST
  5653.     CALL    ILPRT
  5654.     DB    '         SPECIAL FUNCTION KEY TABLE'
  5655.     DB    CR,LF,LF,0
  5656.     POP    PSW        ;get the character back
  5657.     CPI    ' '        ;see if a printing character
  5658.     JNC    FUNCT1        ;if a printing character, show it
  5659.     PUSH    PSW
  5660.     CALL    ILPRT
  5661.     DB    'CTL-',0
  5662.     POP    PSW
  5663.     ADI    40H        ;convert binary to ASCII character
  5664. ;
  5665. FUNCT1    CALL    TYPE        ;show on the CRT
  5666.     CALL    ILPRT
  5667.     DB    ' current function key intercept character',CR,LF,LF,0
  5668. ;
  5669. ; Shows the functions of the (0-9) keys
  5670. ;
  5671.     LXI    H,FNCTBL-1    ;index into the function key table
  5672.     MVI    B,10        ;has ten entries
  5673. ;
  5674. FUNCT2    INX    H        ;next table location
  5675.     MOV    A,M        ;get the binary function number
  5676.     ADI    '0'        ;convert binary to ASCII digits
  5677.     CALL    TYPE
  5678.     MVI    A,' '
  5679.     CALL    TYPE
  5680. ;
  5681. FUNCT3    INX    H        ;next table location
  5682.     MOV    A,M
  5683.     ORA    A        ;see if a binary zero
  5684.     JZ    FUNCT5
  5685.     CPI    CR
  5686.     JNZ    FUNCT4
  5687.     CALL    ILPRT
  5688.     DB    '<CR>',0
  5689.     JMP    FUNCT3
  5690. ;
  5691. FUNCT4    CALL    TYPE
  5692.     JMP    FUNCT3
  5693. ;
  5694. FUNCT5    CALL    CRLF
  5695.     DCR    B
  5696.     JNZ    FUNCT2
  5697.     CALL    CRLF
  5698.     JMP    XPRT
  5699. ;
  5700. BYEBYE    LDA    PMMIMD        ;using a PMMI modem?
  5701.     ORA    A
  5702. ;;;    CNZ    J$GOODBY    ;if yes, disconnect
  5703.     DB    0,0,0        ;(PREVENT DOUBLE DISCONNECT)
  5704.     LDA    AUTDIAL        ;using a Hayes-type modem?
  5705.     ORA    A
  5706.     CNZ    SMRST        ;if yes, disconnect
  5707.     CALL    J$GOODBY    ;user's custom-area goodbye routine
  5708.     CALL    ILPRT
  5709.     DB    CR,LF,'<< Exit to CP/M >>',CR,LF,0
  5710.     JMP    EXIT    ;return to CP/M
  5711. ;
  5712. SMRST    MVI    B,20
  5713.     CALL    TIMER
  5714.     LXI    H,SM$DISC
  5715.     CALL    SNDOUT
  5716.     MVI    B,20
  5717.     CALL    TIMER
  5718.     MVI    A,' '
  5719. ;
  5720. ; If showing the +++ and ATH and ATD, etc. move the three semicolons up
  5721. ; one line.
  5722. ;
  5723.     DB    0,0,0
  5724. ;;;    CALL    TYPE
  5725.     LXI    H,SM$ATZ
  5726.     CALL    SNDOUT
  5727. ;
  5728. SMRST1    MVI    B,2
  5729.     CALL    RECV
  5730.     JNC    SMRST1
  5731.     RET
  5732. ;
  5733. SM$ATZ    DB    'ATZ',CR,'$'
  5734. ;
  5735. DIR    MVI    C,CURDSK
  5736.     CALL    BDOS
  5737.     STA    DISKSAV
  5738.     CALL    DRLST
  5739.     LDA    DISKSAV
  5740.     MOV    E,A
  5741.     MVI    C,SELDSK
  5742.     CALL    BDOS
  5743.     JMP    XPRT
  5744. ;
  5745. ERASEF    LXI    D,CMDBUF    ;put cmd line into FCB at 'HL'
  5746.     LXI    H,FCB
  5747.     CALL    CMDLINE
  5748.     CALL    MOVEFCB        ;move FCB+16 to FCB
  5749.     LDA    FCB+1
  5750.     CPI    ' '
  5751.     JZ    NOTVLD        ;go if no file specified
  5752.     LXI    D,FCB
  5753.     MVI    C,SRCHF
  5754.     CALL    BDOS
  5755.     INR    A        ;0 if file not found
  5756.     JNZ    ERAFILE        ;ok, go erase
  5757.     CALL    ILPRT
  5758.     DB    '++ File not found ++',CR,LF,BELL,0
  5759.     JMP    XPRT
  5760. ;
  5761. ERAFILE    LXI    D,FCB
  5762.     MVI    C,ERASE
  5763.     CALL    BDOS
  5764.     CALL    ILPRT
  5765.     DB    'File erased',CR,LF,0
  5766.     JMP    XPRT
  5767. ;
  5768. LOGNW    LDA    NFILFLG        ;file open for memory save to disk?
  5769.     ORA    A
  5770.     JNZ    NORESET        ;if yes, do not reset disk drive now
  5771.     LDA    CMDBUF+6    ;any disk drive specified?
  5772.     CPI    ' '
  5773.     JNZ    LOGNW1        ;if not a blank, exit
  5774.     CALL    GETDISK        ;if not, use current drive
  5775.     ADI    'A'        ;to compensate for next line
  5776. ;
  5777. LOGNW1    SUI    'A'
  5778.     CPI    15+1        ;for drives 0-15
  5779.     JNC    NOTVLD        ;if more than 15, display error message
  5780.     STA    DISKSAV        ;store requested drive
  5781.     CALL    GETUSER        ;pick up current user number
  5782.     MOV    B,A        ;save it
  5783.     LDA    CMDBUF+7    ;get new user number
  5784.     CALL    CHRCK        ;check the character
  5785.     CALL    FNDUSR
  5786.     LDA    CMDBUF+8    ;get 2nd digit
  5787.     CALL    CHRCK        ;check the character
  5788.     CALL    FNDUSR+2
  5789. ;
  5790. LOGNW2    CALL    SVUSER
  5791.     MVI    C,RESET
  5792.     CALL    BDOS
  5793.     LDA    DISKSAV
  5794.     MOV    E,A
  5795.     MVI    C,SELDSK
  5796.     CALL    BDOS
  5797.     LDA    SAVUSR
  5798.     MOV    E,A
  5799.     CALL    STUSER
  5800.     JMP    XPRT
  5801. ;
  5802. CHRCK    CPI    ' '
  5803.     JZ    CHRCK1
  5804.     CPI    ':'        ;in case of A: or A1: or A11:  (etc.)
  5805.     RNZ
  5806. ;
  5807. CHRCK1    POP    PSW        ;reset the 'CALL' on the stack
  5808.     JMP    LOGNW2
  5809. ;
  5810. FNDUSR    MVI    B,0        ;zero the 'B' reg. for 1st time through
  5811.     CALL    NUMCHK        ;if neither, see if a valid number
  5812.     MOV    C,A        ;save
  5813.     MOV    A,B        ;get save first digit
  5814.     ADD    A        ;x2
  5815.     ADD    A        ;x4
  5816.     ADD    A        ;x8
  5817.     ADD    B        ;x9
  5818.     ADD    B        ;x10
  5819.     ADD    C
  5820.     MOV    B,A        ;save
  5821.     RET
  5822. ;
  5823. SVUSER    MOV    A,B
  5824.     CPI    15+1        ;user numbers are 0-15
  5825.     JNC    NOTVLD
  5826.     STA    SAVUSR
  5827.     RET
  5828. ;
  5829. NUMGET    LXI    D,CMDBUF
  5830.     CALL    INBUF
  5831.     LDA    CMDBUF+2    ;get number
  5832.     CPI    ' '
  5833.     RZ
  5834. ;
  5835. NUMCHK    SUI    '0'        ;remove ascii bias
  5836.     CPI    9+1
  5837.     RC            ;ok if 9 or less
  5838.     POP    H        ;remove 1st call from the stack
  5839.     POP    H        ;remove 2nd call from the stack
  5840.     JMP    NOTVLD
  5841. ;
  5842. GETUSER    MVI    E,0FFH        ;get current user
  5843. ;
  5844. STUSER    MVI    C,USER        ;set up BDOS call
  5845.     JMP    BDOS
  5846. ;
  5847. GETDISK    MVI    C,CURDSK    ;get current drive
  5848.     JMP    BDOS
  5849. ;
  5850. NORESET    CALL    ILPRT
  5851.     DB    '++      Terminal mode file open      ++',CR,LF
  5852.     DB    '++ Use WRT or DEL before LOG command ++',CR,LF
  5853.     DB    CR,LF,BELL,0
  5854.     XRA    A
  5855.     JMP    XPRT
  5856. ;
  5857. STSPD    CALL    ILPRT
  5858.     DB    'Delay between chars. (0-9): ',0
  5859. ;
  5860. NOKYS    CALL    STAT
  5861.     JZ    NOKYS
  5862.     CALL    KEYIN
  5863.     CALL    TYPE
  5864.     CALL    SAVEA
  5865.     SUI    '0'
  5866.     CPI    10
  5867.     JNC    NOTVLD
  5868.     STA    BYTDLY
  5869. ;
  5870.     CALL    ILPRT
  5871.     DB    'Delay at end of line (0-9): ',0
  5872. ;
  5873. NOKYS1    CALL    STAT
  5874.     JZ    NOKYS1
  5875.     CALL    KEYIN
  5876.     CALL    TYPE
  5877.     CALL    SAVEA
  5878.     SUI    '0'
  5879.     CPI    10
  5880.     JNC    NOTVLD
  5881.     STA    CRDLY
  5882. ;
  5883. SPDMSG    CALL    ILPRT
  5884.     DB    CR,LF,'Char. delay (terminal file mode) is:  ',0
  5885.     LDA    BYTDLY
  5886.     MOV    B,A
  5887.     MOV    A,B
  5888.     PUSH    H
  5889.     MOV    L,A
  5890.     MVI    H,0
  5891.     CALL    DECOUT
  5892.     POP    H
  5893.     CALL    ILPRT
  5894.     DB    '0 ms. per character',CR,LF
  5895.     DB    'Line  delay (terminal file mode) is: ',0
  5896.     LDA    CRDLY
  5897.     MOV    B,A
  5898.     PUSH    H
  5899.     MOV    L,A
  5900.     MVI    H,0
  5901.     CALL    DECOUT
  5902.     POP    H
  5903.     CALL    ILPRT
  5904.     DB    '00 ms. per character',CR,LF,0
  5905.     JMP    XPRT
  5906. ;
  5907. SAVEA    PUSH    PSW
  5908.     CALL    ILPRT
  5909.     DB    CR,LF,0
  5910.     POP    PSW
  5911.     RET
  5912. ;
  5913. STDRV    LDA    CMDBUF+2    ;get the disk drive
  5914.     SUI    'A'        ;convert to binary value
  5915.     CPI    15+1        ;for drives 0-15
  5916.     JNC    NOTVLD
  5917.     MOV    E,A
  5918.     MVI    C,SELDSK    ;select requested drive
  5919.     CALL    BDOS
  5920.     LDA    CMDBUF+5    ;get user number, if any
  5921.     CPI    ' '        ;keep current user area?
  5922.     JZ    XPRT
  5923.     SUI    '0'        ;convert to binary value
  5924.     CPI    1        ;if a '1', could be units or tens
  5925.     JNZ    STDRV1        ;if not, numbers stop at 15 so exit
  5926.     LDA    CMDBUF+6    ;check for a 2nd digit
  5927.     CPI    '0'
  5928.     JC    STDRV2        ;if less, not a valid number, ignore
  5929.     SUI    '0'-10        ;leave the '10' in as two digits used
  5930. ;
  5931. STDRV1    CPI    15+1        ;user areas are 0-15
  5932.     JNC    NOTVLD
  5933.     MOV    E,A
  5934.     CALL    STUSER
  5935.     JMP    XPRT        ;back to work
  5936. ;
  5937. STDRV2    MVI    A,1
  5938.     JMP    STDRV1
  5939. ;
  5940. STTIM    CALL    SORPTST
  5941.     JNZ    NOTVLD
  5942.     CALL    ILPRT
  5943.     DB    'Use 0-8 to give baud rate for ''S'' mode '
  5944.     DB    'time-to-send message,',CR,LF
  5945.     DB    'where 0=110, 1=300, 2=450, 3=600, 4=710, 5=1200, '
  5946.     DB    '6=2400, ',CR,LF,'7=4800 8=9600 and 9=19200 Baud.'
  5947.     DB    CR,LF,LF,'Enter value: ',0
  5948.     CALL    NUMGET
  5949.     CPI    9+1        ;only looking for 0-9 answers
  5950.     JNC    NOTVLD
  5951.     STA    MSPEED
  5952.     CALL    STTIM1
  5953.     JMP    XPRT
  5954. ;
  5955. STTIM1    CALL    SORPTST
  5956.     JNZ    STTIM2
  5957.     CALL    ILPRT
  5958.     DB    'Rate for the S mode time-to-send message is set to ',0
  5959.     JMP    STTIM3
  5960. ;
  5961. STTIM2    CALL    ILPRT
  5962.     DB    'Modem speed is ',0
  5963. ;
  5964. STTIM3    JMP    PRTBAUD
  5965. ;
  5966. SORPTST    LDA    STUPTST        ;if setup is 'YES' or PMMIMD is
  5967.     MOV    B,A        ;  'YES' or autodial modem is 'YES'
  5968.     LDA    PMMIMD        ;  return with zero bit not set
  5969.     ORA    B
  5970.     RNZ
  5971.     LDA    AUTDIAL
  5972.     ORA    B
  5973.     RET
  5974. ;
  5975. TGCRC    LDA    TGLECRC        ;allowing CRC/CHECKSUM toggle?
  5976.     ORA    A
  5977.     JZ    NOTVLD        ;if not, exit
  5978.     LDA    CRCDFLT        ;get present value and switch it
  5979.     CMA
  5980.     STA    CRCDFLT
  5981.     CALL    TGCRC1        ;show on CRT it has been changed
  5982.     JMP    XPRT
  5983. ;
  5984. TGCRC1    CALL    ILPRT
  5985.     DB    'Mode: ',0
  5986.     LDA    CRCDFLT        ;see if set for 'CRC' or 'CHECKSUM'
  5987.     ORA    A
  5988.     JZ    CHEKMSG
  5989.     CALL    ILPRT
  5990.     DB    'CRC',CR,LF,0
  5991.     RET
  5992. ;
  5993. CHEKMSG    CALL    ILPRT
  5994.     DB    'CHECKSUM',CR,LF,0
  5995.     RET
  5996. ;
  5997. TGRUB    LDA    TGLERUB
  5998.     ORA    A
  5999.     JZ    NOTVLD
  6000.     LDA    CONVRUB
  6001.     CMA
  6002.     STA    CONVRUB
  6003.     CALL    TGRUB1
  6004.     JMP    XPRT
  6005. ;
  6006. TGRUB1    LDA    CONVRUB
  6007.     ORA    A
  6008.     JZ    NORUBMS
  6009.     CALL    ILPRT
  6010.     DB    'Rub is backspace',CR,LF,0
  6011.     RET
  6012. ;
  6013. NORUBMS    CALL    ILPRT
  6014.     DB    'Rub is rub',CR,LF,0
  6015.     RET
  6016. ;
  6017. TGLOC    LDA    TGLELOC
  6018.     ORA    A
  6019.     JZ    NOTVLD
  6020.     LDA    LOCNXT
  6021.     CMA
  6022.     STA    LOCNXT
  6023.     CALL    TGLOC1
  6024.     JMP    XPRT
  6025. ;
  6026. TGLOC1    CALL    ILPRT
  6027.     DB    'Use ',0
  6028.     LDA    LOCNXT
  6029.     ORA    A
  6030.     LDA    EXTCHR
  6031.     JZ    LOCMSG
  6032.     CALL    SHFTYPE
  6033.     DB    ' before local command',CR,LF,0
  6034.     RET
  6035. ;
  6036. LOCMSG    CALL    SHFTYPE
  6037.     DB    ' to send local command to remote',CR,LF,0
  6038.     RET
  6039. ;
  6040. TGLF    LDA    TGLELF
  6041.     ORA    A
  6042.     JZ    NOTVLD
  6043.     LDA    ADDLFD
  6044.     CMA
  6045.     STA    ADDLFD
  6046.     CALL    TGLF1
  6047.     JMP    XPRT
  6048. ;
  6049. TGLF1    CALL    ILPRT
  6050.     DB    'LF ',0
  6051.     LDA    ADDLFD        ;adding LF after CR?
  6052.     ORA    A
  6053.     JNZ    LFMSG        ;if yes, exit
  6054.     CALL    ILPRT
  6055.     DB    'NOT ',0
  6056. ;
  6057. LFMSG    CALL    ILPRT
  6058.     DB    'sent after CR in "L" or "T" for a disk file',CR,LF,0
  6059.     RET
  6060. ;
  6061. TGTXOFF    LDA    TGXOFF
  6062.     ORA    A
  6063.     JZ    NOTVLD
  6064.     CALL    ILPRT
  6065.     DB    'Use XOFF testing? (Y/N): ',0
  6066.     CALL    GETANS
  6067.     JC    NOCHG3
  6068.     STA    XOFFTST
  6069. ;
  6070. NOCHG3    CALL    XOFFMSG
  6071.     CALL    ILPRT
  6072.     DB    CR,LF,'Use XON waiting after <CR> (Y/N): ',0
  6073.     CALL    GETANS
  6074.     JC    NOCHG4
  6075.     STA    XONWAIT
  6076. ;
  6077. NOCHG4    CALL    XONMS
  6078.     LDA    XONWAIT
  6079.     ORA    A
  6080.     JZ    XPRT
  6081.     CMA
  6082.     STA    XOFFTST        ;do not allow both
  6083.     CALL    ILPRT
  6084.     DB    'Therefore ',0
  6085.     CALL    XOFFMSG
  6086.     JMP    XPRT
  6087. ;
  6088. GETANS    LXI    D,CMDBUF
  6089.     CALL    INBUF
  6090.     LDA    CMDBUF+2    ;get answer
  6091.     CPI    ' '
  6092.     CMC            ;set the carry flag
  6093.     RZ
  6094.     MOV    B,A
  6095.     CPI    'N'
  6096.     MVI    A,0
  6097.     RZ
  6098.     MOV    A,B
  6099.     CPI    'Y'
  6100.     MVI    A,1
  6101.     RZ
  6102.     POP    PSW        ;preserve stack
  6103.     JMP    NOTVLD
  6104. ;
  6105. XOFFMSG    CALL    ILPRT
  6106.     DB    'XOFF testing ',0
  6107.     LDA    XOFFTST
  6108.     ORA    A
  6109.     JNZ    XOTSTON
  6110.     CALL    ILPRT
  6111.     DB    'NOT ',0
  6112. ;
  6113. XOTSTON    CALL    ILPRT
  6114.     DB    'used',0
  6115. ;
  6116. XONMS1    CALL    ILPRT
  6117.     DB    ' in terminal mode file output',CR,LF,0
  6118.     RET
  6119. ;
  6120. XONMS    CALL    ILPRT
  6121.     DB    'XON ',0
  6122.     LDA    XONWAIT
  6123.     ORA    A
  6124.     JNZ    XONMS2
  6125.     CALL    ILPRT
  6126.     DB    'NOT ',0
  6127. ;
  6128. XONMS2    CALL    ILPRT
  6129.     DB    'automatically tested after CR',0
  6130.     JMP    XONMS1
  6131. ;
  6132. STUPENT    LDA    STUPTST
  6133.     ORA    A
  6134.     JZ    NOTVLD
  6135.     LXI    D,CMDBUF+1
  6136.     CALL    J$STUPR
  6137.     LDA    AUTDIAL        ;using a Hayes-type modem?
  6138.     ORA    A
  6139.     JZ    XPRT        ;if not, exit, otherwise
  6140.     MVI    B,'A'        ;  send 'AT',CR to autodial modem
  6141.     CALL    SNDCHR        ;  to insure its baud rate
  6142.     MVI    B,'T'        ;  matches that just selected
  6143.     CALL    SNDCHR
  6144.     MVI    B,CR
  6145.     CALL    SNDCHR
  6146.     JMP    XPRT
  6147. ;
  6148. NEWFILE    LDA    NFILFLG        ;file open for disk save?
  6149.     ORA    A
  6150.     JZ    NFILOP        ;if not, show "no file open" message
  6151.     LDA    FCB3+1        ;check that file was requested
  6152.     CPI    ' '
  6153.     JZ    NFILOP        ;if no file, do not erase
  6154.     LXI    D,FCB3        ;otherwise erase the old file
  6155.     MVI    C,ERASE
  6156.     CALL    BDOS
  6157.     XRA    A
  6158.     STA    NFILFLG        ;no file mentioned, reset flags
  6159.     STA    SAVEFLG
  6160.     LXI    H,FCB3
  6161.     CALL    INITFCB
  6162.     LXI    H,BUFFER    ;reset flags to bottom of ram just
  6163.     SHLD    HLSAV        ; to insure they are there
  6164.     JMP    XPRT
  6165. ;
  6166. WRFIL    LDA    NFILFLG        ;saving memory for a disk file?
  6167.     ORA    A
  6168.     JZ    NFILOP        ;not saving a file, don't bother writing
  6169.     CALL    WRFIL1        ;close the file
  6170.     STA    SAVEFLG
  6171.     STA    WRFLG
  6172.     LXI    H,FCB3
  6173.     CALL    INITFCB        ;blank out 'FCB' to written file
  6174.     LXI    H,BUFFER    ;can not be erased
  6175.     SHLD    HLSAV        ;reset to buffer start for next time
  6176.     JMP    XPRT
  6177. ;
  6178. WRFIL1    LDA    FCB3+1        ;check that file was requested
  6179.     CPI    ' '
  6180.     RZ
  6181.     CALL    WRDSK        ;write buffer to disk if not empty
  6182. ;
  6183. WRFIL2    LXI    D,FCB3        ;close the file
  6184.     MVI    C,CLOSE
  6185.     CALL    BDOS
  6186.     XRA    A
  6187.     STA    NFILFLG        ;file written, reset flags
  6188.     RET
  6189. ;
  6190. NFILOP    CALL    ILPRT
  6191.     DB    '++ No File Open ++',CR,LF,BELL,0
  6192.     JMP    XPRT
  6193. ;
  6194. ; THIS ROUTINE DISPLAYS THE PHONE NUMBERS IN THE LIBRARY
  6195. ;
  6196. NUMPR    PUSH    H
  6197.     CALL    CLRTST
  6198.     CALL    ILPRT
  6199.     DB    '           Library of Phone Numbers of Remote Systems'
  6200.     DB    0
  6201.     MVI    C,18        ;number of lines to move
  6202.     LXI    H,NUMLIB    ;address of source memory
  6203.     LXI    D,BUFFER    ;address of target memory
  6204.     CALL    NEWLINE        ;start with CRLF
  6205.     STAX    D        ;+LF
  6206.     INX    D        ;and bump it
  6207. ;
  6208. NUMPR1    INX    H        ;skip PMMI dialing letter
  6209.     INX    H        ;and equal sign
  6210.     MVI    B,LIBLEN-2    ;number of bytes to move
  6211.     CALL    MOVE        ;move to buffer
  6212.     CALL    SPACES        ;2 entries + 3 spaces = 63 characters
  6213.     PUSH    H        ;save source address
  6214.     PUSH    D        ;save destination address
  6215.     INX    H        ;skip next two characters
  6216.     INX    H
  6217.     LXI    D,(17*LIBLEN)    ;get offset of 17 times entry length
  6218.     DAD    D        ;add it to the source address
  6219.     POP    D        ;restore destination address
  6220.     MVI    B,LIBLEN-2    ;get length of library entry
  6221.     CALL    MOVE        ;move another entry
  6222.     POP    H        ;restore source address
  6223.     CALL    NEWLINE        ;start next line
  6224.     DCR    C        ;one less line to print
  6225.     JNZ    NUMPR1        ;if not finished, do another
  6226.     MVI    A,'$'
  6227.     STAX    D
  6228.     MVI    C,PRINT
  6229.     LXI    D,BUFFER    ;point to table of numbers to print
  6230.     CALL    BDOS
  6231.     CALL    CRLF
  6232.     CALL    CRLF
  6233.     POP    H
  6234.     JMP    XPRT        ;finished, back to prompt
  6235. ;
  6236. NEWLINE    MVI    A,CR        ;puts CRLF at memory pointed by 'DE'
  6237.     STAX    D        ;store it
  6238.     MVI    A,LF        ;line feed
  6239.     INX    D        ;bump pointer
  6240.     STAX    D        ;store lf
  6241.     INX    D        ;bump pointer
  6242.     RET
  6243. ;
  6244. SPACES    MVI    A,' '        ;space
  6245.     STAX    D
  6246.     INX    D        ;1
  6247.     STAX    D
  6248.     INX    D        ;2
  6249.     STAX    D
  6250.     INX    D        ;3
  6251.     RET
  6252. ;
  6253. COMPARE    MOV    B,M        ;compares 'A' register with list
  6254. ;
  6255. COMPLP    INX    H        ;addressed by HL - first element
  6256.     CMP    M        ;of list must be number of elements
  6257.     JZ    VALID        ;being compared. returns with
  6258.     DCR    B        ;carry set if 'A' reg. does not
  6259.     JNZ    COMPLP        ;contain an element in list
  6260.     STC
  6261. ;
  6262. VALID    RET
  6263. ;
  6264. NXTSCR    CALL    ILPRT
  6265.     DB    'HIT any KEY to CONTINUE',0
  6266. ;
  6267. NOKEY1    CALL    STAT        ;get keyboard status
  6268.     JZ    NOKEY1        ;keep looping until keypress
  6269.     CALL    KEYIN        ;gobble up keypress
  6270.     CPI    'C'-40H        ;control-c to abort?
  6271.     JNZ    CLRTST
  6272.     POP    H        ;clear stack of return address
  6273.     CALL    CRLF        ;turn up a blank line
  6274.     JMP    XPRT
  6275. ;
  6276. CLRTST    LDA    SCRNTST
  6277.     ORA    A
  6278.     JNZ    CLRSCR
  6279. ;
  6280. LOTSALF    MVI    A,CR
  6281.     CALL    TYPE
  6282.     MVI    B,12
  6283.     MVI    A,LF
  6284. ;
  6285. LFLOOP    CALL    TYPE
  6286.     DCR    B
  6287.     JNZ    LFLOOP
  6288.     RET
  6289. ;
  6290. CURPAR    CALL    CLRTST
  6291.     CALL    ILPRT
  6292.     DB    '                Current Settings',CR,LF,LF,0
  6293.     CALL    TGCRC1
  6294.     CALL    TGRUB1
  6295.     LDA    LSTTST
  6296.     ORA    A
  6297.     JZ    NOLIS1
  6298.     CALL    LSTMS
  6299. ;
  6300. NOLIS1    CALL    STTIM1
  6301.     CALL    ILPRT
  6302.     DB    'Terminal mode file buffer is ',0
  6303.     LDA    NFILFLG        ;saving memory for a disk file?
  6304.     ORA    A
  6305.     JNZ    ACTIVE        ;if yes, go say "active"
  6306.     CALL    ILPRT
  6307.     DB    'in',0        ;if not, say "inactive"
  6308. ;
  6309. ACTIVE    CALL    ILPRT
  6310.     DB    'active',CR,LF,'Unused portion of buffer is ',0
  6311.     CALL    GETSPC
  6312.     CALL    ILPRT
  6313.     DB    ' bytes',CR,LF,0
  6314.     CALL    TGLOC1
  6315.     CALL    TGLF1
  6316.     CALL    XOFFMSG
  6317.     CALL    XONMS
  6318.     CALL    SPDMSG
  6319.     CALL    CRLF
  6320.     CALL    CRLF
  6321.     CALL    CRLF
  6322.     JMP    XPRT
  6323. ;
  6324. GETSPC    LXI    D,BUFTOP    ;top of memory buffer
  6325.     LHLD    HLSAV        ;current buffer location
  6326.     XCHG
  6327.     XRA    A        ;clear the carry bit, if set
  6328.     SUB    E
  6329.     MOV    L,A
  6330.     MOV    A,H
  6331.     SBB    D
  6332.     MOV    H,A
  6333.     CALL    DECOUT        ;print the space remaining
  6334.     RET
  6335. ;
  6336. ;***********************************************************************
  6337. ;        DATA AREA
  6338. ;***********************************************************************
  6339. ;
  6340. COMLST    DB    6,'S','R','T','E','L','M'
  6341. ;
  6342. ; OPTION TABLE
  6343. ;
  6344. OPTBL    EQU    $
  6345. ANSWFLG    DB    'A'
  6346. BCHFLG    DB    'B'
  6347. DISCFLG    DB    'D'
  6348. JMPCMD    DB    'J'
  6349. LOCLFG    DB    'L'
  6350. ORIGFLG    DB    'O'
  6351. QFLG    DB    'Q'
  6352. RSEEFLG    DB    'R'
  6353. SSEEFLG    DB    'S'
  6354. VSEEFLG    DB    'V'
  6355. XITFLG    DB    'X'
  6356. EPRITY    DB    '0'    ;even parity sub-option (only in S or R mode)
  6357. OPRITY    DB    '1'    ;odd parity sub-option    (only in S or R mode)
  6358. OPTBE    EQU    $    ;transfer when program initially called.
  6359. ;
  6360. ; The following must be in the same order as the table above
  6361. ;
  6362. RSTOPT    DB    'A','B','D','J','L','O','Q','R','S','V','X','0','1'
  6363. ;
  6364. ; The next 14 bytes equal the number of bytes between RECNOB and
  6365. ; RECNOE.
  6366. ;
  6367. RESTSN    DB    0,0,0,0,0,0
  6368.     DW    BUFFER
  6369.     DB    0,0,0,0,0,NAK
  6370. ;
  6371. RECNOB    EQU    $        ;start of table marker
  6372. RCVRNO    DB    0        ;\
  6373. RECNO    DB    0,0        ; \
  6374. ERRCT    DB    0        ;  \
  6375. ERRCDE    DB    0        ;   \
  6376. EOFLG    DB    0        ;    \    14 bytes between table markers
  6377. RECPTR    DW    BUFFER        ;    /
  6378. RECINBF    DB    0        ;   /
  6379. MAXEXT    DB    0        ;  /
  6380. RCNT    DB    0,0        ; /
  6381. DATAFLG    DB    0        ;/
  6382. BENHERE    DB    NAK        ;
  6383. RECNOE    EQU    $        ;end of table marker
  6384. ;
  6385. ; Additional 16-bit initialized storage
  6386. ;
  6387. CRCVAL    DW    0
  6388. DIALCT    DW    0
  6389. HLSAV    DW    BUFFER
  6390. HLSAV1    DW    PBUFF
  6391. HLSAV2    DW    PBUFF
  6392. ;
  6393. ; Additional general purpose initialized storage
  6394. ;
  6395. ABTFLG    DB    0
  6396. ACKFLG    DB    0
  6397. CRCFLAG    DB    0
  6398. CRFLAG    DB    0
  6399. CURRENT    DB    52        ;PMMI 300 baud speed value
  6400. DLYFLG    DB    0        ;  (defaults to 300)
  6401. ECHOFLG    DB    0
  6402. EXACFLG    DB    0
  6403. FIRSTME    DB    0
  6404. FNKFLG    DB    0        ;function key activity flag
  6405. FSTFLG    DB    0
  6406. LISTFLG    DB    0
  6407. LOCFLG    DB    0
  6408. MFFLG1    DB    0
  6409. MDCTLB    DB    07FH
  6410. NFILFLG    DB    0
  6411. ONERR    DB    0
  6412. OPTION    DB    0
  6413. ORIGSAV    DB    0
  6414. RNGBKFL    DB    0
  6415. SAVEFLG    DB    0
  6416. UARTCT    DB    ORIGMOD        ;for originate mode
  6417. WRFLG    DB    0
  6418. XFLG    DB    0
  6419. CMDBUF    DB    80H,0        ;command buffer control area
  6420. ;
  6421. ; General purpose unitialized storage area
  6422. ;
  6423.     DS    128        ;storage area for 'CMDBUF'
  6424. BGNMS    DS    2
  6425. TIMFLG    DS    1
  6426. FLTRFLG    DS    1
  6427. CHRFLG    DS    1
  6428. TIMVAL    DS    2
  6429. QUIKTIM    DS    2
  6430. DISKNO    DS    1
  6431. DISKSAV    DS    1
  6432. DSTORE    DS    1
  6433. FILECT    DS    1
  6434. FTYCNT    DS    1
  6435. MAXRAM    DS    1
  6436. NAMECT    DS    1
  6437. NBSAVE    DS    2
  6438. OLDUSER    DS    1
  6439. SNDFLG    DS    1
  6440. SAVUSR    DS    1
  6441. ;
  6442. FCB3    DS    33
  6443. FCB4    DS    33
  6444. FCBBUF    DS    15
  6445. MFNAM5    DS    12
  6446. MFNAM6    DS    12        ;current name
  6447.     DS    100        ;minimum stack depth
  6448. ;
  6449. EVNPAGE    EQU    ($+255)/256*256    ;sets buffers on even page
  6450. ;
  6451.     ORG    EVNPAGE
  6452. ;
  6453. STACK    EQU    EVNPAGE-2    ;store original stack pointer
  6454. CRCTBL    DS    512        ;two tables of 128 bytes each
  6455. BUFFDSK    DS    128        ;buffer for disk save
  6456. BUFFPNT    DS    128        ;buffer for printer
  6457. BUFFER    DS    1024*BUFSIZ    ;send/receive file buffer
  6458. BUFTOP    DS    0        ;filled in when length is found
  6459. PBUFF    EQU    $        ;printer buffer starts here
  6460. NAMEBUF    EQU    $        ;batch-mode filenames buffer
  6461. ;
  6462. ; BDOS EQUATES
  6463. ;
  6464. RDCON    EQU    1
  6465. WRCON    EQU    2
  6466. LIST    EQU    5
  6467. PRINT    EQU    9
  6468. RDBUF    EQU    10
  6469. CONST    EQU    11
  6470. CPMVER    EQU    12
  6471. RESET    EQU    13
  6472. SELDSK    EQU    14
  6473. OPEN    EQU    15
  6474. CLOSE    EQU    16
  6475. SRCHF    EQU    17
  6476. SRCHN    EQU    18
  6477. ERASE    EQU    19
  6478. READ    EQU    20
  6479. WRITE    EQU    21
  6480. MAKE    EQU    22
  6481. REN    EQU    23
  6482. CURDSK    EQU    25
  6483. STDMA    EQU    26
  6484. DSKALL    EQU    27
  6485. DSKPAR    EQU    31
  6486. USER    EQU    32
  6487. FILSIZ    EQU    35
  6488. BDOS    EQU    0005H
  6489. REIPL    EQU    0
  6490. FCB    EQU    5CH
  6491. FCBEXT    EQU    FCB+12
  6492. FCBSNO    EQU    FCB+32
  6493. FCBRNO    EQU    FCB+32
  6494. FCB2    EQU    6CH
  6495. TBUF    EQU    80H
  6496. ;
  6497.     END
  6498.