home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / rcpm / chat46.lbr / CHAT46.AQM / CHAT46.ASM
Assembly Source File  |  1986-07-14  |  22KB  |  891 lines

  1. ;                CHAT.ASM v46
  2. ;                 revised by
  3. ;                   Murray Simsolo
  4. ;                  07/13/86
  5. ;
  6. ;
  7. ;    CHAT is an RCP/M utility which allows a remote user to "chat"
  8. ;               with the local system operator.
  9. ;
  10. ; ===========================
  11. ;
  12. ; NOTE -- A complete CHAT library consists of these files:
  13. ;
  14. ;      CHAT46.ASM    - Current assembly file
  15. ;      CHAT.HIS    - All revisions, current and past
  16. ;      CHAT.HLP    - General set-up help
  17. ;      CHAT.INF    - General information and sysop operation
  18. ;
  19. ; ===========================
  20. ;
  21. VERSION    EQU    4
  22. MODLEV    EQU    6
  23. MONTH    EQU    7
  24. DAY    EQU    13
  25. YEAR    EQU    86
  26. ;
  27. NO    EQU    0
  28. YES    EQU    NOT NO
  29. ;
  30. ; Define ASCII characters used
  31. ;
  32. BS    EQU    8        ; Backspace
  33. BELL    EQU    7        ; Bell
  34. CR    EQU    0DH        ; Carriage return
  35. DEL    EQU    7FH        ; Delete
  36. ESC    EQU    1BH        ; Escape character
  37. LF    EQU    0AH        ; Line feed
  38. TAB    EQU    9        ; Horizontal tab
  39. ;
  40. ; =============================================================
  41. ; Conditional equates - set to suit your system, then assemble.
  42. ; =============================================================
  43. ;
  44. CLOCK    EQU    4        ; Set to your CPU clock speed in MHz
  45. PGTIME    EQU    30        ; Number of seconds to page for sysop
  46. TGUIDE    EQU    YES        ; Yes, print a guide bar for estimated time
  47.                 ;   of summoning sysop prior to abort
  48. ;
  49. IMHERE    EQU    ESC        ; Hit this key to answer page and chat
  50. QKMSG    EQU    '{'        ; Hit this key to drop user into the
  51.                 ; MBBS comment mode, instantly.
  52. QUICK    EQU    'C'        ; Quick chat character (i.e. CHAT C will
  53.                 ;   bypass the paging routine).
  54. ;
  55. MPM    EQU    NO        ; Yes, MP/M program relocatable format
  56. ;
  57. ; ---------------------------
  58. ;
  59. ; Set for your terminal requirements
  60. ;
  61. MXLINE    EQU    79        ; Maximum line length (normally 0 to 79)
  62. WRAP    EQU    70        ; Location to perform wrap
  63. ;
  64. ; ---------------------------
  65. ;
  66. ; Set one equate YES according to which BBS system you operate:
  67. ;
  68. NONE    EQU    NO        ; Yes if none of the below systems are used
  69. ;
  70. CBBS    EQU    NO        ; Yes if CBBS system
  71. DATA    EQU    NO        ; Yes if DataTech system
  72. MBBS    EQU    YES        ; Yes if MBBS system
  73. METAL    EQU    NO        ; Yes if METAL system
  74. MINCBBS    EQU    NO        ; Yes if MINICBBS system
  75. OXGATE    EQU    NO        ; Yes if OxGate system
  76. RBBS    EQU    NO        ; Yes if RBBS system
  77. SIGNON    EQU    NO        ; Yes if Signon
  78. SIMMS    EQU    NO        ; Yes if SiMMS sytem
  79. ;
  80. ; ---------------------------
  81. ;
  82. ; Set only ONE or neither of these two equates to YES, not both:
  83. ;
  84. ASKNAM    EQU    NO        ; Yes if ask user's name before paging
  85. GETCALR    EQU    YES        ; Yes to get name from LASTCALR.DAT
  86. LCNAME    EQU    11        ; Column # where the caller's name starts
  87.                 ;   in LASTCALR.  Normally 0, but MBBS
  88.                 ;   starts in column 11.
  89. ;
  90. ; Drive and user area to find LASTCALR file if GETCALR is set to YES
  91. ;
  92. LASTDRV    EQU    'A'        ; Drive of LASTCALR file
  93. LASTUSR    EQU    14        ; User area of LASTCALR
  94. ;
  95. ; Set only one bell equate (BYEBELL or LMBELL), depending on your system.
  96. ;
  97. BYBELL    EQU    NO        ; Yes, if using BYE's internal bell flag
  98. LMBELL    EQU    YES        ; Yes, if using low memory bell flag (KILBEL)
  99. KILBEL    EQU    3BH        ; Byte for low memory bell flag if LMBELL is
  100.                 ;   set YES (0 = bell on, 0FFH = bell off)
  101. BELOFF    EQU    20        ; Number of bytes from COLDBOOT: to BELLON
  102.                 ; flag (BYE5 uses 20, NUBYE uses 27) if BYBELL
  103.                 ; is YES and BYEBDOS is NO
  104. ;
  105. COMMENT    EQU    YES        ; Yes, allow leaving comment when the
  106.                 ;   sysop isn't available (MBBS only)
  107. ;
  108. ; Set B3RTC to YES if you are running a BYE3 or MBYE version which
  109. ; supports a real-time clock (RTCBUF).    Set BYEBDOS to YES if you are
  110. ; running a BYE3, BYE5, MBYE, or NUBYE version which supports the BYEBDOS
  111. ; extended BDOS calls (do not set both B3RTC and BYEBDOS to YES).
  112. ; Set TIMEON to YES if BYEBDOS is YES and CLOCK and TIMEON in BYE5/NUBYE
  113. ; are yes or if RTC and TIMEUP in MBYE are YES (prevents BYE from hanging
  114. ; up during chats).
  115. ;
  116. BYEBDOS    EQU    YES        ; Yes, using extended BDOS calls  (BYE5/NUBYE)
  117. TIMEON    EQU    YES        ; Yes, limiting time on system (all BYEs)
  118. B3RTC    EQU    NO        ; If YES, your clock is setup in BYE3 (or MBYE)
  119. B3COFF    EQU    25        ; OFFSET from COLDBOOT: to RTCBUF address
  120. B3MXO    EQU    24        ; OFFSET from COLDBOOT: to MXML address
  121. ;
  122. ; ---------------------------
  123. ;
  124. RESCHAT    EQU    NO        ; Yes, restrict sysop paging to pre-
  125.                 ;   determined hours
  126. ;
  127. ; Hours (24-hour mode) during which sysop paging will be possible, when
  128. ; RESCHAT is YES. (Example: 16 = 4 pm  and  21 = 9 pm)
  129. ;
  130. CHATON    EQU    18        ; Start of CHAT period
  131. CHATOFF    EQU    22        ; End of CHAT period
  132. ;
  133. ; Set the following bytes to correspond to the areas used by your system
  134. ; for time storage, if RESCHAT is YES and B3RTC and BYEBDOS are NO.
  135. ;
  136. HOUR    EQU    50H        ; Location of hour
  137. MIN    EQU    51H        ; Location of minute
  138. ;
  139. ;
  140. ; end of normal user definable equates
  141. ; ====================================
  142. ;
  143. ; BDOS equates
  144. ;
  145. BASE    EQU    0        ; Start of CP/M memory area
  146. BDOS    EQU    5        ; BDOS call address
  147. FCB    EQU    5CH        ; CCP file control block
  148. DMAADR    EQU    80H        ; Default DMA buffer address
  149. ;
  150. ; BDOS functions
  151. ;
  152. PRINT    EQU    9        ; Print string function
  153. SELDSK    EQU    14        ; Select disk
  154. FOPEN    EQU    15        ; File open
  155. FREAD    EQU    20        ; File read
  156. RTNDSK    EQU    25        ; Return current disk
  157. SETDMA    EQU    26        ; Set DMA address
  158. SETUSR    EQU    32        ; Get/set user number
  159. ;
  160. ; -------------------
  161. ;
  162.      IF    MPM
  163.     ORG    BASE
  164.      ENDIF
  165. ;
  166.      IF    NOT MPM
  167.     ORG    BASE+100H
  168.      ENDIF
  169. ;
  170. ; ===================
  171. ; Program starts here
  172. ; ===================
  173. ;
  174. START:    LXI    H,0
  175.     DAD    SP        ; Get old stack pointer
  176.     SHLD    STACK        ; Save it
  177.     LXI    SP,STACK    ; Set new stack pointer
  178. ;
  179. ; Initialize jumps to CBIOS for direct I/O
  180. ;
  181.     LHLD    BASE+1        ; Get pointer to CBIOS
  182.     LXI    D,3        ; Ready for address
  183.     DAD    D        ; HL = constat vector
  184.     SHLD    CSTAT+1        ; Modify jump
  185.     DAD    D        ; HL = CONIN vector
  186.     SHLD    CONIN+1        ; Modify jump
  187.     DAD    D        ; HL = CONOUT vector
  188.     SHLD    CONOUT+1    ; Modify jump
  189. ;
  190. ; Check to see if BYE is available, first.
  191. ;
  192.      IF    BYEBDOS
  193.     MVI    C,32
  194.     MVI    E,241
  195.     CALL    BDOS
  196.     CPI    77        ; Is it there?
  197.     JZ    TIME        ; Yes, so get time if used
  198.      ENDIF            ; BYEBDOS
  199. ;
  200.      IF    NOT BYEBDOS
  201.     LHLD    1        ; Point to warm boot
  202.     DCX    H        ; If BYE active,
  203.     MOV    D,M        ; Pick up pointer to BYE variables
  204.     DCX    H
  205.     MOV    E,M
  206.     LXI    H,15        ; Calculate address of BYE variables
  207.     DAD    D        ; Where ptr to orig BIOS vector stored
  208.     MOV    E,M        ; Load that address
  209.     INX    H
  210.     MOV    D,M
  211.     INX    H
  212.     MOV    A,M        ; Get letter
  213.     ANI    5FH        ; Convert to upper case if needed
  214.     CPI    'B'        ; Try to match 'BYE'
  215.     JNZ    NOBYE        ; Out if BYE not active
  216.     INX    H
  217.     MOV    A,M        ; Keep checking
  218.     ANI    5FH
  219.     CPI    'Y'
  220.     JNZ    NOBYE
  221.     INX    H
  222.     MOV    A,M
  223.     ANI    5FH
  224.     CPI    'E'
  225.     JZ    TIME        ; Found it, yes it is running
  226. ;
  227. NOBYE:
  228.      ENDIF            ; NOT BYEBDOS
  229. ;
  230.     CALL    ILPRT
  231.     DB    CR,LF
  232.     DB    'BYE unavailable...aborting...',CR,LF,7,0
  233.     JMP    EXIT2
  234. ;
  235. ; Get RTC data from BYE or other areas
  236. ;
  237. TIME:
  238.      IF    RESCHAT    AND BYEBDOS AND    (NOT B3RTC)
  239.     PUSH    B        ; Hour was safely moved to highmem
  240.     PUSH    D        ; In newer versions of BYE
  241.     MVI    C,79        ; Get RTC buffer addr
  242.     CALL    BDOS
  243.     LXI    D,9        ; Offset to current hour (binary)
  244.     DAD    D
  245.     MOV    A,M        ; Move to A
  246.     STA    CHOUR        ; Store it
  247.     INX    H        ; Increment to current minute (binary)
  248.     MOV    A,M        ; Move to A
  249.     STA    CMIN        ; Store it
  250.     POP    D
  251.     POP    B
  252.      ENDIF
  253. ;
  254. ; Get address of RTCBUF in BYE3 or MBYE
  255. ;
  256.      IF    RESCHAT    AND B3RTC AND (NOT BYEBDOS)
  257.     LHLD    0001H        ; Get COLDBOOT addr
  258.     DCX    H        ; (just before JMP WBOOT)
  259.     MOV    D,M        ; And stuff in DE
  260.     DCX    H
  261.     MOV    E,M
  262.     LXI    H,B3COFF    ; Add offset to RTCBUF address
  263.     DAD    D        ; (in HL)
  264.     MOV    E,M        ; Get RTCBUF address
  265.     INX    H        ; And
  266.     MOV    D,M        ; Stuff in DE
  267.     XCHG            ; Swap into HL
  268.     MOV    A,M        ; Get hours on system
  269.     CALL    BCDBIN        ; Convert BCD value to binary
  270.     STA    CHOUR        ; Save hr
  271.     INX    H        ; Point to minute
  272.     MOV    A,M        ; Get min
  273.     CALL    BCDBIN        ; Convert BCD to binary
  274.     STA    CMIN        ; Save min
  275.      ENDIF
  276. ;
  277.      IF    RESCHAT    AND NOT    (B3RTC OR BYEBDOS)
  278.     LDA    HOUR        ; Get current hour
  279.     STA    CHOUR
  280.     LDA    MIN        ; Get current minute
  281.     STA    CMIN
  282.      ENDIF
  283. ;
  284. ; End of time routines
  285. ; --------------------
  286. ;
  287. ; Print program name, version number and date message
  288. ;
  289. CHAT:    CALL    ILPRT
  290.     DB    CR,LF,'CHAT v'
  291.     DB    VERSION+'0',MODLEV+'0','  '
  292.     DB    MONTH/10+'0',MONTH MOD 10+'0','/'
  293.     DB    DAY/10+'0',DAY MOD 10+'0','/'
  294.     DB    YEAR/10+'0',YEAR MOD 10+'0',CR,LF,0
  295. ;
  296.      IF    BYEBDOS    AND (NOT B3RTC)    AND TIMEON
  297.     MVI    E,255
  298.     MVI    C,81
  299.     CALL    BDOS        ; Get MXTIME from BYE
  300.     STA    TLIMIT        ; And store it
  301.     MVI    E,0
  302.     MVI    C,81
  303.     CALL    BDOS        ; Stop time check for now
  304.      ENDIF
  305. ;
  306.      IF    B3RTC AND (NOT BYEBDOS)    AND TIMEON
  307.     LHLD    0001H        ; Get JMP COLDBOOT
  308.     DCX    H
  309.     MOV    D,M
  310.     DCX    H
  311.     MOV    E,M
  312.     LXI    H,B3MXO        ; + B3MXO offset to MXML
  313.     DAD    D
  314.     MOV    A,M        ; = max time allowed on system
  315.     STA    TLIMIT        ; Store max time
  316.     XRA    A
  317.     MOV    M,A        ; Stop max time check for now
  318.      ENDIF
  319. ;
  320.      IF    RESCHAT
  321.     LXI    H,CHOUR        ; Point at current hour
  322.     MVI    A,CHATON    ; Start of chat period
  323.     DCR    A
  324.     CMP    M        ; Time to allow paging?
  325.     JNC    NOCHAT        ; Carry = continue
  326.     MVI    A,CHATOFF    ; End of chat period
  327.     DCR    A
  328.     CMP    M        ; Time to end paging?
  329.     JNC    TSTBEL        ; Carry = no chatting now
  330. NOCHAT:    CALL    ILPRT
  331.     DB    CR,LF
  332.     DB    'The Sysop is available between '
  333.     DB    CHATON/10+'0',CHATON MOD 10+'0',':00 and '
  334.     DB    CHATOFF/10+'0',CHATOFF MOD 10+'0',':00 hours, only.',0
  335.     JMP    NOHOME
  336.      ENDIF            ; RESCHAT
  337. ;
  338. TSTBEL:
  339.      IF    BYBELL AND (NOT    LMBELL)    AND BYEBDOS
  340.     MVI    E,255
  341.     MVI    C,78        ; BDOS function call
  342.     CALL    BDOS
  343.     CPI    0FFH        ; And check
  344.     JNZ    NOHERE
  345.      ENDIF
  346. ;
  347.      IF    BYBELL AND (NOT    LMBELL)    AND (NOT BYEBDOS)
  348.     LHLD    1        ; Point to bye's cold boot vector
  349.     DCX    H        ; Point to vector high byte
  350.     MOV    D,M        ; Get high byte into D
  351.     DCX    H        ; Point to vector low byte
  352.     MOV    E,M        ; Get low byte into E
  353.     LXI    H,BELOFF    ; Load HL with no bytes to add to cold boot
  354.     DAD    D        ; Cold boot + no bytes = HL has address of bell
  355.     MOV    A,M        ; Move the bell toggle byte to A
  356.     ORA    A        ; 0?
  357.     JZ    NOHERE        ; Yes, so Sysop is not here
  358.      ENDIF
  359. ;
  360.      IF    LMBELL AND (NOT    BYBELL)
  361.     LDA    KILBEL        ; Get status
  362.     ORA    A        ; 0?
  363.     JNZ    NOHERE        ; No, so Sysop is not here
  364.      ENDIF
  365. ;
  366. ;Get caller's name from LASTCALR, user or not at all
  367. ;
  368. WHO:     IF    GETCALR    AND (NOT ASKNAM)
  369.     MVI    E,0FFH        ; Get current user #
  370.     MVI    C,SETUSR
  371.     CALL    BDOS
  372.     STA    CURUSR        ; Save current user
  373.     MVI    E,LASTUSR
  374.     MVI    C,SETUSR    ; Set user of LASTCALR
  375.     CALL    BDOS
  376.     MVI    C,RTNDSK    ; Get current disk
  377.     CALL    BDOS
  378.     STA    CURDSK
  379.     MVI    E,LASTDRV-'A'    ; Set drive of LASTCALR
  380.     MVI    C,SELDSK
  381.     CALL    BDOS
  382.     LXI    D,LFCB        ; Open LASTCALR
  383.     MVI    C,FOPEN
  384.     CALL    BDOS
  385.     INR    A        ; Check if file not found (0FFH)
  386.     JZ    UNDO        ; Not found, don't complain, Zflag set
  387.     LXI    D,DMAADR
  388.     MVI    C,SETDMA    ; Make sure DMA is default address
  389.     CALL    BDOS
  390.     LXI    D,LFCB
  391.     MVI    C,FREAD        ; Fill default buffer
  392.     CALL    BDOS
  393.     ORI    0FFH        ; Make sure the Zflag is clear
  394.      ENDIF            ; GETCALR AND NOT ASKNAM
  395. ;
  396. ; If the file open was not successful, the Z-flag is set.  We still need
  397. ; to return to the current disk and user
  398. ;
  399. UNDO:     IF    GETCALR    AND (NOT ASKNAM)
  400.     PUSH    PSW        ; Save it for for later
  401.     LDA    CURUSR        ; Restore current user
  402.     MOV    E,A
  403.     MVI    C,SETUSR
  404.     CALL    BDOS
  405.     LDA    CURDSK        ; Restore current disk
  406.     MOV    E,A
  407.     MVI    C,SELDSK
  408.     CALL    BDOS
  409.     POP    PSW        ; Was the file open successful?...
  410.     JZ    QCHAT        ; No, so skip the rest of this stuff
  411.      ENDIF            ; GETCALR AND NOT ASKNAM
  412. ;
  413.      IF    GETCALR    AND (NOT ASKNAM)
  414.     LXI    H,DMAADR+LCNAME
  415.      ENDIF
  416. ;
  417. ; CLOOP is a bit more complex because of SIGNON.  The SIGNON* system
  418. ; places additional information into LASTCALR, which need not be
  419. ; presented to the caller. (OxGate, too)
  420. ;
  421.      IF    GETCALR    AND (NOT ASKNAM)
  422.     CALL    ILPRT
  423.     DB    CR,LF,'Hold on, ',0
  424. ;
  425. CLOOP:    MOV    A,M
  426.     CPI    CR
  427.     JZ    CLOOPE        ; Found end of file
  428.     CPI    ','
  429.     JNZ    NOCO
  430.      ENDIF            ; GETCALR AND NOT ASKNAM
  431. ;
  432.      IF    (MBBS OR OXGATE    OR RBBS    OR SIGNON) AND GETCALR AND (NOT    ASKNAM)
  433.     LDA    SECND
  434.     ORA    A
  435.     JNZ    CLOOPE        ; MBBS & OxGate need to stop at the 2nd ','
  436.     MVI    A,1
  437.     STA    SECND
  438.      ENDIF            ; MBBS OR OXGATE OR RBBS OR SIGNON
  439. ;
  440.      IF    GETCALR    AND (NOT ASKNAM)
  441.     MVI    A,' '
  442. ;
  443. NOCO:    PUSH    H
  444.     MOV    C,A
  445.     CALL    CONOUT
  446.     POP    H
  447.     INX    H
  448.     JMP    CLOOP
  449. ;
  450. CLOOPE:    CALL    ILPRT
  451.     DB    ' -- ',0
  452.      ENDIF            ; GETCALR AND NOT ASKNAM
  453. ;
  454. QCHAT:    LDA    FCB+1
  455.     CPI    QUICK        ; Quick chat requested?
  456.     JZ    QCHAT1        ; Yes, so get to it
  457.     JMP    CHAT1        ; ...else, continue with paging message
  458. ;
  459. QCHAT1:    CALL    ILPRT        ; Turn up a new line
  460.     DB    CR,LF,0
  461.     JMP    CRLF        ; Now go chat
  462. ;
  463.      IF    GETCALR    AND (NOT ASKNAM)
  464. LFCB:    DB    0
  465.      ENDIF            ; GETCALR AND (NOT ASKNAM)
  466. ;
  467.      IF    (NOT MBBS) AND (NOT OXGATE) AND    GETCALR    AND (NOT ASKNAM)
  468.     DB    'LASTCALR   '    ; File containing name of last caller
  469.      ENDIF            ; NOT MBBS AND NOT OXGATE
  470. ;
  471.      IF    MBBS AND GETCALR AND (NOT ASKNAM)
  472.     DB    'LASTCALRBBS'
  473.      ENDIF            ; MBBS
  474. ;
  475.      IF    OXGATE AND GETCALR AND (NOT ASKNAM)
  476.     DB    'LASTCALRDAT'
  477.      ENDIF            ; OXGATE
  478. ;
  479.      IF    GETCALR    AND (NOT ASKNAM)
  480.     DB    0,0,0,0,0,0
  481.     DB    0,0,0,0,0,0
  482.     DB    0,0,0,0,0,0
  483.     DB    0,0,0,0,0,0
  484. SECND:    DB    0
  485. CURDSK:    DB    0
  486. CURUSR:    DB    0
  487.      ENDIF            ; GETCALR AND NOT ASKNAM
  488. ;
  489. ; ===========================
  490. ;
  491. CHAT1:     IF    ASKNAM AND (NOT    GETCALR)
  492.     CALL    ILPRT
  493.     DB    CR,LF,'Your name, please? (optional): ',0
  494. ;
  495. GLOOP:    CALL    CKABT        ; Check for abort
  496.     CPI    CR
  497.     JZ    CHAT2        ; CR, end of name
  498.     CPI    ' '
  499.     JC    GLOOP        ; CTRL-character, ignore it
  500.     MOV    C,A
  501.     CALL    CONOUT        ; Else echo it
  502.     LDA    LCNT
  503.     INR    A        ; Increment line count
  504.     STA    LCNT
  505.     JMP    GLOOP        ; Keep looping
  506.      ENDIF            ; ASKNAM AND NOT GETCALR
  507. ;
  508. CHAT2:    CALL    ILPRT
  509. ;
  510.      IF    ASKNAM AND (NOT    GETCALR)
  511.     DB    CR,LF,LF
  512.      ENDIF            ; ASKNAM AND NOT GETCALR
  513. ;
  514.     DB    'will page the operator (abort with ^C or ^X)',CR,LF
  515.     DB    CR,LF,LF,0
  516. ;
  517.      IF    TGUIDE
  518.     CALL    ILPRT
  519.     DB    '        |',0
  520. ;
  521. BARS1:    CALL    ILPRT        ; Print bar and space
  522.     DB    '-',0
  523.     LDA    BCNT        ; Get bar counter
  524.     DCR    A        ; Done with bars?
  525.     STA    BCNT        ; Save new count
  526.     JNZ    BARS1        ; Not done, do it again
  527.     CALL    ILPRT
  528.     DB    '|',CR,LF,0
  529.      ENDIF            ; TGUIDE
  530. ;
  531.     CALL    ILPRT
  532.     DB    'Ringing: ',0
  533. ;
  534. ; Attempt to alert operator
  535. ;
  536. START1:    CALL    ILPRT        ; Print period <BEEP> and space
  537.     DB    '.',BELL,0
  538.     CALL    TIMER
  539.     LDA    CNT        ; Get attempt counter
  540.     DCR    A        ; Decrement alert counter
  541.     STA    CNT        ; Save new count
  542.     JNZ    START1        ; Not done with attempts, do more
  543. ;
  544. ; Operator did not answer
  545. ;
  546. NOHERE:    CALL    ILPRT
  547.     DB    CR,LF,LF,'Sorry, operator is not available.',0
  548. ;
  549. NOHOME:    CALL    ILPRT
  550. ;
  551.      IF    MBBS AND COMMENT
  552.     DB    CR,LF
  553.     DB    'Would you like to leave a private message? <N> '
  554.     DB    0
  555.     CALL    CONIN        ; Get response
  556.     ANI    5FH        ; Convert to upper case
  557.     CPI    'Y'        ; Yes?
  558.     JNZ    EXIT        ; No, so exit
  559.     CALL    ILPRT
  560.     DB    'Yes',CR,LF,0
  561.     JMP    LDCOM        ; Yes, so load the .COM file
  562.      ENDIF            ; MBBS AND COMMENT
  563. ;
  564.      IF    NONE
  565.     DB    CR,LF,LF,'Back to CP/M...',0
  566.      ENDIF            ; NONE
  567. ;
  568.      IF    NOT NONE
  569.     DB    CR,LF,'Please leave a message in the '
  570.      ENDIF            ; NOT NONE
  571. ;
  572.      IF    CBBS
  573.     DB    'CBBS'
  574.      ENDIF            ; CBBS
  575. ;
  576.      IF    DATA
  577.     DB    'DataTech'
  578.      ENDIF            ; DATATECH
  579. ;
  580.      IF    MBBS AND (NOT COMMENT)
  581.     DB    'MBBS'
  582.      ENDIF            ; MBBS AND NOT COMMENT
  583. ;
  584.      IF    METAL
  585.     DB    'METAL'
  586.      ENDIF            ; METAL
  587. ;
  588.      IF    MINCBBS
  589.     DB    'MINICBBS'
  590.      ENDIF            ; MINICBBS
  591. ;
  592.      IF    OXGATE
  593.     DB    'OxGate'
  594.      ENDIF            ; OXGATE
  595. ;
  596.      IF    RBBS
  597.     DB    'RBBS'
  598.      ENDIF            ; RBBS
  599. ;
  600.      IF    SIGNON
  601.     DB    'comments section when exiting the system...',0
  602.      ENDIF            ; SIGNON
  603. ;
  604.      IF    SIMMS
  605.     DB    'SiMMS'
  606.      ENDIF            ; SIMMS
  607. ;
  608.      IF    (NOT NONE) AND (NOT SIGNON)
  609.     DB    ' message system...',0
  610.      ENDIF            ; NONE
  611. ;
  612.     JMP    EXIT1        ; Exit to CP/M
  613. ;
  614. ; ===================
  615. ; Routines start here
  616. ; ===================
  617. ;
  618. ; Backspaces one column, first erasing the current character
  619. ;
  620. BACKIT:    LDA    LCNT        ; Get character count
  621.     ORA    A        ; Column 0, yet?
  622.     RZ            ; Yes, so forget it
  623.     DCR    A        ; Subtract one because of backspace
  624.     STA    LCNT        ; Save new count
  625.     CALL    ILPRT        ; Print
  626.     DB    BS,' ',BS,0
  627.     RET            ; Continue looping
  628. ;
  629. ; Conversation routine - uses direct CBIOS I/O to prevent control char-
  630. ; acters from being echoed.
  631. ;
  632. CONT:    CALL    CKABT        ; Check for abort
  633.     CPI    TAB        ; Tab?
  634.     JZ    SNDTAB        ; Yes, send it
  635.     CPI    CR        ; Carriage return?
  636.     JZ    CRLF        ; Yes, send CRLF
  637.     CPI    ' '        ; Space or above? if not,
  638.     JC    CONT        ; It's a CTRL-character, continue looping
  639.     MOV    C,A        ; Else, save char. in C (also for CBIOS)
  640.     LDA    LCNT        ; Check count
  641.     CPI    WRAP        ; Time to wrap?
  642.     JC    CHROK        ; No, character is ok
  643.     MOV    A,C        ; Get character
  644.     CPI    ' '        ; Space?
  645.     JZ    CRLF        ; Yes, then word wrap
  646.     LDA    LCNT        ; No, check line count again
  647.     CPI    MXLINE        ; At end of line?
  648.     JNZ    CHROK        ; Not at end of line, character is ok
  649.     MVI    C,BELL
  650.     CALL    CONOUT        ; Else ignore charactr and beep
  651.     JMP    CONT        ; And continue
  652. ;
  653. CHROK:    CALL    CONOUT        ; Send character to console
  654.     LDA    LCNT        ; Get character count
  655.     INR    A        ; Increment counter
  656.     JMP    CRLF1        ; Continue looping
  657. ;
  658. CRLF:    CALL    ILPRT
  659.     DB    CR,LF,0
  660.     XRA    A        ; Zero character counter
  661. CRLF1:    STA    LCNT        ; Save new count
  662.     JMP    CONT        ; Continue looping
  663. ;
  664. SNDTAB:    LDA    LCNT        ; Get line count in A
  665.     ADI    8        ; Add tab count
  666.     MOV    C,A        ; Save in C
  667.     CPI    MXLINE        ; Still <MXLINE?
  668.     JNC    CRLF        ; No, so start new line
  669.     MOV    A,C        ; ...else get LCNT back
  670.     STA    LCNT        ; save new count
  671.     CALL    ILPRT
  672.     DB    '        ',0    ; Send 8 spaces for a tab
  673.     JMP    CONT        ; Continue looping
  674. ;
  675. ; CBIOS routines for console status, get character and show character
  676. ;
  677. CSTAT:    JMP    $-$        ; Modified at init
  678. CONIN:    JMP    $-$        ; Modified at init
  679. CONOUT:    JMP    $-$        ; Modified at init
  680. ;
  681. ; =======================================================================
  682. ;
  683. ; Timer routine for paging sysop PGTIME seconds
  684. ;
  685. TIMER:    LXI    H,18*PGTIME    ; Initialize # secs to page for sysop
  686.     SHLD    CNTDWN        ; Save it
  687. ;
  688. TIMER1:    CALL    CSTAT        ; Get console status
  689.     ORA    A        ; Incoming character?
  690.     CNZ    KEYCHK        ; Yes, so check it
  691. ;
  692. TIMER2:    CALL    DELAY        ; Wait 1ms
  693.     PUSH    H
  694.     LHLD    CNTDWN        ; Decrement countdown timer
  695.     DCX    H
  696.     SHLD    CNTDWN
  697.     MOV    A,H
  698.     ORA    L
  699.     POP    H
  700.     JNZ    TIMER1        ; Loop until time is up
  701. ;
  702. ; 1ms delay routine
  703. ;
  704. DELAY:    PUSH    B
  705.     LXI    B,42*CLOCK    ; Timing constant x clock (MHz)
  706. ;
  707. DELAY1:    DCX    B
  708.     MOV    A,B
  709.     ORA    C
  710.     JNZ    DELAY1
  711.     POP    B
  712.     RET
  713. ;
  714. KEYCHK:    CALL    CKABT        ; Check for abort
  715.     CPI    IMHERE        ; Sysop ready to chat?
  716.     RNZ            ; No, so keep paging
  717. ;
  718. ; The sysop is ready to chat...
  719. ;
  720.     LXI    SP,STACK    ; Fix stack
  721.     CALL    ILPRT
  722.     DB    CR,LF,LF
  723.     DB    'Operator is available, please go ahead...',CR,LF
  724.     DB    '(Use ^C or ^X to exit and return to CP/M)',CR,LF
  725.     DB    LF,0
  726.     JMP    CRLF        ; Now in chat mode
  727. ;
  728. EXIT:     IF    MBBS AND COMMENT
  729.     CALL    ILPRT        ; No comment - return to CP/M
  730.     DB    'No',CR,LF,0
  731.      ENDIF            ; MBBS AND COMMENT
  732. ;
  733. EXIT1:
  734.      IF    (BYEBDOS OR B3RTC) AND TIMEON
  735.     CALL    RESMXT        ; Reset max time to pre-chat value
  736.      ENDIF
  737. ;
  738. EXIT2:    CALL    ILPRT
  739.     DB    CR,LF,0
  740.     LHLD    STACK        ; Get old CP/M (or MP/M) stack
  741.     SPHL            ; Restore old stack pointer
  742.     RET            ; To CP/M
  743. ;
  744. ;  Load routine
  745. ;
  746. LDCOM:
  747.      IF    MBBS AND COMMENT AND (BYEBDOS OR B3RTC)    AND TIMEON
  748.     CALL    RESMXT        ; Get back max time
  749.      ENDIF
  750. ;
  751.      IF    MBBS AND COMMENT
  752.     LHLD    STACK        ; Get old stack
  753.     SPHL            ; Restore it
  754.     CALL    ILPRT
  755.     DB    CR,LF,LF
  756.     DB    'Loading for COMMENT...please stand by...'
  757.     DB    CR,LF,LF,0
  758.     MVI    A,'P'
  759.     STA    80H        ; 80H=0 if public, "P" if private
  760.     LXI    D,82H        ; Our buffer starts at 82H
  761.     MVI    C,0        ; C=# of characters (stuff at 81H)
  762.     LXI    H,COMHDR    ; Subject heading
  763. LDCOM1:    MOV    A,M
  764.     ORA    A
  765.     JZ    LDCOM2
  766.     CALL    PUTHDR
  767.     INX    H
  768.     JMP    LDCOM1
  769. ;
  770. LDCOM2:    MOV    A,C
  771.     STA    81H        ; Save # of chars in 81H
  772.     MVI    A,0CAH        ; Stuff 0CAH (JZ) in location 0
  773.     STA    0        ; for MBYE/BYE5/NUBYE handling
  774.     XRA    A        ; Make sure Z flag set so JZ will jump
  775.     JMP    0
  776. ;
  777. ; COMHDR is loaded as the message subject
  778. ;
  779. COMHDR:    DB    'General (COMMENT)',0
  780. ;
  781. PUTHDR:    STAX    D
  782.     INX    D
  783.     INR    C
  784.     RET
  785.      ENDIF            ; MBBS AND COMMENT
  786. ;
  787. ; Convert BCD value in A to binary in A
  788. ;
  789.      IF    RESCHAT    AND B3RTC AND (NOT BYEBDOS)
  790. BCDBIN:    PUSH    PSW        ; Save A
  791.     ANI    0F0H        ; Mask high nibble
  792.     RRC            ; Move to low nibble
  793.     RRC
  794.     RRC
  795.     RRC
  796.     MOV    C,A        ; And stuff in C (C=A)
  797.     MVI    B,9        ; X10 (*9)
  798. ;
  799. BCDBL:    ADD    C        ; Add orig value to A
  800.     DCR    B        ; Decrement B
  801.     JNZ    BCDBL        ; Loop nine times (A+(C*9)=A*10)
  802.     MOV    B,A        ; Save result in B
  803.     POP    PSW        ; Get original value
  804.     ANI    0FH        ; Mask low nibble
  805.     ADD    B        ; +B gives binary value of BCD digit A
  806.     RET            ; Return
  807.      ENDIF
  808. ;
  809. RESMXT:
  810.      IF    BYEBDOS    AND (NOT B3RTC)    AND TIMEON
  811.     LDA    TLIMIT        ; Get MXTIME back
  812.     MOV    E,A        ; Store it
  813.     MVI    C,81
  814.     CALL    BDOS        ; Restore MXTIME to pre-chat status
  815.     XRA    A        ; Clear carry flag
  816.     RET            ; And return
  817.      ENDIF
  818. ;
  819.      IF    B3RTC AND (NOT BYEBDOS)    AND TIMEON
  820.     LHLD    0001H        ; Get JMP COLDBOOT
  821.     DCX    H
  822.     MOV    D,M
  823.     DCX    H
  824.     MOV    E,M
  825.     LXI    H,B3MXO        ; + B3MXO offset to MXML
  826.     DAD    D
  827.     LDA    TLIMIT        ; Get max time back
  828.     MOV    M,A        ; Restore to pre-chat status
  829.     RET
  830.      ENDIF
  831. ;
  832. ; Inline print routine
  833. ;
  834. ILPRT:    XTHL            ; Save HL, generate message
  835. ;
  836. ILPLP:    MOV    C,M        ; Get character
  837.     PUSH    H
  838.     CALL    CONOUT        ; Output it
  839.     POP    H
  840.     INX    H        ; Point to next character
  841.     MOV    A,M        ; Test
  842.     ORA    A        ; For end
  843.     JNZ    ILPLP
  844.     XTHL            ; Restore HL, return address
  845.     RET            ; Return past message string
  846. ;
  847. ; Check for abort request
  848. ;
  849. CKABT:    CALL    CONIN        ; Get a character
  850.     CPI    'C'-40H        ; CTRL-C?
  851.     JZ    EXIT1        ; Yes, so exit chat
  852.     CPI    'X'-40H        ; CTRL-X?
  853.     JZ    EXIT1        ; Yes
  854. ;
  855.      IF    MBBS AND COMMENT
  856.     CPI    QKMSG        ; Sysop requesting fast msg entry?
  857.     JZ    LDCOM        ; Yes, so do it
  858.      ENDIF            ; MBBS AND COMMENT
  859. ;
  860.     CPI    DEL        ; Delete?
  861.     JZ    BACKIT        ; Yes
  862.     CPI    BS        ; Backspace?
  863.     JZ    BACKIT        ; Yes, so treat as delete
  864.     RET            ; ...else return
  865. ;
  866. ;            end of routines
  867. ;=======================================================================
  868. ;
  869.     DS    64        ; Room for 32 level stack
  870. STACK:    DS    2        ; Old CP/M (or MP/M) stack saved here
  871. ;
  872. BCNT:    DB    PGTIME        ; Bar counter
  873. CNT:    DB    PGTIME        ; Alert counter
  874. CNTDWN:    DS    2        ; Countdown Timer
  875. LCNT:    DB    0        ; Line position counter
  876. ;
  877.      IF    (BYEBDOS OR B3RTC) AND TIMEON
  878. TLIMIT:    DB    0        ; Storage byte for MXTIME
  879.      ENDIF
  880. ;
  881.      IF    RESCHAT
  882. CHOUR:    DS    1        ; Current hour
  883. CMIN:    DS    1        ; Current minute
  884.      ENDIF
  885. ;
  886.      IF    MPM
  887.     DB    0        ; Force allocation of storage space
  888.      ENDIF
  889. ;
  890.     END
  891.